From: Florian Brosch Date: Sun, 18 Dec 2011 17:51:14 +0000 (+0100) Subject: libvaladoc: gir-importer, c-resolver : various improvements X-Git-Tag: 0.37.1~3^2~268 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=726d32238c7ff6958664bb766cbb5d78c283024a;p=thirdparty%2Fvala.git libvaladoc: gir-importer, c-resolver : various improvements --- diff --git a/src/driver/0.10.x/treebuilder.vala b/src/driver/0.10.x/treebuilder.vala index 6bc66b4aa..2f1cd7c99 100644 --- a/src/driver/0.10.x/treebuilder.vala +++ b/src/driver/0.10.x/treebuilder.vala @@ -776,7 +776,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { bool is_basic_type = element.base_class == null && element.name == "string"; - Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name (element), element.get_param_spec_function (), element.get_type_id (), element.get_ref_function (), element.get_unref_function (), element.get_take_value_function (), element.get_get_value_function (), element.get_set_value_function (), element.is_fundamental (), element.is_abstract, is_basic_type, element); + Class node = new Class (parent, file, element.name, get_access_modifier (element), comment, element.get_cname (), Vala.GDBusModule.get_dbus_name (element), element.get_type_id (), element.get_param_spec_function (), element.get_ref_function (), element.get_unref_function (), element.get_take_value_function (), element.get_get_value_function (), element.get_set_value_function (), element.is_fundamental (), element.is_abstract, is_basic_type, element); symbol_map.set (element, node); parent.add_child (node); @@ -836,7 +836,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { bool is_basic_type = element.base_type == null && (element.is_boolean_type () || element.is_floating_type () || element.is_integer_type ()); - Struct node = new Struct (parent, file, element.name, get_access_modifier(element), comment, element.get_cname(), element.get_dup_function (), element.get_free_function (), is_basic_type, element); + Struct node = new Struct (parent, file, element.name, get_access_modifier (element), comment, element.get_cname(), element.get_type_id (), element.get_dup_function (), element.get_free_function (), is_basic_type, element); symbol_map.set (element, node); parent.add_child (node); diff --git a/src/driver/0.13.x/treebuilder.vala b/src/driver/0.13.x/treebuilder.vala index 9cfac5258..d898cee2b 100644 --- a/src/driver/0.13.x/treebuilder.vala +++ b/src/driver/0.13.x/treebuilder.vala @@ -233,11 +233,17 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { } } - private string get_ccode_type_id (Vala.Class node) { + private string? get_ccode_type_id (Vala.CodeNode node) { #if VALA_0_13_X return Vala.CCodeBaseModule.get_ccode_type_id (node); #else - return node.get_type_id (); + if (node is Vala.Class) { + return ((Vala.Class) node).get_type_id (); + } else (node is Vala.Struct) { + return ((Vala.Struct) node).get_type_id (); + } + + return null; #endif } @@ -874,7 +880,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { bool is_basic_type = element.base_class == null && element.name == "string"; - Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, get_cname (element), Vala.GDBusModule.get_dbus_name (element), get_param_spec_function (element), get_ccode_type_id (element), get_ref_function (element), get_unref_function (element), get_take_value_function (element), get_get_value_function (element), get_set_value_function (element), element.is_fundamental (), element.is_abstract, is_basic_type, element); + Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, get_cname (element), Vala.GDBusModule.get_dbus_name (element), get_ccode_type_id (element), get_param_spec_function (element), get_ref_function (element), get_unref_function (element), get_take_value_function (element), get_get_value_function (element), get_set_value_function (element), element.is_fundamental (), element.is_abstract, is_basic_type, element); symbol_map.set (element, node); parent.add_child (node); @@ -934,7 +940,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { bool is_basic_type = element.base_type == null && (element.is_boolean_type () || element.is_floating_type () || element.is_integer_type ()); - Struct node = new Struct (parent, file, element.name, get_access_modifier(element), comment, get_cname(element), get_dup_function (element), get_free_function (element), is_basic_type, element); + Struct node = new Struct (parent, file, element.name, get_access_modifier (element), comment, get_cname (element), get_ccode_type_id (element), get_dup_function (element), get_free_function (element), is_basic_type, element); symbol_map.set (element, node); parent.add_child (node); diff --git a/src/driver/0.14.x/treebuilder.vala b/src/driver/0.14.x/treebuilder.vala index daff9b253..f61b08f24 100644 --- a/src/driver/0.14.x/treebuilder.vala +++ b/src/driver/0.14.x/treebuilder.vala @@ -233,7 +233,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { } } - private string get_ccode_type_id (Vala.Class node) { + private string get_ccode_type_id (Vala.CodeNode node) { return Vala.CCodeBaseModule.get_ccode_type_id (node); } @@ -808,7 +808,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { bool is_basic_type = element.base_class == null && element.name == "string"; - Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, get_cname (element), Vala.GDBusModule.get_dbus_name (element), get_param_spec_function (element), get_ccode_type_id (element), get_ref_function (element), get_unref_function (element), get_take_value_function (element), get_get_value_function (element), get_set_value_function (element), element.is_fundamental (), element.is_abstract, is_basic_type, element); + Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, get_cname (element), Vala.GDBusModule.get_dbus_name (element), get_ccode_type_id (element), get_param_spec_function (element), get_ref_function (element), get_unref_function (element), get_take_value_function (element), get_get_value_function (element), get_set_value_function (element), element.is_fundamental (), element.is_abstract, is_basic_type, element); symbol_map.set (element, node); parent.add_child (node); @@ -868,7 +868,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { bool is_basic_type = element.base_type == null && (element.is_boolean_type () || element.is_floating_type () || element.is_integer_type ()); - Struct node = new Struct (parent, file, element.name, get_access_modifier(element), comment, get_cname(element), get_dup_function (element), get_free_function (element), is_basic_type, element); + Struct node = new Struct (parent, file, element.name, get_access_modifier(element), comment, get_cname(element), get_ccode_type_id (element), get_dup_function (element), get_free_function (element), is_basic_type, element); symbol_map.set (element, node); parent.add_child (node); diff --git a/src/driver/0.16.x/treebuilder.vala b/src/driver/0.16.x/treebuilder.vala index 512d7b18f..3687610f2 100644 --- a/src/driver/0.16.x/treebuilder.vala +++ b/src/driver/0.16.x/treebuilder.vala @@ -237,7 +237,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { } } - private string get_ccode_type_id (Vala.Class node) { + private string? get_ccode_type_id (Vala.CodeNode node) { return Vala.CCodeBaseModule.get_ccode_type_id (node); } @@ -245,32 +245,32 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { return Vala.CCodeBaseModule.is_reference_counting (sym); } - private string get_ref_function (Vala.Class sym) { + private string? get_ref_function (Vala.Class sym) { return Vala.CCodeBaseModule.get_ccode_ref_function (sym); } - private string get_unref_function (Vala.Class sym) { + private string? get_unref_function (Vala.Class sym) { return Vala.CCodeBaseModule.get_ccode_unref_function (sym); } - private string get_finish_name (Vala.Method m) { + private string? get_finish_name (Vala.Method m) { return Vala.CCodeBaseModule.get_ccode_finish_name (m); } - private string get_take_value_function (Vala.Class sym) { + private string? get_take_value_function (Vala.Class sym) { return Vala.CCodeBaseModule.get_ccode_take_value_function (sym); } - private string get_get_value_function (Vala.Class sym) { + private string? get_get_value_function (Vala.Class sym) { return Vala.CCodeBaseModule.get_ccode_get_value_function (sym); } - private string get_set_value_function (Vala.Class sym) { + private string? get_set_value_function (Vala.Class sym) { return Vala.CCodeBaseModule.get_ccode_set_value_function (sym); } - private string get_param_spec_function (Vala.CodeNode sym) { + private string? get_param_spec_function (Vala.CodeNode sym) { return Vala.CCodeBaseModule.get_ccode_param_spec_function (sym); } @@ -278,11 +278,11 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { return Vala.CCodeBaseModule.get_ccode_dup_function (sym); } - private string get_free_function (Vala.TypeSymbol sym) { + private string? get_free_function (Vala.TypeSymbol sym) { return Vala.CCodeBaseModule.get_ccode_free_function (sym); } - private string get_nick (Vala.Property prop) { + private string? get_nick (Vala.Property prop) { return Vala.CCodeBaseModule.get_ccode_nick (prop); } @@ -832,7 +832,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { bool is_basic_type = element.base_class == null && element.name == "string"; - Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, get_cname (element), Vala.GDBusModule.get_dbus_name (element), get_param_spec_function (element), get_ccode_type_id (element), get_ref_function (element), get_unref_function (element), get_take_value_function (element), get_get_value_function (element), get_set_value_function (element), element.is_fundamental (), element.is_abstract, is_basic_type, element); + Class node = new Class (parent, file, element.name, get_access_modifier(element), comment, get_cname (element), Vala.GDBusModule.get_dbus_name (element), get_ccode_type_id (element), get_param_spec_function (element), get_ref_function (element), get_unref_function (element), get_take_value_function (element), get_get_value_function (element), get_set_value_function (element), element.is_fundamental (), element.is_abstract, is_basic_type, element); symbol_map.set (element, node); parent.add_child (node); @@ -892,7 +892,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor { bool is_basic_type = element.base_type == null && (element.is_boolean_type () || element.is_floating_type () || element.is_integer_type ()); - Struct node = new Struct (parent, file, element.name, get_access_modifier(element), comment, get_cname(element), get_dup_function (element), get_free_function (element), is_basic_type, element); + Struct node = new Struct (parent, file, element.name, get_access_modifier (element), comment, get_cname (element), get_ccode_type_id (element), get_dup_function (element), get_free_function (element), is_basic_type, element); symbol_map.set (element, node); parent.add_child (node); diff --git a/src/libvaladoc/Makefile.am b/src/libvaladoc/Makefile.am index 14a8bfa90..310a3dbd1 100755 --- a/src/libvaladoc/Makefile.am +++ b/src/libvaladoc/Makefile.am @@ -41,6 +41,7 @@ libvaladoc_la_VALASOURCES = \ importer/documentationimporter.vala \ importer/valadocdocumentationimporter.vala \ importer/valadocdocumentationimporterscanner.vala \ + importer/girdocumentationimporter.vala \ api/symbolaccessibility.vala \ api/sourcecomment.vala \ api/girsourcecomment.vala \ diff --git a/src/libvaladoc/api/struct.vala b/src/libvaladoc/api/struct.vala index d0ebe5b80..58d33f3d1 100755 --- a/src/libvaladoc/api/struct.vala +++ b/src/libvaladoc/api/struct.vala @@ -30,9 +30,10 @@ using Valadoc.Content; public class Valadoc.Api.Struct : TypeSymbol { private string? dup_function_cname; private string? free_function_cname; + private string? type_id; private string? cname; - public Struct (Node parent, SourceFile file, string name, SymbolAccessibility accessibility, SourceComment? comment, string? cname, string? dup_function_cname, string? free_function_cname, bool is_basic_type, void* data) { + public Struct (Node parent, SourceFile file, string name, SymbolAccessibility accessibility, SourceComment? comment, string? cname, string? type_id, string? dup_function_cname, string? free_function_cname, bool is_basic_type, void* data) { base (parent, file, name, accessibility, comment, is_basic_type, data); this.dup_function_cname = dup_function_cname; @@ -57,6 +58,13 @@ public class Valadoc.Api.Struct : TypeSymbol { return cname; } + /** + * Returns the C symbol representing the runtime type id for this data type. + */ + public string? get_type_id () { + return type_id; + } + /** * Returns the C function name that duplicates instances of this data * type. diff --git a/src/libvaladoc/api/tree.vala b/src/libvaladoc/api/tree.vala index 1298d0692..0133b0bef 100755 --- a/src/libvaladoc/api/tree.vala +++ b/src/libvaladoc/api/tree.vala @@ -156,6 +156,14 @@ public class Valadoc.Api.Tree { return null; } + public TypeSymbol? search_symbol_type_cstr (string cname) { + if (_cresolver == null) { + _cresolver = new CTypeResolver (this); + } + + return _cresolver.resolve_symbol_type (cname); + } + public Node? search_symbol_cstr (Node? element, string cname) { if (_cresolver == null) { _cresolver = new CTypeResolver (this); diff --git a/src/libvaladoc/ctyperesolver.vala b/src/libvaladoc/ctyperesolver.vala index a7adac8b2..0467d48c7 100755 --- a/src/libvaladoc/ctyperesolver.vala +++ b/src/libvaladoc/ctyperesolver.vala @@ -28,13 +28,15 @@ using Gee; * Resolves symbols by C-names */ public class Valadoc.CTypeResolver : Visitor { + private Map types = new HashMap (); private Map nodes = new HashMap (); + private Api.Tree tree; public CTypeResolver (Api.Tree tree) { tree.accept (this); + this.tree = tree; } - private string convert_array_to_camelcase (string[] elements) { StringBuilder builder = new StringBuilder (); @@ -72,10 +74,7 @@ public class Valadoc.CTypeResolver : Visitor { if (is_capitalized_and_underscored (name)) { string[] segments = name.split ("_"); unowned string last_segment = segments[segments.length - 1]; - if (last_segment == "ERROR") { - } else if (last_segment == "TYPE") { - segments.resize (segments.length - 1); - } else { + if (last_segment != "ERROR") { return null; } @@ -92,6 +91,28 @@ public class Valadoc.CTypeResolver : Visitor { return null; } + public Api.TypeSymbol? resolve_symbol_type (string name) { + TypeSymbol? symbol = types.get (name); + if (symbol != null) { + return symbol; + } + + if (is_capitalized_and_underscored (name)) { + string[] segments = name.split ("_"); + + if (segments[segments.length - 1] == "TYPE") { + segments.resize (segments.length - 1); + return types.get (convert_array_to_camelcase (segments)); + } else if (segments.length > 2 && segments[1] == "TYPE") { + string[] _segments = segments[1:segments.length]; + _segments[0] = segments[0]; + return types.get (convert_array_to_camelcase (_segments)); + } + } + + return null; + } + /** * Resolves symbols by C-names * @@ -127,9 +148,29 @@ public class Valadoc.CTypeResolver : Visitor { return nodes.get (alternative); } + if (element != null && _name.has_prefix (":")) { + if (element is Class && ((Class) element).get_cname () != null) { + return nodes.get (((Class) element).get_cname () + "." + _name); + } else if (element is Struct && ((Struct) element).get_cname () != null) { + return nodes.get (((Struct) element).get_cname () + "." + _name); + } + } + + if (name == "dgettext") { + return nodes.get ("g_dgettext"); + } else if (name == "printf") { + return this.tree.search_symbol_str (null, "GLib.FileStream.printf"); + } + return null; } + private void register_symbol_type (string? name, Api.TypeSymbol symbol) { + if (name != null) { + types.set (name, symbol); + } + } + private void register_symbol (string? name, Api.Node node) { if (name != null) { nodes.set (name.replace ("-", "_"), node); @@ -187,6 +228,7 @@ public class Valadoc.CTypeResolver : Visitor { * {@inheritDoc} */ public override void visit_class (Class item) { + register_symbol_type (item.get_type_id (), item); register_symbol (item.get_cname (), item); item.accept_all_children (this, false); } @@ -195,6 +237,7 @@ public class Valadoc.CTypeResolver : Visitor { * {@inheritDoc} */ public override void visit_struct (Struct item) { + register_symbol_type (item.get_type_id (), item); register_symbol (item.get_cname (), item); item.accept_all_children (this, false); } diff --git a/src/libvaladoc/documentation/gtkdoccommentparser.vala b/src/libvaladoc/documentation/gtkdoccommentparser.vala index 48e52276b..e9873e43f 100644 --- a/src/libvaladoc/documentation/gtkdoccommentparser.vala +++ b/src/libvaladoc/documentation/gtkdoccommentparser.vala @@ -32,6 +32,7 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { private Token current; private LinkedList stack = new LinkedList (); + private LinkedList> footnotes = new LinkedList> (); private ContentFactory factory; private ErrorReporter reporter; @@ -47,9 +48,10 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { this.scanner.reset (comment.content); this.show_warnings = !comment.file.package.is_package || settings.verbose; this.comment_lines = null; + this.footnotes.clear (); this.comment = comment; - current = null; - stack.clear (); + this.current = null; + this.stack.clear (); } private void report_unexpected_token (Token got, string expected) { @@ -100,6 +102,21 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { comment.taglets.add (taglet); } + bool first = true; + foreach (LinkedList note in this.footnotes) { + if (first == true && note.size > 0) { + Paragraph p = note.first () as Paragraph; + if (p == null) { + p = factory.create_paragraph (); + comment.content.add (p); + } + + p.content.insert (0, factory.create_text ("\n")); + } + comment.content.add_all (note); + first = false; + } + comment.check (tree, element, reporter, settings); return comment; } @@ -234,7 +251,7 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { next (); // TODO: check xml - while (current.type != TokenType.XML_CLOSE && current.content != tagname && current.type != TokenType.EOF) { + while (!(current.type == TokenType.XML_CLOSE && current.content == tagname) && current.type != TokenType.EOF) { if (current.type == TokenType.XML_OPEN) { } else if (current.type == TokenType.XML_CLOSE) { } else if (current.type == TokenType.XML_COMMENT) { @@ -311,22 +328,26 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { next (); } - private void parse_xref () { + private Run? parse_xref () { if (!check_xml_open_tag ("xref")) { this.report_unexpected_token (current, ""); - return; + return null; } string linkend = current.attributes.get ("linkend"); next (); // TODO register xref + Run run = factory.create_run (Run.Style.ITALIC); + run.content.add (factory.create_text (linkend)); + if (!check_xml_close_tag ("xref")) { this.report_unexpected_token (current, ""); - return; + return run; } next (); + return run; } private Run? parse_highlighted_template (string tag_name, Run.Style style) { @@ -674,7 +695,15 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { parse_docbook_spaces (); } - append_block_content_not_null (content, parse_docbook_programlisting ()); + if (current.type == TokenType.XML_OPEN && current.content == "programlisting") { + append_block_content_not_null (content, parse_docbook_programlisting ()); + } else if (current.type == TokenType.XML_OPEN && current.content == "programlisting") { + Embedded? img = parse_docbook_inlinegraphic (); + Paragraph p = factory.create_paragraph (); + append_block_content_not_null (content, p); + p.content.add (img); + + } parse_docbook_spaces (); @@ -761,6 +790,58 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { return content; } + private Run? parse_docbook_footnote () { + if (!check_xml_open_tag ("footnote")) { + this.report_unexpected_token (current, ""); + return null; + } + next (); + + int counter = this.footnotes.size + 1; + Run? nr = factory.create_run (Run.Style.ITALIC); + nr.content.add (factory.create_text ("[%d] ".printf (counter))); + LinkedList content = new LinkedList (); + this.footnotes.add (content); + + Token tmp = null; + while (tmp != current) { + tmp = current; + parse_docbook_spaces (); + + Run? run = parse_inline_content (); + if (run != null && run.content.size > 0) { + Paragraph p = factory.create_paragraph (); + p.content.add (run); + content.add (p); + continue; + } + + LinkedList lst = parse_block_content (); + if (lst != null && run.content.size > 0) { + content.add_all (lst); + continue; + } + } + + Paragraph first = content.first () as Paragraph; + if (first == null) { + first = factory.create_paragraph (); + content.insert (0, first); + } + + Run entry = factory.create_run (Run.Style.ITALIC); + entry.content.add (factory.create_text (counter.to_string () + ": ")); + first.content.insert (0, entry); + + if (!check_xml_close_tag ("footnote")) { + this.report_unexpected_token (current, ""); + return nr; + } + + next (); + return nr; + } + private inline void append_block_content_not_null_all (LinkedList run, LinkedList? elements) { if (elements != null) { run.add_all (elements); @@ -781,6 +862,8 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { if (current.type == TokenType.XML_OPEN && current.content == "itemizedlist") { this.append_block_content_not_null (content, parse_docbook_itemizedlist ()); + } else if (current.type == TokenType.XML_OPEN && current.content == "programlisting") { + this.append_block_content_not_null (content, parse_docbook_programlisting ()); } else if (current.type == TokenType.XML_OPEN && current.content == "para") { this.append_block_content_not_null_all (content, parse_docbook_para ()); } else if (current.type == TokenType.XML_OPEN && current.content == "informalexample") { @@ -805,6 +888,45 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { return content; } + private Run? parse_xml_tag () { + if (!check_xml_open_tag ("tag")) { + this.report_unexpected_token (current, ""); + return null; + } + string? _class = current.attributes.get ("class"); + next (); + + parse_docbook_spaces (false); + + if (current.type != TokenType.WORD) { + this.report_unexpected_token (current, ""); + return null; + } + + Run run = factory.create_run (Run.Style.MONOSPACED); + if (_class == null || _class == "starttag") { + run.content.add (factory.create_text ("<" + current.content + ">")); + next (); + } else if (_class == "endtag") { + run.content.add (factory.create_text ("")); + next (); + } else { + this.report_unexpected_token (current, "".printf (_class)); + return run; + } + + parse_docbook_spaces (false); + + + if (!check_xml_close_tag ("tag")) { + this.report_unexpected_token (current, ""); + return run; + } + + next (); + return run; + } + private void append_inline_content_string (Run run, string current) { Text last_as_text = null; @@ -824,7 +946,7 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { private Inline create_type_link (string name) { if (name == "TRUE" || name == "FALSE" || name == "NULL") { var monospaced = factory.create_run (Run.Style.MONOSPACED); - monospaced.content.add (factory.create_text (name)); + monospaced.content.add (factory.create_text (name.down ())); return monospaced; } else { Taglets.Link? taglet = factory.create_taglet ("link") as Taglets.Link; @@ -846,14 +968,20 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { while (current.type != TokenType.EOF) { if (current.type == TokenType.XML_OPEN && current.content == "firstterm") { append_inline_content_not_null (run, parse_highlighted_template ("firstterm", Run.Style.ITALIC)); + } else if (current.type == TokenType.XML_OPEN && current.content == "term") { + append_inline_content_not_null (run, parse_highlighted_template ("term", Run.Style.ITALIC)); } else if (current.type == TokenType.XML_OPEN && current.content == "literal") { append_inline_content_not_null (run, parse_highlighted_template ("literal", Run.Style.ITALIC)); } else if (current.type == TokenType.XML_OPEN && current.content == "application") { append_inline_content_not_null (run, parse_highlighted_template ("application", Run.Style.MONOSPACED)); } else if (current.type == TokenType.XML_OPEN && current.content == "emphasis") { append_inline_content_not_null (run, parse_highlighted_template ("emphasis", Run.Style.MONOSPACED)); + } else if (current.type == TokenType.XML_OPEN && current.content == "pre") { + append_inline_content_not_null (run, parse_highlighted_template ("pre", Run.Style.MONOSPACED)); } else if (current.type == TokenType.XML_OPEN && current.content == "code") { append_inline_content_not_null (run, parse_highlighted_template ("code", Run.Style.MONOSPACED)); + } else if (current.type == TokenType.XML_OPEN && current.content == "guimenuitem") { + append_inline_content_not_null (run, parse_highlighted_template ("guimenuitem", Run.Style.MONOSPACED)); } else if (current.type == TokenType.XML_OPEN && current.content == "command") { append_inline_content_not_null (run, parse_highlighted_template ("command", Run.Style.MONOSPACED)); } else if (current.type == TokenType.XML_OPEN && current.content == "option") { @@ -866,8 +994,12 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { append_inline_content_not_null (run, parse_highlighted_template ("envar", Run.Style.MONOSPACED)); } else if (current.type == TokenType.XML_OPEN && current.content == "filename") { append_inline_content_not_null (run, parse_highlighted_template ("filename", Run.Style.MONOSPACED)); + } else if (current.type == TokenType.XML_OPEN && current.content == "parameter") { + append_inline_content_not_null (run, parse_highlighted_template ("parameter", Run.Style.MONOSPACED)); } else if (current.type == TokenType.XML_OPEN && current.content == "replaceable") { append_inline_content_not_null (run, parse_highlighted_template ("replaceable", Run.Style.ITALIC)); + } else if (current.type == TokenType.XML_OPEN && current.content == "footnote") { + append_inline_content_not_null (run, parse_docbook_footnote ()); } else if (current.type == TokenType.XML_OPEN && current.content == "type") { append_inline_content_not_null (run, parse_symbol_link ("type")); } else if (current.type == TokenType.XML_OPEN && current.content == "function") { @@ -889,7 +1021,9 @@ public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator { } else if (current.type == TokenType.XML_OPEN && current.content == "ulink") { append_inline_content_not_null (run, parse_docbook_link_tempalte ("ulink")); } else if (current.type == TokenType.XML_OPEN && current.content == "xref") { - parse_xref (); + append_inline_content_not_null (run, parse_xref ()); + } else if (current.type == TokenType.XML_OPEN && current.content == "tag") { + append_inline_content_not_null (run, parse_xml_tag ()); } else if (current.type == TokenType.GTKDOC_FUNCTION) { run.content.add (this.create_type_link (current.content)); next (); diff --git a/src/libvaladoc/importer/documentationimporter.vala b/src/libvaladoc/importer/documentationimporter.vala index 85ba188f2..1a0f0bab5 100755 --- a/src/libvaladoc/importer/documentationimporter.vala +++ b/src/libvaladoc/importer/documentationimporter.vala @@ -29,13 +29,9 @@ public abstract class Valadoc.Importer.DocumentationImporter : Object, ResourceL protected Settings settings; protected Api.Tree tree; - protected Content.ContentFactory factory; - public abstract string file_extension { get; } public DocumentationImporter (Api.Tree tree, ModuleLoader modules, Settings settings) { - factory = new Content.ContentFactory (settings, this, modules); - this.settings = settings; this.modules = null; this.tree = tree; diff --git a/src/libvaladoc/importer/girdocumentationimporter.vala b/src/libvaladoc/importer/girdocumentationimporter.vala new file mode 100644 index 000000000..789409b2e --- /dev/null +++ b/src/libvaladoc/importer/girdocumentationimporter.vala @@ -0,0 +1,635 @@ +/* girdocumentationimporter.vala + * + * Copyright (C) 2008-2010 Jürg Billeter + * Copyright (C) 2011 Luca Bruno + * Copyright (C) 2011 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: + * Jürg Billeter + * Luca Bruno + * Florian Brosch + */ + + +using Valadoc; +using GLib; + + + +public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { + public override string file_extension { get { return "gir"; } } + + private MarkupTokenType current_token; + private MarkupSourceLocation begin; + private MarkupSourceLocation end; + private MarkupReader reader; + + private DocumentationParser parser; + private ErrorReporter reporter; + private Api.SourceFile file; + + private string parent_c_identifier; + + public GirDocumentationImporter (Api.Tree tree, DocumentationParser parser, ModuleLoader modules, Settings settings, ErrorReporter reporter) { + base (tree, modules, settings); + this.reporter = reporter; + this.parser = parser; + } + + public override void process (string source_file) { + this.file = new Api.SourceFile (new Api.Package (Path.get_basename (source_file), true, null), source_file, null); + this.reader = new MarkupReader (source_file, reporter); + + // xml prolog + next (); + next (); + + next (); + parse_repository (); + + reader = null; + file = null; + } + + private void attach_comment (string cname, Api.GirSourceComment? comment) { + if (comment == null) { + return ; + } + + Api.Node? node = this.tree.search_symbol_cstr (null, cname); + if (node == null) { + return; + } + + Content.Comment? content = this.parser.parse (node, comment); + if (content == null) { + return; + } + + node.documentation = content; + } + + 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); + } + + private void next () { + current_token = reader.read_token (out begin, out end); + } + + private void start_element (string name) { + if (current_token != MarkupTokenType.START_ELEMENT || reader.name != name) { + // error + error ("expected start element of `%s'".printf (name)); + } + } + + private void end_element (string name) { + if (current_token != MarkupTokenType.END_ELEMENT || reader.name != name) { + // error + error ("expected end element of `%s'".printf (name)); + } + next (); + } + + private const string GIR_VERSION = "1.2"; + + private void parse_repository () { + start_element ("repository"); + if (reader.get_attribute ("version") != GIR_VERSION) { + error ("unsupported GIR version %s (supported: %s)".printf (reader.get_attribute ("version"), GIR_VERSION)); + return; + } + next (); + + while (current_token == MarkupTokenType.START_ELEMENT) { + if (reader.name == "namespace") { + parse_namespace (); + } else if (reader.name == "include") { + parse_include (); + } else if (reader.name == "package") { + parse_package (); + } else if (reader.name == "c:include") { + parse_c_include (); + } else { + // error + error ("unknown child element `%s' in `repository'".printf (reader.name)); + skip_element (); + } + } + end_element ("repository"); + } + + private void parse_include () { + start_element ("include"); + next (); + + end_element ("include"); + } + + private void parse_package () { + start_element ("package"); + next (); + + end_element ("package"); + } + + private void parse_c_include () { + start_element ("c:include"); + next (); + + end_element ("c:include"); + } + + private void skip_element () { + next (); + + int level = 1; + while (level > 0) { + if (current_token == MarkupTokenType.START_ELEMENT) { + level++; + } else if (current_token == MarkupTokenType.END_ELEMENT) { + level--; + } else if (current_token == MarkupTokenType.EOF) { + error ("unexpected end of file"); + break; + } + next (); + } + } + + private void parse_namespace () { + start_element ("namespace"); + + next (); + while (current_token == MarkupTokenType.START_ELEMENT) { + if (reader.name == "alias") { + parse_alias (); + } else if (reader.name == "enumeration") { + parse_enumeration (); + } else if (reader.name == "bitfield") { + parse_bitfield (); + } else if (reader.name == "function") { + parse_method ("function"); + } else if (reader.name == "callback") { + parse_callback (); + } else if (reader.name == "record") { + parse_record (); + } else if (reader.name == "class") { + parse_class (); + } else if (reader.name == "interface") { + parse_interface (); + } else if (reader.name == "glib:boxed") { + parse_boxed ("glib:boxed"); + } else if (reader.name == "union") { + parse_union (); + } else if (reader.name == "constant") { + parse_constant (); + } else { + // error + error ("unknown child element `%s' in `namespace'".printf (reader.name)); + skip_element (); + } + } + + end_element ("namespace"); + } + + private void parse_alias () { + start_element ("alias"); + string c_identifier = reader.get_attribute ("c:type"); + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (c_identifier, comment); + + parse_type (); + + end_element ("alias"); + } + + private Api.GirSourceComment? parse_symbol_doc () { + if (reader.name != "doc") { + return null; + } + + start_element ("doc"); + next (); + + Api.GirSourceComment? comment = null; + + if (current_token == MarkupTokenType.TEXT) { + comment = new Api.GirSourceComment (reader.content, file, begin.line, begin.column, end.line, end.column); + next (); + } + + end_element ("doc"); + return comment; + } + + private Api.SourceComment? parse_doc () { + if (reader.name != "doc") { + return null; + } + + start_element ("doc"); + next (); + + Api.SourceComment? comment = null; + + if (current_token == MarkupTokenType.TEXT) { + comment = new Api.SourceComment (reader.content, file, begin.line, begin.column, end.line, end.column); + next (); + } + + end_element ("doc"); + return comment; + } + + private void parse_enumeration (string element_name = "enumeration") { + start_element (element_name); + this.parent_c_identifier = reader.get_attribute ("c:type"); + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (this.parent_c_identifier, comment); + + while (current_token == MarkupTokenType.START_ELEMENT) { + if (reader.name == "member") { + parse_enumeration_member (); + } else if (reader.name == "function") { + skip_element (); + } else { + // error + error ("unknown child element `%s' in `%s'".printf (reader.name, element_name)); + skip_element (); + } + } + + this.parent_c_identifier = null; + end_element (element_name); + } + + private void parse_bitfield () { + parse_enumeration ("bitfield"); + } + + private void parse_enumeration_member () { + start_element ("member"); + string c_identifier = reader.get_attribute ("c:identifier"); + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (c_identifier, comment); + + end_element ("member"); + } + + private void parse_return_value (out Api.SourceComment? comment = null) { + start_element ("return-value"); + next (); + + comment = parse_doc (); + + parse_type (); + + end_element ("return-value"); + } + + private void parse_parameter (out Api.SourceComment? comment, out string param_name) { + start_element ("parameter"); + param_name = reader.get_attribute ("name"); + next (); + + comment = parse_doc (); + + if (reader.name == "varargs") { + start_element ("varargs"); + param_name = "..."; + next (); + + end_element ("varargs"); + } else { + parse_type (); + } + + end_element ("parameter"); + } + + private void parse_type () { + skip_element (); + } + + private void parse_record () { + start_element ("record"); + this.parent_c_identifier = reader.get_attribute ("c:type"); + if (this.parent_c_identifier.has_suffix ("Private")) { + this.parent_c_identifier = null; + skip_element (); + return ; + } + + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (this.parent_c_identifier, comment); + + while (current_token == MarkupTokenType.START_ELEMENT) { + if (reader.name == "field") { + parse_field (); + } else if (reader.name == "constructor") { + parse_constructor (); + } else if (reader.name == "method") { + parse_method ("method"); + } else if (reader.name == "function") { + skip_element (); + } else if (reader.name == "union") { + parse_union (); + } else { + // error + error ("unknown child element `%s' in `record'".printf (reader.name)); + skip_element (); + } + } + + this.parent_c_identifier = null; + end_element ("record"); + } + + private void parse_class () { + start_element ("class"); + this.parent_c_identifier = reader.get_attribute ("c:type"); + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (this.parent_c_identifier, comment); + + while (current_token == MarkupTokenType.START_ELEMENT) { + if (reader.name == "implements") { + skip_element (); + } else if (reader.name == "constant") { + parse_constant (); + } else if (reader.name == "field") { + parse_field (); + } else if (reader.name == "property") { + parse_property (); + } else if (reader.name == "constructor") { + parse_constructor (); + } else if (reader.name == "function") { + parse_method ("function"); + } else if (reader.name == "method") { + parse_method ("method"); + } else if (reader.name == "virtual-method") { + parse_method ("virtual-method"); + } else if (reader.name == "union") { + parse_union (); + } else if (reader.name == "glib:signal") { + parse_signal (); + } else { + // error + error ("unknown child element `%s' in `class'".printf (reader.name)); + skip_element (); + } + } + + this.parent_c_identifier = null; + end_element ("class"); + } + + private void parse_interface () { + start_element ("interface"); + this.parent_c_identifier = reader.get_attribute ("c:type"); + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (this.parent_c_identifier, comment); + + while (current_token == MarkupTokenType.START_ELEMENT) { + if (reader.name == "prerequisite") { + skip_element (); + } else if (reader.name == "field") { + parse_field (); + } else if (reader.name == "property") { + parse_property (); + } else if (reader.name == "virtual-method") { + parse_method ("virtual-method"); + } else if (reader.name == "function") { + parse_method ("function"); + } else if (reader.name == "method") { + parse_method ("method"); + } else if (reader.name == "glib:signal") { + parse_signal (); + } else { + // error + error ("unknown child element `%s' in `interface'".printf (reader.name)); + skip_element (); + } + } + + this.parent_c_identifier = null; + end_element ("interface"); + } + + private void parse_field () { + start_element ("field"); + string c_identifier = reader.get_attribute ("name"); + if (this.parent_c_identifier != null) { + c_identifier = this.parent_c_identifier + "." + c_identifier; + } + next (); + + parse_symbol_doc (); + + parse_type (); + + end_element ("field"); + } + + private void parse_property () { + start_element ("property"); + string c_identifier = "%s:%s".printf (parent_c_identifier, reader.get_attribute ("name").replace ("-", "_")); + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (c_identifier, comment); + + parse_type (); + + end_element ("property"); + } + + private void parse_callback () { + skip_element (); + } + + private void parse_constructor () { + parse_function ("constructor"); + } + + private void parse_function (string element_name) { + start_element (element_name); + + string? c_identifier = null; + switch (element_name) { + case "constructor": + case "function": + case "method": + c_identifier = reader.get_attribute ("c:identifier"); + break; + + case "virtual-method": + c_identifier = "%s->%s".printf (this.parent_c_identifier, reader.get_attribute ("name").replace ("-", "_")); + break; + + case "glib:signal": + c_identifier = "%s::%s".printf (this.parent_c_identifier, reader.get_attribute ("name").replace ("-", "_")); + break; + + default: + skip_element (); + return ; + } + + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + + if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "return-value") { + Api.SourceComment? return_comment; + parse_return_value (out return_comment); + if (return_comment != null) { + if (comment == null) { + comment = new Api.GirSourceComment ("", file, begin.line, begin.column, end.line, end.column); + } + comment.return_comment = return_comment; + } + } + + + if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "parameters") { + start_element ("parameters"); + next (); + + while (current_token == MarkupTokenType.START_ELEMENT) { + Api.SourceComment? param_comment; + string? param_name; + + parse_parameter (out param_comment, out param_name); + + if (param_comment != null) { + if (comment == null) { + comment = new Api.GirSourceComment ("", file, begin.line, begin.column, end.line, end.column); + } + + comment.add_parameter_content (param_name, param_comment); + } + } + end_element ("parameters"); + } + + attach_comment (c_identifier, comment); + end_element (element_name); + } + + private void parse_method (string element_name) { + parse_function (element_name); + } + + private void parse_signal () { + parse_function ("glib:signal"); + } + + private void parse_boxed (string element_name) { + start_element (element_name); + + this.parent_c_identifier = reader.get_attribute ("name"); + if (this.parent_c_identifier == null) { + this.parent_c_identifier = reader.get_attribute ("glib:name"); + } + + next (); + + parse_symbol_doc (); + + // TODO: process comments + + while (current_token == MarkupTokenType.START_ELEMENT) { + if (reader.name == "field") { + parse_field (); + } else if (reader.name == "constructor") { + parse_constructor (); + } else if (reader.name == "method") { + parse_method ("method"); + } else if (reader.name == "function") { + skip_element (); + } else if (reader.name == "union") { + parse_union (); + } else { + // error + error ("unknown child element `%s' in `class'".printf (reader.name)); + skip_element (); + } + } + + this.parent_c_identifier = null; + end_element (element_name); + } + + private void parse_union () { + start_element ("union"); + this.parent_c_identifier = reader.get_attribute ("c:type"); + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (this.parent_c_identifier, comment); + + while (current_token == MarkupTokenType.START_ELEMENT) { + if (reader.name == "field") { + parse_field (); + } else if (reader.name == "constructor") { + parse_constructor (); + } else if (reader.name == "method") { + parse_method ("method"); + } else if (reader.name == "function") { + skip_element (); + } else if (reader.name == "record") { + parse_record (); + } else { + // error + error ("unknown child element `%s' in `union'".printf (reader.name)); + skip_element (); + } + } + + this.parent_c_identifier = null; + end_element ("union"); + } + + private void parse_constant () { + start_element ("constant"); + string c_identifier = reader.get_attribute ("c:type"); + next (); + + Api.GirSourceComment? comment = parse_symbol_doc (); + attach_comment (c_identifier, comment); + + parse_type (); + + end_element ("constant"); + } +} + diff --git a/src/libvaladoc/importer/valadocdocumentationimporter.vala b/src/libvaladoc/importer/valadocdocumentationimporter.vala index 16bb1086d..2cbedc61d 100755 --- a/src/libvaladoc/importer/valadocdocumentationimporter.vala +++ b/src/libvaladoc/importer/valadocdocumentationimporter.vala @@ -37,11 +37,14 @@ public class Valadoc.Importer.ValadocDocumentationImporter : DocumentationImport private string _cname; private StringBuilder _comment; private SourceLocation _comment_location; + protected Content.ContentFactory factory; + private ErrorReporter reporter; public ValadocDocumentationImporter (Api.Tree tree, DocumentationParser parser, ModuleLoader modules, Settings settings, ErrorReporter reporter) { base (tree, modules, settings); + this.factory = new Content.ContentFactory (settings, this, modules); this.reporter = reporter; _scanner = new ValadoDocumentationScanner (settings); diff --git a/src/libvaladoc/markupreader.vala b/src/libvaladoc/markupreader.vala index 626508e1a..825b2b2d5 100644 --- a/src/libvaladoc/markupreader.vala +++ b/src/libvaladoc/markupreader.vala @@ -46,6 +46,7 @@ public class Valadoc.MarkupReader : Object { private MappedFile mapped_file; + private string[] lines; private char* begin; private char* current; private char* end; @@ -62,6 +63,7 @@ public class Valadoc.MarkupReader : Object { this.filename = filename; this.reporter = reporter; + lines = content.split ("\n"); begin = content; end = begin + content.size (); current = begin; @@ -77,6 +79,7 @@ public class Valadoc.MarkupReader : Object { try { mapped_file = new MappedFile (filename, false); begin = mapped_file.get_contents (); + lines = ((string) begin).split ("\n"); end = begin + mapped_file.get_length (); current = begin; @@ -88,6 +91,14 @@ public class Valadoc.MarkupReader : Object { } } + public string? get_line_content (int line_nr) { + if (this.lines.length > line_nr) { + return this.lines[line_nr]; + } + + return null; + } + public string? get_attribute (string attr) { return attributes[attr]; } diff --git a/src/libvaladoc/taglets/tagletlink.vala b/src/libvaladoc/taglets/tagletlink.vala index 57b14747c..633fc4184 100755 --- a/src/libvaladoc/taglets/tagletlink.vala +++ b/src/libvaladoc/taglets/tagletlink.vala @@ -27,6 +27,12 @@ using Valadoc.Content; public class Valadoc.Taglets.Link : InlineTaglet { public string symbol_name { internal set; get; } + private enum SymbolContext { + NORMAL, + TYPE + } + + private SymbolContext _context = SymbolContext.NORMAL; private Api.Node _symbol; public override Rule? get_parser_rule (Rule run_rule) { @@ -48,8 +54,13 @@ public class Valadoc.Taglets.Link : InlineTaglet { if (symbol_name.has_prefix ("c::")) { _symbol_name = _symbol_name.substring (3); _symbol = api_root.search_symbol_cstr (container, symbol_name); + _context = SymbolContext.NORMAL; + if (_symbol == null) { - + _symbol = api_root.search_symbol_type_cstr (symbol_name); + if (_symbol != null) { + _context = SymbolContext.TYPE; + } } if (_symbol != null) { @@ -59,7 +70,7 @@ public class Valadoc.Taglets.Link : InlineTaglet { _symbol = api_root.search_symbol_str (container, symbol_name); } - if (_symbol == null) { + if (_symbol == null && symbol_name != "main") { // TODO use ContentElement's source reference reporter.simple_warning ("%s: %s does not exist", container.get_full_name (), symbol_name); } @@ -71,6 +82,22 @@ public class Valadoc.Taglets.Link : InlineTaglet { var link = new Content.SymbolLink (); link.symbol = _symbol; link.label = symbol_name; - return link; + + switch (_context) { + case SymbolContext.TYPE: + Content.Run content = new Content.Run (Run.Style.MONOSPACED); + + Content.Run keyword = new Content.Run (Run.Style.LANG_KEYWORD); + keyword.content.add (new Content.Text ("typeof")); + content.content.add (keyword); + + content.content.add (new Content.Text (" (")); + content.content.add (link); + content.content.add (new Content.Text (")")); + return content; + + default: + return link; + } } }