From: Florian Brosch Date: Thu, 9 Aug 2012 02:15:01 +0000 (+0200) Subject: gir-importer: Process implicit parameters X-Git-Tag: 0.37.1~3^2~173 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1eebb3a020b0a91f153cf313bd90b0600b94a56f;p=thirdparty%2Fvala.git gir-importer: Process implicit parameters --- diff --git a/src/libvaladoc/Makefile.am b/src/libvaladoc/Makefile.am index b54bbdef1..7ec0b656f 100644 --- a/src/libvaladoc/Makefile.am +++ b/src/libvaladoc/Makefile.am @@ -55,6 +55,7 @@ libvaladoc_la_VALASOURCES = \ api/attributeargument.vala \ api/attribute.vala \ api/array.vala \ + api/callable.vala \ api/childsymbolregistrar.vala \ api/class.vala \ api/constant.vala \ diff --git a/src/libvaladoc/api/callable.vala b/src/libvaladoc/api/callable.vala new file mode 100644 index 000000000..60515ee1b --- /dev/null +++ b/src/libvaladoc/api/callable.vala @@ -0,0 +1,51 @@ +/* callable.vala + * + * Copyright (C) 2012 Florian Brosch + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Florian Brosch + */ + + +using Valadoc; +using GLib; +using Gee; + + +/** + * Used to translate imported C-documentation + */ +public interface Valadoc.Api.Callable : Symbol { + /** + * The return type of this symbol. + * + * @return The return type of this symbol or null for void + */ + public abstract TypeReference? return_type { + set; + get; + } + + /** + * Used to avoid warnings for implicit parameters + */ + internal abstract string? implicit_array_length_cparameter_name { + get; + set; + } +} + diff --git a/src/libvaladoc/api/delegate.vala b/src/libvaladoc/api/delegate.vala index 2e4379163..d57c80d60 100644 --- a/src/libvaladoc/api/delegate.vala +++ b/src/libvaladoc/api/delegate.vala @@ -27,9 +27,18 @@ using Valadoc.Content; /** * Represents a Delegate. */ -public class Valadoc.Api.Delegate : TypeSymbol { +public class Valadoc.Api.Delegate : TypeSymbol, Callable { private string? cname; + /** + * {@inheritDoc} + */ + internal string? implicit_array_length_cparameter_name { + get; + set; + } + + public Delegate (Node parent, SourceFile file, string name, SymbolAccessibility accessibility, SourceComment? comment, string? cname, bool is_static, void* data) { base (parent, file, name, accessibility, comment, false, data); @@ -45,9 +54,7 @@ public class Valadoc.Api.Delegate : TypeSymbol { } /** - * The return type of this callback. - * - * @return The return type of this callback or null for void + * {@inheritDoc} */ public TypeReference? return_type { set; diff --git a/src/libvaladoc/api/formalparameter.vala b/src/libvaladoc/api/formalparameter.vala index 0a781e31f..82ed872a2 100644 --- a/src/libvaladoc/api/formalparameter.vala +++ b/src/libvaladoc/api/formalparameter.vala @@ -32,6 +32,30 @@ public class Valadoc.Api.FormalParameter : Symbol { set; } + /** + * Used to translate imported C-documentation + */ + internal string? implicit_array_length_cparameter_name { + get; + set; + } + + /** + * Used to translate imported C-documentation + */ + internal string? implicit_closure_cparameter_name { + get; + set; + } + + /** + * Used to translate imported C-documentation + */ + internal string? implicit_destroy_cparameter_name { + get; + set; + } + private FormalParameterType type; public FormalParameter (Node parent, SourceFile file, string? name, SymbolAccessibility accessibility, FormalParameterType type, bool ellipsis, void* data) { diff --git a/src/libvaladoc/api/method.vala b/src/libvaladoc/api/method.vala index 0a142e3d2..d222bf0cc 100644 --- a/src/libvaladoc/api/method.vala +++ b/src/libvaladoc/api/method.vala @@ -20,14 +20,14 @@ * Florian Brosch */ -using Gee; using Valadoc.Content; +using Gee; /** * Represents a function or a method. */ -public class Valadoc.Api.Method : Member { +public class Valadoc.Api.Method : Member, Callable { private string? finish_function_cname; private string? dbus_result_name; private string? dbus_name; @@ -35,6 +35,15 @@ public class Valadoc.Api.Method : Member { private MethodBindingType binding_type; + /** + * {@inheritDoc} + */ + internal string? implicit_array_length_cparameter_name { + get; + set; + } + + public Method (Node parent, SourceFile file, string name, SymbolAccessibility accessibility, SourceComment? comment, string? cname, string? dbus_name, string? dbus_result_name, string? finish_function_cname, MethodBindingType binding_type, bool is_yields, bool is_dbus_visible, bool is_constructor, void* data) { base (parent, file, name, accessibility, comment, data); @@ -83,9 +92,7 @@ public class Valadoc.Api.Method : Member { } /** - * The return type of this method. - * - * @return The return type of this method or null for void + * {@inheritDoc} */ public TypeReference? return_type { set; diff --git a/src/libvaladoc/api/signal.vala b/src/libvaladoc/api/signal.vala index 87a380cdb..0e21dfb81 100644 --- a/src/libvaladoc/api/signal.vala +++ b/src/libvaladoc/api/signal.vala @@ -27,10 +27,20 @@ using Valadoc.Content; /** * Represents an signal. */ -public class Valadoc.Api.Signal : Member { +public class Valadoc.Api.Signal : Member, Callable { private string? dbus_name; private string? cname; + + /** + * {@inheritDoc} + */ + internal string? implicit_array_length_cparameter_name { + get; + set; + } + + public Signal (Node parent, SourceFile file, string name, SymbolAccessibility accessibility, SourceComment? comment, string? cname, string? dbus_name, bool is_dbus_visible, bool is_virtual, void* data) { base (parent, file, name, accessibility, comment, data); @@ -56,9 +66,7 @@ public class Valadoc.Api.Signal : Member { } /** - * The return type of this signal. - * - * @return The return type of this signal or null for void + * {@inheritDoc} */ public TypeReference? return_type { set; diff --git a/src/libvaladoc/documentation/gtkdoccommentparser.vala b/src/libvaladoc/documentation/gtkdoccommentparser.vala index 79392168a..eb154ad2f 100644 --- a/src/libvaladoc/documentation/gtkdoccommentparser.vala +++ b/src/libvaladoc/documentation/gtkdoccommentparser.vala @@ -1537,15 +1537,13 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { } } - return null; + return {id}; } - private string? resolve_parameter_ctype (string parameter_name, out string? param_name) { - string[]? parts = split_type_name (current.content); - param_name = null; - if (parts == null) { - return null; - } + private string? resolve_parameter_ctype (string parameter_name, out string? param_name, out string? param_array_name, out bool is_return_type_len) { + string[]? parts = split_type_name (parameter_name); + is_return_type_len = false; + param_array_name = null; Api.FormalParameter? param = null; // type parameter or formal parameter foreach (Api.Node node in this.element.get_children_by_type (Api.NodeType.FORMAL_PARAMETER, false)) { @@ -1553,10 +1551,31 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { param = node as Api.FormalParameter; break; } + + if (((Api.FormalParameter) node).implicit_array_length_cparameter_name == parts[0]) { + param_array_name = ((Api.FormalParameter) node).name; + break; + } } + if (this.element is Api.Callable && ((Api.Callable) this.element).implicit_array_length_cparameter_name == parts[0]) { + is_return_type_len = true; + } + + if (parts.length == 1) { + param_name = parameter_name; + return null; + } + + + Api.Item? inner = null; + + if (param_array_name != null || is_return_type_len) { + inner = tree.search_symbol_str (null, "int"); + } else if (param != null) { + inner = param.parameter_type; + } - Api.Item? inner = param.parameter_type; while (inner != null) { if (inner is Api.TypeReference) { inner = ((Api.TypeReference) inner).data_type; @@ -1571,6 +1590,7 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { if (inner == null) { + param_name = parameter_name; return null; } @@ -1671,17 +1691,27 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { run.content.add (this.create_type_link (current.content)); next (); } else if (current.type == TokenType.GTKDOC_PARAM) { + string? param_array_name; + bool is_return_type_len; string? param_name; - string? cname = resolve_parameter_ctype (current.content, out param_name); + + string? cname = resolve_parameter_ctype (current.content, out param_name, out param_array_name, out is_return_type_len); Run current_run = factory.create_run (Run.Style.MONOSPACED); + run.content.add (current_run); - if (cname == null) { - current_run.content.add (factory.create_text (current.content)); - run.content.add (current_run); + if (is_return_type_len) { + Run keyword_run = factory.create_run (Run.Style.LANG_KEYWORD); + keyword_run.content.add (factory.create_text ("return")); + current_run.content.add (keyword_run); + + current_run.content.add (factory.create_text (".length")); + } else if (param_array_name != null) { + current_run.content.add (factory.create_text (param_array_name + ".length")); } else { current_run.content.add (factory.create_text (param_name)); - run.content.add (current_run); + } + if (cname != null) { run.content.add (factory.create_text (".")); Taglets.Link link = factory.create_taglet ("link") as Taglets.Link; diff --git a/src/libvaladoc/errorreporter.vala b/src/libvaladoc/errorreporter.vala index 073eb4b3d..b7359820d 100644 --- a/src/libvaladoc/errorreporter.vala +++ b/src/libvaladoc/errorreporter.vala @@ -42,8 +42,9 @@ public class Valadoc.ErrorReporter : Object { set; } - public ErrorReporter () { - this.stream = GLib.stderr; + public Settings? settings { + get; + set; } public int errors { @@ -58,6 +59,12 @@ public class Valadoc.ErrorReporter : Object { } } + + public ErrorReporter (Settings? settings = null) { + this.stream = GLib.stderr; + this.settings = settings; + } + private inline void msg (string type, string file, long line, long startpos, long endpos, string errline, string msg_format, va_list args) { this.stream.printf ("%s:%lu.%lu-%lu.%lu: %s: ", file, line, startpos, line, endpos, type); this.stream.vprintf (msg_format, args); @@ -92,6 +99,15 @@ public class Valadoc.ErrorReporter : Object { this._errors++; } + public void simple_note (string msg_format, ...) { + if (_settings == null || _settings.verbose) { + var args = va_list(); + this.stream.vprintf (msg_format, args); + this.stream.putc ('\n'); + this._warnings++; + } + } + public void error (string file, long line, long startpos, long endpos, string errline, string msg_format, ...) { var args = va_list(); this.msg ("error", file, line, startpos, endpos, errline, msg_format, args); diff --git a/src/libvaladoc/importer/girdocumentationimporter.vala b/src/libvaladoc/importer/girdocumentationimporter.vala index 789409b2e..d097e26fd 100644 --- a/src/libvaladoc/importer/girdocumentationimporter.vala +++ b/src/libvaladoc/importer/girdocumentationimporter.vala @@ -1,8 +1,8 @@ /* girdocumentationimporter.vala * * Copyright (C) 2008-2010 Jürg Billeter - * Copyright (C) 2011 Luca Bruno - * Copyright (C) 2011 Florian Brosch + * Copyright (C) 2011 Luca Bruno + * Copyright (C) 2011-2012 Florian Brosch * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ using Valadoc; using GLib; - +using Gee; public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { @@ -44,6 +44,16 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { private string parent_c_identifier; + private struct ImplicitParameterPos { + public int parameter; + public int position; + + public ImplicitParameterPos (int parameter, int position) { + this.parameter = parameter; + this.position = position; + } + } + public GirDocumentationImporter (Api.Tree tree, DocumentationParser parser, ModuleLoader modules, Settings settings, ErrorReporter reporter) { base (tree, modules, settings); this.reporter = reporter; @@ -65,7 +75,26 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { file = null; } - private void attach_comment (string cname, Api.GirSourceComment? comment) { + private Api.FormalParameter? find_parameter (Api.Node node, string name) { + Gee.List parameters = node.get_children_by_type (Api.NodeType.FORMAL_PARAMETER, false); + foreach (Api.Node param in parameters) { + if (((Api.FormalParameter) param).name == name) { + return (Api.FormalParameter) param; + } + } + + return null; + } + + private inline string? get_cparameter_name (string[] param_names, int length_pos) { + if (length_pos < 0 || param_names.length < length_pos) { + return null; + } + + return param_names[length_pos]; + } + + private void attach_comment (string cname, Api.GirSourceComment? comment, string[]? param_names = null, ImplicitParameterPos[]? destroy_notifies = null, ImplicitParameterPos[]? closures = null, ImplicitParameterPos[]? array_lengths = null, int array_length_ret = -1) { if (comment == null) { return ; } @@ -75,6 +104,39 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { return; } + if (param_names != null) { + foreach (ImplicitParameterPos pos in destroy_notifies) { + Api.FormalParameter? param = find_parameter (node, param_names[pos.parameter]); + if (param == null) { + continue ; + } + + param.implicit_destroy_cparameter_name = get_cparameter_name (param_names, pos.position); + } + + foreach (ImplicitParameterPos pos in closures) { + Api.FormalParameter? param = find_parameter (node, param_names[pos.parameter]); + if (param == null) { + continue ; + } + + param.implicit_closure_cparameter_name = get_cparameter_name (param_names, pos.position); + } + + foreach (ImplicitParameterPos pos in array_lengths) { + Api.FormalParameter? param = find_parameter (node, param_names[pos.parameter]); + if (param == null) { + continue ; + } + + param.implicit_array_length_cparameter_name = get_cparameter_name (param_names, pos.position); + } + + if (node is Api.Callable) { + ((Api.Callable) node).implicit_array_length_cparameter_name = get_cparameter_name (param_names, array_length_ret); + } + } + Content.Comment? content = this.parser.parse (node, comment); if (content == null) { return; @@ -83,6 +145,10 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { node.documentation = content; } + private void warning (string message) { + reporter.warning (this.file.relative_path, this.begin.line, this.begin.column, this.end.column, this.reader.get_line_content (this.begin.line), message); + } + private void error (string message) { reporter.error (this.file.relative_path, this.begin.line, this.begin.column, this.end.column, this.reader.get_line_content (this.begin.line), message); } @@ -299,20 +365,39 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { end_element ("member"); } - private void parse_return_value (out Api.SourceComment? comment = null) { + private void parse_return_value (out Api.SourceComment? comment, out int array_length_ret) { start_element ("return-value"); next (); comment = parse_doc (); - parse_type (); + parse_type (out array_length_ret); end_element ("return-value"); } - private void parse_parameter (out Api.SourceComment? comment, out string param_name) { + private void parse_parameter (out Api.SourceComment? comment, out string param_name, out int destroy_pos, out int closure_pos, out int array_length_pos) { start_element ("parameter"); param_name = reader.get_attribute ("name"); + array_length_pos = -1; + destroy_pos = -1; + closure_pos = -1; + + string? closure = reader.get_attribute ("closure"); + if (closure != null) { + closure_pos = int.parse (closure); + if (closure_pos < 0) { + warning ("invalid closure position"); + } + } + + string? destroy = reader.get_attribute ("destroy"); + if (destroy != null) { + destroy_pos = int.parse (destroy); + if (destroy_pos < 0) { + warning ("invalid destroy position"); + } + } next (); comment = parse_doc (); @@ -324,14 +409,28 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { end_element ("varargs"); } else { - parse_type (); + parse_type (out array_length_pos); } end_element ("parameter"); } - private void parse_type () { - skip_element (); + private void parse_type (out int array_length_pos = null) { + array_length_pos = -1; + + if (reader.name == "array") { + string? length = reader.get_attribute ("length"); + if (length != null) { + array_length_pos = int.parse (length); + if (array_length_pos < 0) { + warning ("invalid array lenght position"); + } + } + + skip_element (); + } else { + skip_element (); + } } private void parse_record () { @@ -508,9 +607,15 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { Api.GirSourceComment? comment = parse_symbol_doc (); + ImplicitParameterPos[] destroy_notifies = new ImplicitParameterPos[0]; + ImplicitParameterPos[] array_lengths = new ImplicitParameterPos[0]; + ImplicitParameterPos[] closures = new ImplicitParameterPos[0]; + string[] param_names = new string[0]; + int array_length_ret = -1; + if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "return-value") { Api.SourceComment? return_comment; - parse_return_value (out return_comment); + parse_return_value (out return_comment, out array_length_ret); if (return_comment != null) { if (comment == null) { comment = new Api.GirSourceComment ("", file, begin.line, begin.column, end.line, end.column); @@ -524,11 +629,27 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { start_element ("parameters"); next (); - while (current_token == MarkupTokenType.START_ELEMENT) { + for (int pcount = 0; current_token == MarkupTokenType.START_ELEMENT; pcount++) { Api.SourceComment? param_comment; + int array_length_pos; + int destroy_pos; + int closure_pos; string? param_name; - parse_parameter (out param_comment, out param_name); + parse_parameter (out param_comment, out param_name, out destroy_pos, out closure_pos, out array_length_pos); + param_names += param_name; + + if (destroy_pos >= 0 && pcount != destroy_pos) { + destroy_notifies += ImplicitParameterPos (pcount, destroy_pos); + } + + if (closure_pos >= 0 && pcount != closure_pos) { + closures += ImplicitParameterPos (pcount, closure_pos); + } + + if (array_length_pos >= 0 && pcount != destroy_pos) { + array_lengths += ImplicitParameterPos (pcount, array_length_pos); + } if (param_comment != null) { if (comment == null) { @@ -541,7 +662,7 @@ public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { end_element ("parameters"); } - attach_comment (c_identifier, comment); + attach_comment (c_identifier, comment, param_names, destroy_notifies, closures, array_lengths, array_length_ret); end_element (element_name); } diff --git a/src/libvaladoc/taglets/tagletlink.vala b/src/libvaladoc/taglets/tagletlink.vala index 49699a5c7..d49aa4b84 100644 --- a/src/libvaladoc/taglets/tagletlink.vala +++ b/src/libvaladoc/taglets/tagletlink.vala @@ -84,6 +84,7 @@ public class Valadoc.Taglets.Link : InlineTaglet { link.symbol = _symbol; link.label = symbol_name; + // TODO: move typeof () to gtkdoc-importer switch (_context) { case SymbolContext.TYPE: Content.Run content = new Content.Run (Run.Style.MONOSPACED); diff --git a/src/libvaladoc/taglets/tagletparam.vala b/src/libvaladoc/taglets/tagletparam.vala index 36a21eb6b..78e9d163d 100644 --- a/src/libvaladoc/taglets/tagletparam.vala +++ b/src/libvaladoc/taglets/tagletparam.vala @@ -21,8 +21,8 @@ * Didier 'Ptitjes Villevalois */ -using Gee; using Valadoc.Content; +using Gee; public class Valadoc.Taglets.Param : InlineContent, Taglet, Block { @@ -40,11 +40,21 @@ public class Valadoc.Taglets.Param : InlineContent, Taglet, Block { }); } - public override void check (Api.Tree api_root, Api.Node container, string file_path, ErrorReporter reporter, Settings settings) { // Check for the existence of such a parameter + unowned string? implicit_return_array_length = null; + bool is_implicit = false; this.parameter = null; + if (container is Api.Callable) { + implicit_return_array_length = ((Api.Callable) container).implicit_array_length_cparameter_name; + } else { + reporter.simple_warning ("%s: %s: @param: warning: @param used outside method/delegate/signal context", file_path, container.get_full_name ()); + base.check (api_root, container, file_path, reporter, settings); + return ; + } + + if (parameter_name == "...") { Gee.List params = container.get_children_by_type (Api.NodeType.FORMAL_PARAMETER, false); foreach (Api.Node param in params) { @@ -65,12 +75,27 @@ public class Valadoc.Taglets.Param : InlineContent, Taglet, Block { break; } + Api.FormalParameter formalparam = param as Api.FormalParameter; + if (formalparam != null && (formalparam.implicit_array_length_cparameter_name == parameter_name || formalparam.implicit_closure_cparameter_name == parameter_name || formalparam.implicit_destroy_cparameter_name == parameter_name)) { + is_implicit = true; + break; + } + pos++; } + + if (this.parameter == null && (parameter_name == "error" && container.has_children ({Api.NodeType.ERROR_DOMAIN, Api.NodeType.CLASS}) + || parameter_name == implicit_return_array_length)) { + is_implicit = true; + } } if (this.parameter == null) { - reporter.simple_warning ("%s: %s: @param: warning: Unknown parameter `%s'", file_path, container.get_full_name (), parameter_name); + if (is_implicit) { + reporter.simple_note ("%s: %s: @param: warning: Implicit parameter `%s' exposed in documentation", file_path, container.get_full_name (), parameter_name); + } else { + reporter.simple_warning ("%s: %s: @param: warning: Unknown parameter `%s'", file_path, container.get_full_name (), parameter_name); + } } base.check (api_root, container, file_path, reporter, settings); diff --git a/src/libvaladoc/taglets/tagletreturn.vala b/src/libvaladoc/taglets/tagletreturn.vala index 655fb7ace..e616791f6 100644 --- a/src/libvaladoc/taglets/tagletreturn.vala +++ b/src/libvaladoc/taglets/tagletreturn.vala @@ -37,10 +37,8 @@ public class Valadoc.Taglets.Return : InlineContent, Taglet, Block { if (container is Api.Method) { creation_method = ((Api.Method) container).is_constructor; type_ref = ((Api.Method) container).return_type; - } else if (container is Api.Delegate) { - type_ref = ((Api.Delegate) container).return_type; - } else if (container is Api.Signal) { - type_ref = ((Api.Signal) container).return_type; + } else if (container is Api.Callable) { + type_ref = ((Api.Callable) container).return_type; } else { reporter.simple_warning ("%s: %s: @return: warning: @return used outside method/delegate/signal context", file_path, container.get_full_name ()); } diff --git a/src/valadoc/valadoc.vala b/src/valadoc/valadoc.vala index 7c6bdba5a..cca16b167 100644 --- a/src/valadoc/valadoc.vala +++ b/src/valadoc/valadoc.vala @@ -198,6 +198,8 @@ public class ValaDoc : Object { private int run (ErrorReporter reporter) { // settings: var settings = new Valadoc.Settings (); + reporter.settings = settings; + settings.pkg_name = this.get_pkg_name (); settings.gir_namespace = this.gir_namespace; settings.gir_version = this.gir_version;