[valadoc] gir: basic reading support
- From: Florian Brosch <flobrosch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [valadoc] gir: basic reading support
- Date: Fri, 27 Jan 2012 16:43:46 +0000 (UTC)
commit dc6edfc736bb630b805d0c3f7afc6ca4768e605c
Author: Florian Brosch <flo brosch gmail com>
Date: Mon Nov 28 17:11:49 2011 +0100
gir: basic reading support
src/doclets/htm/doclet.vala | 4 +-
src/driver/0.10.x/treebuilder.vala | 2 +-
src/driver/0.11.0/treebuilder.vala | 2 +-
src/driver/0.11.x/treebuilder.vala | 2 +-
src/driver/0.12.x/treebuilder.vala | 2 +-
src/driver/0.13.x/treebuilder.vala | 2 +-
src/driver/0.14.x/Makefile.am | 2 -
src/driver/0.14.x/treebuilder.vala | 2 +-
src/driver/0.16.x/treebuilder.vala | 45 +-
src/libvaladoc/Makefile.am | 3 +
src/libvaladoc/api/girsourcecomment.vala | 55 ++
src/libvaladoc/api/sourcefile.vala | 8 +-
src/libvaladoc/api/tree.vala | 14 +-
src/libvaladoc/ctyperesolver.vala | 97 ++-
.../documentation/documentationparser.vala | 11 +-
.../documentation/gtkdoccommentparser.vala | 942 ++++++++++++++++++++
.../documentation/gtkdoccommentscanner.vala | 644 +++++++++++++
.../importer/valadocdocumentationimporter.vala | 2 +-
src/libvaladoc/taglets/tagletlink.vala | 6 +-
src/libvaladoc/taglets/tagletsee.vala | 2 +-
20 files changed, 1802 insertions(+), 45 deletions(-)
---
diff --git a/src/doclets/htm/doclet.vala b/src/doclets/htm/doclet.vala
index 23dec68..7613f17 100755
--- a/src/doclets/htm/doclet.vala
+++ b/src/doclets/htm/doclet.vala
@@ -74,9 +74,9 @@ public class Valadoc.HtmlDoclet : Valadoc.Html.BasicDoclet {
string path = GLib.Path.build_filename ( this.settings.path, pkg_name );
var rt = DirUtils.create (path, 0777);
- rt = DirUtils.create (GLib.Path.build_filename ( path, "img" ), 0777);
+ rt = DirUtils.create (GLib.Path.build_filename (path, "img"), 0777);
- GLib.FileStream file = GLib.FileStream.open (GLib.Path.build_filename ( path, "index.htm" ), "w");
+ GLib.FileStream file = GLib.FileStream.open (GLib.Path.build_filename (path, "index.htm"), "w");
writer = new Html.MarkupWriter (file);
_renderer.set_writer (writer);
write_file_header (this.css_path, this.js_path, pkg_name);
diff --git a/src/driver/0.10.x/treebuilder.vala b/src/driver/0.10.x/treebuilder.vala
index c3543a5..6bc66b4 100644
--- a/src/driver/0.10.x/treebuilder.vala
+++ b/src/driver/0.10.x/treebuilder.vala
@@ -271,7 +271,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
}
private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) {
- SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ());
+ SourceFile file = new SourceFile (meta_data.package, source_file.get_relative_filename (), source_file.get_csource_filename ());
files.set (source_file, file);
meta_data.register_source_file (source_file);
diff --git a/src/driver/0.11.0/treebuilder.vala b/src/driver/0.11.0/treebuilder.vala
index 6ebc871..ba51196 100644
--- a/src/driver/0.11.0/treebuilder.vala
+++ b/src/driver/0.11.0/treebuilder.vala
@@ -273,7 +273,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
}
private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) {
- SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ());
+ SourceFile file = new SourceFile (meta_data.package, source_file.get_relative_filename (), source_file.get_csource_filename ());
files.set (source_file, file);
meta_data.register_source_file (source_file);
diff --git a/src/driver/0.11.x/treebuilder.vala b/src/driver/0.11.x/treebuilder.vala
index f297a1e..130a3ca 100644
--- a/src/driver/0.11.x/treebuilder.vala
+++ b/src/driver/0.11.x/treebuilder.vala
@@ -224,7 +224,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
}
private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) {
- SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ());
+ SourceFile file = new SourceFile (meta_data.package, source_file.get_relative_filename (), source_file.get_csource_filename ());
files.set (source_file, file);
meta_data.register_source_file (source_file);
diff --git a/src/driver/0.12.x/treebuilder.vala b/src/driver/0.12.x/treebuilder.vala
index 455a0e6..ac91568 100644
--- a/src/driver/0.12.x/treebuilder.vala
+++ b/src/driver/0.12.x/treebuilder.vala
@@ -273,7 +273,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
}
private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) {
- SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ());
+ SourceFile file = new SourceFile (meta_data.package, source_file.get_relative_filename (), source_file.get_csource_filename ());
files.set (source_file, file);
meta_data.register_source_file (source_file);
diff --git a/src/driver/0.13.x/treebuilder.vala b/src/driver/0.13.x/treebuilder.vala
index 9739d92..9cfac52 100644
--- a/src/driver/0.13.x/treebuilder.vala
+++ b/src/driver/0.13.x/treebuilder.vala
@@ -392,7 +392,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
}
private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) {
- SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ());
+ SourceFile file = new SourceFile (meta_data.package, source_file.get_relative_filename (), source_file.get_csource_filename ());
files.set (source_file, file);
meta_data.register_source_file (source_file);
diff --git a/src/driver/0.14.x/Makefile.am b/src/driver/0.14.x/Makefile.am
index a2c24a1..b8bb596 100755
--- a/src/driver/0.14.x/Makefile.am
+++ b/src/driver/0.14.x/Makefile.am
@@ -2,8 +2,6 @@ NULL =
VERSIONED_VAPI_DIR=`pkg-config libvala-0.14 --variable vapidir`
-
-
AM_CFLAGS = -g \
-DPACKAGE_ICONDIR=\"$(datadir)/valadoc/icons/\" \
-I ../../libvaladoc/ \
diff --git a/src/driver/0.14.x/treebuilder.vala b/src/driver/0.14.x/treebuilder.vala
index 691fadd..daff9b2 100644
--- a/src/driver/0.14.x/treebuilder.vala
+++ b/src/driver/0.14.x/treebuilder.vala
@@ -326,7 +326,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
}
private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) {
- SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ());
+ SourceFile file = new SourceFile (meta_data.package, source_file.get_relative_filename (), source_file.get_csource_filename ());
files.set (source_file, file);
meta_data.register_source_file (source_file);
diff --git a/src/driver/0.16.x/treebuilder.vala b/src/driver/0.16.x/treebuilder.vala
index 7d52395..512d7b1 100644
--- a/src/driver/0.16.x/treebuilder.vala
+++ b/src/driver/0.16.x/treebuilder.vala
@@ -82,7 +82,11 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
foreach (Vala.Comment c in vns.get_comments()) {
if (c.source_reference.file == vns.source_reference.file) {
Vala.SourceReference pos = c.source_reference;
- comment = new SourceComment (c.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column);
+ if (c is Vala.GirComment) {
+ comment = new GirSourceComment (c.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column);
+ } else {
+ comment = new SourceComment (c.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column);
+ }
break;
}
}
@@ -290,7 +294,24 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
if (comment != null) {
Vala.SourceReference pos = comment.source_reference;
SourceFile file = files.get (pos.file);
- return new SourceComment (comment.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column);
+ if (comment is Vala.GirComment) {
+ var tmp = new GirSourceComment (comment.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column);
+ if (((Vala.GirComment) comment).return_content != null) {
+ Vala.SourceReference return_pos = ((Vala.GirComment) comment).return_content.source_reference;
+ tmp.return_comment = new SourceComment (((Vala.GirComment) comment).return_content.content, file, return_pos.first_line, return_pos.first_column, return_pos.last_line, return_pos.last_column);
+ }
+
+ Vala.MapIterator<string, Vala.Comment> it = ((Vala.GirComment) comment).parameter_iterator ();
+ while (it.next ()) {
+ Vala.Comment vala_param = it.get_value ();
+ Vala.SourceReference param_pos = vala_param.source_reference;
+ var param_comment = new SourceComment (vala_param.content, file, param_pos.first_line, param_pos.first_column, param_pos.last_line, param_pos.last_column);
+ tmp.add_parameter_content (it.get_key (), param_comment);
+ }
+ return tmp;
+ } else {
+ return new SourceComment (comment.content, file, pos.first_line, pos.first_column, pos.last_line, pos.last_column);
+ }
}
return null;
@@ -326,7 +347,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
}
private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) {
- SourceFile file = new SourceFile (source_file.get_relative_filename (), source_file.get_csource_filename ());
+ SourceFile file = new SourceFile (meta_data.package, source_file.get_relative_filename (), source_file.get_csource_filename ());
files.set (source_file, file);
meta_data.register_source_file (source_file);
@@ -340,7 +361,6 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
}
SourceFile? file = files.get (source_ref.file);
-
assert (file != null);
return file;
}
@@ -534,6 +554,11 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
// Vala tree creation:
//
+ private string get_package_name (string path) {
+ string file_name = Path.get_basename (path);
+ return file_name.substring (0, file_name.last_index_of_char ('.'));
+ }
+
private bool add_package (Vala.CodeContext context, string pkg) {
// ignore multiple occurences of the same package
if (context.has_package (pkg)) {
@@ -636,8 +661,7 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
context.add_source_file (source_file);
} else if (source.has_suffix (".vapi") || source.has_suffix (".gir")) {
- string file_name = Path.get_basename (source);
- file_name = file_name.substring (0, file_name.last_index_of_char ('.'));
+ string file_name = get_package_name (source);
var vfile = new Vala.SourceFile (context, Vala.SourceFileType.PACKAGE, rpath);
context.add_source_file (vfile);
@@ -1126,6 +1150,15 @@ public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
return null;
}
+ // TODO: Register all packages here
+ // register packages included by gir-files
+ foreach (Vala.SourceFile vfile in context.get_source_files ()) {
+ if (vfile.file_type == Vala.SourceFileType.PACKAGE && vfile.get_nodes ().size > 0 && files.contains (vfile) == false) {
+ Package vdpkg = new Package (get_package_name (vfile.filename), true, null);
+ register_source_file (register_package (vdpkg), vfile);
+ }
+ }
+
context.accept(this);
return (reporter.errors == 0)? tree : null;
diff --git a/src/libvaladoc/Makefile.am b/src/libvaladoc/Makefile.am
index 9fba548..14a8bfa 100755
--- a/src/libvaladoc/Makefile.am
+++ b/src/libvaladoc/Makefile.am
@@ -36,11 +36,14 @@ libvaladoc_la_VALASOURCES = \
documentation/documentationparser.vala \
documentation/wiki.vala \
documentation/wikiscanner.vala \
+ documentation/gtkdoccommentparser.vala \
+ documentation/gtkdoccommentscanner.vala \
importer/documentationimporter.vala \
importer/valadocdocumentationimporter.vala \
importer/valadocdocumentationimporterscanner.vala \
api/symbolaccessibility.vala \
api/sourcecomment.vala \
+ api/girsourcecomment.vala \
api/attributeargument.vala \
api/attribute.vala \
api/array.vala \
diff --git a/src/libvaladoc/api/girsourcecomment.vala b/src/libvaladoc/api/girsourcecomment.vala
new file mode 100644
index 0000000..e554092
--- /dev/null
+++ b/src/libvaladoc/api/girsourcecomment.vala
@@ -0,0 +1,55 @@
+/* sourcecomment.vala
+ *
+ * Copyright (C) 2011 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Gee;
+
+
+/**
+ * A documentation comment used by valadoc
+ */
+public class Valadoc.Api.GirSourceComment : SourceComment {
+ private Map<string, SourceComment> parameters = new HashMap<string, SourceComment> ();
+
+ public SourceComment return_comment { set; get; }
+
+ public MapIterator<string, SourceComment> parameter_iterator () {
+ return parameters.map_iterator ();
+ }
+
+ public void add_parameter_content (string param_name, SourceComment comment) {
+ this.parameters.set (param_name, comment);
+ }
+
+ public SourceComment? get_parameter_comment (string param_name) {
+ if (parameters == null) {
+ return null;
+ }
+
+ return parameters.get (param_name);
+ }
+
+ public GirSourceComment (string content, SourceFile file, int first_line, int first_column, int last_line, int last_column) {
+ base (content, file, first_line, first_column, last_line, last_column);
+ }
+}
+
diff --git a/src/libvaladoc/api/sourcefile.vala b/src/libvaladoc/api/sourcefile.vala
index 6ac6720..09b821f 100644
--- a/src/libvaladoc/api/sourcefile.vala
+++ b/src/libvaladoc/api/sourcefile.vala
@@ -24,6 +24,11 @@
* Represents a source file
*/
public class Valadoc.Api.SourceFile : Object {
+ public Package package {
+ private set;
+ get;
+ }
+
public string relative_path {
private set;
get;
@@ -38,9 +43,10 @@ public class Valadoc.Api.SourceFile : Object {
return Path.get_basename (relative_path);
}
- public SourceFile (string relative_path, string? relative_c_path) {
+ public SourceFile (Package package, string relative_path, string? relative_c_path) {
this.relative_c_path = relative_c_path;
this.relative_path = relative_path;
+ this.package = package;
}
}
diff --git a/src/libvaladoc/api/tree.vala b/src/libvaladoc/api/tree.vala
index bddb1bf..1298d06 100755
--- a/src/libvaladoc/api/tree.vala
+++ b/src/libvaladoc/api/tree.vala
@@ -143,21 +143,25 @@ public class Valadoc.Api.Tree {
// absolute
foreach (Package package in packages) {
// search in root namespace
- node = search_relative_to (package.find_by_name (""), path);
- if (node != null) {
- return node;
+
+ Node? global = package.find_by_name ("");
+ if (global != null) {
+ node = search_relative_to (global, path);
+ if (node != null) {
+ return node;
+ }
}
}
return null;
}
- public Node? search_symbol_cstr (string cname) {
+ public Node? search_symbol_cstr (Node? element, string cname) {
if (_cresolver == null) {
_cresolver = new CTypeResolver (this);
}
- return _cresolver.resolve_symbol (cname);
+ return _cresolver.resolve_symbol (element, cname);
}
public Node? search_symbol_str (Node? element, string symname) {
diff --git a/src/libvaladoc/ctyperesolver.vala b/src/libvaladoc/ctyperesolver.vala
index 87fc6f3..a7adac8 100755
--- a/src/libvaladoc/ctyperesolver.vala
+++ b/src/libvaladoc/ctyperesolver.vala
@@ -34,40 +34,99 @@ public class Valadoc.CTypeResolver : Visitor {
tree.accept (this);
}
+
+ private string convert_array_to_camelcase (string[] elements) {
+ StringBuilder builder = new StringBuilder ();
+
+ foreach (string element in elements) {
+ builder.append_c (((char[])element)[0].toupper ());
+ builder.append (element.next_char ().down ());
+ }
+
+ return (owned) builder.str;
+ }
+
+ private bool is_capitalized_and_underscored (string name) {
+ unowned string pos;
+
+ unichar c = name.get_char ();
+
+
+ if (c < 'A' || c > 'Z') {
+ return false;
+ }
+
+ bool last_was_underscore = false;
+ for (c = (pos = name).get_char (); c != '\0' ; c = (pos = pos.next_char ()).get_char ()) {
+ if ((c != '_' && !(c >= 'A' && c <= 'Z')) || (last_was_underscore && c == '_')) {
+ return false;
+ }
+
+ last_was_underscore = (c == '_');
+ }
+
+ return !last_was_underscore;
+ }
+
+ private string? translate_cname (string name) {
+ if (is_capitalized_and_underscored (name)) {
+ string[] segments = name.split ("_");
+ unowned string last_segment = segments[segments.length - 1];
+ if (last_segment == "ERROR") {
+ } else if (last_segment == "TYPE") {
+ segments.resize (segments.length - 1);
+ } else {
+ return null;
+ }
+
+ return convert_array_to_camelcase (segments);
+ }
+
+ int length = name.length;
+ if (length > 5 && name.has_suffix ("Iface")) {
+ return name.substring (0, length - 5);
+ } else if (length > 5 && name.has_suffix ("Class")) {
+ return name.substring (0, length - 5);
+ }
+
+ return null;
+ }
+
/**
* Resolves symbols by C-names
*
* @param name a C-name
* @return the resolved node or null
*/
- public Api.Node? resolve_symbol (string _name) {
+ public Api.Node? resolve_symbol (Api.Node? element, string _name) {
string name = _name.replace ("-", "_");
+ if (element != null && _name.has_prefix (":")) {
+ Item parent = element;
+ while (parent != null && !(parent is Class || parent is Interface)) {
+ parent = parent.parent;
+ }
+
+ if (parent is Class && ((Class) parent).get_cname () != null) {
+ name = ((Class) parent).get_cname () + name;
+ } else if (parent is Interface && ((Interface) parent).get_cname () != null) {
+ name = ((Interface) parent).get_cname () + name;
+ } else {
+ return null;
+ }
+
+ }
+
Api.Node? node = nodes.get (name);
if (node != null) {
return node;
}
- var name_length = name.length;
- if (name_length > 5 && name.has_suffix ("Class")) {
- return nodes.get (name.substring (0, name_length - 5));
+ string? alternative = translate_cname (_name);
+ if (alternative != null) {
+ return nodes.get (alternative);
}
- /*
- for (int i = 0; name[i] != '\0' ; i++) {
- if (name[i] == ':' && name[i+1] == ':') {
- string first_part = name.substring (0, i - 1);
- string second_part = name.substring (i + 2, -1);
- string nick = first_part + ":" + second_part;
- return nodes.get (nick);
- } else if (name[i] == ':') {
- string first_part = name.substring (0, i);
- string second_part = name.substring (i + 1, -1);
- string nick = first_part + "::" + second_part;
- return nodes.get (nick);
- }
- } */
-
return null;
}
diff --git a/src/libvaladoc/documentation/documentationparser.vala b/src/libvaladoc/documentation/documentationparser.vala
index 92aa698..b2a96f0 100755
--- a/src/libvaladoc/documentation/documentationparser.vala
+++ b/src/libvaladoc/documentation/documentationparser.vala
@@ -43,9 +43,13 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
_comment_parser = new Parser (_settings, _comment_scanner, _reporter);
_comment_scanner.set_parser (_comment_parser);
+ gtkdoc_parser = new Gtkdoc.Parser (settings, reporter, tree, modules);
+
init_valadoc_rules ();
}
+ private Gtkdoc.Parser gtkdoc_parser;
+
private Settings _settings;
private ErrorReporter _reporter;
private Api.Tree _tree;
@@ -61,7 +65,12 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
private Scanner _scanner;
public Comment? parse (Api.Node element, Api.SourceComment comment) {
- return parse_comment_str (element, comment.content, comment.file.get_name (), comment.first_line, comment.first_column);
+ if (comment is Api.GirSourceComment) {
+ Comment doc_comment = gtkdoc_parser.parse (element, (Api.GirSourceComment) comment);
+ return doc_comment;
+ } else {
+ return parse_comment_str (element, comment.content, comment.file.get_name (), comment.first_line, comment.first_column);
+ }
}
public Comment? parse_comment_str (Api.Node element, string content, string filename, int first_line, int first_column) {
diff --git a/src/libvaladoc/documentation/gtkdoccommentparser.vala b/src/libvaladoc/documentation/gtkdoccommentparser.vala
new file mode 100644
index 0000000..48e5227
--- /dev/null
+++ b/src/libvaladoc/documentation/gtkdoccommentparser.vala
@@ -0,0 +1,942 @@
+/* gtkcommentparser.vala
+ *
+ * Copyright (C) 2011 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Valadoc.Content;
+using Valadoc.Gtkdoc;
+using Gee;
+
+
+
+public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator {
+ private Scanner scanner = new Scanner ();
+ private Token current;
+
+ private LinkedList<string> stack = new LinkedList<string> ();
+
+ private ContentFactory factory;
+ private ErrorReporter reporter;
+ private Settings settings;
+ private Api.Tree tree;
+
+ private bool show_warnings;
+ private Api.SourceComment comment;
+
+ private string[]? comment_lines;
+
+ private void reset (Api.SourceComment comment) {
+ this.scanner.reset (comment.content);
+ this.show_warnings = !comment.file.package.is_package || settings.verbose;
+ this.comment_lines = null;
+ this.comment = comment;
+ current = null;
+ stack.clear ();
+ }
+
+ private void report_unexpected_token (Token got, string expected) {
+ if (this.show_warnings) {
+ return ;
+ }
+
+ int startpos = (got.line == 0)? comment.first_column + got.first_column : got.first_column;
+ int endpos = (got.line == 0)? comment.first_column + got.last_column : got.last_column;
+
+ if (this.comment_lines == null) {
+ this.comment_lines = this.comment.content.split ("\n");
+ }
+
+ this.reporter.warning (this.comment.file.get_name (), comment.first_line + got.line, startpos + 1, endpos + 1, this.comment_lines[got.line], "Unexpected Token: %s (Expected: %s)", got.to_string (), expected);
+ }
+
+ public Parser (Settings settings, ErrorReporter reporter, Api.Tree tree, ModuleLoader modules) {
+ this.factory = new ContentFactory (settings, this, modules);
+ this.reporter = reporter;
+ this.settings = settings;
+ this.tree = tree;
+ }
+
+ public Comment? parse (Api.Node element, Api.GirSourceComment gir_comment) {
+ Comment? comment = this.parse_main_content (gir_comment);
+ if (comment == null) {
+ return null;
+ }
+
+ if (gir_comment.return_comment != null) {
+ Taglet? taglet = this.parse_block_taglet (gir_comment.return_comment, "return");
+ if (taglet == null) {
+ return null;
+ }
+
+ comment.taglets.add (taglet);
+ }
+
+ MapIterator<string, Api.SourceComment> iter = gir_comment.parameter_iterator ();
+ for (bool has_next = iter.first (); has_next; has_next = iter.next ()) {
+ Taglets.Param? taglet = this.parse_block_taglet (iter.get_value (), "param") as Taglets.Param;
+ if (taglet == null) {
+ return null;
+ }
+
+ taglet.parameter_name = iter.get_key ();
+ comment.taglets.add (taglet);
+ }
+
+ comment.check (tree, element, reporter, settings);
+ return comment;
+ }
+
+ private Taglet? parse_block_taglet (Api.SourceComment gir_comment, string taglet_name) {
+ this.reset (gir_comment);
+ current = null;
+ next ();
+
+ parse_docbook_spaces (false);
+ var ic = parse_inline_content ();
+ parse_docbook_spaces (false);
+
+ if (current.type != TokenType.EOF) {
+ this.report_unexpected_token (current, "<EOF>");
+ return null;
+ }
+
+ InlineContent? taglet = factory.create_taglet (taglet_name) as InlineContent;
+ assert (taglet != null);
+ taglet.content.add (ic);
+ return taglet as Taglet;
+ }
+
+ private Comment? parse_main_content (Api.GirSourceComment gir_comment) {
+ this.reset (gir_comment);
+ current = null;
+
+ next ();
+
+ Token tmp = null;
+ parse_docbook_spaces (false);
+
+ Comment comment = factory.create_comment ();
+ while (current.type != TokenType.EOF && tmp != current) {
+ tmp = current;
+ var ic = parse_inline_content ();
+ if (ic != null && ic.content.size > 0) {
+ Paragraph p = factory.create_paragraph ();
+ p.content.add (ic);
+ comment.content.add (p);
+ }
+
+ var bc = parse_block_content ();
+ if (bc != null && bc.size > 0) {
+ comment.content.add_all (bc);
+ }
+ }
+
+ if (current.type != TokenType.EOF) {
+ this.report_unexpected_token (current, "<INLINE|BLOCK>");
+ return null;
+ }
+
+ return comment;
+ }
+
+
+
+ //
+ // Common:
+ //
+
+ private Token next () {
+ current = scanner.next ();
+ return current;
+ }
+
+ private bool ignore_current_xml_close () {
+ if (current.type != TokenType.XML_CLOSE) {
+ return false;
+ }
+
+ string name = current.content;
+ if ((name in stack) == false) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool check_xml_open_tag (string tagname) {
+ if (current.type == TokenType.XML_OPEN && current.content != tagname) {
+ return false;
+ }
+
+ stack.offer_head (tagname);
+ return true;
+ }
+
+ private bool check_xml_close_tag (string tagname) {
+ if (current.type == TokenType.XML_CLOSE && current.content != tagname) {
+ return false;
+ }
+
+ if (stack.poll_head () == tagname) {
+ stack.peek_head ();
+ }
+
+ return true;
+ }
+
+
+ private void parse_docbook_spaces (bool accept_paragraphs = true) {
+ while (true) {
+ if (current.type == TokenType.SPACE) {
+ next ();
+ } else if (current.type == TokenType.NEWLINE) {
+ next ();
+ } else if (accept_paragraphs && current.type == TokenType.GTKDOC_PARAGRAPH) {
+ next ();
+ } else {
+ break;
+ }
+ }
+ }
+
+
+
+ //
+ // Rules, Ground:
+ //
+
+ private Inline? parse_docbook_link_tempalte (string tagname) {
+ if (!check_xml_open_tag (tagname)) {
+ this.report_unexpected_token (current, "<%s>".printf (tagname));
+ return null;
+ }
+
+ StringBuilder builder = new StringBuilder ();
+ string url = current.attributes.get ("linkend");
+ next ();
+
+ // TODO: check xml
+ while (current.type != TokenType.XML_CLOSE && current.content != tagname && current.type != TokenType.EOF) {
+ if (current.type == TokenType.XML_OPEN) {
+ } else if (current.type == TokenType.XML_CLOSE) {
+ } else if (current.type == TokenType.XML_COMMENT) {
+ } else {
+ builder.append (current.content);
+ }
+
+ next ();
+ }
+
+ var link = factory.create_link ();
+ link.url = url;
+
+ if (builder.len == 0) {
+ link.content.add (factory.create_text (url));
+ } else {
+ link.content.add (factory.create_text (builder.str));
+ }
+
+ if (!check_xml_close_tag (tagname)) {
+ this.report_unexpected_token (current, "</%s>".printf (tagname));
+ return link;
+ }
+
+ next ();
+ return link;
+ }
+
+ private InlineTaglet? parse_symbol_link (string tagname) {
+ if (!check_xml_open_tag (tagname)) {
+ this.report_unexpected_token (current, "<%s>".printf (tagname));
+ return null;
+ }
+
+ if (next ().type == TokenType.SPACE) {
+ next ();
+ }
+
+ InlineTaglet? taglet = null;
+
+ if (current.type == TokenType.GTKDOC_FUNCTION || current.type == TokenType.GTKDOC_CONST || current.type == TokenType.GTKDOC_TYPE || current.type == TokenType.WORD || current.type == TokenType.GTKDOC_PROPERTY || current.type == TokenType.GTKDOC_SIGNAL) {
+ taglet = this.create_type_link (current.content) as InlineTaglet;
+ assert (taglet != null);
+ }
+
+ if (next ().type == TokenType.SPACE) {
+ next ();
+ }
+
+ if (!check_xml_close_tag (tagname)) {
+ this.report_unexpected_token (current, "</%s>".printf (tagname));
+ return taglet;
+ }
+
+ next ();
+ return taglet;
+ }
+
+ private void parse_anchor () {
+ if (!check_xml_open_tag ("anchor")) {
+ this.report_unexpected_token (current, "<anchor>");
+ return;
+ }
+
+ string id = current.attributes.get ("id");
+ next ();
+ // TODO register xref
+
+ if (!check_xml_close_tag ("anchor")) {
+ this.report_unexpected_token (current, "</anchor>");
+ return;
+ }
+
+ next ();
+ }
+
+ private void parse_xref () {
+ if (!check_xml_open_tag ("xref")) {
+ this.report_unexpected_token (current, "<xref>");
+ return;
+ }
+
+ string linkend = current.attributes.get ("linkend");
+ next ();
+ // TODO register xref
+
+ if (!check_xml_close_tag ("xref")) {
+ this.report_unexpected_token (current, "</xref>");
+ return;
+ }
+
+ next ();
+ }
+
+ private Run? parse_highlighted_template (string tag_name, Run.Style style) {
+ if (!check_xml_open_tag (tag_name)) {
+ this.report_unexpected_token (current, "<%s>".printf (tag_name));
+ return null;
+ }
+
+ next ();
+ Run run = parse_inline_content ();
+ if (run.style != Run.Style.NONE && run.style != style) {
+ Run tmp = factory.create_run (style);
+ tmp.content.add (run);
+ run = tmp;
+ } else {
+ run.style = style;
+ }
+
+ if (!check_xml_close_tag (tag_name)) {
+ this.report_unexpected_token (current, "</%s>".printf (tag_name));
+ return run;
+ }
+
+ next ();
+ return run;
+ }
+
+ private ListItem? parse_docbook_listitem () {
+ if (!check_xml_open_tag ("listitem")) {
+ this.report_unexpected_token (current, "<listitem>");
+ return null;
+ }
+
+ next ();
+
+ ListItem item = factory.create_list_item ();
+
+ while (current.type != TokenType.XML_CLOSE && current.type != TokenType.EOF) {
+ if (current.type == TokenType.XML_OPEN && current.content == "para") {
+ foreach (Block block in parse_docbook_para ()) {
+ if (block is Paragraph) {
+ if (item.content.size > 0) {
+ item.content.add (factory.create_text ("\n"));
+ }
+
+ item.content.add_all (((Paragraph) block).content);
+ } else {
+ // TODO: extend me
+ this.report_unexpected_token (current, "<para>|</listitem>");
+ return null;
+ }
+ }
+ } else {
+ Token tmp_t = current;
+ parse_inline_content ();
+ if (tmp_t == current) {
+ break;
+ }
+ }
+ }
+
+ if (!check_xml_close_tag ("listitem")) {
+ this.report_unexpected_token (current, "</listitem>");
+ return item;
+ }
+
+ next ();
+ return item;
+ }
+
+ private LinkedList<Block>? parse_docbook_information_box_template (string tagname) {
+ if (!check_xml_open_tag (tagname)) {
+ this.report_unexpected_token (current, "<%s>".printf (tagname));
+ return null;
+ }
+
+ next ();
+ parse_docbook_spaces ();
+
+ LinkedList<Block> content = new LinkedList<Block> ();
+
+ var header_run = factory.create_run (Run.Style.BOLD);
+ header_run.content.add (factory.create_text ("Note:"));
+
+ while (current.type != TokenType.XML_CLOSE && current.type != TokenType.EOF) {
+ if (current.type == TokenType.XML_OPEN && current.content == "para") {
+ var paragraphs = parse_docbook_para ();
+ if (header_run != null) {
+ content.add_all (paragraphs);
+ } else {
+ Paragraph fp = paragraphs.first ();
+ fp.content.insert (0, factory.create_text (" "));
+ fp.content.insert (0, header_run);
+ }
+ } else {
+ Token tmp_t = current;
+
+ Run? inline_run = parse_inline_content ();
+ Paragraph p = factory.create_paragraph ();
+
+ if (content != null) {
+ p.content.add (header_run);
+ p.content.add (factory.create_text (" "));
+ header_run = null;
+ }
+
+ p.content.add (inline_run);
+ content.add (p);
+
+ if (tmp_t == current) {
+ break;
+ }
+ }
+ }
+
+ //parse_block_content ();
+ parse_docbook_spaces ();
+
+ if (!check_xml_close_tag (tagname)) {
+ this.report_unexpected_token (current, "</%s>".printf (tagname));
+ return content;
+ }
+
+ next ();
+ return content;
+ }
+
+ private LinkedList<Block>? parse_docbook_note () {
+ return parse_docbook_information_box_template ("note");
+ }
+
+ private LinkedList<Block>? parse_docbook_warning () {
+ return parse_docbook_information_box_template ("warning");
+ }
+
+ private Content.List? parse_docbook_itemizedlist () {
+ if (!check_xml_open_tag ("itemizedlist")) {
+ this.report_unexpected_token (current, "<itemizedlist>");
+ return null;
+ }
+
+ next ();
+
+ parse_docbook_spaces ();
+
+ Content.List list = factory.create_list ();
+ list.bullet = Content.List.Bullet.UNORDERED;
+
+ while (current.type == TokenType.XML_OPEN) {
+ if (current.content == "listitem") {
+ list.items.add (parse_docbook_listitem ());
+ } else {
+ break;
+ }
+
+ parse_docbook_spaces ();
+ }
+
+ if (!check_xml_close_tag ("itemizedlist")) {
+ this.report_unexpected_token (current, "</itemizedlist>");
+ return list;
+ }
+
+ next ();
+ return list;
+ }
+
+ private Paragraph? parse_gtkdoc_paragraph () {
+ if (current.type != TokenType.GTKDOC_PARAGRAPH) {
+ this.report_unexpected_token (current, "<GTKDOC-PARAGRAPH>");
+ return null;
+ }
+
+ next ();
+
+ Paragraph p = factory.create_paragraph ();
+
+ Run? run = parse_inline_content ();
+ p.content.add (run);
+ return p;
+ }
+
+ private LinkedList<Paragraph>? parse_docbook_para () {
+ if (!check_xml_open_tag ("para")) {
+ this.report_unexpected_token (current, "<para>");
+ return null;
+ }
+
+ next ();
+
+ LinkedList<Paragraph> content = new LinkedList<Paragraph> ();
+
+ Token tmp = null;
+ while (tmp != current) {
+ tmp = current;
+ parse_docbook_spaces ();
+
+ Run? run = parse_inline_content ();
+ if (run != null && run.content.size > 0) {
+ Paragraph p = factory.create_paragraph ();
+ p.content.add (run);
+ content.add (p);
+ continue;
+ }
+
+ LinkedList<Block> lst = parse_block_content ();
+ if (lst != null && run.content.size > 0) {
+ content.add_all (lst);
+ continue;
+ }
+ }
+
+ if (!check_xml_close_tag ("para")) {
+ this.report_unexpected_token (current, "</para>");
+ return content;
+ }
+
+ next ();
+ return content;
+ }
+
+ private Paragraph? parse_gtkdoc_source () {
+ if (current.type != TokenType.GTKDOC_SOURCE_OPEN) {
+ this.report_unexpected_token (current, "|[");
+ return null;
+ }
+
+
+ StringBuilder builder = new StringBuilder ();
+
+ for (next (); current.type != TokenType.EOF && current.type != TokenType.GTKDOC_SOURCE_CLOSE; next ()) {
+ if (current.type == TokenType.WORD) {
+ builder.append (current.content);
+ } else if (current.type != TokenType.XML_COMMENT) {
+ builder.append_len (current.start, current.length);
+ }
+ }
+
+ SourceCode src = factory.create_source_code ();
+ src.language = SourceCode.Language.C;
+ src.code = builder.str;
+
+ Paragraph p = factory.create_paragraph ();
+ p.content.add (src);
+
+ if (current.type != TokenType.GTKDOC_SOURCE_CLOSE) {
+ this.report_unexpected_token (current, "|]");
+ return p;
+ }
+
+ next ();
+ return p;
+ }
+
+ private Paragraph? parse_docbook_title () {
+ if (!check_xml_open_tag ("title")) {
+ this.report_unexpected_token (current, "<title>");
+ return null;
+ }
+
+ next ();
+
+ Paragraph p = factory.create_paragraph ();
+ Run content = parse_inline_content ();
+ content.content.add (factory.create_text (":"));
+ content.style = Run.Style.BOLD;
+ p.content.add (content);
+
+ if (!check_xml_close_tag ("title")) {
+ this.report_unexpected_token (current, "</title>");
+ return p;
+ }
+
+ next ();
+ return p;
+ }
+
+ private Embedded? parse_docbook_inlinegraphic () {
+ if (!check_xml_open_tag ("inlinegraphic")) {
+ this.report_unexpected_token (current, "<inlinegraphic>");
+ return null;
+ }
+
+ Embedded e = factory.create_embedded ();
+ e.url = current.attributes.get ("fileref");
+
+ next ();
+ parse_docbook_spaces ();
+
+ if (!check_xml_close_tag ("inlinegraphic")) {
+ this.report_unexpected_token (current, "</inlinegrapic>");
+ return e;
+ }
+
+ next ();
+ return e;
+ }
+
+ private Paragraph? parse_docbook_programlisting () {
+ if (!check_xml_open_tag ("programlisting")) {
+ this.report_unexpected_token (current, "<programlisting>");
+ return null;
+ }
+
+ StringBuilder builder = new StringBuilder ();
+
+ for (next (); current.type != TokenType.EOF && !(current.type == TokenType.XML_CLOSE && current.content == "programlisting"); next ()) {
+ if (current.type == TokenType.WORD) {
+ builder.append (current.content);
+ } else if (current.type != TokenType.XML_COMMENT) {
+ builder.append_len (current.start, current.length);
+ }
+ }
+
+ SourceCode src = factory.create_source_code ();
+ src.language = SourceCode.Language.C;
+ src.code = builder.str;
+
+ Paragraph p = factory.create_paragraph ();
+ p.content.add (src);
+
+ if (!check_xml_close_tag ("programlisting")) {
+ this.report_unexpected_token (current, "</programlisting>");
+ return p;
+ }
+
+ next ();
+ return p;
+ }
+
+ private LinkedList<Block>? parse_docbook_informalexample () {
+ if (!check_xml_open_tag ("informalexample")) {
+ this.report_unexpected_token (current, "<informalexample>");
+ return null;
+ }
+
+ next ();
+
+ parse_docbook_spaces ();
+
+ LinkedList<Block> content = new LinkedList<Block> ();
+
+ if (current.type == TokenType.XML_OPEN && current.content == "title") {
+ append_block_content_not_null (content, parse_docbook_title ());
+ parse_docbook_spaces ();
+ }
+
+ append_block_content_not_null (content, parse_docbook_programlisting ());
+
+ parse_docbook_spaces ();
+
+ if (!check_xml_close_tag ("informalexample")) {
+ this.report_unexpected_token (current, "</informalexample>");
+ return content;
+ }
+
+ next ();
+ return content;
+ }
+
+ private LinkedList<Block>? parse_docbook_example () {
+ if (!check_xml_open_tag ("example")) {
+ this.report_unexpected_token (current, "<example>");
+ return null;
+ }
+
+ next ();
+
+ parse_docbook_spaces ();
+
+ LinkedList<Block> content = new LinkedList<Block> ();
+
+ if (current.type == TokenType.XML_OPEN && current.content == "title") {
+ append_block_content_not_null (content, parse_docbook_title ());
+ parse_docbook_spaces ();
+ }
+
+ while (current.type == TokenType.XML_OPEN) {
+ if (current.content == "inlinegraphic") {
+ Paragraph p = factory.create_paragraph ();
+ while (current.type == TokenType.XML_OPEN && current.content == "inlinegraphic") {
+ p.content.add (parse_docbook_inlinegraphic ());
+ next ();
+ parse_docbook_spaces ();
+ }
+ } else if (current.content == "programlisting") {
+ append_block_content_not_null (content, parse_docbook_programlisting ());
+ next ();
+ } else {
+ break;
+ }
+
+ parse_docbook_spaces ();
+ }
+
+ if (!check_xml_close_tag ("example")) {
+ this.report_unexpected_token (current, "</example>");
+ return content;
+ }
+
+ next ();
+ return content;
+ }
+
+ private LinkedList<Block>? parse_docbook_refsect2 () {
+ if (!check_xml_open_tag ("refsect2")) {
+ this.report_unexpected_token (current, "<refsect2>");
+ return null;
+ }
+
+ // TODO: register id
+ string id = current.attributes.get ("id");
+ next ();
+
+ parse_docbook_spaces ();
+
+ LinkedList<Block> content = new LinkedList<Block> ();
+
+ if (current.type == TokenType.XML_OPEN && current.content == "title") {
+ append_block_content_not_null (content, parse_docbook_title ());
+ parse_docbook_spaces ();
+ }
+
+ this.append_block_content_not_null_all (content, parse_block_content ());
+
+ if (!check_xml_close_tag ("refsect2")) {
+ this.report_unexpected_token (current, "</refsect2>");
+ return content;
+ }
+
+ next ();
+ return content;
+ }
+
+ private inline void append_block_content_not_null_all (LinkedList<Block> run, LinkedList<Block>? elements) {
+ if (elements != null) {
+ run.add_all (elements);
+ }
+ }
+
+ private inline void append_block_content_not_null (LinkedList<Block> run, Block? element) {
+ if (element != null) {
+ run.add (element);
+ }
+ }
+
+ private LinkedList<Block> parse_block_content () {
+ LinkedList<Block> content = new LinkedList<Block> ();
+
+ while (current.type != TokenType.EOF) {
+ parse_docbook_spaces (false);
+
+ if (current.type == TokenType.XML_OPEN && current.content == "itemizedlist") {
+ this.append_block_content_not_null (content, parse_docbook_itemizedlist ());
+ } else if (current.type == TokenType.XML_OPEN && current.content == "para") {
+ this.append_block_content_not_null_all (content, parse_docbook_para ());
+ } else if (current.type == TokenType.XML_OPEN && current.content == "informalexample") {
+ this.append_block_content_not_null_all (content, parse_docbook_informalexample ());
+ } else if (current.type == TokenType.XML_OPEN && current.content == "example") {
+ this.append_block_content_not_null_all (content, parse_docbook_example ());
+ } else if (current.type == TokenType.XML_OPEN && current.content == "warning") {
+ this.append_block_content_not_null_all (content, parse_docbook_warning ());
+ } else if (current.type == TokenType.XML_OPEN && current.content == "note") {
+ this.append_block_content_not_null_all (content, parse_docbook_note ());
+ } else if (current.type == TokenType.XML_OPEN && current.content == "refsect2") {
+ this.append_block_content_not_null_all (content, parse_docbook_refsect2 ());
+ } else if (current.type == TokenType.GTKDOC_PARAGRAPH) {
+ this.append_block_content_not_null (content, parse_gtkdoc_paragraph ());
+ } else if (current.type == TokenType.GTKDOC_SOURCE_OPEN) {
+ this.append_block_content_not_null (content, parse_gtkdoc_source ());
+ } else {
+ break;
+ }
+ }
+
+ return content;
+ }
+
+ private void append_inline_content_string (Run run, string current) {
+ Text last_as_text = null;
+
+ if (run.content.size > 0) {
+ last_as_text = run.content.last () as Text;
+ }
+
+ if (last_as_text == null) {
+ run.content.add (factory.create_text (current));
+ } else if (current.has_prefix (" ") && last_as_text.content.has_suffix (" ")) {
+ last_as_text.content += current.chug ();
+ } else {
+ last_as_text.content += current;
+ }
+ }
+
+ private Inline create_type_link (string name) {
+ if (name == "TRUE" || name == "FALSE" || name == "NULL") {
+ var monospaced = factory.create_run (Run.Style.MONOSPACED);
+ monospaced.content.add (factory.create_text (name));
+ return monospaced;
+ } else {
+ Taglets.Link? taglet = factory.create_taglet ("link") as Taglets.Link;
+ assert (taglet != null);
+ taglet.symbol_name = "c::"+name;
+ return taglet;
+ }
+ }
+
+ private inline void append_inline_content_not_null (Run run, Inline element) {
+ if (element != null) {
+ run.content.add (element);
+ }
+ }
+
+ private Run parse_inline_content () {
+ Run run = factory.create_run (Run.Style.NONE);
+
+ while (current.type != TokenType.EOF) {
+ if (current.type == TokenType.XML_OPEN && current.content == "firstterm") {
+ append_inline_content_not_null (run, parse_highlighted_template ("firstterm", Run.Style.ITALIC));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "literal") {
+ append_inline_content_not_null (run, parse_highlighted_template ("literal", Run.Style.ITALIC));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "application") {
+ append_inline_content_not_null (run, parse_highlighted_template ("application", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "emphasis") {
+ append_inline_content_not_null (run, parse_highlighted_template ("emphasis", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "code") {
+ append_inline_content_not_null (run, parse_highlighted_template ("code", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "command") {
+ append_inline_content_not_null (run, parse_highlighted_template ("command", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "option") {
+ append_inline_content_not_null (run, parse_highlighted_template ("option", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "keycap") {
+ append_inline_content_not_null (run, parse_highlighted_template ("keycap", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "keycombo") {
+ append_inline_content_not_null (run, parse_highlighted_template ("keycombo", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "envar") {
+ append_inline_content_not_null (run, parse_highlighted_template ("envar", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "filename") {
+ append_inline_content_not_null (run, parse_highlighted_template ("filename", Run.Style.MONOSPACED));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "replaceable") {
+ append_inline_content_not_null (run, parse_highlighted_template ("replaceable", Run.Style.ITALIC));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "type") {
+ append_inline_content_not_null (run, parse_symbol_link ("type"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "function") {
+ append_inline_content_not_null (run, parse_symbol_link ("function"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "classname") {
+ append_inline_content_not_null (run, parse_symbol_link ("classname"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "structname") {
+ append_inline_content_not_null (run, parse_symbol_link ("structname"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "structfield") {
+ append_inline_content_not_null (run, parse_symbol_link ("structfield"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "errorcode") {
+ append_inline_content_not_null (run, parse_symbol_link ("errorcode"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "constant") {
+ append_inline_content_not_null (run, parse_symbol_link ("constant"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "anchor") {
+ parse_anchor ();
+ } else if (current.type == TokenType.XML_OPEN && current.content == "link") {
+ append_inline_content_not_null (run, parse_docbook_link_tempalte ("link"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "ulink") {
+ append_inline_content_not_null (run, parse_docbook_link_tempalte ("ulink"));
+ } else if (current.type == TokenType.XML_OPEN && current.content == "xref") {
+ parse_xref ();
+ } else if (current.type == TokenType.GTKDOC_FUNCTION) {
+ run.content.add (this.create_type_link (current.content));
+ next ();
+ } else if (current.type == TokenType.GTKDOC_PARAM) {
+ Run current_run = factory.create_run (Run.Style.MONOSPACED);
+ current_run.content.add (factory.create_text (current.content));
+ run.content.add (current_run);
+ next ();
+ } else if (current.type == TokenType.GTKDOC_SIGNAL) {
+ run.content.add (this.create_type_link ("::"+current.content));
+ next ();
+ } else if (current.type == TokenType.GTKDOC_PROPERTY) {
+ run.content.add (this.create_type_link (":"+current.content));
+ next ();
+ } else if (current.type == TokenType.GTKDOC_CONST) {
+ run.content.add (this.create_type_link (current.content));
+ next ();
+ } else if (current.type == TokenType.GTKDOC_TYPE) {
+ run.content.add (this.create_type_link (current.content));
+ next ();
+ } else if (current.type == TokenType.NEWLINE || current.type == TokenType.SPACE) {
+ append_inline_content_string (run, " ");
+ next ();
+ } else if (current.type == TokenType.WORD) {
+ append_inline_content_string (run, current.content);
+ next ();
+ } else if (current.type == TokenType.XML_CLOSE && ignore_current_xml_close ()) {
+ next ();
+ } else if (current.type == TokenType.XML_COMMENT) {
+ next ();
+ } else {
+ break;
+ }
+ }
+
+ return run;
+ }
+
+
+
+ //
+ // Resource Locator:
+ //
+
+ public string resolve (string path) {
+ return path;
+ }
+}
+
+
diff --git a/src/libvaladoc/documentation/gtkdoccommentscanner.vala b/src/libvaladoc/documentation/gtkdoccommentscanner.vala
new file mode 100644
index 0000000..ca03b15
--- /dev/null
+++ b/src/libvaladoc/documentation/gtkdoccommentscanner.vala
@@ -0,0 +1,644 @@
+/* gtkcommentscanner.vala
+ *
+ * Copyright (C) 2011 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Valadoc.Gtkdoc;
+using Gee;
+
+
+
+public enum Valadoc.Gtkdoc.TokenType {
+ XML_OPEN,
+ XML_CLOSE,
+ XML_COMMENT,
+ GTKDOC_FUNCTION,
+ GTKDOC_CONST,
+ GTKDOC_TYPE,
+ GTKDOC_PARAM,
+ GTKDOC_SOURCE_OPEN,
+ GTKDOC_SOURCE_CLOSE,
+ GTKDOC_SIGNAL,
+ GTKDOC_PROPERTY,
+ GTKDOC_PARAGRAPH,
+ NEWLINE,
+ SPACE,
+ WORD,
+ EOF
+}
+
+
+public class Valadoc.Gtkdoc.Token {
+ public TokenType type;
+ public string content;
+ public HashMap<string, string>? attributes;
+ public unowned string start;
+ public int length;
+ public int line;
+ public int first_column;
+ public int last_column;
+
+ public Token (TokenType type, string content, HashMap<string, string>? attributes, string start, int length, int line, int first_column, int last_column) {
+ this.attributes = attributes;
+ this.content = content;
+ this.length = length;
+ this.start = start;
+ this.type = type;
+ this.line = line;
+ this.first_column = first_column;
+ this.last_column = last_column;
+ }
+
+ public string to_string () {
+ switch (this.type) {
+ case TokenType.XML_OPEN:
+ return "`<%s>'".printf (this.content);
+
+ case TokenType.XML_CLOSE:
+ return "`<%s>'".printf (this.content);
+
+ case TokenType.XML_COMMENT:
+ return "<XML-COMMENT>";
+
+ case TokenType.GTKDOC_FUNCTION:
+ return "`%s ()'".printf (this.content);
+
+ case TokenType.GTKDOC_CONST:
+ return "`%%%s'".printf (this.content);
+
+ case TokenType.GTKDOC_TYPE:
+ return "`#%s'".printf (this.content);
+
+ case TokenType.GTKDOC_PARAM:
+ return "<GTKDOC-PARAM>";
+
+ case TokenType.GTKDOC_SOURCE_OPEN:
+ return "[|";
+
+ case TokenType.GTKDOC_SOURCE_CLOSE:
+ return "|]";
+
+ case TokenType.GTKDOC_SIGNAL:
+ return "`::%s'".printf (this.content);
+
+ case TokenType.GTKDOC_PROPERTY:
+ return "`:%s'".printf (this.content);
+
+ case TokenType.GTKDOC_PARAGRAPH:
+ return "<GKTDOC-PARAGRAPH>";
+
+ case TokenType.NEWLINE:
+ return "<NEWLNIE>";
+
+ case TokenType.SPACE:
+ return "<SPACE>";
+
+ case TokenType.WORD:
+ return "`%s'".printf (this.content);
+
+ case TokenType.EOF:
+ return "<EOF>";
+
+ default:
+ assert_not_reached ();
+ }
+ }
+}
+
+
+public class Valadoc.Gtkdoc.Scanner {
+ private unowned string content;
+ private unowned string pos;
+ private int column;
+ private int line;
+ private Token tmp_token;
+
+ public Scanner () {
+ }
+
+ public void reset (string content) {
+ this.content = content;
+ this.tmp_token = null;
+ this.pos = content;
+ this.column = 0;
+ this.line = 0;
+ }
+
+ private inline unichar next_char () {
+ this.pos = this.pos.next_char ();
+ this.column++;
+
+ return this.pos.get_char ();
+ }
+
+ private inline unichar get () {
+ return this.pos.get_char ();
+ }
+
+ private inline bool letter (unichar c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ }
+
+ private inline bool letter_or_number (unichar c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
+ }
+
+ private inline bool space (unichar c) {
+ return c == ' ' || c == '\t';
+ }
+
+ private inline bool space_or_newline (unichar c) {
+ if (c == '\n') {
+ this.line++;
+ this.column = 0;
+ return true;
+ }
+
+ return space (c);
+ }
+
+ private inline int offset (string a, string b) {
+ return (int) ((char*) a - (char*) b);
+ }
+
+ private inline int id_prefix () {
+ if (!letter (get ())) {
+ return 0;
+ }
+
+ int start = this.column;
+ unichar c;
+ while ((c = next_char ()) == '_' || letter_or_number (c));
+ return this.column - start;
+ }
+
+ private inline int g_id_prefix () {
+ unowned string start = this.pos;
+
+ if (!letter (get ())) {
+ return 0;
+ }
+
+ unichar c;
+ while ((c = next_char ()) == '_' || c == '-' || letter_or_number (c));
+ return offset (this.pos, start);
+ }
+
+ private inline int skip_spaces_and_newlines () {
+ unowned string start = this.pos;
+ if (space_or_newline (get ())) {
+ while (space_or_newline (next_char ()));
+ }
+
+ return offset (this.pos, start);
+ }
+
+ private inline Token? function_prefix () {
+ unowned string start = this.pos;
+ int column_start = this.column;
+ int id_len = 0;
+ if ((id_len = id_prefix ()) == 0) {
+ return null;
+ }
+
+ space_prefix ();
+
+ if (get () != '(') {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ next_char ();
+ space_prefix ();
+
+ if (get () != ')') {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ next_char ();
+ return new Token (TokenType.GTKDOC_FUNCTION, start.substring (0, id_len), null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ private inline Token? gtkdoc_symbolic_link_prefix (unichar c, TokenType type) {
+ if (get () != c) {
+ return null;
+ }
+
+ unowned string start = this.pos;
+ int column_start = this.column;
+ next_char ();
+
+ int id_len = 0;
+
+ if ((id_len = id_prefix ()) == 0) {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ unowned string separator = this.pos;
+ if (get () == ':') {
+ int separator_len = 1;
+ if (next_char () == ':') {
+ next_char ();
+ separator_len++;
+ }
+
+ int id_len2;
+ if ((id_len2 = g_id_prefix ()) == 0) {
+ this.pos = separator;
+ } else {
+ id_len += id_len2 + separator_len;
+ }
+ }
+
+ return new Token (type, start.substring (1, id_len), null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ private inline Token? gtkdoc_property_prefix () {
+ if (get () != ':') {
+ return null;
+ }
+
+ unowned string start = this.pos;
+ int column_start = this.column;
+ next_char ();
+
+ int id_len = 0;
+
+ if ((id_len = g_id_prefix ()) == 0) {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ return new Token (TokenType.GTKDOC_PROPERTY, start.substring (1, id_len), null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ private inline Token? gtkdoc_signal_prefix () {
+ if (get () != ':') {
+ return null;
+ }
+
+ unowned string start = this.pos;
+ int column_start = this.column;
+ if (next_char () != ':') {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+
+ start = this.pos;
+ next_char ();
+
+ int id_len = 0;
+
+ if ((id_len = g_id_prefix ()) == 0) {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ return new Token (TokenType.GTKDOC_SIGNAL, start.substring (1, id_len), null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ private inline Token? gtkdoc_const_prefix () {
+ return gtkdoc_symbolic_link_prefix ('%', TokenType.GTKDOC_CONST);
+ }
+
+ private inline Token? gtkdoc_param_prefix () {
+ return gtkdoc_symbolic_link_prefix ('@', TokenType.GTKDOC_PARAM);
+ }
+
+ private inline Token? gtkdoc_type_prefix () {
+ return gtkdoc_symbolic_link_prefix ('#', TokenType.GTKDOC_TYPE);
+ }
+
+ private inline Token? xml_prefix () {
+ if (get () != '<') {
+ return null;
+ }
+
+ unowned string start = this.pos;
+ int line_start = this.line;
+ int column_start = this.column;
+ next_char ();
+
+ if (get () == '!') {
+ // comment
+ if (next_char () == '-') {
+ if (next_char () != '-') {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ for (unichar c = next_char (); c != '\0'; c = next_char ()) {
+ if (c == '\n') {
+ this.line++;
+ this.column = 0;
+ } else if (this.pos.has_prefix ("-->")) {
+ next_char ();
+ next_char ();
+ next_char ();
+ return new Token (TokenType.XML_COMMENT, "", null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+ }
+ } else if (this.pos.has_prefix ("[CDATA[")) {
+ next_char ();
+ next_char ();
+ next_char ();
+ next_char ();
+ next_char ();
+ next_char ();
+
+ for (unichar c = next_char (); c != '\0'; c = next_char ()) {
+ if (c == '\n') {
+ this.line++;
+ this.column = 0;
+ } else if (this.pos.has_prefix ("]]>")) {
+ string content = start.substring (9, offset (this.pos, start) - 9);
+ next_char ();
+ next_char ();
+ next_char ();
+ return new Token (TokenType.WORD, content, null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+ }
+ }
+
+ this.pos = start;
+ this.column = column_start;
+ this.line = line_start;
+ return null;
+ }
+
+ bool close = false;
+ if (get () == '/') {
+ next_char ();
+ close = true;
+ }
+
+ unowned string id_start = this.pos;
+
+ int id_len = 0;
+ if ((id_len = id_prefix ()) == 0) {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ HashMap<string, string> map = new HashMap<string, string> ();
+
+ while (close == false && skip_spaces_and_newlines () > 0) {
+ string name;
+ string val;
+
+ unowned string att_pos = this.pos;
+ int att_id_len = 0;
+ if ((att_id_len = id_prefix ()) == 0) {
+ break;
+ }
+
+ name = att_pos.substring (0, att_id_len);
+
+ if (get() != '=') {
+ break;
+ }
+
+ next_char ();
+ skip_spaces_and_newlines ();
+
+ if (get() != '"') {
+ break;
+ }
+
+ unichar c = next_char ();
+ att_pos = this.pos;
+ for (; c != '\0' && c != '\n' && c != '"' ; c = next_char ());
+
+ val = att_pos.substring (0, offset (this.pos, att_pos));
+
+ if (get() != '"') {
+ break;
+ }
+
+ next_char ();
+
+ map.set (name, val);
+ }
+
+ skip_spaces_and_newlines ();
+
+ bool open_and_close = false;
+
+ if (!close && get () == '/') {
+ open_and_close = true;
+ next_char ();
+ }
+
+ if (get () != '>') {
+ this.line = line_start;
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ next_char ();
+
+ if (open_and_close) {
+ this.tmp_token = new Token (TokenType.XML_CLOSE, id_start.substring (0, id_len), null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ if (close) {
+ return new Token (TokenType.XML_CLOSE, id_start.substring (0, id_len), null, start, offset (this.pos, start), this.line, column_start, this.column);
+ } else {
+ return new Token (TokenType.XML_OPEN, id_start.substring (0, id_len), map, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+ }
+
+ private Token? newline_prefix () {
+ if (get () != '\n') {
+ return null;
+ }
+
+ unowned string start = this.pos;
+ this.line++;
+ this.column = 0;
+
+ for (unichar c = next_char (); c == ' ' || c == '\t' ; c = next_char ());
+
+ if (get () == '\n') {
+ next_char ();
+ this.line++;
+ this.column = 0;
+ return new Token (TokenType.GTKDOC_PARAGRAPH, "\n\n", null, start, offset (this.pos, start), this.line, this.column, this.column);
+ } else {
+ return new Token (TokenType.NEWLINE, "\n", null, start, offset (this.pos, start), this.line, this.column, this.column);
+ }
+ }
+
+ private Token? eof_prefix () {
+ if (get () != '\0') {
+ return null;
+ }
+
+ return new Token (TokenType.EOF, "", null, this.pos, 1, this.line, this.column, this.column);
+ }
+
+ private Token? space_prefix () {
+ unowned string start = this.pos;
+ int column_start = this.column;
+ for (unichar c = get (); c == ' ' || c == '\t'; c = next_char ());
+ int len = offset (this.pos, start);
+ if (len == 0) {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ return new Token (TokenType.SPACE, start.substring (0, len), null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ private Token? word_prefix () {
+ unowned string start = this.pos;
+ int column_start = this.column;
+ if (get () == '<') {
+ next_char ();
+ }
+
+ for (unichar c = get (); c != ' ' && c != '\t' && c != '\n' && c != '\0' && c != '<'; c = next_char ());
+ int len = offset (this.pos, start);
+ if (len == 0) {
+ this.column = column_start;
+ this.pos = start;
+ return null;
+ }
+
+ return new Token (TokenType.WORD, start.substring (0, len), null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ private Token? gtkdoc_source_open_prefix () {
+ if (!this.pos.has_prefix ("|[")) {
+ return null;
+ }
+
+ unowned string start = this.pos;
+ int column_start = this.column;
+ next_char ();
+ next_char ();
+
+ return new Token (TokenType.GTKDOC_SOURCE_OPEN, "|[", null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ private Token? gtkdoc_source_close_prefix () {
+ if (!this.pos.has_prefix ("]|")) {
+ return null;
+ }
+
+ unowned string start = this.pos;
+ int column_start = this.column;
+ next_char ();
+ next_char ();
+
+ return new Token (TokenType.GTKDOC_SOURCE_CLOSE, "]|", null, start, offset (this.pos, start), this.line, column_start, this.column);
+ }
+
+ public Token next () {
+ if (tmp_token != null) {
+ var tmp = tmp_token;
+ tmp_token = null;
+ return tmp;
+ }
+
+ Token? token = function_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = xml_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = gtkdoc_param_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = gtkdoc_const_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = gtkdoc_type_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = space_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = newline_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = gtkdoc_signal_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = gtkdoc_property_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = gtkdoc_source_open_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = gtkdoc_source_close_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = eof_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ token = word_prefix ();
+ if (token != null) {
+ return token;
+ }
+
+ assert_not_reached ();
+ }
+}
+
+
diff --git a/src/libvaladoc/importer/valadocdocumentationimporter.vala b/src/libvaladoc/importer/valadocdocumentationimporter.vala
index d0cdb84..16bb108 100755
--- a/src/libvaladoc/importer/valadocdocumentationimporter.vala
+++ b/src/libvaladoc/importer/valadocdocumentationimporter.vala
@@ -116,7 +116,7 @@ public class Valadoc.Importer.ValadocDocumentationImporter : DocumentationImport
Api.Node? symbol = null;
if (symbol_name.has_prefix ("c::")) {
- symbol = tree.search_symbol_cstr (symbol_name.substring (3));
+ symbol = tree.search_symbol_cstr (null, symbol_name.substring (3));
} else {
symbol = tree.search_symbol_str (null, symbol_name);
}
diff --git a/src/libvaladoc/taglets/tagletlink.vala b/src/libvaladoc/taglets/tagletlink.vala
index 93ba7ab..57b1474 100755
--- a/src/libvaladoc/taglets/tagletlink.vala
+++ b/src/libvaladoc/taglets/tagletlink.vala
@@ -47,7 +47,11 @@ public class Valadoc.Taglets.Link : InlineTaglet {
public override void check (Api.Tree api_root, Api.Node container, ErrorReporter reporter, Settings settings) {
if (symbol_name.has_prefix ("c::")) {
_symbol_name = _symbol_name.substring (3);
- _symbol = api_root.search_symbol_cstr (symbol_name);
+ _symbol = api_root.search_symbol_cstr (container, symbol_name);
+ if (_symbol == null) {
+
+ }
+
if (_symbol != null) {
symbol_name = _symbol.name;
}
diff --git a/src/libvaladoc/taglets/tagletsee.vala b/src/libvaladoc/taglets/tagletsee.vala
index eb4562e..d976688 100755
--- a/src/libvaladoc/taglets/tagletsee.vala
+++ b/src/libvaladoc/taglets/tagletsee.vala
@@ -41,7 +41,7 @@ public class Valadoc.Taglets.See : ContentElement, Taglet, Block {
public override void check (Api.Tree api_root, Api.Node container, ErrorReporter reporter, Settings settings) {
if (symbol_name.has_prefix ("c::")) {
symbol_name = symbol_name.substring (3);
- symbol = api_root.search_symbol_cstr (symbol_name);
+ symbol = api_root.search_symbol_cstr (container, symbol_name);
if (symbol != null) {
symbol_name = _symbol.name;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]