summaryrefslogtreecommitdiff
path: root/tools/pm/DocsParser.pm
diff options
context:
space:
mode:
Diffstat (limited to 'tools/pm/DocsParser.pm')
-rw-r--r--tools/pm/DocsParser.pm257
1 files changed, 197 insertions, 60 deletions
diff --git a/tools/pm/DocsParser.pm b/tools/pm/DocsParser.pm
index c771fc3c..8dae9c14 100644
--- a/tools/pm/DocsParser.pm
+++ b/tools/pm/DocsParser.pm
@@ -25,7 +25,7 @@ use XML::Parser;
use strict;
use warnings;
-# use Util;
+use Util;
use Function;
use GtkDefs;
use Object;
@@ -112,18 +112,19 @@ sub parse_on_start($$%)
$tag = lc($tag);
- if($tag eq "function" or $tag eq "signal" or $tag eq "enum")
+ if($tag eq "function" or $tag eq "signal" or $tag eq "property" or $tag eq "enum")
{
if(defined $DocsParser::objCurrentFunction)
{
$objParser->xpcroak(
- "\nClose a function, signal or enum tag before you open another one.");
+ "\nClose a function, signal, property or enum tag before you open another one.");
}
my $functionName = $attr{name};
- # Change signal name from Class::a-signal-name to Class::a_signal_name.
- $functionName =~ s/-/_/g if($tag eq "signal");
+ # Change signal name from Class::a-signal-name to Class::a_signal_name
+ # and property name from Class:a-property-name to Class:a_property_name
+ $functionName =~ s/-/_/g if ($tag eq "signal" or $tag eq "property");
#Reuse existing Function, if it exists:
#(For instance, if this is the override parse)
@@ -195,7 +196,7 @@ sub parse_on_end($$)
$tag = lc($tag);
- if($tag eq "function" or $tag eq "signal" or $tag eq "enum")
+ if($tag eq "function" or $tag eq "signal" or $tag eq "property" or $tag eq "enum")
{
# Store the Function structure in the array:
my $functionName = $$DocsParser::objCurrentFunction{name};
@@ -233,14 +234,15 @@ sub parse_on_cdata($$)
}
}
-sub lookup_enum_documentation($$$)
+sub lookup_enum_documentation($$$$)
{
- my ($c_enum_name, $cpp_enum_name, $ref_flags) = @_;
+ my ($c_enum_name, $cpp_enum_name, $indent, $ref_flags) = @_;
my @subst_in = [];
my @subst_out = [];
+ my $newin = "";
- # Get the substitutions.
+ # Get the substitutions, and recognize some flags too.
foreach(@$ref_flags)
{
if(/^\s*s#([^#]+)#([^#]*)#\s*$/)
@@ -248,6 +250,10 @@ sub lookup_enum_documentation($$$)
push(@subst_in, $1);
push(@subst_out, $2);
}
+ elsif(/^\s*newin(.*)/) #If newin is at the start.
+ {
+ $newin = string_unquote(string_trim($1));
+ }
}
my $objFunction = $DocsParser::hasharrayFunctions{$c_enum_name};
@@ -285,19 +291,23 @@ sub lookup_enum_documentation($$$)
$param =~ s/([a-zA-Z0-9]*(_[a-zA-Z0-9]+)*)_?/$1/g;
if(length($desc) > 0)
{
- $desc =~ s/\n/ /g;
- $desc =~ s/ $//;
- $desc =~ s/^\s+//; # Chop off leading whitespace
+ # Chop off leading and trailing whitespace.
+ $desc =~ s/^\s+//;
+ $desc =~ s/\s+$//;
$desc .= '.' unless($desc =~ /(?:^|\.)$/);
- $docs .= "\@var $cpp_enum_name ${param}\n \u${desc}\n\n"; # \u = Convert next char to uppercase
+ $docs .= "\@var $cpp_enum_name ${param}\n\u${desc}\n\n"; # \u = Convert next char to uppercase
}
}
- # Append the enum description docs.
- $docs .= "\@enum $cpp_enum_name\n";
- $docs .= $$objFunction{description};
+ # Replace @newin in the enum description, but don't in the element descriptions.
+ my $description = "\@enum $cpp_enum_name\n";
+ $description .= $$objFunction{description};
+ DocsParser::convert_docs_to_cpp($objFunction, \$description);
+ DocsParser::replace_or_add_newin(\$description, $newin);
+ # Append the enum description docs.
DocsParser::convert_docs_to_cpp($objFunction, \$docs);
+ $docs .= "\n\n$description";
DocsParser::add_m4_quotes(\$docs);
# Escape the space after "i.e." or "e.g." in the brief description.
@@ -305,20 +315,21 @@ sub lookup_enum_documentation($$$)
remove_example_code($c_enum_name, \$docs);
- # Convert to Doxygen-style comment.
- $docs =~ s/\n/\n \* /g;
- $docs = "\/\*\* " . $docs;
+ # Add indentation and an asterisk on all lines except the first.
+ # $docs does not contain leading "/**" and trailing "*/".
+ $docs =~ s/\n/\n${indent}\* /g;
return $docs;
}
-# $strCommentBlock lookup_documentation($strFunctionName, $deprecation_docs, $objCppfunc)
+# $strCommentBlock lookup_documentation($strFunctionName, $deprecation_docs, $newin, $objCppfunc)
# The final objCppfunc parameter is optional. If passed, it is used to
# decide if the final C parameter should be omitted if the C++ method
-# has a slot parameter.
-sub lookup_documentation($$;$)
+# has a slot parameter. It is also used for converting C parameter names to
+# C++ parameter names in the documentation, if they differ.
+sub lookup_documentation($$$;$)
{
- my ($functionName, $deprecation_docs, $objCppfunc) = @_;
+ my ($functionName, $deprecation_docs, $newin, $objCppfunc) = @_;
my $objFunction = $DocsParser::hasharrayFunctions{$functionName};
if(!$objFunction)
@@ -335,18 +346,30 @@ sub lookup_documentation($$;$)
}
DocsParser::convert_docs_to_cpp($objFunction, \$text);
+ DocsParser::replace_or_add_newin(\$text, $newin);
# A blank line, marking the end of a paragraph, is needed after @newin.
# Most @newins are at the end of a function description.
$text .= "\n";
- #Add note about deprecation if we have specified that in our _WRAP_METHOD() call:
+ # Add note about deprecation if we have specified that in our _WRAP_METHOD(),
+ # _WRAP_SIGNAL(), _WRAP_PROPERTY() or _WRAP_CHILD_PROPERTY() call:
if($deprecation_docs ne "")
{
$text .= "\n\@deprecated $deprecation_docs\n";
}
- DocsParser::append_parameter_docs($objFunction, \$text, $objCppfunc);
+ my %param_name_mappings = DocsParser::append_parameter_docs($objFunction, \$text, $objCppfunc);
DocsParser::append_return_docs($objFunction, \$text);
+
+ # Convert C parameter names to C++ parameter names where they differ.
+ foreach my $key (keys %param_name_mappings)
+ {
+ $text =~ s/\@(param|a) $key\b/\@$1 $param_name_mappings{$key}/g;
+ }
+
+ # Remove leading and trailing white space.
+ $text = string_trim($text);
+
DocsParser::add_m4_quotes(\$text);
# Escape the space after "i.e." or "e.g." in the brief description.
@@ -375,7 +398,8 @@ sub remove_example_code($$)
($$text =~ s"<programlisting>.*?</programlisting>"\n[C example ellipted]"sg);
$example_removals += ($$text =~ s"\|\[.*?]\|"\n[C example ellipted]"sg);
- print STDERR "gmmproc: $main::source: $obj_name: Example code discarded.\n"
+ # See "MS Visual Studio" comment in gmmproc.in.
+ print STDERR "gmmproc, $main::source, $obj_name: Example code discarded.\n"
if ($example_removals);
}
@@ -396,51 +420,143 @@ sub add_m4_quotes($)
# The final objCppfunc is optional. If passed, it is used to determine
# if the final C parameter should be omitted if the C++ method has a
-# slot parameter.
+# slot parameter. It is also used for converting C parameter names to
+# C++ parameter names in the documentation, if they differ.
sub append_parameter_docs($$;$)
{
my ($obj_function, $text, $objCppfunc) = @_;
- my @param_names = @{$$obj_function{param_names}};
+ my @docs_param_names = @{$$obj_function{param_names}};
my $param_descriptions = \$$obj_function{param_descriptions};
-
- # Strip first parameter if this is a method.
my $defs_method = GtkDefs::lookup_method_dont_mark($$obj_function{name});
- # the second alternative is for use with method-mappings meaning:
- # this function is mapped into this Gtk::class
- shift(@param_names) if(($defs_method && $$defs_method{class} ne "") ||
- ($$obj_function{mapped_class} ne ""));
+ my @c_param_names = $defs_method ? @{$$defs_method{param_names}} : @docs_param_names;
+
+ # The information in
+ # $obj_function comes from the docs.xml file,
+ # $objCppfunc comes from _WRAP_METHOD() or _WRAP_SIGNAL() in the .hg file,
+ # $defs_method comes from the methods.defs file.
+
+ # Ideally @docs_param_names and @c_param_names are identical.
+ # In the real world the parameters in the C documentation are sometimes not
+ # listed in the same order as the arguments in the C function declaration.
+ # We try to handle that case to some extent. If no argument name is misspelt
+ # in either the docs or the C function declaration, it usually succeeds for
+ # methods, but not for signals. For signals there is no C function declaration
+ # to compare with. If the docs of some method or signal get badly distorted
+ # due to imperfections in the C docs, and it's difficult to get the C docs
+ # corrected, correct docs can be added to the docs_override.xml file.
+
+ # Skip first param if this is a signal.
+ if ($$obj_function{name} =~ /\w+::/)
+ {
+ shift(@docs_param_names);
+ shift(@c_param_names);
+ }
+ # Skip first parameter if this is a non-static method.
+ elsif (defined($objCppfunc))
+ {
+ if (!$$objCppfunc{static})
+ {
+ shift(@docs_param_names);
+ shift(@c_param_names);
+ }
+ }
+ # The second alternative is for use with method-mappings meaning:
+ # this function is mapped into this Gtk::class.
+ elsif (($defs_method && $$defs_method{class} ne "") ||
+ $$obj_function{mapped_class} ne "")
+ {
+ shift(@docs_param_names);
+ shift(@c_param_names);
+ }
- # Also skip first param if this is a signal.
- shift(@param_names) if ($$obj_function{name} =~ /\w+::/);
# Skip the last param if there is a slot because it would be a
# gpointer user_data parameter.
- pop(@param_names) if (defined($objCppfunc) && $$objCppfunc{slot_name});
+ if (defined($objCppfunc) && $$objCppfunc{slot_name})
+ {
+ pop(@docs_param_names);
+ pop(@c_param_names);
+ }
- foreach my $param (@param_names)
+ # Skip the last param if it's an error output param.
+ if (scalar @docs_param_names && $docs_param_names[-1] eq "error")
+ {
+ pop(@docs_param_names);
+ pop(@c_param_names);
+ }
+
+ my $cpp_param_names;
+ my $param_mappings;
+ my $out_param_index = 1000; # No method has that many arguments, hopefully.
+ if (defined($objCppfunc))
{
- if ($param ne "error" ) #We wrap GErrors as exceptions, so ignore these.
+ $cpp_param_names = $$objCppfunc{param_names};
+ $param_mappings = $$objCppfunc{param_mappings}; # C name -> C++ index
+ if (exists $$param_mappings{OUT})
{
- my $desc = $$param_descriptions->{$param};
+ $out_param_index = $$param_mappings{OUT};
+ }
+ }
+ my %param_name_mappings; # C name -> C++ name
- # Deal with callback parameters converting the docs to a slot
- # compatible format.
- if ($param eq "callback")
+ for (my $i = 0; $i < @docs_param_names; ++$i)
+ {
+ my $param = $docs_param_names[$i];
+ my $desc = $$param_descriptions->{$param};
+
+ if (defined($objCppfunc))
+ {
+ # If the C++ name is not equal to the C name, mark that the name
+ # shall be changed in the documentation.
+ my $cpp_name = $param;
+ if (exists $$param_mappings{$param})
{
- $param = "slot";
- $$text =~ s/\@a callback/\@a slot/g;
+ # Rename and/or reorder declaration ({c_name} or {.}) in _WRAP_*().
+ $cpp_name = $$cpp_param_names[$$param_mappings{$param}];
}
-
- $param =~ s/([a-zA-Z0-9]*(_[a-zA-Z0-9]+)*)_?/$1/g;
- DocsParser::convert_docs_to_cpp($obj_function, \$desc);
- if(length($desc) > 0)
+ elsif ($c_param_names[$i] eq $param)
+ {
+ # Location in docs coincides with location in C declaration.
+ my $cpp_index = $i;
+ $cpp_index++ if ($i >= $out_param_index);
+ $cpp_name = $$cpp_param_names[$cpp_index];
+ }
+ else
+ {
+ # Search for the param in the C declaration.
+ for (my $j = 0; $j < @c_param_names; ++$j)
+ {
+ if ($c_param_names[$j] eq $param)
+ {
+ my $cpp_index = $j;
+ $cpp_index++ if ($j >= $out_param_index);
+ $cpp_name = $$cpp_param_names[$cpp_index];
+ last;
+ }
+ }
+ }
+ if ($cpp_name ne $param)
{
- $desc .= '.' unless($desc =~ /(?:^|\.)$/);
- $$text .= "\n\@param ${param} \u${desc}";
+ $param_name_mappings{$param} = $cpp_name;
}
}
+ elsif ($param eq "callback")
+ {
+ # Deal with callback parameters converting the docs to a slot
+ # compatible format.
+ $param_name_mappings{$param} = "slot";
+ }
+
+ $param =~ s/([a-zA-Z0-9]*(_[a-zA-Z0-9]+)*)_?/$1/g;
+ DocsParser::convert_docs_to_cpp($obj_function, \$desc);
+ if(length($desc) > 0)
+ {
+ $desc .= '.' unless($desc =~ /(?:^|\.)$/);
+ $$text .= "\n\@param ${param} \u${desc}";
+ }
}
+ return %param_name_mappings;
}
@@ -513,14 +629,20 @@ sub convert_tags_to_doxygen($)
s"<variablelist>\n?(.*?)</variablelist>\n?"&DocsParser::convert_variablelist($1)"esg;
# Use our Doxygen @newin alias.
- # If Since is not followed by a colon, substitute @newin only if it's
- # in a sentence of its own at the end of the string.
- s/\bSince:\s*(\d+)\.(\d+)\.(\d+)\b\.?/\@newin{$1,$2,$3}/g;
- s/\bSince:\s*(\d+)\.(\d+)\b\.?/\@newin{$1,$2}/g;
- s/(\.\s+)Since\s+(\d+)\.(\d+)\.(\d+)\.?$/$1\@newin{$2,$3,$4}/;
- s/(\.\s+)Since\s+(\d+)\.(\d+)\.?$/$1\@newin{$2,$3}/;
-
- s"\b->\b"->"g;
+ # Accept "Since" with or without a following colon.
+ # Require the Since clause to be
+ # - at the end of the string,
+ # - at the end of a line and followed by a blank line, or
+ # - followed by "Deprecated".
+ # If none of these requirements is met, "Since" may be embedded inside
+ # a function description, referring to only a part of the description.
+ # See e.g. g_date_time_format() and gdk_cursor_new_from_pixbuf().
+ # Doxygen assumes that @newin is followed by a paragraph that describes
+ # what is new, but we don't use it that way.
+ my $first_part = '\bSince[:\h]\h*(\d+)\.(\d+)'; # \h == [\t ] (horizontal whitespace)
+ my $last_part = '\.?(\s*$|\h*\n\h*\n|\s+Deprecated)';
+ s/$first_part\.(\d+)$last_part/\@newin{$1,$2,$3}$4/g;
+ s/$first_part$last_part/\@newin{$1,$2}$3/g;
# Doxygen is too dumb to handle &mdash;
s"&mdash;" \@htmlonly&mdash;\@endhtmlonly "g;
@@ -540,6 +662,21 @@ sub convert_tags_to_doxygen($)
}
}
+# void replace_or_add_newin(\$text, $newin)
+# If $newin is not empty, replace the version numbers in an existing @newin
+# Doxygen alias, or add one if there is none.
+sub replace_or_add_newin($$)
+{
+ my ($text, $newin) = @_;
+
+ return if ($newin eq "");
+
+ if (!($$text =~ s/\@newin\{[\d,]+\}/\@newin{$newin}/))
+ {
+ $$text .= "\n\n\@newin{$newin}";
+ }
+}
+
# Convert <simplelist> tags to a list of newline-separated elements.
sub convert_simplelist($)
{
@@ -691,7 +828,7 @@ sub lookup_object_of_method($$)
}
else
{
- print "DocsParser.pm:lookup_object_of_method(): Warning: GtkDefs::lookup_object() failed for object name=" . $object . ", function name=" . $name . "\n";
+ print "DocsParser.pm: lookup_object_of_method(): Warning: GtkDefs::lookup_object() failed for object name=" . $object . ", function name=" . $name . "\n";
print " This may be a missing define-object in a *.defs file.\n"
}
}