]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
add gir documentation importer
authorFlorian Brosch <flo.brosch@gmail.com>
Thu, 19 Aug 2010 22:04:48 +0000 (00:04 +0200)
committerFlorian Brosch <flo.brosch@gmail.com>
Wed, 1 Sep 2010 17:32:13 +0000 (19:32 +0200)
16 files changed:
src/libvaladoc/Makefile.am
src/libvaladoc/api/package.vala
src/libvaladoc/api/tree.vala
src/libvaladoc/ctyperesolver.vala [moved from src/libvaladoc/importer/ctyperesolver.vala with 98% similarity]
src/libvaladoc/documentation/documentationparser.vala
src/libvaladoc/documentation/girdocumentationscanner.vala [new file with mode: 0644]
src/libvaladoc/html/htmlrenderer.vala
src/libvaladoc/importer/documentationimporter.vala
src/libvaladoc/importer/girdocumentationbuilder.vala [new file with mode: 0644]
src/libvaladoc/importer/girdocumentationimporter.vala [new file with mode: 0644]
src/libvaladoc/parser/tokentype.vala
src/libvaladoc/settings.vala
src/libvaladoc/taglets/tagletlink.vala
src/libvaladoc/taglets/tagletparam.vala
src/libvaladoc/taglets/tagletsee.vala
src/valadoc/valadoc.vala

index b7695767abb1f30e3a7aaa4de3d22643b891bd7e..d95cd941fa9f0911a8a602d76d4c37670c7a9bbd 100644 (file)
@@ -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 \
index 16ddd3c35c11c8ed5582bc1f232d785a24953f49..031ad409fea984f0a0f42c1577a151d25ae5462a 100644 (file)
@@ -22,6 +22,7 @@
 
 using Gee;
 using Valadoc.Content;
