From: Florian Brosch Date: Thu, 19 Aug 2010 22:04:48 +0000 (+0200) Subject: add gir documentation importer X-Git-Tag: 0.37.1~3^2~429 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76f8fb19dc8cd090bd69fe0abfd62ac2f2f3fada;p=thirdparty%2Fvala.git add gir documentation importer --- diff --git a/src/libvaladoc/Makefile.am b/src/libvaladoc/Makefile.am index b7695767a..d95cd941f 100644 --- a/src/libvaladoc/Makefile.am +++ b/src/libvaladoc/Makefile.am @@ -30,13 +30,16 @@ libvaladoc_la_VALASOURCES = \ settings.vala \ markupwriter.vala \ devhelp-markupwriter.vala \ + ctyperesolver.vala \ + documentation/girdocumentationscanner.vala \ documentation/commentscanner.vala \ documentation/documentation.vala \ documentation/documentationparser.vala \ documentation/wiki.vala \ documentation/wikiscanner.vala \ + importer/girdocumentationimporter.vala \ importer/documentationimporter.vala \ - importer/ctyperesolver.vala \ + importer/girdocumentationbuilder.vala \ api/array.vala \ api/class.vala \ api/constant.vala \ diff --git a/src/libvaladoc/api/package.vala b/src/libvaladoc/api/package.vala index 16ddd3c35..031ad409f 100644 --- a/src/libvaladoc/api/package.vala +++ b/src/libvaladoc/api/package.vala @@ -22,6 +22,7 @@ using Gee; using Valadoc.Content; +using Valadoc.Importer; public class Valadoc.Api.Package : Node { private ArrayList vfiles = new ArrayList (); @@ -110,10 +111,6 @@ public class Valadoc.Api.Package : Node { .get (); } - internal void import_documentation (string path, Settings settings, DocumentationImporter importer) { - importer.process (path, settings, this); - } - internal Namespace get_namespace (Tree root, Vala.Symbol symbol) { Vala.Symbol namespace_symbol = symbol; while (!(namespace_symbol is Vala.Namespace)) { diff --git a/src/libvaladoc/api/tree.vala b/src/libvaladoc/api/tree.vala index 3a90dd5d8..7a3d69854 100644 --- a/src/libvaladoc/api/tree.vala +++ b/src/libvaladoc/api/tree.vala @@ -31,23 +31,18 @@ public class Valadoc.Api.Tree { private ArrayList packages = new ArrayList(); private Package source_package = null; private Settings settings; - private Vala.CodeContext context; private ErrorReporter reporter; private Package sourcefiles = null; private CTypeResolver _cresolver = null; - public WikiPageTree? wikitree { + internal Vala.CodeContext context { private set; get; } - public CTypeResolver cresolver { - get { - if (_cresolver == null) { - _cresolver = new CTypeResolver (this); - } - return _cresolver; - } + public WikiPageTree? wikitree { + private set; + get; } public Collection get_package_list () { @@ -117,6 +112,14 @@ public class Valadoc.Api.Tree { return null; } + public Node? search_symbol_cstr (string cname) { + if (_cresolver == null) { + _cresolver = new CTypeResolver (this); + } + + return _cresolver.resolve_symbol (cname); + } + public Node? search_symbol_str (Node? element, string symname) { string[] path = split_name (symname); @@ -208,6 +211,25 @@ public class Valadoc.Api.Tree { } } + private void add_deps (string file_path, string pkg_name) { + if (FileUtils.test (file_path, FileTest.EXISTS)) { + try { + string deps_content; + ulong deps_len; + FileUtils.get_contents (file_path, out deps_content, out deps_len); + foreach (string dep in deps_content.split ("\n")) { + dep.strip (); + if (dep != "") { + if (!add_package (dep)) { + Vala.Report.error (null, "%s, dependency of %s, not found in specified Vala API directories".printf (dep, pkg_name)); + } + } + } + } catch (FileError e) { + Vala.Report.error (null, "Unable to read dependency file: %s".printf (e.message)); + } + } + } private bool add_package (string pkg) { if (context.has_package (pkg)) { @@ -216,7 +238,6 @@ public class Valadoc.Api.Tree { } var package_path = context.get_package_path (pkg, settings.vapi_directories); - if (package_path == null) { return false; } @@ -230,30 +251,12 @@ public class Valadoc.Api.Tree { Package vdpkg = new Package (vfile, pkg, true); this.packages.add (vdpkg); - var deps_filename = Path.build_filename (Path.get_dirname (package_path), "%s.deps".printf (pkg)); - if (FileUtils.test (deps_filename, FileTest.EXISTS)) { - try { - string deps_content; - ulong deps_len; - FileUtils.get_contents (deps_filename, out deps_content, out deps_len); - foreach (string dep in deps_content.split ("\n")) { - dep.strip (); - if (dep != "") { - if (!add_package (dep)) { - Vala.Report.error (null, "%s, dependency of %s, not found in specified Vala API directories".printf (dep, pkg)); - } - } - } - } catch (FileError e) { - Vala.Report.error (null, "Unable to read dependency file: %s".printf (e.message)); - } - } - + add_deps (Path.build_filename (Path.get_dirname (package_path), "%s.deps".printf (pkg)), pkg); return true; } // copied from valacodecontext.vala - private string? get_file_path (string basename, string data_dir, string[] directories) { + private string? get_file_path (string basename, string[] directories) { string filename = null; if (directories != null) { @@ -266,7 +269,7 @@ public class Valadoc.Api.Tree { } foreach (string dir in Environment.get_system_data_dirs ()) { - filename = Path.build_filename (dir, data_dir, basename); + filename = Path.build_filename (dir, basename); if (FileUtils.test (filename, FileTest.EXISTS)) { return filename; } @@ -275,21 +278,6 @@ public class Valadoc.Api.Tree { return null; } - // copied from valacodecontext.vala - private string? get_external_documentation_path (string pkg) { - var path = get_file_path (Path.build_filename (pkg, "documentation.xml"), "vala/vapi/documentation", settings.docu_directories); - - if (path == null) { - /* last chance: try the package compiled-in vapi dir */ - var filename = Path.build_filename (Config.vapi_dir, "vapi", "documentation", pkg, "documentation.xml"); - if (FileUtils.test (filename, FileTest.EXISTS)) { - path = filename; - } - } - - return path; - } - public void add_depencies (string[] packages) { foreach (string package in packages) { if (!add_package (package)) { @@ -332,12 +320,13 @@ public class Valadoc.Api.Tree { context.add_source_file (source_file); } else if (source.has_suffix (".vapi")) { string file_name = Path.get_basename (source); - file_name = file_name.ndup ( file_name.size() - ".vapi".size() ); + file_name = file_name.ndup (file_name.size() - ".vapi".size()); var vfile = new Vala.SourceFile (context, rpath, true); Package vdpkg = new Package (vfile, file_name); context.add_source_file (vfile); this.packages.add (vdpkg); + add_deps (Path.build_filename (Path.get_dirname (source), "%s.deps".printf (file_name)), file_name); } else if (source.has_suffix (".c")) { context.add_c_source_file (rpath); } else { @@ -376,6 +365,15 @@ public class Valadoc.Api.Tree { return true; } + private Package? find_package_by_name (string name) { + foreach (Package pkg in packages) { + if (name == pkg.name) { + return pkg; + } + } + return null; + } + private Package? find_package_for_file (Vala.SourceFile vfile) { foreach (Package pkg in this.packages) { if (pkg.is_package_for_file (vfile)) @@ -426,15 +424,16 @@ public class Valadoc.Api.Tree { } } - public void import_documentation (DocumentationImporter importer) { - foreach (Package pkg in this.packages) { - string? path = (pkg.is_package)? get_external_documentation_path (pkg.name) : null; + public void import_documentation (DocumentationImporter importer, string[] packages, string[] import_directories) { + foreach (string pkg_name in packages) { + string? path = get_file_path ("%s.%s".printf (pkg_name, importer.file_extension), import_directories); - if (pkg.is_browsable (settings) && path != null) { - pkg.import_documentation (path, settings, importer); + if (path == null) { + Vala.Report.error (null, "%s not found in specified import directories".printf (pkg_name)); + } else { + importer.process (path); } } - } internal Symbol? search_vala_symbol (Vala.Symbol symbol) { diff --git a/src/libvaladoc/importer/ctyperesolver.vala b/src/libvaladoc/ctyperesolver.vala similarity index 98% rename from src/libvaladoc/importer/ctyperesolver.vala rename to src/libvaladoc/ctyperesolver.vala index 83af7791d..b9641bfd8 100644 --- a/src/libvaladoc/importer/ctyperesolver.vala +++ b/src/libvaladoc/ctyperesolver.vala @@ -24,7 +24,7 @@ using Valadoc.Api; using Gee; -public class Valadoc.Importer.CTypeResolver : Visitor { +public class Valadoc.CTypeResolver : Visitor { private Map nodes = new HashMap (); public CTypeResolver (Api.Tree tree) { diff --git a/src/libvaladoc/documentation/documentationparser.vala b/src/libvaladoc/documentation/documentationparser.vala index 869c5e0f0..0c735c94c 100644 --- a/src/libvaladoc/documentation/documentationparser.vala +++ b/src/libvaladoc/documentation/documentationparser.vala @@ -21,6 +21,7 @@ */ using Valadoc.Content; +using Valadoc.Importer; using Gee; @@ -42,7 +43,16 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator { _comment_parser = new Parser (_settings, _comment_scanner, _reporter); _comment_scanner.set_parser (_comment_parser); - init_rules (); + _gir_scanner = new GirDocumentationScanner (_settings); + _gir_parser = new Parser (_settings, _gir_scanner, _reporter); + _gir_scanner.set_parser (_gir_parser); + + _gir_taglet_scanner = new GirDocumentationScanner (_settings); + _gir_taglet_parser = new Parser (_settings, _gir_taglet_scanner, _reporter); + _gir_taglet_scanner.set_parser (_gir_taglet_parser); + + init_valadoc_rules (); + init_girdoc_rules (); } private Settings _settings; @@ -51,13 +61,17 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator { private ModuleLoader _modules; private ContentFactory _factory; + private GirDocumentationScanner _gir_taglet_scanner; + private GirDocumentationScanner _gir_scanner; private WikiScanner _wiki_scanner; private CommentScanner _comment_scanner; + private Parser _gir_parser; + private Parser _gir_taglet_parser; private Parser _wiki_parser; private Parser _comment_parser; private Parser _parser; - private WikiScanner _scanner; + private Scanner _scanner; public Comment? parse (Api.Node element, Vala.Comment source_comment) { weak string content = source_comment.content; @@ -71,6 +85,48 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator { } } + public Comment? parse_gir_comment (Api.Node element, GirDocumentationBuilder doc) { + try { + _stack.clear (); + + if (doc.content != null) { + _parser = _gir_parser; + _scanner = _gir_scanner; + _gir_parser.parse (doc.content, doc.source_reference.file.filename, doc.source_reference.first_line, doc.source_reference.first_column); + } else { + push (_factory.create_comment ()); + } + + + _parser = _gir_taglet_parser; + _scanner = _gir_taglet_scanner; + + if (doc.return_value != null && !(element is Api.Method && ((Api.Method) element).is_constructor)) { + push (_factory.create_taglet ("return")); + _gir_taglet_parser.parse (doc.return_value.content, doc.return_value.source_reference.file.filename, doc.return_value.source_reference.first_line, doc.return_value.source_reference.first_column); + } + + var iter = doc.parameters.map_iterator (); + for (iter.next (); iter.has_next (); iter.next ()) { + var val = iter.get_value (); + var key = iter.get_key (); + if (key != "self") { + var param = _factory.create_taglet ("param") as Taglets.Param; + param.parameter_name = key; + push (param); + _gir_taglet_parser.parse (val.content, val.source_reference.file.filename, val.source_reference.first_line, val.source_reference.first_column); + } + } + + var doc_comment = (Comment) pop (); + doc_comment.check (_tree, element, _reporter, _settings); + + return doc_comment; + } catch (ParserError error) { + return null; + } + } + public Page? parse_wikipage (WikiPage page, Api.Package pkg) { if (page.documentation != null) { return page.documentation; @@ -216,7 +272,465 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator { text.content += str; } - private void init_rules () { + private void gir_append_link (Token token) throws ParserError { + var taglet = _factory.create_taglet ("link") as Taglets.Link; + if (!(taglet is Inline)) { + _parser.error ("Invalid taglet in this context: link"); + } + taglet.symbol_name = "c::"+token.to_string (); + push (taglet); + } + + private bool _gir_is_first_paragraph = true; + + private void init_girdoc_rules () { + StubRule run = new StubRule (); + run.set_name ("Run"); + + TokenType.Action add_text = (token) => { + add_content_string (token.to_string ()); + }; + + TokenType dot = TokenType.GTKDOC_DOT.action ((token) => { add_content_string ("."); }); + TokenType word = TokenType.GTKDOC_ANY_WORD.action (add_text); + TokenType space = TokenType.GTKDOC_SPACE.action (add_text); + TokenType newline = TokenType.GTKDOC_EOL.action ((token) => { add_content_string (" "); }); + Rule unprinted_space = Rule.one_of ({ space.action ((token) => {}), newline.action ((token) => {}) }); + Rule unprinted_spaces = Rule.many ({ unprinted_space }); + Rule optional_unprinted_spaces = Rule.option ({ unprinted_spaces }); + + Rule raw_text = Rule.many ({ + Rule.one_of ({ + word, space, newline, dot + }) + .set_reduce (() => { ((InlineContent) peek ()).content.add ((Inline) pop ()); }) + }) + .set_name ("RawText"); + + Rule run_with_dot = Rule.many ({ + Rule.one_of ({ + run, dot + }) + .set_reduce (() => { ((InlineContent) peek ()).content.add ((Inline) pop ()); }) + }) + .set_name ("FormatedText"); + + Rule xml_comment_raw = Rule.seq ({ + TokenType.GTKDOC_XML_COMMENT_START, + Rule.option ({ + Rule.many ({ + Rule.one_of ({ + word.action ((token) => {}), + space.action ((token) => {}), + newline.action ((token) => {}), + dot.action ((token) => {}) + //TODO + }) + }) + }), + TokenType.GTKDOC_XML_COMMENT_END + }); + + + Rule xml_comment = Rule.seq ({ + xml_comment_raw + }) + .set_name ("XmlComment") + .set_start (() => { push (_factory.create_text ("")); }); + + + Rule word_or_function = Rule.seq ({ + TokenType.GTKDOC_ANY_WORD.action ((token) => { push (token); }), + Rule.option ({ + Rule.many ({ + Rule.one_of ({ + space.action ((token) => { + if (((Token) peek ()).is_word) { + push (token); + } + }), + xml_comment_raw + }) + }) + }), + Rule.option ({ + TokenType.GTKDOC_FUNCTION_BRACKETS.action ((token) => { + var last_token = (Token) pop (); + if (!last_token.is_word) { + last_token = (Token) pop (); + } + + gir_append_link (last_token); + }) + }).set_skip (() => { + var last_token = (Token) pop (); + if (last_token.is_word) { + add_content_string (last_token.to_string ()); + } else { + add_content_string (((Token) pop ()).to_string ()); + add_content_string (last_token.to_string ()); + } + }) + }); + + Rule node_link = Rule.one_of ({ + Rule.seq ({ + TokenType.GTKDOC_SYMBOL, + word.action ((token) => { + switch (token.to_string ()) { + case "FALSE": + case "TRUE": + case "NULL": + var myrun = _factory.create_run (Run.Style.MONOSPACED); + var mytext = _factory.create_text (); + mytext.content = token.to_string ().down (); + myrun.content.add (mytext); + push (myrun); + break; + + default: + gir_append_link (token); + break; + } + }) + }) + }) + .set_name ("TypeLink"); + + Rule link_element = Rule.seq ({ + TokenType.GTKDOC_LINK_ELEMENT_OPEN, + run_with_dot, + TokenType.GTKDOC_LINK_ELEMENT_CLOSE + }) + .set_name ("Link") + .set_start (() => { push (_factory.create_run (Run.Style.NONE)); }); + + Rule filename_element = Rule.seq ({ + TokenType.GTKDOC_FILENAME_ELEMENT_OPEN, + raw_text, + TokenType.GTKDOC_FILENAME_ELEMENT_CLOSE + }) + .set_name ("Filename") + .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); }); + + Rule envar_element = Rule.seq ({ + TokenType.GTKDOC_ENVAR_ELEMENT_OPEN, + run_with_dot, + TokenType.GTKDOC_ENVAR_ELEMENT_CLOSE + }) + .set_name ("Envar") + .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); }); + + Rule emphasis_element = Rule.seq ({ + TokenType.GTKDOC_EMPHASIS_ELEMENT_OPEN, + run_with_dot, + TokenType.GTKDOC_EMPHASIS_ELEMENT_CLOSE + }) + .set_name ("Emphasis") + .set_start (() => { push (_factory.create_run (Run.Style.ITALIC)); }); + + Rule option_element = Rule.seq ({ + TokenType.GTKDOC_OPTION_ELEMENT_OPEN, + run_with_dot, + TokenType.GTKDOC_OPTION_ELEMENT_CLOSE + }) + .set_name ("Option") + .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); }); + + Rule term_element = Rule.seq ({ + TokenType.GTKDOC_TERM_ELEMENT_OPEN, + run_with_dot, + TokenType.GTKDOC_TERM_ELEMENT_CLOSE + }) + .set_name ("Term") + .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); }); + + Rule literal_element = Rule.seq ({ + TokenType.GTKDOC_LITERAL_ELEMENT_OPEN, + run_with_dot, + TokenType.GTKDOC_LITERAL_ELEMENT_CLOSE + }) + .set_name ("Literal") + .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); }); + + Rule replaceable_element = Rule.seq ({ + TokenType.GTKDOC_REPLACEABLE_ELEMENT_OPEN, + raw_text, + TokenType.GTKDOC_REPLACEABLE_ELEMENT_CLOSE + }) + .set_name ("Replaceable") + .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); }); + + Rule guimenuitem_element = Rule.seq ({ + TokenType.GTKDOC_GUI_MENU_ITEM_ELEMENT_OPEN, + raw_text, + TokenType.GTKDOC_GUI_MENU_ITEM_ELEMENT_CLOSE + }) + .set_name ("GuiMenuItem") + .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); }); + + Rule struct_name_element = Rule.seq ({ + TokenType.GTKDOC_STRUCTNAME_ELEMENT_OPEN, + word.action ((token) => { + gir_append_link (token); + }), + TokenType.GTKDOC_STRUCTNAME_ELEMENT_CLOSE + }) + .set_name ("Structname"); + + Rule param = Rule.one_of ({ + Rule.seq ({ + TokenType.GTKDOC_PARAM, + word + }) + }) + .set_name ("Parameter") + .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); }) + .set_reduce (() => { ((InlineContent) peek ()).content.add ((Inline) pop ()); }); + + run.set_rule ( + Rule.many ({ + Rule.one_of ({ + newline, space, word_or_function, node_link, param, struct_name_element, link_element, xml_comment, + literal_element, guimenuitem_element, replaceable_element, envar_element, emphasis_element, + option_element, term_element, filename_element + }) + }) + .set_name ("Run") + ); + + Rule paragraph_element = Rule.seq ({ + TokenType.GTKDOC_PARA_ELEMENT_OPEN, + run_with_dot, + TokenType.GTKDOC_PARA_ELEMENT_CLOSE, + Rule.option ({ + Rule.many({ + Rule.one_of ({ + space.action ((token) => {}), + newline.action ((token) => {}) + }) + }) + }) + }) + .set_name ("ParagraphElement") + .set_start (() => { push (_factory.create_paragraph ()); }) + .set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); }); + + Rule source = Rule.seq ({ + TokenType.GTKDOC_SOURCE_OPEN.action ((token) => { ((GirDocumentationScanner) _scanner).set_code_escape_mode (true); }), + Rule.many ({ + word.action ((token) => { ((SourceCode) peek ()).code = token.to_string (); }) + }) + .set_start (() => { push (_factory.create_source_code ()); }) + .set_reduce (() => { ((Paragraph) peek ()).content.add ((Inline) pop ()); }), + TokenType.GTKDOC_SOURCE_CLOSE.action ((token) => { ((GirDocumentationScanner) _scanner).set_code_escape_mode (false); }), + optional_unprinted_spaces + }) + .set_name ("Source") + .set_start (() => { push (_factory.create_paragraph ()); }) + .set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); }); + + Rule program_listing_element = Rule.seq ({ + TokenType.GTKDOC_PROGRAMLISTING_ELEMENT_OPEN.action ((token) => { ((GirDocumentationScanner) _scanner).set_code_element_escape_mode (true); }), + Rule.many ({ + word.action ((token) => { ((SourceCode) peek ()).code = token.to_string (); }) + }) + .set_start (() => { push (_factory.create_source_code ()); }) + .set_reduce (() => { ((Paragraph) peek ()).content.add ((Inline) pop ()); }), + TokenType.GTKDOC_PROGRAMLISTING_ELEMENT_CLOSE.action ((token) => { ((GirDocumentationScanner) _scanner).set_code_element_escape_mode (false); }), + optional_unprinted_spaces + }) + .set_name ("ProgramListing") + .set_start (() => { push (_factory.create_paragraph ()); }) + .set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); }); + + Rule example_element = Rule.seq ({ + Rule.one_of ({ + program_listing_element, + Rule.seq ({ + TokenType.GTKDOC_EXAMPLE_ELEMENT_OPEN, + optional_unprinted_spaces, + Rule.option ({ + TokenType.GTKDOC_TITLE_ELEMENT_OPEN, + Rule.many ({ + Rule.one_of ({ word.action ((token) => {}) }) + }), + TokenType.GTKDOC_TITLE_ELEMENT_CLOSE, + optional_unprinted_spaces + }), + program_listing_element, + TokenType.GTKDOC_EXAMPLE_ELEMENT_CLOSE + }) + }), + optional_unprinted_spaces + }) + .set_name ("SourceElement"); + + Rule paragraph = Rule.seq ({ + run_with_dot + }) + .set_name ("Paragraph") + .set_start (() => { push (_factory.create_paragraph ()); }) + .set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); }); + + Rule note_element = Rule.seq ({ + TokenType.GTKDOC_NOTE_ELEMENT_OPEN, + optional_unprinted_spaces, + Rule.option ({ + paragraph + }), + Rule.option ({ + Rule.many ({ + paragraph_element, + Rule.option ({ paragraph }) + }) + }), + TokenType.GTKDOC_NOTE_ELEMENT_CLOSE, + optional_unprinted_spaces + }) + .set_name ("Note"); + + Rule warning_element = Rule.seq ({ + TokenType.GTKDOC_WARNING_ELEMENT_OPEN, + optional_unprinted_spaces, + Rule.option ({ + paragraph + }), + Rule.option ({ + Rule.many ({ + paragraph_element, + Rule.option ({ paragraph }) + }) + }), + TokenType.GTKDOC_WARNING_ELEMENT_CLOSE, + optional_unprinted_spaces + }) + .set_name ("Warning"); + + Rule variable_list_element = Rule.seq ({ + TokenType.GTKDOC_VARIABLE_LIST_ELEMENT_OPEN, + optional_unprinted_spaces, + Rule.many ({ + Rule.seq ({ + TokenType.GTKDOC_VARIABLE_LIST_ENTRY_ELEMENT_OPEN, + optional_unprinted_spaces, + + TokenType.GTKDOC_TERM_ELEMENT_OPEN, + optional_unprinted_spaces, + run_with_dot, + TokenType.GTKDOC_TERM_ELEMENT_CLOSE.action ((token) => { add_content_string (": "); }), + optional_unprinted_spaces, + + TokenType.GTKDOC_LIST_ITEM_ELEMENT_OPEN, + optional_unprinted_spaces, + run_with_dot, + TokenType.GTKDOC_LIST_ITEM_ELEMENT_CLOSE, + optional_unprinted_spaces, + + TokenType.GTKDOC_VARIABLE_LIST_ENTRY_ELEMENT_CLOSE, + optional_unprinted_spaces + }) + .set_start (() => { push (_factory.create_list_item ()); }) + .set_reduce (() => { ((Content.List) peek ()).items.add ((Content.ListItem) pop ()); }) + }), + TokenType.GTKDOC_VARIABLE_LIST_ELEMENT_CLOSE, + optional_unprinted_spaces + }) + .set_name ("VariableList") + .set_start (() => { push (_factory.create_list ()); }) + .set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); }); + + Rule list_element = Rule.seq ({ + TokenType.GTKDOC_ITEMIZED_LIST_ELEMENT_OPEN, + optional_unprinted_spaces, + Rule.many ({ + Rule.seq ({ + TokenType.GTKDOC_LIST_ITEM_ELEMENT_OPEN, + optional_unprinted_spaces, + run_with_dot, + TokenType.GTKDOC_LIST_ITEM_ELEMENT_CLOSE, + optional_unprinted_spaces + }) + .set_start (() => { push (_factory.create_list_item ()); }) + .set_reduce (() => { ((Content.List) peek ()).items.add ((Content.ListItem) pop ()); }) + }), + TokenType.GTKDOC_ITEMIZED_LIST_ELEMENT_CLOSE, + optional_unprinted_spaces + }) + .set_name ("ItemizedList") + .set_start (() => { push (_factory.create_list ()); }) + .set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); }); + + Rule simple_list_element = Rule.seq ({ + TokenType.GTKDOC_SIMPLELIST_ELEMENT_OPEN, + optional_unprinted_spaces, + Rule.many ({ + Rule.seq ({ + TokenType.GTKDOC_MEMBER_ELEMENT_OPEN, + optional_unprinted_spaces, + run_with_dot, + TokenType.GTKDOC_MEMBER_ELEMENT_CLOSE, + optional_unprinted_spaces + }) + .set_start (() => { push (_factory.create_list_item ()); }) + .set_reduce (() => { ((Content.List) peek ()).items.add ((Content.ListItem) pop ()); }) + }), + TokenType.GTKDOC_SIMPLELIST_ELEMENT_CLOSE, + optional_unprinted_spaces + }) + .set_name ("SimpleList") + .set_start (() => { push (_factory.create_list ()); }) + .set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); }); + + Rule block_element = Rule.one_of ({ + paragraph_element, list_element, note_element, warning_element, source, + example_element, variable_list_element, simple_list_element + }) + .set_name ("Block"); + + // TODO: find out why the clean version does not work ... + Rule first_paragraph = Rule.many ({ + Rule.one_of ({ + Rule.seq ({ run }).set_reduce (() => { ((InlineContent) peek ()).content.add ((Inline) pop ()); }), + TokenType.GTKDOC_DOT.action ((token) => { + ((InlineContent) peek ()).content.add (_factory.create_text (".")); + if (_gir_is_first_paragraph) { + ((BlockContent) peek ()).content.add ((Block) pop ()); + push (_factory.create_paragraph ()); + _gir_is_first_paragraph = false; + } + }) + }) + }) + .set_name ("BriefDescription") + .set_start (() => { push (_factory.create_paragraph ()); }) + .set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); _gir_is_first_paragraph = true; }); + + Rule comment = Rule.seq ({ + Rule.option ({ + first_paragraph + }), + Rule.option ({ + Rule.many ({ + block_element, + Rule.option ({ paragraph }) + }) + }) + }) + .set_name ("Comment") + .set_start (() => { push (_factory.create_comment ()); }); + + Rule taglet = Rule.many ({ + run_with_dot + }) + .set_name ("Taglet") + .set_reduce (() => { ((Comment) peek ()).taglets.add ((Taglet) pop ()); }); + + _gir_taglet_parser.set_root_rule (taglet); + _gir_parser.set_root_rule (comment); + } + + private void init_valadoc_rules () { // Inline rules StubRule run = new StubRule (); @@ -311,35 +825,35 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator { Rule embedded = Rule.seq ({ - TokenType.DOUBLE_OPEN_BRACE.action (() => { _scanner.set_url_escape_mode (true); }), + TokenType.DOUBLE_OPEN_BRACE.action (() => { ((WikiScanner) _scanner).set_url_escape_mode (true); }), TokenType.any_word ().action ((token) => { ((Embedded) peek ()).url = token.to_string (); }), Rule.option ({ - TokenType.PIPE.action (() => { _scanner.set_url_escape_mode (false); }), + TokenType.PIPE.action (() => { ((WikiScanner) _scanner).set_url_escape_mode (false); }), text }) .set_reduce (() => { var caption = pop () as Text; ((Embedded) peek ()).caption = caption.content; }), - TokenType.DOUBLE_CLOSED_BRACE.action (() => { _scanner.set_url_escape_mode (false); }) + TokenType.DOUBLE_CLOSED_BRACE.action (() => { ((WikiScanner) _scanner).set_url_escape_mode (false); }) }) .set_name ("Embedded") .set_start (() => { push (_factory.create_embedded ()); }); Rule link = Rule.seq ({ - TokenType.DOUBLE_OPEN_BRACKET.action (() => { _scanner.set_url_escape_mode (true); }), + TokenType.DOUBLE_OPEN_BRACKET.action (() => { ((WikiScanner) _scanner).set_url_escape_mode (true); }), TokenType.any_word ().action ((token) => { ((Link) peek ()).url = token.to_string (); }), Rule.option ({ - TokenType.PIPE.action (() => { _scanner.set_url_escape_mode (false); }), + TokenType.PIPE.action (() => { ((WikiScanner) _scanner).set_url_escape_mode (false); }), run }), - TokenType.DOUBLE_CLOSED_BRACKET.action (() => { _scanner.set_url_escape_mode (false); }) + TokenType.DOUBLE_CLOSED_BRACKET.action (() => { ((WikiScanner) _scanner).set_url_escape_mode (false); }) }) .set_name ("Link") .set_start (() => { push (_factory.create_link ()); }); Rule source_code = Rule.seq ({ - TokenType.TRIPLE_OPEN_BRACE.action ((token) => { _scanner.set_code_escape_mode (true); }), + TokenType.TRIPLE_OPEN_BRACE.action ((token) => { ((WikiScanner) _scanner).set_code_escape_mode (true); }), TokenType.any_word ().action ((token) => { ((SourceCode) peek ()).code = token.to_string (); }), - TokenType.TRIPLE_CLOSED_BRACE.action ((token) => { _scanner.set_code_escape_mode (false); }) + TokenType.TRIPLE_CLOSED_BRACE.action ((token) => { ((WikiScanner) _scanner).set_code_escape_mode (false); }) }) .set_name ("SourceCode") .set_start (() => { push (_factory.create_source_code ()); }); diff --git a/src/libvaladoc/documentation/girdocumentationscanner.vala b/src/libvaladoc/documentation/girdocumentationscanner.vala new file mode 100644 index 000000000..aed78db60 --- /dev/null +++ b/src/libvaladoc/documentation/girdocumentationscanner.vala @@ -0,0 +1,610 @@ +/* girdocuscanner.vala + * + * Copyright (C) 2010 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; + +public class Valadoc.Importer.GirDocumentationScanner : Object, Scanner { + + public GirDocumentationScanner (Settings settings) { + _settings = settings; + } + + private Settings _settings; + private Parser _parser; + + private string _content; + private int _index; + private bool _stop; + private int _last_index; + private int _last_line; + private int _last_column; + private int _line; + private int _column; + private bool _code_element_escape_mode; + private bool _code_escape_mode; + private bool _node_name; + private unichar _last_char; + private int _skip; + private StringBuilder _current_string = new StringBuilder (); + + public void set_parser (Parser parser) { + _parser = parser; + } + + public void reset () { + _stop = false; + _last_index = 0; + _last_line = 0; + _last_column = 0; + _line = 0; + _column = 0; + _code_element_escape_mode = false; + _code_escape_mode = false; + _node_name = false; + _last_char = 0; + _skip = 0; + _current_string.erase (0, -1); + } + + public void scan (string _content) throws ParserError { + this._content = _content; + for (_index = 0; !_stop && _index < _content.length; _index++) { + unichar c = _content[_index]; + accept (c); + } + } + + public void end () throws ParserError { + emit_token (TokenType.GTKDOC_EOF); + } + + public void stop () { + _stop = true; + } + + public void set_code_element_escape_mode (bool escape_mode) { + _code_element_escape_mode = escape_mode; + } + + public void set_code_escape_mode (bool escape_mode) { + _code_escape_mode = escape_mode; + } + + public int get_line () { + return _line; + } + + public virtual string get_line_content () { + int i = _index; + while (i > 0 && _content[i-1] != '\n') { + i--; + } + StringBuilder builder = new StringBuilder (); + while (i < _content.length && _content[i] != '\n') { + unichar c = _content[i++]; + if (c == '\t') { + builder.append (" "); + } else { + builder.append_unichar (c); + } + } + return builder.str; + } + + protected unichar get_next_char (int offset = 1) { + return _content[_index + offset]; + } + + private void emit_xml_node_open_token (string name, int offset) throws ParserError { + switch (name) { + case "structname": + emit_token (TokenType.GTKDOC_STRUCTNAME_ELEMENT_OPEN); + _skip = offset; + break; + + case "link": + emit_token (TokenType.GTKDOC_LINK_ELEMENT_OPEN); + _skip = offset; + break; + + case "literal": + emit_token (TokenType.GTKDOC_LITERAL_ELEMENT_OPEN); + _skip = offset; + break; + + case "guimenuitem": + emit_token (TokenType.GTKDOC_GUI_MENU_ITEM_ELEMENT_OPEN); + _skip = offset; + break; + + case "replaceable": + emit_token (TokenType.GTKDOC_REPLACEABLE_ELEMENT_OPEN); + _skip = offset; + break; + + case "para": + emit_token (TokenType.GTKDOC_PARA_ELEMENT_OPEN); + _skip = offset; + break; + + case "note": + emit_token (TokenType.GTKDOC_NOTE_ELEMENT_OPEN); + _skip = offset; + break; + + case "itemizedlist": + emit_token (TokenType.GTKDOC_ITEMIZED_LIST_ELEMENT_OPEN); + _skip = offset; + break; + + case "listitem": + emit_token (TokenType.GTKDOC_LIST_ITEM_ELEMENT_OPEN); + _skip = offset; + break; + + case "warning": + emit_token (TokenType.GTKDOC_WARNING_ELEMENT_OPEN); + _skip = offset; + break; + + case "programlisting": + emit_token (TokenType.GTKDOC_PROGRAMLISTING_ELEMENT_OPEN); + _skip = offset; + break; + + case "informalexample": + emit_token (TokenType.GTKDOC_EXAMPLE_ELEMENT_OPEN); + _skip = offset; + break; + + case "variablelist": + emit_token (TokenType.GTKDOC_VARIABLE_LIST_ELEMENT_OPEN); + _skip = offset; + break; + + case "varlistentry": + emit_token (TokenType.GTKDOC_VARIABLE_LIST_ENTRY_ELEMENT_OPEN); + _skip = offset; + break; + + case "term": + emit_token (TokenType.GTKDOC_TERM_ELEMENT_OPEN); + _skip = offset; + break; + + case "envar": + emit_token (TokenType.GTKDOC_ENVAR_ELEMENT_OPEN); + _skip = offset; + break; + + case "option": + emit_token (TokenType.GTKDOC_OPTION_ELEMENT_OPEN); + _skip = offset; + break; + + case "emphasis": + emit_token (TokenType.GTKDOC_EMPHASIS_ELEMENT_OPEN); + _skip = offset; + break; + + case "filename": + emit_token (TokenType.GTKDOC_FILENAME_ELEMENT_OPEN); + _skip = offset; + break; + + case "simplelist": + emit_token (TokenType.GTKDOC_SIMPLELIST_ELEMENT_OPEN); + _skip = offset; + break; + + case "member": + emit_token (TokenType.GTKDOC_MEMBER_ELEMENT_OPEN); + _skip = offset; + break; + + default: + append_char ('<'); + break; + } + } + + private void emit_xml_node_close_token (string name, int offset) throws ParserError { + switch (name) { + case "structname": + emit_token (TokenType.GTKDOC_STRUCTNAME_ELEMENT_CLOSE); + _skip = offset; + break; + + case "link": + emit_token (TokenType.GTKDOC_LINK_ELEMENT_CLOSE); + _skip = offset; + break; + + case "literal": + emit_token (TokenType.GTKDOC_LITERAL_ELEMENT_CLOSE); + _skip = offset; + break; + + case "guimenuitem": + emit_token (TokenType.GTKDOC_GUI_MENU_ITEM_ELEMENT_CLOSE); + _skip = offset; + break; + + case "replaceable": + emit_token (TokenType.GTKDOC_REPLACEABLE_ELEMENT_CLOSE); + _skip = offset; + break; + + case "para": + emit_token (TokenType.GTKDOC_PARA_ELEMENT_CLOSE); + _skip = offset; + break; + + case "note": + emit_token (TokenType.GTKDOC_NOTE_ELEMENT_CLOSE); + _skip = offset; + break; + + case "itemizedlist": + emit_token (TokenType.GTKDOC_ITEMIZED_LIST_ELEMENT_CLOSE); + _skip = offset; + break; + + case "listitem": + emit_token (TokenType.GTKDOC_LIST_ITEM_ELEMENT_CLOSE); + _skip = offset; + break; + + case "warning": + emit_token (TokenType.GTKDOC_WARNING_ELEMENT_CLOSE); + _skip = offset; + break; + + case "programlisting": + emit_token (TokenType.GTKDOC_PROGRAMLISTING_ELEMENT_CLOSE); + _skip = offset; + break; + + case "informalexample": + emit_token (TokenType.GTKDOC_EXAMPLE_ELEMENT_CLOSE); + _skip = offset; + break; + + case "variablelist": + emit_token (TokenType.GTKDOC_VARIABLE_LIST_ELEMENT_CLOSE); + _skip = offset; + break; + + case "varlistentry": + emit_token (TokenType.GTKDOC_VARIABLE_LIST_ENTRY_ELEMENT_CLOSE); + _skip = offset; + break; + + case "term": + emit_token (TokenType.GTKDOC_TERM_ELEMENT_CLOSE); + _skip = offset; + break; + + case "envar": + emit_token (TokenType.GTKDOC_ENVAR_ELEMENT_CLOSE); + _skip = offset; + break; + + case "option": + emit_token (TokenType.GTKDOC_OPTION_ELEMENT_CLOSE); + _skip = offset; + break; + + case "emphasis": + emit_token (TokenType.GTKDOC_EMPHASIS_ELEMENT_CLOSE); + _skip = offset; + break; + + case "filename": + emit_token (TokenType.GTKDOC_FILENAME_ELEMENT_CLOSE); + _skip = offset; + break; + + case "simplelist": + emit_token (TokenType.GTKDOC_SIMPLELIST_ELEMENT_CLOSE); + _skip = offset; + break; + + case "member": + emit_token (TokenType.GTKDOC_MEMBER_ELEMENT_CLOSE); + _skip = offset; + break; + + default: + append_char ('<'); + break; + } + } + + private inline bool is_numeric (unichar c) { + return c >= '0' && c <= '9'; + } + + private inline bool is_letter (unichar c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); + } + + private void emmit_qualified_function_name (int offset) throws ParserError { + unichar c = get_next_char (offset); + + if (!is_letter (c) && c != '_') { + emit_current_word (); + return; + } + + append_char (c); + + for (offset++; ; offset++) { + c = get_next_char (offset); + + if (!is_letter (c) && c != '_' && !is_numeric (c) && c != '\0') { + break; + } + + append_char (c); + } + + unichar nc = get_next_char (offset+1); + + if (c == '\0' || !((c == ':' && nc == ':' && is_letter (get_next_char (offset+2))) || (c == ':' && is_letter (nc)))) { + emit_current_word (); + _skip = offset-1; + return; + } + + append_char (c); + + if (nc == ':') { + append_char (nc); + offset++; + } + + for (offset++; ; offset++) { + c = get_next_char (offset); + + if (!is_letter (c) && c != '_' && !is_numeric (c)&& c != '-' && c != '\0') { + break; + } + + append_char (c); + } + + emit_current_word (); + _skip = offset-1; + } + + protected void accept (unichar c) throws ParserError { + _column++; + + if (_skip == 0) { + if (_code_element_escape_mode == true) { + switch (c) { + case '<': + if (get_next_char (1) == '/' && get_next_char (2) == 'p' && + get_next_char (3) == 'r' && get_next_char (4) == 'o' && + get_next_char (5) == 'g' && get_next_char (6) == 'r' && + get_next_char (7) == 'a' && get_next_char (8) == 'm' && + get_next_char (9) == 'l' && get_next_char (10) == 'i' && + get_next_char (11) == 's' && get_next_char (12) == 't' && + get_next_char (13) == 'i' && get_next_char (14) == 'n' && + get_next_char (15) == 'g' && get_next_char (16) == '>') { + + _code_element_escape_mode = false; + emit_token (TokenType.GTKDOC_PROGRAMLISTING_ELEMENT_CLOSE); + _skip = 16; + } else { + append_char (c); + } + return; + default: + append_char (c); + return; + } + } else if (_code_escape_mode == true) { + switch (c) { + case ']': + if (get_next_char (1) == '|') { + _code_escape_mode = false; + emit_token (TokenType.GTKDOC_SOURCE_CLOSE); + _skip = 2; + } else { + append_char (c); + } + return; + default: + append_char (c); + return; + } + } else { + switch (c) { + case '#': + case '%': + unichar nc = get_next_char (1); + if (is_letter (nc) || nc == '_') { + emit_token (TokenType.GTKDOC_SYMBOL); + emmit_qualified_function_name (1); + } else { + append_char (c); + } + break; + + case '@': + if (_last_char.isspace ()) { + emit_token (TokenType.GTKDOC_PARAM); + } else { + append_char (c); + } + break; + + case '-': + if (get_next_char (1) == '-' && get_next_char (2) == '>') { + emit_token (TokenType.GTKDOC_XML_COMMENT_END); + _skip = 2; + } else { + append_char (c); + } + break; + + case '(': // "(?)" + int i = 1; + + for (; get_next_char(i).isspace (); i++); + if (get_next_char(i) == ')') { + emit_token (TokenType.GTKDOC_FUNCTION_BRACKETS); + _skip = i; + } else { + append_char (c); + } + break; + + case '<': + if (get_next_char(1) == '!' && get_next_char(2) == '-' && get_next_char(3) == '-') { + emit_token (TokenType.GTKDOC_XML_COMMENT_START); + _skip = 3; + break; + } + + var name = new StringBuilder (); + bool is_end_tag = false; + int i = 1; + + if (get_next_char(i) == '/') { + is_end_tag = true; + i++; + } + + + for (; get_next_char(i) != '>' && !get_next_char(i).isspace (); i++) { + name.append_unichar (get_next_char(i)); + } + + if (name.len == 0) { + append_char (c); + break; + } + + if (is_end_tag) { + if (get_next_char(i) != '>') { + append_char (c); + break; + } + emit_xml_node_close_token (name.str, i); + } else { + for (; get_next_char(i) != '>' && get_next_char(i) != '\0'; i++); + if (get_next_char(i) == '\0') { + append_char (c); + break; + } + emit_xml_node_open_token (name.str, i); + } + break; + + case '|': + if (get_next_char (1) == '[') { + emit_token (TokenType.GTKDOC_SOURCE_OPEN); + _skip = 1; + } else { + append_char (c); + } + break; + + case ']': + if (get_next_char (1) == '|') { + emit_token (TokenType.GTKDOC_SOURCE_CLOSE); + _skip = 1; + } else { + append_char (c); + } + break; + + case '\r': + break; + + case '\n': + emit_token (TokenType.GTKDOC_EOL); + _line++; + _column = 0; + _last_column = 0; + break; + + case '\t': + case ' ': + emit_token (TokenType.GTKDOC_SPACE); + break; + + case '.': + emit_token (TokenType.GTKDOC_DOT); + break; + + default: + append_char (c); + break; + } + } + } else { + _skip--; + } + _last_char = c; + } + + private void append_char (unichar c) { + _current_string.append_unichar (c); + } + + public int get_line_start_column () { + return 0; + } + + private SourceLocation get_begin () { + return SourceLocation (_last_line, get_line_start_column () + _last_column); + } + + private SourceLocation get_end (int offset = 0) { + return SourceLocation (_line, get_line_start_column () + _column + offset); + } + + private void emit_current_word () throws ParserError { + if (_current_string.len > 0) { + _parser.accept_token (new Token.from_word (_current_string.str, get_begin (), get_end (-1))); + _current_string.erase (0, -1); + + _last_index = _index; + _last_line = _line; + _last_column = _column - 1; + } + } + + private void emit_token (TokenType type) throws ParserError { + emit_current_word (); + + _parser.accept_token (new Token.from_type (type, get_begin (), get_end (_skip))); + + _last_index = _index; + _last_line = _line; + _last_column = _column; + } +} diff --git a/src/libvaladoc/html/htmlrenderer.vala b/src/libvaladoc/html/htmlrenderer.vala index 322dd6165..66ef4d420 100755 --- a/src/libvaladoc/html/htmlrenderer.vala +++ b/src/libvaladoc/html/htmlrenderer.vala @@ -57,11 +57,17 @@ public class Valadoc.Html.HtmlRenderer : ContentRenderer { return linker.get_relative_link (_container, symbol, _doclet.settings); } - private void write_symbol_link (Api.Node symbol, string? label) { - var url = get_url (symbol); - writer.link (url, - (label == null || label == "") ? symbol.get_full_name () : label, - cssresolver.resolve (symbol)); + private void write_symbol_link (Api.Node? symbol, string? label) { + if (symbol == null && label != null) { + writer.start_tag ("code"); + writer.text (label); + writer.end_tag ("code"); + } else if (symbol != null) { + var url = get_url (symbol); + writer.link (url, + (label == null || label == "") ? symbol.get_full_name () : label, + cssresolver.resolve (symbol)); + } } private delegate void Write (); @@ -230,10 +236,12 @@ public class Valadoc.Html.HtmlRenderer : ContentRenderer { } public override void visit_symbol_link (SymbolLink element) { - if (element.symbol == _container + if (element.symbol == null || element.symbol == _container || !element.symbol.is_browsable (_doclet.settings) || !element.symbol.package.is_browsable (_doclet.settings)) { + writer.start_tag ("code"); writer.text (element.label); + writer.end_tag ("code"); } else { write_symbol_link (element.symbol, element.label); } diff --git a/src/libvaladoc/importer/documentationimporter.vala b/src/libvaladoc/importer/documentationimporter.vala index d19f01967..9cdf7b04f 100644 --- a/src/libvaladoc/importer/documentationimporter.vala +++ b/src/libvaladoc/importer/documentationimporter.vala @@ -24,19 +24,18 @@ using Gee; -public abstract class Valadoc.DocumentationImporter : Object, ResourceLocator { - protected ErrorReporter errorreporter; +public abstract class Valadoc.Importer.DocumentationImporter : Object, ResourceLocator { protected ModuleLoader modules; 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, ErrorReporter errorreporter) { + public DocumentationImporter (Api.Tree tree, ModuleLoader modules, Settings settings) { factory = new Content.ContentFactory (settings, this, modules); - this.errorreporter = errorreporter; this.settings = settings; this.modules = null; this.tree = tree; @@ -46,7 +45,7 @@ public abstract class Valadoc.DocumentationImporter : Object, ResourceLocator { return path; } - public abstract bool process (string filename, Settings settings, Api.Package package); + public abstract void process (string filename); } diff --git a/src/libvaladoc/importer/girdocumentationbuilder.vala b/src/libvaladoc/importer/girdocumentationbuilder.vala new file mode 100644 index 000000000..d502cf382 --- /dev/null +++ b/src/libvaladoc/importer/girdocumentationbuilder.vala @@ -0,0 +1,56 @@ +/* DocumentationBuilderimporter.vala + * + * Copyright (C) 2010 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 Gee; + + +/** + * A documentation comment used by valadoc + */ +public class Valadoc.Importer.GirDocumentationBuilder : Vala.Comment { + private HashMap _parameters = new HashMap (); + + public Map parameters { owned get { return _parameters.read_only_view; } } + + public Vala.Comment? return_value { get; internal set; } + + public GirDocumentationBuilder.empty (Vala.SourceReference _source_reference) { + base ("", _source_reference); + return_value = null; + } + + public GirDocumentationBuilder (Vala.Comment comment) { + base (comment.content, comment.source_reference); + return_value = null; + } + + internal void add_parameter (string name, Vala.Comment comment) { + _parameters.set (name, comment); + } + + public bool is_empty () { + return return_value == null && (content == null || content == "") && parameters.is_empty; + } +} + diff --git a/src/libvaladoc/importer/girdocumentationimporter.vala b/src/libvaladoc/importer/girdocumentationimporter.vala new file mode 100644 index 000000000..a76215ba5 --- /dev/null +++ b/src/libvaladoc/importer/girdocumentationimporter.vala @@ -0,0 +1,687 @@ +/* DocumentationBuilderimporter.vala + * + * Copyright (C) 2010 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 + */ + +// based on valagirparser.vala + +using Gee; + +public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter { + DocumentationParser docparser; + Vala.MarkupReader reader; + + Vala.SourceFile current_source_file; + Vala.SourceLocation begin; + Vala.SourceLocation end; + Vala.MarkupTokenType current_token; + + Vala.DataType dummy_type; + + LinkedList type_cname_stack = new LinkedList (); + + int anonymous_param_count = 0; + + public override string file_extension { get { return "gir"; } } + + public GirDocumentationImporter (Api.Tree tree, DocumentationParser docparser, ModuleLoader modules, Settings settings) { + base (tree, modules, settings); + this.dummy_type = new Vala.StructValueType (new Vala.Struct ("Dummy")); + this.docparser = docparser; + } + + public override void process (string filename) { + parse_file (filename); + } + + void parse_file (string gir_file) { + reader = new Vala.MarkupReader (gir_file); + this.current_source_file = new Vala.SourceFile (tree.context, GLib.Path. get_basename (gir_file)); + + // xml prolog + next (); + next (); + + next (); + parse_repository (); + this.current_source_file = null; + } + + Vala.Comment? parse_doc () { + start_element ("doc"); + + Vala.Comment comment = null; + next (); + + if (current_token == Vala.MarkupTokenType.TEXT) { + comment = new Vala.Comment (reader.content, get_current_src ()); + next (); + } + + end_element ("doc"); + return comment; + } + + void next () { + current_token = reader.read_token (out begin, out end); + } + + void start_element (string name) { + if (current_token != Vala.MarkupTokenType.START_ELEMENT || reader.name != name) { + // error + Vala.Report.error (get_current_src (), "expected start element of `%s' instead of `%s'".printf (name, reader.name)); + } + } + + void end_element (string name) { + if (current_token != Vala.MarkupTokenType.END_ELEMENT || reader.name != name) { + // error + Vala.Report.error (get_current_src (), "expected end element of `%s' instead of `%s'".printf (name, reader.name)); + } + next (); + } + + Vala.SourceReference get_current_src () { + return new Vala.SourceReference (this.current_source_file, begin.line, begin.column, end.line, end.column); + } + + void parse_repository () { + start_element ("repository"); + next (); + while (current_token == Vala.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 + Vala.Report.error (get_current_src (), "unknown child element `%s' in `repository'".printf (reader.name)); + break; + } + } + end_element ("repository"); + } + + void parse_include () { + start_element ("include"); + next (); + end_element ("include"); + } + + void parse_package () { + start_element ("package"); + next (); + end_element ("package"); + } + + void parse_c_include () { + start_element ("c:include"); + next (); + end_element ("c:include"); + } + + void skip_element () { + next (); + + int level = 1; + while (level > 0) { + if (current_token == Vala.MarkupTokenType.START_ELEMENT) { + level++; + } else if (current_token == Vala.MarkupTokenType.END_ELEMENT) { + level--; + } else if (current_token == Vala.MarkupTokenType.EOF) { + Vala.Report.error (get_current_src (), "unexpected end of file"); + break; + } + next (); + } + } + + void parse_namespace () { + start_element ("namespace"); + next (); + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + if (reader.get_attribute ("introspectable") == "0") { + skip_element (); + continue; + } + + 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") { + if (reader.get_attribute ("glib:get-type") != null) { + parse_boxed (); + } else { + parse_record (); + } + } else if (reader.name == "class") { + parse_class (); + } else if (reader.name == "interface") { + parse_interface (); + } else if (reader.name == "glib:boxed") { + parse_boxed (); + } else if (reader.name == "union") { + parse_union (); + } else if (reader.name == "constant") { + parse_constant (); + } else { + // error + Vala.Report.error (get_current_src (), "unknown child element `%s' in `namespace'".printf (reader.name)); + break; + } + } + end_element ("namespace"); + } + + void parse_alias () { + start_element ("alias"); + next (); + end_element ("alias"); + } + + void parse_enumeration () { + start_element ("enumeration"); + string cname = reader.get_attribute ("c:type"); + type_cname_stack.add (cname); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (cname, new GirDocumentationBuilder (parse_doc ())); + } + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + if (reader.get_attribute ("introspectable") == "0") { + skip_element (); + continue; + } + + if (reader.name == "member") { + parse_enumeration_member (); + } else { + // error + break; + } + } + + type_cname_stack.poll_head (); + end_element ("enumeration"); + } + + void parse_bitfield () { + start_element ("bitfield"); + string cname = reader.get_attribute ("c:type"); + type_cname_stack.add (cname); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (cname, new GirDocumentationBuilder (parse_doc ())); + } + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + if (reader.get_attribute ("introspectable") == "0") { + skip_element (); + continue; + } + + if (reader.name == "member") { + parse_enumeration_member (); + } else { + // error + break; + } + } + + type_cname_stack.poll_head (); + end_element ("bitfield"); + } + + void parse_enumeration_member () { + start_element ("member"); + string cname = reader.get_attribute ("c:identifier"); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (cname, new GirDocumentationBuilder (parse_doc ())); + } + + end_element ("member"); + } + + void parse_return_value (GirDocumentationBuilder doc) { + start_element ("return-value"); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + doc.return_value = parse_doc (); + } + + parse_type (); + + end_element ("return-value"); + } + + void parse_parameter (GirDocumentationBuilder doc) { + start_element ("parameter"); + string name = reader.get_attribute ("name"); + + if (name == null) { + name = "param%d".printf (anonymous_param_count); + anonymous_param_count++; + } + + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + doc.add_parameter (name, parse_doc ()); + } + + if (reader.name == "varargs") { + start_element ("varargs"); + next (); + end_element ("varargs"); + } else { + parse_type (); + } + + end_element ("parameter"); + } + + void parse_type () { + if (reader.name == "array" || reader.name == "callback" || reader.name == "type") { + skip_element (); + } + } + + void parse_record () { + start_element ("record"); + string glib_is_gtype_struct_for = reader.get_attribute ("glib:is-gtype-struct-for"); + string cname = reader.get_attribute ("c:type"); + type_cname_stack.add (cname); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (cname, new GirDocumentationBuilder (parse_doc ())); + } + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + if (reader.get_attribute ("introspectable") == "0") { + skip_element (); + continue; + } + + if (reader.name == "field") { + parse_field (); + } else if (reader.name == "callback") { + if (glib_is_gtype_struct_for != null) { + parse_method ("callback"); + } else { + parse_callback (); + } + } else if (reader.name == "constructor") { + parse_constructor (); + } else if (reader.name == "method") { + parse_method ("method"); + } else if (reader.name == "union") { + parse_union (); + } else { + // error + Vala.Report.error (get_current_src (), "unknown child element `%s' in `record'".printf (reader.name)); + break; + } + } + + type_cname_stack.poll_head (); + end_element ("record"); + } + + void parse_class () { + start_element ("class"); + string cname = reader.get_attribute ("c:type"); + type_cname_stack.add (cname); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (cname, new GirDocumentationBuilder (parse_doc ())); + } + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + if (reader.get_attribute ("introspectable") == "0") { + skip_element (); + continue; + } + + if (reader.name == "implements") { + start_element ("implements"); + next (); + end_element ("implements"); + } 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 (cname); + } 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 + Vala.Report.error (get_current_src (), "unknown child element `%s' in `class'".printf (reader.name)); + break; + } + } + + type_cname_stack.poll_head (); + end_element ("class"); + } + + void parse_interface () { + start_element ("interface"); + string cname = reader.get_attribute ("c:type"); + type_cname_stack.add (cname); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (cname, new GirDocumentationBuilder (parse_doc ())); + } + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + if (reader.get_attribute ("introspectable") == "0") { + skip_element (); + continue; + } + + if (reader.name == "prerequisite") { + start_element ("prerequisite"); + next (); + end_element ("prerequisite"); + } 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 + Vala.Report.error (get_current_src (), "unknown child element `%s' in `interface'".printf (reader.name)); + break; + } + } + + type_cname_stack.poll_head (); + end_element ("interface"); + } + + void parse_field () { + start_element ("field"); + string cname = reader.get_attribute ("name"); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc" && cname != null) { + string real_cname = type_cname_stack.peek(); + real_cname = (real_cname == null)? cname : real_cname+"."+cname; + process_documentation (real_cname, new GirDocumentationBuilder (parse_doc ())); + } + + parse_type (); + + end_element ("field"); + } + + void parse_property () { + start_element ("property"); + string cname = reader.get_attribute ("name"); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc" && cname != null) { + process_documentation (type_cname_stack.peek()+":"+cname, new GirDocumentationBuilder (parse_doc ())); + } + + parse_type (); + + end_element ("property"); + } + + void parse_callback () { + this.parse_function ("callback"); + } + + void parse_constructor (string? parent_ctype = null) { + start_element ("constructor"); + string cname = reader.get_attribute ("c:identifier"); + next (); + + GirDocumentationBuilder doc; + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + doc = new GirDocumentationBuilder (parse_doc ()); + } else { + doc = new GirDocumentationBuilder.empty (get_current_src ()); + } + + parse_return_value (doc); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "parameters") { + start_element ("parameters"); + next (); + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + parse_parameter (doc); + } + end_element ("parameters"); + } + + if (!doc.is_empty ()) { + process_documentation (cname, doc); + } + + end_element ("constructor"); + } + + void parse_function (string element_name) { + start_element (element_name); + string cname = reader.get_attribute ("c:identifier"); + next (); + + GirDocumentationBuilder doc; + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + doc = new GirDocumentationBuilder (parse_doc ()); + } else { + doc = new GirDocumentationBuilder.empty (get_current_src ()); + } + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "return-value") { + parse_return_value (doc); + } + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "parameters") { + start_element ("parameters"); + next (); + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + parse_parameter (doc); + } + + end_element ("parameters"); + } + + if (!doc.is_empty ()) { + process_documentation (cname, doc); + } + + end_element (element_name); + } + + void parse_method (string element_name) { + this.parse_function (element_name); + } + + void parse_signal () { + start_element ("glib:signal"); + string cname = reader.get_attribute ("name"); + next (); + + GirDocumentationBuilder doc; + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + doc = new GirDocumentationBuilder (parse_doc ()); + } else { + doc = new GirDocumentationBuilder.empty (get_current_src ()); + } + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "return-value") { + parse_return_value (doc); + } + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "parameters") { + start_element ("parameters"); + next (); + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + parse_parameter (doc); + } + end_element ("parameters"); + } + if (!doc.is_empty ()) { + process_documentation (type_cname_stack.peek()+"::"+cname, doc); + } + end_element ("glib:signal"); + } + + void parse_boxed () { + string cname = reader.get_attribute ("c:type"); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (cname, new GirDocumentationBuilder (parse_doc ())); + } + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + if (reader.get_attribute ("introspectable") == "0") { + skip_element (); + continue; + } + + if (reader.name == "field") { + parse_field (); + } else if (reader.name == "constructor") { + parse_constructor (); + } else if (reader.name == "union") { + parse_union (); + } else if (reader.name == "method") { + parse_method ("method"); + } else { + // error + Vala.Report.error (get_current_src (), "unknown child element `%s' in `class'".printf (reader.name)); + break; + } + } + + if (current_token != Vala.MarkupTokenType.END_ELEMENT) { + // error + Vala.Report.error (get_current_src (), "expected end element"); + } + next (); + } + + void parse_union () { + start_element ("union"); + string cname = reader.get_attribute ("c:type"); + type_cname_stack.add (cname); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (cname, new GirDocumentationBuilder (parse_doc ())); + } + + while (current_token == Vala.MarkupTokenType.START_ELEMENT) { + if (reader.get_attribute ("introspectable") == "0") { + skip_element (); + continue; + } + + 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 == "record") { + parse_record (); + } + } + + type_cname_stack.poll_head (); + end_element ("union"); + } + + void parse_constant () { + start_element ("constant"); + string name = reader.get_attribute ("name"); + next (); + + if (current_token == Vala.MarkupTokenType.START_ELEMENT && reader.name == "doc") { + process_documentation (name, new GirDocumentationBuilder (parse_doc ())); + } + + parse_type (); + + end_element ("constant"); + } + + void process_documentation (string? cname, GirDocumentationBuilder? doc) { + if (cname == null || doc == null) { + return; + } + + var node = tree.search_symbol_cstr (cname); + + if (node != null) { + node.documentation = docparser.parse_gir_comment (node, doc); + } + } +} + diff --git a/src/libvaladoc/parser/tokentype.vala b/src/libvaladoc/parser/tokentype.vala index 86f87dc4f..bd53da9f6 100644 --- a/src/libvaladoc/parser/tokentype.vala +++ b/src/libvaladoc/parser/tokentype.vala @@ -23,7 +23,7 @@ using Gee; public class Valadoc.TokenType : Object { - + // valadoc-comments: public static TokenType ANY; public static TokenType ANY_WORD; public static TokenType ANY_NUMBER; @@ -60,6 +60,64 @@ public class Valadoc.TokenType : Object { public static TokenType ALIGN_RIGHT; public static TokenType ALIGN_CENTER; + // Gir, doc-nodes: + public static TokenType GTKDOC_FUNCTION_BRACKETS; + public static TokenType GTKDOC_XML_COMMENT_START; + public static TokenType GTKDOC_XML_COMMENT_END; + public static TokenType GTKDOC_PARAM; + public static TokenType GTKDOC_SYMBOL; + public static TokenType GTKDOC_ANY_WORD; + public static TokenType GTKDOC_SPACE; + public static TokenType GTKDOC_EOF; + public static TokenType GTKDOC_EOL; + public static TokenType GTKDOC_STRUCTNAME_ELEMENT_CLOSE; + public static TokenType GTKDOC_STRUCTNAME_ELEMENT_OPEN; + public static TokenType GTKDOC_LINK_ELEMENT_CLOSE; + public static TokenType GTKDOC_LINK_ELEMENT_OPEN; + public static TokenType GTKDOC_ITEMIZED_LIST_ELEMENT_CLOSE; + public static TokenType GTKDOC_ITEMIZED_LIST_ELEMENT_OPEN; + public static TokenType GTKDOC_LIST_ITEM_ELEMENT_CLOSE; + public static TokenType GTKDOC_LIST_ITEM_ELEMENT_OPEN; + public static TokenType GTKDOC_NOTE_ELEMENT_CLOSE; + public static TokenType GTKDOC_NOTE_ELEMENT_OPEN; + public static TokenType GTKDOC_PARA_ELEMENT_CLOSE; + public static TokenType GTKDOC_PARA_ELEMENT_OPEN; + public static TokenType GTKDOC_LITERAL_ELEMENT_CLOSE; + public static TokenType GTKDOC_LITERAL_ELEMENT_OPEN; + public static TokenType GTKDOC_GUI_MENU_ITEM_ELEMENT_CLOSE; + public static TokenType GTKDOC_GUI_MENU_ITEM_ELEMENT_OPEN; + public static TokenType GTKDOC_REPLACEABLE_ELEMENT_CLOSE; + public static TokenType GTKDOC_REPLACEABLE_ELEMENT_OPEN; + public static TokenType GTKDOC_WARNING_ELEMENT_CLOSE; + public static TokenType GTKDOC_WARNING_ELEMENT_OPEN; + public static TokenType GTKDOC_SOURCE_CLOSE; + public static TokenType GTKDOC_SOURCE_OPEN; + public static TokenType GTKDOC_EXAMPLE_ELEMENT_CLOSE; + public static TokenType GTKDOC_EXAMPLE_ELEMENT_OPEN; + public static TokenType GTKDOC_TITLE_ELEMENT_CLOSE; + public static TokenType GTKDOC_TITLE_ELEMENT_OPEN; + public static TokenType GTKDOC_PROGRAMLISTING_ELEMENT_CLOSE; + public static TokenType GTKDOC_PROGRAMLISTING_ELEMENT_OPEN; + public static TokenType GTKDOC_VARIABLE_LIST_ELEMENT_CLOSE; + public static TokenType GTKDOC_VARIABLE_LIST_ELEMENT_OPEN; + public static TokenType GTKDOC_VARIABLE_LIST_ENTRY_ELEMENT_CLOSE; + public static TokenType GTKDOC_VARIABLE_LIST_ENTRY_ELEMENT_OPEN; + public static TokenType GTKDOC_TERM_ELEMENT_CLOSE; + public static TokenType GTKDOC_TERM_ELEMENT_OPEN; + public static TokenType GTKDOC_ENVAR_ELEMENT_CLOSE; + public static TokenType GTKDOC_ENVAR_ELEMENT_OPEN; + public static TokenType GTKDOC_OPTION_ELEMENT_CLOSE; + public static TokenType GTKDOC_OPTION_ELEMENT_OPEN; + public static TokenType GTKDOC_EMPHASIS_ELEMENT_CLOSE; + public static TokenType GTKDOC_EMPHASIS_ELEMENT_OPEN; + public static TokenType GTKDOC_FILENAME_ELEMENT_CLOSE; + public static TokenType GTKDOC_FILENAME_ELEMENT_OPEN; + public static TokenType GTKDOC_SIMPLELIST_ELEMENT_CLOSE; + public static TokenType GTKDOC_SIMPLELIST_ELEMENT_OPEN; + public static TokenType GTKDOC_MEMBER_ELEMENT_CLOSE; + public static TokenType GTKDOC_MEMBER_ELEMENT_OPEN; + public static TokenType GTKDOC_DOT; + private static bool initialized = false; internal static void init_token_types () { @@ -99,6 +157,64 @@ public class Valadoc.TokenType : Object { DOUBLE_PIPE = new TokenType.basic ("||"); ALIGN_RIGHT = new TokenType.basic ("))"); ALIGN_CENTER = new TokenType.basic (")("); + + GTKDOC_FUNCTION_BRACKETS = new TokenType.basic ("()"); + GTKDOC_XML_COMMENT_START = new TokenType.basic (""); + GTKDOC_PARAM = new TokenType.basic (""); + GTKDOC_SYMBOL = new TokenType.basic (""); + GTKDOC_STRUCTNAME_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_STRUCTNAME_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_LINK_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_LINK_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_ITEMIZED_LIST_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_ITEMIZED_LIST_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_LIST_ITEM_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_LIST_ITEM_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_NOTE_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_NOTE_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_PARA_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_PARA_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_LITERAL_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_LITERAL_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_GUI_MENU_ITEM_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_GUI_MENU_ITEM_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_REPLACEABLE_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_REPLACEABLE_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_WARNING_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_WARNING_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_SOURCE_CLOSE = new TokenType.basic ("|]"); + GTKDOC_SOURCE_OPEN = new TokenType.basic ("[|"); + GTKDOC_EXAMPLE_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_EXAMPLE_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_TITLE_ELEMENT_CLOSE = new TokenType.basic (""); + GTKDOC_TITLE_ELEMENT_OPEN = new TokenType.basic (""); + GTKDOC_PROGRAMLISTING_ELEMENT_CLOSE = new TokenType.basic ("</programlisting>"); + GTKDOC_PROGRAMLISTING_ELEMENT_OPEN = new TokenType.basic ("<programlisting>"); + GTKDOC_VARIABLE_LIST_ELEMENT_CLOSE = new TokenType.basic ("</variablelist>"); + GTKDOC_VARIABLE_LIST_ELEMENT_OPEN = new TokenType.basic ("<variablelist>"); + GTKDOC_VARIABLE_LIST_ENTRY_ELEMENT_CLOSE = new TokenType.basic ("</varlistentry>"); + GTKDOC_VARIABLE_LIST_ENTRY_ELEMENT_OPEN = new TokenType.basic ("<varlistentry>"); + GTKDOC_TERM_ELEMENT_CLOSE = new TokenType.basic ("</term>"); + GTKDOC_TERM_ELEMENT_OPEN = new TokenType.basic ("<term>"); + GTKDOC_ENVAR_ELEMENT_CLOSE = new TokenType.basic ("</envar>"); + GTKDOC_ENVAR_ELEMENT_OPEN = new TokenType.basic ("<envar>"); + GTKDOC_OPTION_ELEMENT_CLOSE = new TokenType.basic ("</option>"); + GTKDOC_OPTION_ELEMENT_OPEN = new TokenType.basic ("<option>"); + GTKDOC_EMPHASIS_ELEMENT_CLOSE = new TokenType.basic ("</emphasis>"); + GTKDOC_EMPHASIS_ELEMENT_OPEN = new TokenType.basic ("<emphasis>"); + GTKDOC_FILENAME_ELEMENT_CLOSE = new TokenType.basic ("</filename>"); + GTKDOC_FILENAME_ELEMENT_OPEN = new TokenType.basic ("<filename>"); + GTKDOC_SIMPLELIST_ELEMENT_CLOSE = new TokenType.basic ("</simplelist>"); + GTKDOC_SIMPLELIST_ELEMENT_OPEN = new TokenType.basic ("<simplelist>"); + GTKDOC_MEMBER_ELEMENT_CLOSE = new TokenType.basic ("</member>"); + GTKDOC_MEMBER_ELEMENT_OPEN = new TokenType.basic ("<member>"); + GTKDOC_DOT = new TokenType.basic ("."); + GTKDOC_ANY_WORD = ANY_WORD; + GTKDOC_EOL = TokenType.EOL; + GTKDOC_SPACE = SPACE; + GTKDOC_EOF = EOF; + initialized = true; } } diff --git a/src/libvaladoc/settings.vala b/src/libvaladoc/settings.vala index eca9f1c4a..f53113673 100755 --- a/src/libvaladoc/settings.vala +++ b/src/libvaladoc/settings.vala @@ -46,7 +46,6 @@ public class Valadoc.Settings : Object { public string[] defines; public string[] vapi_directories; - public string[] docu_directories; } diff --git a/src/libvaladoc/taglets/tagletlink.vala b/src/libvaladoc/taglets/tagletlink.vala index a25976da9..ad77b4cc2 100755 --- a/src/libvaladoc/taglets/tagletlink.vala +++ b/src/libvaladoc/taglets/tagletlink.vala @@ -25,7 +25,7 @@ using Valadoc.Content; public class Valadoc.Taglets.Link : InlineTaglet { - public string symbol_name { private set; get; } + public string symbol_name { internal set; get; } private Api.Node _symbol; @@ -36,10 +36,19 @@ public class Valadoc.Taglets.Link : InlineTaglet { } public override void check (Api.Tree api_root, Api.Node container, ErrorReporter reporter, Settings settings) { - _symbol = api_root.search_symbol_str (container, symbol_name); + if (symbol_name.has_prefix ("c::")) { + _symbol_name = _symbol_name.offset (3); + _symbol = api_root.search_symbol_cstr (symbol_name); + if (_symbol != null) { + symbol_name = _symbol.name; + } + } else { + _symbol = api_root.search_symbol_str (container, symbol_name); + } + if (_symbol == null) { // TODO use ContentElement's source reference - reporter.simple_error ("%s does not exist".printf (symbol_name)); + reporter.simple_warning ("%s does not exist".printf (symbol_name)); } base.check (api_root, container, reporter, settings); diff --git a/src/libvaladoc/taglets/tagletparam.vala b/src/libvaladoc/taglets/tagletparam.vala index a4f16948e..d0c7eff68 100755 --- a/src/libvaladoc/taglets/tagletparam.vala +++ b/src/libvaladoc/taglets/tagletparam.vala @@ -25,7 +25,7 @@ using Valadoc.Content; public class Valadoc.Taglets.Param : InlineContent, Taglet, Block { - public string parameter_name { private set; get; } + public string parameter_name { internal set; get; } public Rule? get_parser_rule (Rule run_rule) { return Rule.seq ({ diff --git a/src/libvaladoc/taglets/tagletsee.vala b/src/libvaladoc/taglets/tagletsee.vala index 6610d9893..e1b3dc597 100755 --- a/src/libvaladoc/taglets/tagletsee.vala +++ b/src/libvaladoc/taglets/tagletsee.vala @@ -35,10 +35,19 @@ public class Valadoc.Taglets.See : ContentElement, Taglet, Block { } public override void check (Api.Tree api_root, Api.Node container, ErrorReporter reporter, Settings settings) { - symbol = api_root.search_symbol_str (container, symbol_name); + if (symbol_name.has_prefix ("c::")) { + symbol_name = symbol_name.offset (3); + symbol = api_root.search_symbol_cstr (symbol_name); + if (symbol != null) { + symbol_name = _symbol.name; + } + } else { + symbol = api_root.search_symbol_str (container, symbol_name); + } + if (symbol == null) { // TODO use ContentElement's source reference - reporter.simple_error ("%s does not exist".printf (symbol_name)); + reporter.simple_warning ("%s does not exist".printf (symbol_name)); } } diff --git a/src/valadoc/valadoc.vala b/src/valadoc/valadoc.vala index 2bdeb5ca3..8946dba0d 100755 --- a/src/valadoc/valadoc.vala +++ b/src/valadoc/valadoc.vala @@ -21,6 +21,7 @@ */ using GLib.Path; +using Valadoc.Importer; using Valadoc; using Config; using Gee; @@ -54,9 +55,10 @@ public class ValaDoc : Object { private static bool experimental_non_null = false; private static bool disable_dbus_transformation; private static string profile; - [CCode (array_length = false, array_null_terminated = true)] - private static string[] docu_directories; + private static string[] import_packages; + [CCode (array_length = false, array_null_terminated = true)] + private static string[] import_directories; [CCode (array_length = false, array_null_terminated = true)] private static string[] vapi_directories; [CCode (array_length = false, array_null_terminated = true)] @@ -73,11 +75,11 @@ public class ValaDoc : Object { { "enable-experimental-non-null", 0, 0, OptionArg.NONE, ref experimental_non_null, "Enable experimental enhancements for non-null types", null }, { "disable-dbus-transformation", 0, 0, OptionArg.NONE, ref disable_dbus_transformation, "Disable transformation of D-Bus member names", null }, { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." }, - { "docudir", 0, 0, OptionArg.FILENAME_ARRAY, ref docu_directories, "Look for external documentation in DIRECTORY", "DIRECTORY..." }, + { "importdir", 0, 0, OptionArg.FILENAME_ARRAY, ref import_directories, "Look for external documentation in DIRECTORY", "DIRECTORY..." }, { "profile", 0, 0, OptionArg.STRING, ref profile, "Use the given profile instead of the default", "PROFILE" }, - { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", "PACKAGE..." }, + { "import", 0, 0, OptionArg.STRING_ARRAY, ref import_packages, "Include binding for PACKAGE", "PACKAGE..." }, { "directory", 'o', 0, OptionArg.FILENAME, ref directory, "Output directory", "DIRECTORY" }, { "wiki", 0, 0, OptionArg.FILENAME, ref wikidirectory, "Wiki directory", "DIRECTORY" }, @@ -155,7 +157,6 @@ public class ValaDoc : Object { settings.basedir = basedir; settings.directory = directory; settings.vapi_directories = vapi_directories; - settings.docu_directories = docu_directories; settings.profile = profile; settings.defines = defines; @@ -163,19 +164,16 @@ public class ValaDoc : Object { string fulldirpath = ""; if (pluginpath == null) { fulldirpath = build_filename (Config.plugin_dir, "html"); - } - else if ( is_absolute (pluginpath ) == false) { + } else if (is_absolute (pluginpath ) == false) { // Test to see if the plugin exists in the expanded path and then fallback // to using the configured plugin directory string local_path = build_filename (Environment.get_current_dir(), pluginpath); if ( FileUtils.test(local_path, FileTest.EXISTS)) { fulldirpath = local_path; - } - else { + } else { fulldirpath = build_filename (Config.plugin_dir, pluginpath); } - } - else { + } else { fulldirpath = pluginpath; } @@ -211,6 +209,12 @@ public class ValaDoc : Object { return quit (reporter); } + var gir_importer = new GirDocumentationImporter (doctree, docparser, modules, settings); + doctree.import_documentation (gir_importer, import_packages, import_directories); + if (reporter.errors > 0) { + return quit (reporter); + } + modules.doclet.process (settings, doctree); return quit (reporter); }