+using Valadoc.Importer;
 
 public class Valadoc.Api.Package : Node {
        private ArrayList<Vala.SourceFile> vfiles = new ArrayList<Vala.SourceFile> ();
@@ -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)) {
index 3a90dd5d8b44f6005d5aad29e7612fd73bee390c..7a3d698546ffced77904f1d002bd3d1d4713bc1b 100644 (file)
@@ -31,23 +31,18 @@ public class Valadoc.Api.Tree {
        private ArrayList<Package> packages = new ArrayList<Package>();
        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<Package> 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) {
similarity index 98%
rename from src/libvaladoc/importer/ctyperesolver.vala
rename to src/libvaladoc/ctyperesolver.vala
index 83af7791dce0fb23f0c3435464d05d5cade96eec..b9641bfd8dfc6b9d79a6b17d5cb7ed0f1c01d056 100644 (file)
@@ -24,7 +24,7 @@
 using Valadoc.Api;
 using Gee;
 
-public class Valadoc.Importer.CTypeResolver : Visitor {
+public class Valadoc.CTypeResolver : Visitor {
        private Map<string, Api.Node> nodes = new HashMap<string, Api.Node> ();
 
        public CTypeResolver (Api.Tree tree) {
index 869c5e0f0cc73dcb61d85146419d8e59f83c1331..0c735c94c2e1867cf41cfcdecaa42d7ea5d8cd64 100644 (file)
@@ -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 (file)
index 0000000..aed78db
--- /dev/null
@@ -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 <flo.brosch@gmail.com>
+ */
+
+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 '(': // "(<spaces>?)"
+                                       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;
+       }
+}
index 322dd61656865f1cad07399381f0654855d53ce2..66ef4d420b2293eb150b3eaa8b71c0addc9e4047 100755 (executable)
@@ -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);
                }
index d19f0196757964dec6fbde1e39e2687035855836..9cdf7b04fee033a205379404ec4c5d6533104dee 100644 (file)
 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 (file)
index 0000000..d502cf3
--- /dev/null
@@ -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 <flo.brosch@gmail.com>
+ */
+
+
+using Valadoc;
+using Gee;
+
+
+/**
+ * A documentation comment used by valadoc
+ */
+public class Valadoc.Importer.GirDocumentationBuilder : Vala.Comment {
+       private HashMap<string, Vala.Comment> _parameters = new HashMap<string, Vala.Comment> ();
+
+       public Map<string, Vala.Comment> 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 (file)
index 0000000..a76215b
--- /dev/null
@@ -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 <flo.brosch@gmail.com>
+ */
+
+// 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<string> type_cname_stack = new LinkedList<string> ();
+
+       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);
+               }
+       }
+}
+
index 86f87dc4f24c30a311522c5c5ba1f84c6dc9a956..bd53da9f6602fd42a1e3dbbccea2e1144c62551f 100644 (file)
@@ -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_XML_COMMENT_END = new TokenType.basic ("-->");
+                       GTKDOC_PARAM = new TokenType.basic ("<c-parameter>");
+                       GTKDOC_SYMBOL = new TokenType.basic ("<symbol>");
+                       GTKDOC_STRUCTNAME_ELEMENT_CLOSE = new TokenType.basic ("</structname>");
+                       GTKDOC_STRUCTNAME_ELEMENT_OPEN = new TokenType.basic ("<structname>");
+                       GTKDOC_LINK_ELEMENT_CLOSE = new TokenType.basic ("</link>");
+                       GTKDOC_LINK_ELEMENT_OPEN = new TokenType.basic ("<link>");
+                       GTKDOC_ITEMIZED_LIST_ELEMENT_CLOSE = new TokenType.basic ("</itemizedlist>");
+                       GTKDOC_ITEMIZED_LIST_ELEMENT_OPEN = new TokenType.basic ("<itemizedlist>");
+                       GTKDOC_LIST_ITEM_ELEMENT_CLOSE = new TokenType.basic ("</listitem>");
+                       GTKDOC_LIST_ITEM_ELEMENT_OPEN = new TokenType.basic ("<listitem>");
+                       GTKDOC_NOTE_ELEMENT_CLOSE = new TokenType.basic ("</note>");
+                       GTKDOC_NOTE_ELEMENT_OPEN = new TokenType.basic ("<note>");
+                       GTKDOC_PARA_ELEMENT_CLOSE = new TokenType.basic ("</para>");
+                       GTKDOC_PARA_ELEMENT_OPEN = new TokenType.basic ("<para>");
+                       GTKDOC_LITERAL_ELEMENT_CLOSE = new TokenType.basic ("</literal>");
+                       GTKDOC_LITERAL_ELEMENT_OPEN = new TokenType.basic ("<literal>");
+                       GTKDOC_GUI_MENU_ITEM_ELEMENT_CLOSE = new TokenType.basic ("</guimenuitem>");
+                       GTKDOC_GUI_MENU_ITEM_ELEMENT_OPEN = new TokenType.basic ("<guimenuitem>");
+                       GTKDOC_REPLACEABLE_ELEMENT_CLOSE = new TokenType.basic ("</replaceable>");
+                       GTKDOC_REPLACEABLE_ELEMENT_OPEN = new TokenType.basic ("<replaceable>");
+                       GTKDOC_WARNING_ELEMENT_CLOSE = new TokenType.basic ("</warning>");
+                       GTKDOC_WARNING_ELEMENT_OPEN = new TokenType.basic ("<warning>");
+                       GTKDOC_SOURCE_CLOSE = new TokenType.basic ("|]");
+                       GTKDOC_SOURCE_OPEN = new TokenType.basic ("[|");
+                       GTKDOC_EXAMPLE_ELEMENT_CLOSE = new TokenType.basic ("</example>");
+                       GTKDOC_EXAMPLE_ELEMENT_OPEN = new TokenType.basic ("<example>");
+                       GTKDOC_TITLE_ELEMENT_CLOSE = new TokenType.basic ("</title>");
+                       GTKDOC_TITLE_ELEMENT_OPEN = new TokenType.basic ("<title>");
+                       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;
                }
        }
index eca9f1c4a21d50ee87c564e6404353b5e9250e77..f53113673947fdf5d292f1a9cc59bcaa8355500f 100755 (executable)
@@ -46,7 +46,6 @@ public class Valadoc.Settings : Object {
 
        public string[] defines;
        public string[] vapi_directories;
-       public string[] docu_directories;
 }
 
 
index a25976da971113070694e5503f7af8920cd537c1..ad77b4cc23adb28926dd8536e6e519580d21a477 100755 (executable)
@@ -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);
index a4f16948effb91ada6125a480cdd107284e9a401..d0c7eff6887d7d9134c5960de2d61579732cf3c1 100755 (executable)
@@ -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 ({
index 6610d989306adcd2a2a5e0cb04d9e7f0a7709887..e1b3dc5978d0a97c9365a83e7b582d45d0bd9ffd 100755 (executable)
@@ -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));
                }
        }
 
index 2bdeb5ca3210365f4e24d2f704546b164337548d..8946dba0d6d67e5d515038dedcb86bb839fb06d7 100755 (executable)
@@ -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);
        }