[vala/wip/merge-valadoc: 5/5] Merge valadoc 0.36.0



commit 82b88bce378048549ebfeef4141a08fe23b0a6a2
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Thu May 18 16:59:57 2017 +0200

    Merge valadoc 0.36.0
    
    Consider valadoc a part of vala's toolchain and therefore let it live in
    the main repository.
    
    With this merge there is no need to maintain multiple driver sources since
    only one is required from now on.
    
    There is no dependency on gee-0.8 and vala's internal gee copy has made to
    be sufficient.
    
    The libvaladoc library will be suffixed with vala's version suffix too.
    Besides this renaming the rest of the valadoc file layout is kept the same.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=782782

 .gitignore                                         |    1 +
 Makefile.am                                        |    2 +
 configure.ac                                       |   46 +-
 doc/Makefile.am                                    |   10 +-
 doc/valadoc.1                                      |  114 +
 doc/valadoc.h2m                                    |   19 +
 libvaladoc/.gitignore                              |    2 +
 libvaladoc/Makefile.am                             |  238 ++
 libvaladoc/api/array.vala                          |   69 +
 libvaladoc/api/attribute.vala                      |  108 +
 libvaladoc/api/attributeargument.vala              |  132 +
 libvaladoc/api/browsable.vala                      |   33 +
 libvaladoc/api/callable.vala                       |   48 +
 libvaladoc/api/childsymbolregistrar.vala           |   98 +
 libvaladoc/api/class.vala                          |  360 +++
 libvaladoc/api/constant.vala                       |   81 +
 libvaladoc/api/delegate.vala                       |  142 +
 libvaladoc/api/driver.vala                         |   42 +
 libvaladoc/api/enum.vala                           |   71 +
 libvaladoc/api/enumvalue.vala                      |  114 +
 libvaladoc/api/errorcode.vala                      |  107 +
 libvaladoc/api/errordomain.vala                    |  100 +
 libvaladoc/api/field.vala                          |  110 +
 libvaladoc/api/formalparameter.vala                |  155 ++
 libvaladoc/api/formalparametertype.vala            |   44 +
 libvaladoc/api/girsourcecomment.vala               |   57 +
 libvaladoc/api/interface.vala                      |  213 ++
 libvaladoc/api/item.vala                           |   70 +
 libvaladoc/api/member.vala                         |   62 +
 libvaladoc/api/method.vala                         |  265 ++
 libvaladoc/api/methodbindingtype.vala              |   55 +
 libvaladoc/api/namespace.vala                      |   96 +
 libvaladoc/api/node.vala                           |  723 +++++
 libvaladoc/api/nodetype.vala                       |  117 +
 libvaladoc/api/ownership.vala                      |   47 +
 libvaladoc/api/package.vala                        |  139 +
 libvaladoc/api/pointer.vala                        |   54 +
 libvaladoc/api/property.vala                       |  201 ++
 libvaladoc/api/propertyaccessor.vala               |  133 +
 libvaladoc/api/propertyaccessortype.vala           |   43 +
 libvaladoc/api/propertybindingtype.vala            |   48 +
 libvaladoc/api/signal.vala                         |  145 +
 libvaladoc/api/signaturebuilder.vala               |  180 ++
 libvaladoc/api/sourcecomment.vala                  |   85 +
 libvaladoc/api/sourcefile.vala                     |   61 +
 libvaladoc/api/struct.vala                         |  173 ++
 libvaladoc/api/symbol.vala                         |  157 ++
 libvaladoc/api/symbolaccessibility.vala            |   51 +
 libvaladoc/api/tree.vala                           |  350 +++
 libvaladoc/api/typeparameter.vala                  |   61 +
 libvaladoc/api/typereference.vala                  |  167 ++
 libvaladoc/api/typesymbol.vala                     |  112 +
 libvaladoc/api/visitor.vala                        |  171 ++
 libvaladoc/charts/chart.vala                       |   73 +
 libvaladoc/charts/chartfactory.vala                |   53 +
 libvaladoc/charts/hierarchychart.vala              |   80 +
 libvaladoc/charts/simplechartfactory.vala          |   87 +
 libvaladoc/content/block.vala                      |   25 +
 libvaladoc/content/blockcontent.vala               |   65 +
 libvaladoc/content/comment.vala                    |  105 +
 libvaladoc/content/contentelement.vala             |   44 +
 libvaladoc/content/contentfactory.vala             |  122 +
 libvaladoc/content/contentrenderer.vala            |   30 +
 libvaladoc/content/contentvisitor.vala             |   84 +
 libvaladoc/content/embedded.vala                   |  123 +
 libvaladoc/content/headline.vala                   |   64 +
 libvaladoc/content/inline.vala                     |   25 +
 libvaladoc/content/inlinecontent.vala              |   73 +
 libvaladoc/content/inlinetaglet.vala               |   69 +
 libvaladoc/content/link.vala                       |  113 +
 libvaladoc/content/list.vala                       |  154 ++
 libvaladoc/content/listitem.vala                   |   57 +
 libvaladoc/content/note.vala                       |   53 +
 libvaladoc/content/page.vala                       |   63 +
 libvaladoc/content/paragraph.vala                  |   72 +
 libvaladoc/content/resourcelocator.vala            |   27 +
 libvaladoc/content/run.vala                        |  206 ++
 libvaladoc/content/sourcecode.vala                 |  239 ++
 libvaladoc/content/styleattributes.vala            |  114 +
 libvaladoc/content/symbollink.vala                 |   70 +
 libvaladoc/content/table.vala                      |   77 +
 libvaladoc/content/tablecell.vala                  |   91 +
 libvaladoc/content/tablerow.vala                   |   75 +
 libvaladoc/content/taglet.vala                     |   36 +
 libvaladoc/content/text.vala                       |   61 +
 libvaladoc/content/warning.vala                    |   53 +
 libvaladoc/content/wikilink.vala                   |   76 +
 libvaladoc/ctyperesolver.vala                      |  401 +++
 libvaladoc/devhelp-markupwriter.vala               |   94 +
 libvaladoc/doclet.vala                             |   51 +
 libvaladoc/documentation/commentscanner.vala       |   69 +
 libvaladoc/documentation/documentation.vala        |   38 +
 libvaladoc/documentation/documentationparser.vala  |  896 +++++++
 libvaladoc/documentation/girmetadata.vala          |  154 ++
 libvaladoc/documentation/gtkdoccommentparser.vala  | 1663 ++++++++++++
 libvaladoc/documentation/gtkdoccommentscanner.vala |  887 +++++++
 libvaladoc/documentation/gtkdocmarkdownparser.vala |  837 ++++++
 .../documentation/gtkdocmarkdownscanner.vala       |  758 ++++++
 libvaladoc/documentation/importerhelper.vala       |  264 ++
 libvaladoc/documentation/wiki.vala                 |  157 ++
 libvaladoc/documentation/wikiscanner.vala          |  396 +++
 libvaladoc/errorreporter.vala                      |  390 +++
 libvaladoc/filehelper.vala                         |  199 ++
 libvaladoc/gtkdocmarkupwriter.vala                 |   73 +
 libvaladoc/gtkdocrenderer.vala                     |  503 ++++
 libvaladoc/highlighter/codescanner.vala            |  572 ++++
 libvaladoc/highlighter/codetoken.vala              |   58 +
 libvaladoc/highlighter/highlighter.vala            |  366 +++
 libvaladoc/highlighter/scanner.vala                |   32 +
 libvaladoc/highlighter/xmlscanner.vala             |  374 +++
 libvaladoc/html/basicdoclet.vala                   | 1159 ++++++++
 libvaladoc/html/cssclassresolver.vala              |  117 +
 libvaladoc/html/htmlchartfactory.vala              |   54 +
 libvaladoc/html/htmlmarkupwriter.vala              |  132 +
 libvaladoc/html/htmlrenderer.vala                  |  632 +++++
 libvaladoc/html/linkhelper.vala                    |  186 ++
 libvaladoc/importer/documentationimporter.vala     |   44 +
 libvaladoc/importer/girdocumentationimporter.vala  |  859 ++++++
 libvaladoc/importer/internalidregistrar.vala       |   87 +
 .../importer/valadocdocumentationimporter.vala     |  198 ++
 .../valadocdocumentationimporterscanner.vala       |  188 ++
 libvaladoc/markupreader.vala                       |  334 +++
 libvaladoc/markupsourcelocation.vala               |   39 +
 libvaladoc/markuptokentype.vala                    |   51 +
 libvaladoc/markupwriter.vala                       |  272 ++
 libvaladoc/moduleloader.vala                       |  122 +
 libvaladoc/parser/manyrule.vala                    |  111 +
 libvaladoc/parser/oneofrule.vala                   |   97 +
 libvaladoc/parser/optionalrule.vala                |   87 +
 libvaladoc/parser/parser.vala                      |  305 +++
 libvaladoc/parser/parsercallback.vala              |   36 +
 libvaladoc/parser/rule.vala                        |  172 ++
 libvaladoc/parser/scanner.vala                     |   37 +
 libvaladoc/parser/sequencerule.vala                |  131 +
 libvaladoc/parser/sourcelocation.vala              |   35 +
 libvaladoc/parser/stubrule.vala                    |   61 +
 libvaladoc/parser/token.vala                       |  109 +
 libvaladoc/parser/tokentype.vala                   |  270 ++
 libvaladoc/settings.vala                           |  169 ++
 libvaladoc/taglets/tagletdeprecated.vala           |   60 +
 libvaladoc/taglets/tagletinheritdoc.vala           |  232 ++
 libvaladoc/taglets/tagletinit.vala                 |   35 +
 libvaladoc/taglets/tagletlink.vala                 |  185 ++
 libvaladoc/taglets/tagletparam.vala                |  165 ++
 libvaladoc/taglets/tagletreturn.vala               |   78 +
 libvaladoc/taglets/tagletsee.vala                  |   76 +
 libvaladoc/taglets/tagletsince.vala                |   62 +
 libvaladoc/taglets/tagletthrows.vala               |  124 +
 libvaladoc/valadoc.deps.in                         |    3 +
 libvaladoc/valadoc.pc.in                           |   14 +
 valadoc/.gitignore                                 |    1 +
 valadoc/Makefile.am                                |   79 +
 valadoc/doclets/Makefile.am                        |    9 +
 valadoc/doclets/devhelp/Makefile.am                |   53 +
 valadoc/doclets/devhelp/doclet.vala                |  247 ++
 valadoc/doclets/gtkdoc/Makefile.am                 |   58 +
 valadoc/doclets/gtkdoc/commentconverter.vala       |  305 +++
 valadoc/doclets/gtkdoc/dbus.vala                   |  300 +++
 valadoc/doclets/gtkdoc/doclet.vala                 |  443 ++++
 valadoc/doclets/gtkdoc/gcomment.vala               |  192 ++
 valadoc/doclets/gtkdoc/generator.vala              | 1412 ++++++++++
 valadoc/doclets/gtkdoc/utils.vala                  |  265 ++
 valadoc/doclets/html/Makefile.am                   |   53 +
 valadoc/doclets/html/doclet.vala                   |  217 ++
 valadoc/driver.vala                                |   68 +
 valadoc/girwriter.vala                             |  203 ++
 valadoc/icons/Makefile.am                          |   38 +
 valadoc/icons/abstractclass.png                    |  Bin 0 -> 693 bytes
 valadoc/icons/abstractmethod.png                   |  Bin 0 -> 482 bytes
 valadoc/icons/abstractproperty.png                 |  Bin 0 -> 776 bytes
 valadoc/icons/class.png                            |  Bin 0 -> 624 bytes
 valadoc/icons/coll_close.png                       |  Bin 0 -> 185 bytes
 valadoc/icons/coll_open.png                        |  Bin 0 -> 204 bytes
 valadoc/icons/constant.png                         |  Bin 0 -> 489 bytes
 valadoc/icons/constructor.png                      |  Bin 0 -> 418 bytes
 valadoc/icons/delegate.png                         |  Bin 0 -> 688 bytes
 valadoc/icons/devhelpstyle.css                     |  578 ++++
 valadoc/icons/enum.png                             |  Bin 0 -> 634 bytes
 valadoc/icons/enumvalue.png                        |  Bin 0 -> 2978 bytes
 valadoc/icons/errorcode.png                        |  Bin 0 -> 340 bytes
 valadoc/icons/errordomain.png                      |  Bin 0 -> 668 bytes
 valadoc/icons/field.png                            |  Bin 0 -> 560 bytes
 valadoc/icons/interface.png                        |  Bin 0 -> 544 bytes
 valadoc/icons/method.png                           |  Bin 0 -> 559 bytes
 valadoc/icons/namespace.png                        |  Bin 0 -> 390 bytes
 valadoc/icons/package.png                          |  Bin 0 -> 633 bytes
 valadoc/icons/packages.png                         |  Bin 0 -> 618 bytes
 valadoc/icons/property.png                         |  Bin 0 -> 884 bytes
 valadoc/icons/scripts.js                           |   49 +
 valadoc/icons/signal.png                           |  Bin 0 -> 536 bytes
 valadoc/icons/staticmethod.png                     |  Bin 0 -> 580 bytes
 valadoc/icons/struct.png                           |  Bin 0 -> 329 bytes
 valadoc/icons/style.css                            |  631 +++++
 valadoc/icons/tip.png                              |  Bin 0 -> 766 bytes
 valadoc/icons/virtualmethod.png                    |  Bin 0 -> 608 bytes
 valadoc/icons/virtualproperty.png                  |  Bin 0 -> 765 bytes
 valadoc/icons/warning.png                          |  Bin 0 -> 2959 bytes
 valadoc/icons/wikistyle.css                        |  547 ++++
 valadoc/initializerbuilder.vala                    |  667 +++++
 valadoc/symbolresolver.vala                        |  322 +++
 valadoc/tests/Makefile.am                          |   34 +
 valadoc/tests/drivers/api-test.data.vapi           |  151 ++
 valadoc/tests/drivers/generic-api-test.vala        | 2786 ++++++++++++++++++++
 valadoc/tests/libvaladoc/errorreporter.vala        |   70 +
 valadoc/tests/libvaladoc/gtkdoc-scanner.vala       |  225 ++
 valadoc/tests/libvaladoc/markupreader.vala         |  207 ++
 .../tests/libvaladoc/parser/generic-scanner.vala   |   70 +
 valadoc/tests/libvaladoc/parser/manyrule.vala      |   90 +
 valadoc/tests/libvaladoc/parser/oneofrule.vala     |   99 +
 valadoc/tests/libvaladoc/parser/optionalrule.vala  |   84 +
 valadoc/tests/libvaladoc/parser/sequencerule.vala  |  103 +
 valadoc/tests/libvaladoc/parser/stubrule.vala      |   92 +
 valadoc/tests/testrunner.sh                        |  129 +
 valadoc/treebuilder.vala                           | 1535 +++++++++++
 valadoc/valadoc.vala                               |  403 +++
 215 files changed, 38213 insertions(+), 3 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 1a59179..b5d7950 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ Makefile
 *.stamp
 *.gir
 .deps
+.dirstamp
 .libs
 libvala-*.vapi
 
diff --git a/Makefile.am b/Makefile.am
index 813b3fc..e5dc0cc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,6 +13,8 @@ SUBDIRS = \
        doc \
        gobject-introspection \
        vapigen \
+       libvaladoc \
+       valadoc \
        $(NULL)
 
 if ENABLE_UNVERSIONED
diff --git a/configure.ac b/configure.ac
index b8525ab..89824ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_HEADERS(config.h)
 AC_CONFIG_MACRO_DIR([m4])
-AM_INIT_AUTOMAKE([1.11 dist-xz no-dist-gzip])
+AM_INIT_AUTOMAKE([1.11 dist-xz no-dist-gzip subdir-objects])
 AM_MAINTAINER_MODE([enable])
 
 API_VERSION=0.38
@@ -85,6 +85,7 @@ AC_SUBST(COVERAGE_CFLAGS)
 AC_SUBST(COVERAGE_LIBS)
 
 GLIB_REQUIRED=2.40.0
+LIBGVC_REQUIRED=2.16
 
 PKG_CHECK_MODULES(GLIB, glib-2.0 >= $GLIB_REQUIRED gobject-2.0 >= $GLIB_REQUIRED)
 
@@ -96,6 +97,36 @@ PKG_CHECK_MODULES(GMODULE, gmodule-2.0 >= $GLIB_REQUIRED)
 AC_SUBST(GMODULE_CFLAGS)
 AC_SUBST(GMODULE_LIBS)
 
+PKG_CHECK_MODULES(LIBGVC, libgvc >= $LIBGVC_REQUIRED)
+AC_MSG_CHECKING([for CGRAPH])
+cgraph_tmp_LIBADD="$LIBADD"
+cgraph_tmp_CFLAGS="$CFLAGS"
+LIBADD="$LIBADD $LIBGVC_LIBS"
+CFLAGS="$CFLAGS $LIBGVC_CFLAGS"
+AC_RUN_IFELSE(
+       [AC_LANG_SOURCE([
+               #include <gvc.h>
+
+               int main(void) {
+                       #ifdef WITH_CGRAPH
+                               return 0;
+                       #else
+                               return -1;
+                       #endif
+               }
+       ])], [
+               AC_MSG_RESULT([yes])
+               VALAFLAGS="$VALAFLAGS -D WITH_CGRAPH"
+               have_cgraph=yes
+       ], [
+               AC_MSG_RESULT([no])
+               have_cgraph=no
+       ]
+)
+LIBADD="$cgraph_tmp_LIBADD"
+CFLAGS="$cgraph_tmp_CFLAGS"
+AM_CONDITIONAL(HAVE_CGRAPH, test "$have_cgraph" = "yes")
+
 AC_PATH_PROG([XSLTPROC], [xsltproc], :)
 AM_CONDITIONAL(HAVE_XSLTPROC, test "$XSLTPROC" != :)
 
@@ -123,6 +154,17 @@ AC_CONFIG_FILES([Makefile
            vapigen/vapigen.pc
            vapigen/Makefile
            vapigen/vala-gen-introspect/Makefile
-           vapigen/vala-gen-introspect/vala-gen-introspect])
+           vapigen/vala-gen-introspect/vala-gen-introspect
+           libvaladoc/valadoc.pc
+           libvaladoc/valadoc.deps
+           libvaladoc/Makefile
+           valadoc/Makefile
+           valadoc/doclets/Makefile
+           valadoc/doclets/html/Makefile
+           valadoc/doclets/devhelp/Makefile
+           valadoc/doclets/gtkdoc/Makefile
+           valadoc/icons/Makefile
+           valadoc/tests/Makefile
+])
 
 AC_OUTPUT
diff --git a/doc/Makefile.am b/doc/Makefile.am
index b6ca6aa..d742011 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -6,18 +6,20 @@ SUBDIRS = \
 
 dist_man_MANS = \
        valac.1 \
+       valadoc.1 \
        vala-gen-introspect.1 \
        vapigen.1 \
        $(NULL)
 
 EXTRA_DIST = \
        valac.h2m \
+       valadoc.h2m \
        vala-gen-introspect.h2m \
        vapigen.h2m \
        $(NULL)
 
 if HAVE_HELP2MAN
-manpages: valac.1 vala-gen-introspect.1 vapigen.1
+manpages: valac.1 valadoc.1 vala-gen-introspect.1 vapigen.1
        @rm $^
        $(MAKE) $(AM_MAKEFLAGS) $^
 
@@ -26,6 +28,11 @@ valac.1:
                --include $(srcdir)/valac.h2m \
                --libtool --no-info \
                --output=$@
+valadoc.1:
+       $(HELP2MAN) $(top_builddir)/valadoc/valadoc \
+               --include $(srcdir)/valadoc.h2m \
+               --libtool --no-info \
+               --output=$@
 vala-gen-introspect.1:
        $(HELP2MAN) $(top_builddir)/gobject-introspection/gen-introspect \
                --include $(srcdir)/vala-gen-introspect.h2m \
@@ -42,6 +49,7 @@ endif
 if ENABLE_UNVERSIONED
 install-data-hook:
        cd $(DESTDIR)$(man1dir) && $(LN_S) -f valac@PACKAGE_SUFFIX@.1 valac.1
+       cd $(DESTDIR)$(man1dir) && $(LN_S) -f valadoc@PACKAGE_SUFFIX@.1 valadoc.1
        cd $(DESTDIR)$(man1dir) && $(LN_S) -f vala-gen-introspect@PACKAGE_SUFFIX@.1 vala-gen-introspect.1
        cd $(DESTDIR)$(man1dir) && $(LN_S) -f vapigen@PACKAGE_SUFFIX@.1 vapigen.1
 endif
diff --git a/doc/valadoc.1 b/doc/valadoc.1
new file mode 100644
index 0000000..9601f7c
--- /dev/null
+++ b/doc/valadoc.1
@@ -0,0 +1,114 @@
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.4.
+.TH VALADOC "1" "March 2017" "valadoc 0.36.0" "User Commands"
+.SH NAME
+valadoc \- Vala Documentation Tool
+.SH SYNOPSIS
+.B valadoc
+[\fIOPTION\fR]... \fIFILE\fR...
+.SH DESCRIPTION
+Valadoc is a documentation generator for generating API documentation
+from Vala source code based on libvala.
+.SS "Usage:"
+.IP
+valadoc [OPTION?] FILE... \- Vala Documentation Tool
+.SS "Help Options:"
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show help options
+.SS "Application Options:"
+.TP
+\fB\-o\fR, \fB\-\-directory\fR=\fI\,DIRECTORY\/\fR
+Output directory
+.TP
+\fB\-b\fR, \fB\-\-basedir\fR=\fI\,DIRECTORY\/\fR
+Base source directory
+.TP
+\fB\-D\fR, \fB\-\-define\fR=\fI\,SYMBOL\/\fR...
+Define SYMBOL
+.TP
+\fB\-\-profile\fR=\fI\,PROFILE\/\fR
+Use the given profile instead of the default
+.TP
+\fB\-\-enable\-experimental\fR
+Enable experimental features
+.TP
+\fB\-\-enable\-experimental\-non\-null\fR
+Enable experimental enhancements for non\-null types
+.TP
+\fB\-\-metadatadir\fR=\fI\,DIRECTORY\/\fR...
+Look for GIR .metadata files in DIRECTORY
+.TP
+\fB\-\-girdir\fR=\fI\,DIRECTORY\/\fR...
+Look for .gir files in DIRECTORY
+.TP
+\fB\-\-vapidir\fR=\fI\,DIRECTORY\/\fR...
+Look for package bindings in DIRECTORY
+.TP
+\fB\-\-pkg\fR=\fI\,PACKAGE\/\fR...
+Include binding for PACKAGE
+.TP
+\fB\-\-driver\fR
+Name of an driver or path to a custom driver
+.TP
+\fB\-\-importdir\fR=\fI\,DIRECTORY\/\fR...
+Look for external documentation in DIRECTORY
+.TP
+\fB\-\-import\fR=\fI\,PACKAGE\/\fR...
+Include binding for PACKAGE
+.TP
+\fB\-\-alternative\-resource\-dir\fR=\fI\,DIRECTORY\/\fR...
+Alternative resource directories
+.TP
+\fB\-\-wiki\fR=\fI\,DIRECTORY\/\fR
+Wiki directory
+.TP
+\fB\-\-deps\fR
+Adds packages to the documentation
+.TP
+\fB\-\-doclet\fR=\fI\,PLUGIN\/\fR
+Name of an included doclet or path to custom doclet
+.TP
+\fB\-X\fR, \fB\-\-doclet\-arg\fR=\fI\,ARG\/\fR
+Pass arguments to the doclet
+.TP
+\fB\-\-no\-protected\fR
+Removes protected elements from documentation
+.TP
+\fB\-\-internal\fR
+Adds internal elements to documentation
+.TP
+\fB\-\-private\fR
+Adds private elements to documentation
+.TP
+\fB\-\-use\-svg\-images\fR
+Generate SVG image charts instead of PNG
+.TP
+\fB\-\-package\-name\fR=\fI\,NAME\/\fR
+package name
+.TP
+\fB\-\-package\-version\fR=\fI\,VERSION\/\fR
+package version
+.TP
+\fB\-\-gir\fR=\fI\,NAME\-VERSION\/\fR.gir
+GObject\-Introspection repository file name
+.TP
+\fB\-\-version\fR
+Display version number
+.TP
+\fB\-\-force\fR
+force
+.TP
+\fB\-\-verbose\fR
+Show all warnings
+.TP
+\fB\-\-no\-color\fR
+Disable colored output
+.TP
+\fB\-\-target\-glib\fR=\fI\,MAJOR\/\fR.MINOR
+Target version of glib for code generation
+.SH BUGS
+https://bugzilla.gnome.org/page.cgi?id=browse.html&product=valadoc
+.SH "HOMEPAGE OR CONTACT"
+https://wiki.gnome.org/Projects/Valadoc
+.SH AUTHORS
+Florian Brosch
diff --git a/doc/valadoc.h2m b/doc/valadoc.h2m
new file mode 100644
index 0000000..69c7c3e
--- /dev/null
+++ b/doc/valadoc.h2m
@@ -0,0 +1,19 @@
+[NAME]
+valadoc \- Vala Documentation Tool
+
+[SYNOPSIS]
+.B valadoc
+[\fIOPTION\fR]... \fIFILE\fR...
+
+[DESCRIPTION]
+Valadoc is a documentation generator for generating API documentation
+from Vala source code based on libvala.
+
+[BUGS]
+https://bugzilla.gnome.org/page.cgi?id=browse.html&product=valadoc
+
+[HOMEPAGE or CONTACT]
+https://wiki.gnome.org/Projects/Valadoc
+
+[AUTHORS]
+Florian Brosch
diff --git a/libvaladoc/.gitignore b/libvaladoc/.gitignore
new file mode 100644
index 0000000..22a1a17
--- /dev/null
+++ b/libvaladoc/.gitignore
@@ -0,0 +1,2 @@
+valadoc*.deps
+valadoc*.vapi
diff --git a/libvaladoc/Makefile.am b/libvaladoc/Makefile.am
new file mode 100644
index 0000000..4452e7b
--- /dev/null
+++ b/libvaladoc/Makefile.am
@@ -0,0 +1,238 @@
+include $(top_srcdir)/Makefile.common
+
+NULL =
+
+AM_CFLAGS = \
+       -DPACKAGE_ICONDIR=\"$(datadir)/valadoc/icons/\" \
+       -DPACKAGE_DATADIR=\"$(libdir)/valadoc\" \
+       -DPACKAGE_VERSION=\"$(VERSION)\" \
+       $(LIBGVC_CFLAGS) \
+       $(GLIB_CFLAGS) \
+       $(GMODULE_CFLAGS) \
+       -I$(top_srcdir)/gee \
+       $(NULL)
+
+AM_VALAFLAGS = \
+       $(NULL)
+
+BUILT_SOURCES = \
+       libvaladoc.vala.stamp \
+       valadoc.h \
+       $(NULL)
+
+lib_LTLIBRARIES = libvaladoc@PACKAGE_SUFFIX@.la
+
+libvaladoc_la_VALASOURCES = \
+       doclet.vala \
+       errorreporter.vala \
+       filehelper.vala \
+       moduleloader.vala \
+       settings.vala \
+       markupwriter.vala \
+       gtkdocmarkupwriter.vala \
+       devhelp-markupwriter.vala \
+       ctyperesolver.vala \
+       markupsourcelocation.vala \
+       markuptokentype.vala \
+       markupreader.vala \
+       gtkdocrenderer.vala \
+       documentation/commentscanner.vala \
+       documentation/documentation.vala \
+       documentation/documentationparser.vala \
+       documentation/wiki.vala \
+       documentation/wikiscanner.vala \
+       documentation/gtkdoccommentparser.vala \
+       documentation/gtkdoccommentscanner.vala \
+       documentation/gtkdocmarkdownparser.vala \
+       documentation/gtkdocmarkdownscanner.vala \
+       documentation/importerhelper.vala \
+       documentation/girmetadata.vala \
+       importer/documentationimporter.vala \
+       importer/valadocdocumentationimporter.vala \
+       importer/valadocdocumentationimporterscanner.vala \
+       importer/girdocumentationimporter.vala \
+       importer/internalidregistrar.vala \
+       api/symbolaccessibility.vala \
+       api/sourcecomment.vala \
+       api/girsourcecomment.vala \
+       api/attributeargument.vala \
+       api/attribute.vala \
+       api/array.vala \
+       api/callable.vala \
+       api/childsymbolregistrar.vala \
+       api/class.vala \
+       api/constant.vala \
+       api/delegate.vala \
+       api/enum.vala \
+       api/enumvalue.vala \
+       api/errorcode.vala \
+       api/errordomain.vala \
+       api/field.vala \
+       api/formalparameter.vala \
+       api/formalparametertype.vala \
+       api/interface.vala \
+       api/item.vala \
+       api/member.vala \
+       api/method.vala \
+       api/methodbindingtype.vala \
+       api/namespace.vala \
+       api/node.vala \
+       api/nodetype.vala \
+       api/ownership.vala \
+       api/package.vala \
+       api/pointer.vala \
+       api/property.vala \
+       api/propertyaccessor.vala \
+       api/propertyaccessortype.vala \
+       api/propertybindingtype.vala \
+       api/signal.vala \
+       api/signaturebuilder.vala \
+       api/sourcefile.vala \
+       api/struct.vala \
+       api/symbol.vala \
+       api/tree.vala \
+       api/typeparameter.vala \
+       api/typereference.vala \
+       api/typesymbol.vala \
+       api/browsable.vala \
+       api/visitor.vala \
+       api/driver.vala \
+       content/block.vala \
+       content/blockcontent.vala \
+       content/comment.vala \
+       content/contentfactory.vala \
+       content/contentelement.vala \
+       content/contentrenderer.vala \
+       content/contentvisitor.vala \
+       content/embedded.vala \
+       content/headline.vala \
+       content/inline.vala \
+       content/inlinetaglet.vala \
+       content/inlinecontent.vala \
+       content/wikilink.vala \
+       content/link.vala \
+       content/list.vala \
+       content/listitem.vala \
+       content/page.vala \
+       content/paragraph.vala \
+       content/warning.vala \
+       content/note.vala \
+       content/resourcelocator.vala \
+       content/run.vala \
+       content/sourcecode.vala \
+       content/styleattributes.vala \
+       content/symbollink.vala \
+       content/table.vala \
+       content/tablecell.vala \
+       content/tablerow.vala \
+       content/taglet.vala \
+       content/text.vala \
+       charts/chart.vala \
+       charts/chartfactory.vala \
+       charts/hierarchychart.vala \
+       charts/simplechartfactory.vala \
+       parser/manyrule.vala \
+       parser/oneofrule.vala \
+       parser/optionalrule.vala \
+       parser/parser.vala \
+       parser/parsercallback.vala \
+       parser/rule.vala \
+       parser/scanner.vala \
+       parser/sequencerule.vala \
+       parser/sourcelocation.vala \
+       parser/stubrule.vala \
+       parser/token.vala \
+       parser/tokentype.vala \
+       taglets/tagletdeprecated.vala \
+       taglets/tagletinheritdoc.vala \
+       taglets/tagletinit.vala \
+       taglets/tagletlink.vala \
+       taglets/tagletparam.vala \
+       taglets/tagletreturn.vala \
+       taglets/tagletsee.vala \
+       taglets/tagletsince.vala \
+       taglets/tagletthrows.vala \
+       highlighter/scanner.vala \
+       highlighter/codescanner.vala \
+       highlighter/xmlscanner.vala \
+       highlighter/codetoken.vala \
+       highlighter/highlighter.vala \
+       html/basicdoclet.vala \
+       html/htmlchartfactory.vala \
+       html/linkhelper.vala \
+       html/cssclassresolver.vala \
+       html/htmlmarkupwriter.vala \
+       html/htmlrenderer.vala \
+       $(NULL)
+
+libvaladoc@PACKAGE_SUFFIX@_la_SOURCES = \
+       libvaladoc.vala.stamp \
+       $(libvaladoc_la_VALASOURCES:.vala=.c) \
+       $(NULL)
+
+valadoc@PACKAGE_SUFFIX@.vapi valadoc.h: libvaladoc.vala.stamp
+libvaladoc.vala.stamp: $(libvaladoc_la_VALASOURCES)
+       $(VALAC) \
+               $(VALAFLAGS) \
+               --basedir $(srcdir) \
+               --directory $(builddir) \
+               -C \
+               -H valadoc.h \
+               --library valadoc \
+               --vapi valadoc@PACKAGE_SUFFIX@.vapi \
+               --vapidir $(top_srcdir)/vapi --pkg gmodule-2.0 \
+               --vapidir $(top_srcdir)/valadoc/vapi --pkg libgvc \
+               --vapidir $(top_srcdir)/gee --pkg gee \
+               --pkg config \
+               $(filter %.vala %.c,$^)
+       touch $@
+
+libvaladoc@PACKAGE_SUFFIX@_la_LDFLAGS = \
+       -no-undefined \
+       $(NULL)
+
+libvaladoc@PACKAGE_SUFFIX@_la_LIBADD = \
+       $(LIBGVC_LIBS) \
+       $(GLIB_LIBS) \
+       $(GMODULE_LIBS) \
+       $(top_builddir)/vala/libvala@PACKAGE_SUFFIX@.la \
+       $(NULL)
+
+libvaladocincludedir = $(includedir)/valadoc@PACKAGE_SUFFIX@
+libvaladocinclude_HEADERS = \
+       valadoc.h \
+       $(NULL)
+
+pkgconfigdir = $(libdir)/pkgconfig
+nodist_pkgconfig_DATA = valadoc@PACKAGE_SUFFIX@.pc
+
+valadoc@PACKAGE_SUFFIX@.pc: valadoc.pc
+       cp $< $@
+
+vapidir = $(datadir)/vala/vapi
+dist_vapi_DATA = valadoc@PACKAGE_SUFFIX@.vapi
+nodist_vapi_DATA = valadoc@PACKAGE_SUFFIX@.deps
+
+valadoc@PACKAGE_SUFFIX@.deps: valadoc.deps
+       cp $< $@
+
+EXTRA_DIST = \
+       $(libvaladoc_la_VALASOURCES) \
+       libvaladoc.vala.stamp \
+       valadoc.deps.in \
+       valadoc.pc.in \
+       $(NULL)
+
+CLEANFILES = \
+       valadoc@PACKAGE_SUFFIX@.deps \
+       valadoc@PACKAGE_SUFFIX@.pc \
+       $(NULL)
+
+MAINTAINERCLEANFILES = \
+       valadoc.deps \
+       valadoc.pc \
+       valadoc.vapi \
+       valadoc.h \
+       $(libvaladoc_la_VALASOURCES:.vala=.c) \
+       $(NULL)
+
diff --git a/libvaladoc/api/array.vala b/libvaladoc/api/array.vala
new file mode 100644
index 0000000..8e3cbe5
--- /dev/null
+++ b/libvaladoc/api/array.vala
@@ -0,0 +1,69 @@
+/* array.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;
+
+/**
+ * Represents an array declaration.
+ */
+public class Valadoc.Api.Array : Item {
+
+       /**
+        * The element type.
+        */
+       public Item data_type {
+               set;
+               get;
+       }
+
+       public Array (Item parent, void* data) {
+               base (data);
+
+               this.parent = parent;
+       }
+
+       private inline bool element_is_owned () {
+               TypeReference reference = data_type as TypeReference;
+               if (reference == null) {
+                       return true;
+               }
+
+               return !reference.is_unowned && !reference.is_weak;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               SignatureBuilder builder = new SignatureBuilder ();
+               if (element_is_owned ()) {
+                       builder.append_content (data_type.signature);
+               } else {
+                       builder.append ("(", false);
+                       builder.append_content (data_type.signature, false);
+                       builder.append (")", false);
+               }
+               builder.append ("[]", false);
+               return builder.get ();
+       }
+}
diff --git a/libvaladoc/api/attribute.vala b/libvaladoc/api/attribute.vala
new file mode 100644
index 0000000..da65919
--- /dev/null
+++ b/libvaladoc/api/attribute.vala
@@ -0,0 +1,108 @@
+/* attribute.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;
+
+public class Valadoc.Api.Attribute : Item {
+       private Vala.ArrayList<AttributeArgument> args = new Vala.ArrayList<AttributeArgument> ();
+       private SourceFile file;
+
+       public string name {
+               private set;
+               get;
+       }
+
+       public Attribute (Node parent, SourceFile file, string name, void* data) {
+               base (data);
+
+               this.parent = parent;
+               this.name = name;
+               this.file = file;
+       }
+
+       public AttributeArgument? get_argument (string name) {
+               if (args != null) {
+                       foreach (AttributeArgument arg in args) {
+                               if (arg.name == name) {
+                                       return arg;
+                               }
+                       }
+               }
+
+               return null;
+       }
+
+       public AttributeArgument add_boolean (string name, bool value, void* data = null) {
+               AttributeArgument arg = new AttributeArgument.boolean (this, file, name, value, data);
+               args.add (arg);
+               return arg;
+       }
+
+       public AttributeArgument add_integer (string name, int value, void* data = null) {
+               AttributeArgument arg = new AttributeArgument.integer (this, file, name, value, data);
+               args.add (arg);
+               return arg;
+       }
+
+       public AttributeArgument add_double (string name, double value, void* data = null) {
+               AttributeArgument arg = new AttributeArgument.double (this, file, name, value, data);
+               args.add (arg);
+               return arg;
+       }
+
+       public AttributeArgument add_string (string name, string value, void* data = null) {
+               AttributeArgument arg = new AttributeArgument.string (this, file, name, value, data);
+               args.add (arg);
+               return arg;
+       }
+
+       public SourceFile get_source_file () {
+               return file;
+       }
+
+       protected override Inline build_signature () {
+               SignatureBuilder builder = new SignatureBuilder ();
+
+               builder.append_attribute ("[");
+               builder.append_type_name (name);
+
+               if (args.size > 0) {
+                       builder.append_attribute ("(");
+                       bool first = true;
+
+                       foreach (AttributeArgument arg in args) {
+                               if (first == false) {
+                                       builder.append_attribute (", ");
+                               }
+                               builder.append_content (arg.signature);
+                               first = false;
+                       }
+                       builder.append_attribute (")");
+               }
+
+               builder.append_attribute ("]");
+       
+               return builder.get ();
+       }
+}
+
diff --git a/libvaladoc/api/attributeargument.vala b/libvaladoc/api/attributeargument.vala
new file mode 100644
index 0000000..1a3b01f
--- /dev/null
+++ b/libvaladoc/api/attributeargument.vala
@@ -0,0 +1,132 @@
+/* attributeargument.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;
+
+public class Valadoc.Api.AttributeArgument : Item {
+       public enum Type {
+               BOOLEAN,
+               INTEGER,
+               DOUBLE,
+               STRING
+       }
+
+       private SourceFile file;
+
+       public string name {
+               private set;
+               get;
+       }
+
+       public AttributeArgument.Type argument_type {
+               private set;
+               get;
+       }
+
+       public string value {
+               private set;
+               get;
+       }
+
+       public AttributeArgument.boolean (Attribute parent, SourceFile file, string name, bool value, void* 
data) {
+               this (parent, file, name, Type.BOOLEAN, value.to_string (), data);
+       }
+
+       public AttributeArgument.integer (Attribute parent, SourceFile file, string name, int value, void* 
data) {
+               this (parent, file, name, Type.INTEGER, value.to_string (), data);
+       }
+
+       public AttributeArgument.double (Attribute parent, SourceFile file, string name, double value, void* 
data) {
+               this (parent, file, name, Type.DOUBLE, value.to_string (), data);
+       }
+
+       public AttributeArgument.string (Attribute parent, SourceFile file, string name, string value, void* 
data) {
+               this (parent, file, name, Type.STRING, value, data);
+       }
+
+       private AttributeArgument (Attribute parent, SourceFile file, string name, Type type, string value, 
void* data) {
+               base (data);
+
+               this.argument_type = type;
+               this.parent = parent;
+               this.value = value;
+               this.file = file;
+               this.name = name;
+       }
+
+       public SourceFile get_source_file () {
+               return file;
+       }
+
+       public bool get_value_as_boolean () {
+               assert (argument_type == Type.BOOLEAN);
+
+               bool tmp;
+
+               if (bool.try_parse (value, out tmp)) {
+                       return tmp;
+               }
+
+               assert_not_reached ();
+       }
+
+       public int get_value_as_integer () {
+               assert (argument_type == Type.INTEGER);
+
+               double tmp;
+
+               if (global::double.try_parse (value, out tmp) && tmp >= int.MIN && tmp <= int.MAX) {
+                       return (int) tmp;
+               }
+
+               assert_not_reached ();
+       }
+
+       public double get_value_as_double () {
+               assert (argument_type == Type.DOUBLE);
+
+               double tmp;
+
+               if (global::double.try_parse (value, out tmp)) {
+                       return tmp;
+               }
+
+               assert_not_reached ();
+       }
+
+       public string get_value_as_string () {
+               assert (argument_type == Type.STRING);
+
+               return value;
+       }
+
+       protected override Inline build_signature () {
+               SignatureBuilder builder = new SignatureBuilder ();
+
+               builder.append_attribute (name);
+               builder.append_attribute ("=");
+               builder.append_literal (value);
+
+               return builder.get ();
+       }
+}
diff --git a/libvaladoc/api/browsable.vala b/libvaladoc/api/browsable.vala
new file mode 100644
index 0000000..7ae9b80
--- /dev/null
+++ b/libvaladoc/api/browsable.vala
@@ -0,0 +1,33 @@
+/* browsable.vala
+ *
+ * Copyright (C) 2008  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>
+ */
+
+
+/**
+ * Specifies whether users are able to browse the item.
+ */
+public interface Valadoc.Api.Browsable : Item {
+
+       /**
+        * Specifies whether users are able to browse the item.
+        */
+       public abstract bool is_browsable (Settings settings);
+}
diff --git a/libvaladoc/api/callable.vala b/libvaladoc/api/callable.vala
new file mode 100644
index 0000000..29d965d
--- /dev/null
+++ b/libvaladoc/api/callable.vala
@@ -0,0 +1,48 @@
+/* callable.vala
+ *
+ * Copyright (C) 2012  Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Valadoc;
+
+/**
+ * Used to translate imported C-documentation
+ */
+public interface Valadoc.Api.Callable : Symbol {
+       /**
+        * The return type of this symbol.
+        *
+        * @return The return type of this symbol or null for void
+        */
+       public abstract TypeReference? return_type {
+               set;
+               get;
+       }
+
+       /**
+        * Used to avoid warnings for implicit parameters
+        */
+       internal abstract string? implicit_array_length_cparameter_name {
+               get;
+               set;
+       }
+}
+
diff --git a/libvaladoc/api/childsymbolregistrar.vala b/libvaladoc/api/childsymbolregistrar.vala
new file mode 100644
index 0000000..75b072d
--- /dev/null
+++ b/libvaladoc/api/childsymbolregistrar.vala
@@ -0,0 +1,98 @@
+/* childsymbolregistrar.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.Api;
+
+public class Valadoc.Api.ChildSymbolRegistrar : Visitor {
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_tree (Api.Tree item) {
+               item.accept_children (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_package (Package item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_namespace (Namespace item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_interface (Interface item) {
+               Vala.Collection<TypeReference> interfaces = item.get_implemented_interface_list ();
+               foreach (var type_ref in interfaces) {
+                       ((Interface) type_ref.data_type).register_related_interface (item);
+               }
+
+               if (item.base_type != null) {
+                       ((Class) item.base_type.data_type).register_derived_interface (item);
+               }
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_class (Class item) {
+               Vala.Collection<TypeReference> interfaces = item.get_implemented_interface_list ();
+               foreach (TypeReference type_ref in interfaces) {
+                       ((Interface) type_ref.data_type).register_implementation (item);
+               }
+
+               if (item.base_type != null)     {
+                       ((Class) item.base_type.data_type).register_child_class (item);
+               }
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_struct (Struct item) {
+               if (item.base_type != null) {
+                       ((Struct) item.base_type.data_type).register_child_struct (item);
+               }
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_property (Property item) {
+               item.accept_all_children (this, false);
+       }
+}
+
diff --git a/libvaladoc/api/class.vala b/libvaladoc/api/class.vala
new file mode 100644
index 0000000..4ef99ea
--- /dev/null
+++ b/libvaladoc/api/class.vala
@@ -0,0 +1,360 @@
+/* class.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a class declaration.
+ */
+public class Valadoc.Api.Class : TypeSymbol {
+       private Vala.ArrayList<TypeReference> interfaces;
+
+       private string? dbus_name;
+       private string? take_value_function_cname;
+       private string? get_value_function_cname;
+       private string? set_value_function_cname;
+       private string? unref_function_name;
+       private string? ref_function_name;
+       private string? free_function_name;
+       private string? finalize_function_name;
+       private string? param_spec_function_name;
+       private string? type_id;
+       private string? is_class_type_macro_name;
+       private string? class_type_macro_name;
+       private string? class_macro_name;
+       private string? private_cname;
+       private string? cname;
+
+       public Class (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                 SourceComment? comment, string? cname, string? private_cname, string? 
class_macro_name,
+                                 string? type_macro_name, string? is_type_macro_name, string? 
type_cast_macro_name,
+                                 string? type_function_name, string? class_type_macro_name, string? 
is_class_type_macro_name,
+                                 string? dbus_name, string? type_id, string? param_spec_function_name, 
string? ref_function_name,
+                                 string? unref_function_name, string? free_function_name, string? 
finalize_function_name,
+                                 string? take_value_function_cname, string? get_value_function_cname, 
string? set_value_function_cname,
+                                 bool is_fundamental, bool is_abstract, bool is_basic_type, void* data)
+       {
+               base (parent, file, name, accessibility, comment, type_macro_name,
+                       is_type_macro_name, type_cast_macro_name, type_function_name, is_basic_type, data);
+
+               this.interfaces = new Vala.ArrayList<TypeReference> ();
+
+               this.is_class_type_macro_name = is_class_type_macro_name;
+               this.class_type_macro_name = class_type_macro_name;
+               this.class_macro_name = class_macro_name;
+               this.private_cname = private_cname;
+               this.dbus_name = dbus_name;
+               this.type_id = type_id;
+               this.cname = cname;
+
+               this.param_spec_function_name = param_spec_function_name;
+
+               this.unref_function_name = unref_function_name;
+               this.ref_function_name = ref_function_name;
+               this.finalize_function_name = finalize_function_name;
+               this.free_function_name = free_function_name;
+
+               this.take_value_function_cname = take_value_function_cname;
+               this.get_value_function_cname = get_value_function_cname;
+               this.set_value_function_cname = set_value_function_cname;
+
+               this.is_fundamental = is_fundamental;
+               this.is_abstract = is_abstract;
+       }
+
+       /**
+        * Specifies the base class.
+        */
+       public TypeReference? base_type {
+               set;
+               get;
+       }
+
+       /**
+        * Returns the name of this class as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * Returns the name of this class' private data structure as it is used in C.
+        */
+       public string? get_private_cname () {
+               return private_cname;
+       }
+
+       /**
+        * Returns the C symbol representing the runtime type id for this data type.
+        */
+       public string? get_type_id () {
+               return type_id;
+       }
+
+       /**
+        * Returns the C function name that increments the reference count of
+        * instances of this data type.
+        *
+        * @return the name of the C function or null if this data type does not
+        *         support reference counting
+        */
+       public string? get_ref_function_cname () {
+               return ref_function_name;
+       }
+
+       /**
+        * Returns the C function name that decrements the reference count of
+        * instances of this data type.
+        *
+        * @return the name of the C function or null if this data type does not
+        *         support reference counting
+        */
+       public string? get_unref_function_cname () {
+               return unref_function_name;
+       }
+
+       /**
+        * Returns the C function name that frees the
+        * instances of this data type.
+        *
+        * @return the name of the C function or null
+        */
+       public string? get_free_function_name () {
+               return free_function_name;
+       }
+
+       /**
+        * Returns the C function name that finalizes the
+        * instances of this data type.
+        *
+        * @return the name of the C function or null
+        */
+       public string? get_finalize_function_name () {
+               return finalize_function_name;
+       }
+
+       /**
+        * Returns the cname of the GValue parameter spec function.
+        */
+       public string? get_param_spec_function_cname () {
+               return param_spec_function_name;
+       }
+
+       /**
+        * Returns the cname of the GValue setter function.
+        */
+       public string? get_set_value_function_cname () {
+               return set_value_function_cname;
+       }
+
+       /**
+        * Returns the cname of the GValue getter function.
+        */
+       public string? get_get_value_function_cname () {
+               return get_value_function_cname;
+       }
+
+       /**
+        * Returns the cname of the GValue taker function.
+        */
+       public string? get_take_value_function_cname () {
+               return take_value_function_cname;
+       }
+
+       /**
+        * Returns the dbus-name.
+        */
+       public string? get_dbus_name () {
+               return dbus_name;
+       }
+
+       /**
+        * Gets the name of the GType macro which returns the class struct.
+        */
+       public string get_class_macro_name () {
+               return class_macro_name;
+       }
+
+       /**
+        * Gets the name of the GType macro which returns the type of the class.
+        */
+       public string get_class_type_macro_name () {
+               return class_type_macro_name;
+       }
+
+       /**
+        * Gets the name of the GType macro which returns whether a class instance is of a given type.
+        */
+       public string get_is_class_type_macro_name () {
+               return is_class_type_macro_name;
+       }
+
+       /**
+        * Returns a list of all newly implemented interfaces.
+        *
+        * @see get_full_implemented_interface_list
+        */
+       public Vala.Collection<TypeReference> get_implemented_interface_list () {
+               return this.interfaces;
+       }
+
+       private Vala.Collection<TypeReference> _full_implemented_interfaces = null;
+
+       /**
+        * Returns a list of all implemented interfaces.
+        *
+        * @see get_implemented_interface_list
+        */
+       public Vala.Collection<TypeReference> get_full_implemented_interface_list () {
+               if (_full_implemented_interfaces == null) {
+                       _full_implemented_interfaces = new Vala.ArrayList<TypeReference> ();
+                       _full_implemented_interfaces.add_all (this.interfaces);
+
+                       if (base_type != null) {
+                               _full_implemented_interfaces.add_all (((Class) 
base_type.data_type).get_full_implemented_interface_list ());
+                       }
+               }
+
+               return _full_implemented_interfaces;
+       }
+
+       public void add_interface (TypeReference iface) {
+               interfaces.add (iface);
+       }
+
+       /**
+        * Specifies whether this class is abstract.
+        */
+       public bool is_abstract {
+               private set;
+               get;
+       }
+
+       /**
+        * Specifies whether this class is fundamental.
+        */
+       public bool is_fundamental {
+               private set;
+               get;
+       }
+
+       public bool is_compact {
+               get {
+                       return base_type == null && get_attribute ("Compact") != null;
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type { get { return NodeType.CLASS; } }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_class (this);
+       }
+
+       private Vala.Set<Interface> _known_derived_interfaces = new Vala.HashSet<Interface> ();
+       private Vala.Set<Class> _known_child_classes = new Vala.HashSet<Class> ();
+
+       /**
+        * Returns a list of all known classes based on this class
+        */
+       public Vala.Collection<Class> get_known_child_classes () {
+               return _known_child_classes;
+       }
+
+       /**
+        * Returns a list of all known interfaces based on this class
+        */
+       public Vala.Collection<Interface> get_known_derived_interfaces () {
+               return _known_derived_interfaces;
+       }
+
+       public void register_derived_interface (Interface iface) {
+               _known_derived_interfaces.add (iface);
+       }
+
+       public void register_child_class (Class cl) {
+               if (this.base_type != null) {
+                       ((Class) this.base_type.data_type).register_child_class (cl);
+               }
+
+               _known_child_classes.add (cl);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               signature.append_keyword (accessibility.to_string ());
+               if (is_abstract) {
+                       signature.append_keyword ("abstract");
+               }
+               signature.append_keyword ("class");
+               signature.append_symbol (this);
+
+               var type_parameters = get_children_by_type (NodeType.TYPE_PARAMETER, false);
+               if (type_parameters.size > 0) {
+                       signature.append ("<", false);
+                       bool first = true;
+                       foreach (Item param in type_parameters) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_content (param.signature, false);
+                               first = false;
+                       }
+                       signature.append (">", false);
+               }
+
+               bool first = true;
+               if (base_type != null) {
+                       signature.append (":");
+
+                       signature.append_content (base_type.signature);
+                       first = false;
+               }
+
+               if (interfaces.size > 0) {
+                       if (first) {
+                               signature.append (":");
+                       }
+
+                       foreach (Item implemented_interface in interfaces) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_content (implemented_interface.signature);
+                               first = false;
+                       }
+               }
+
+               return signature.get ();
+       }
+}
+
diff --git a/libvaladoc/api/constant.vala b/libvaladoc/api/constant.vala
new file mode 100644
index 0000000..0ff79f2
--- /dev/null
+++ b/libvaladoc/api/constant.vala
@@ -0,0 +1,81 @@
+/* constant.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a type member with a constant value.
+ */
+public class Valadoc.Api.Constant : Member {
+       private string? cname;
+
+       /**
+        * The data type of this constant.
+        */
+       public TypeReference constant_type {
+               set;
+               get;
+       }
+
+       public Constant (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                        SourceComment? comment, string? cname, void* data)
+       {
+               base (parent, file, name, accessibility, comment, data);
+
+               this.cname = cname;
+       }
+
+       /**
+        * Returns the name of this constant as it is used in C.
+        */
+       public string get_cname () {
+               return cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               return new SignatureBuilder ()
+                       .append_keyword (accessibility.to_string ())
+                       .append_keyword ("const")
+                       .append_content (constant_type.signature)
+                       .append_symbol (this)
+                       .get ();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.CONSTANT; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_constant (this);
+       }
+}
+
diff --git a/libvaladoc/api/delegate.vala b/libvaladoc/api/delegate.vala
new file mode 100644
index 0000000..9db4d9f
--- /dev/null
+++ b/libvaladoc/api/delegate.vala
@@ -0,0 +1,142 @@
+/* delegate.vala
+ *
+ * Copyright (C) 2008-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;
+
+
+/**
+ * Represents a Delegate.
+ */
+public class Valadoc.Api.Delegate : TypeSymbol, Callable {
+       private string? cname;
+
+       /**
+        * {@inheritDoc}
+        */
+       internal string? implicit_array_length_cparameter_name {
+               get;
+               set;
+       }
+
+
+       public Delegate (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                        SourceComment? comment, string? cname, bool is_static, void* data)
+       {
+               base (parent, file, name, accessibility, comment, null, null, null, null, false, data);
+
+               this.is_static = is_static;
+               this.cname = cname;
+       }
+
+       /**
+        * Returns the name of this delegate as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public TypeReference? return_type {
+               set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.DELEGATE; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_delegate (this);
+       }
+
+       /**
+        * Specifies whether this delegate is static
+        */
+       public bool is_static {
+               private set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               signature.append_keyword (accessibility.to_string ());
+               signature.append_keyword ("delegate");
+               signature.append_content (return_type.signature);
+               signature.append_symbol (this);
+
+               var type_parameters = get_children_by_type (NodeType.TYPE_PARAMETER);
+               if (type_parameters.size > 0) {
+                       signature.append ("<", false);
+                       bool first = true;
+                       foreach (Item param in type_parameters) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_content (param.signature, false);
+                               first = false;
+                       }
+                       signature.append (">", false);
+               }
+
+               signature.append ("(");
+
+               bool first = true;
+               foreach (Node param in get_children_by_type (NodeType.FORMAL_PARAMETER, false)) {
+                       if (!first) {
+                               signature.append (",", false);
+                       }
+                       signature.append_content (param.signature, !first);
+                       first = false;
+               }
+
+               signature.append (")", false);
+
+               var exceptions = get_children_by_types ({NodeType.ERROR_DOMAIN, NodeType.CLASS});
+               if (exceptions.size > 0) {
+                       signature.append_keyword ("throws");
+                       first = true;
+                       foreach (Node param in exceptions) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_type (param);
+                               first = false;
+                       }
+               }
+
+               return signature.get ();
+       }
+}
+
diff --git a/libvaladoc/api/driver.vala b/libvaladoc/api/driver.vala
new file mode 100644
index 0000000..dd09ed3
--- /dev/null
+++ b/libvaladoc/api/driver.vala
@@ -0,0 +1,42 @@
+/* driver.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.Api;
+
+/**
+ * A plugin register function for drivers
+ *
+ * @see ModuleLoader
+ */
+[CCode (has_target = false)]
+public delegate Type Valadoc.DriverRegisterFunction (ModuleLoader module_loader);
+
+
+
+public interface Valadoc.Driver : Object {
+       public abstract void write_gir (Settings settings, ErrorReporter reporter);
+
+       public abstract Api.Tree? build (Settings settings, ErrorReporter reporter);
+}
+
+
diff --git a/libvaladoc/api/enum.vala b/libvaladoc/api/enum.vala
new file mode 100644
index 0000000..cbadb19
--- /dev/null
+++ b/libvaladoc/api/enum.vala
@@ -0,0 +1,71 @@
+/* enum.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents an enum declaration.
+ */
+public class Valadoc.Api.Enum : TypeSymbol {
+       private string cname;
+
+       public Enum (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                SourceComment? comment, string? cname, string? type_macro_name,
+                                string? type_function_name, void* data)
+       {
+               base (parent, file, name, accessibility, comment, type_macro_name, null, null,
+                       type_function_name, false, data);
+               this.cname = cname;
+       }
+
+       /**
+        * Returns the name of this enum as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type { get { return NodeType.ENUM; } }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_enum (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               return new SignatureBuilder ()
+                       .append_keyword (accessibility.to_string ())
+                       .append_keyword ("enum")
+                       .append_symbol (this)
+                       .get ();
+       }
+}
+
diff --git a/libvaladoc/api/enumvalue.vala b/libvaladoc/api/enumvalue.vala
new file mode 100644
index 0000000..e3ec568
--- /dev/null
+++ b/libvaladoc/api/enumvalue.vala
@@ -0,0 +1,114 @@
+/* enumvalue.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents an enum member.
+ */
+public class Valadoc.Api.EnumValue: Symbol {
+       private SourceComment? source_comment;
+       private string? cname;
+
+       public Content.Run default_value {
+               get;
+               set;
+       }
+
+       /**
+        * Specifies whether the parameter has a default value
+        */
+       public bool has_default_value {
+               get {
+                       return default_value != null;
+               }
+       }
+
+       public EnumValue (Enum parent, SourceFile file, string name, SourceComment? comment, string? cname, 
void* data) {
+               base (parent, file, name, parent.accessibility, data);
+
+               this.source_comment = comment;
+               this.cname = cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void parse_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       return ;
+               }
+
+               if (source_comment != null) {
+                       documentation = parser.parse (this, source_comment);
+               }
+
+               base.parse_comments (settings, parser);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void check_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       parser.check (this, documentation);
+               }
+
+               base.check_comments (settings, parser);
+       }
+
+       /**
+        * Returns the name of this enum value as it is used in C.
+        */
+       public string get_cname () {
+               return cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type { get { return NodeType.ENUM_VALUE; } }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_enum_value (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var builder = new SignatureBuilder ()
+                               .append_symbol (this);
+
+               if (has_default_value) {
+                       builder.append ("=");
+                       builder.append_content (default_value);
+               }
+
+               return builder.get ();
+       }
+}
+
diff --git a/libvaladoc/api/errorcode.vala b/libvaladoc/api/errorcode.vala
new file mode 100644
index 0000000..2d10fb6
--- /dev/null
+++ b/libvaladoc/api/errorcode.vala
@@ -0,0 +1,107 @@
+/* errorcode.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents an errordomain member in the source code.
+ */
+public class Valadoc.Api.ErrorCode : Symbol {
+       private SourceComment? source_comment;
+       private string? dbus_name;
+       private string? cname;
+
+       public ErrorCode (ErrorDomain parent, SourceFile file, string name, SourceComment? comment,
+                                         string? cname, string? dbus_name, void* data)
+       {
+               base (parent, file, name, parent.accessibility, data);
+
+               this.source_comment = comment;
+               this.dbus_name = dbus_name;
+               this.cname = cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void parse_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       return ;
+               }
+
+               if (source_comment != null) {
+                       documentation = parser.parse (this, source_comment);
+               }
+
+               base.parse_comments (settings, parser);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void check_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       parser.check (this, documentation);
+               }
+
+               base.check_comments (settings, parser);
+       }
+
+       /**
+        * Returns the name of this class as it is used in C.
+        */
+       public string get_cname () {
+               return cname;
+       }
+
+       /**
+        * Returns the dbus-name.
+        */
+       public string get_dbus_name () {
+               return dbus_name;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.ERROR_CODE; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_error_code (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               return new SignatureBuilder ()
+                       .append_symbol (this)
+                       .get ();
+       }
+}
+
diff --git a/libvaladoc/api/errordomain.vala b/libvaladoc/api/errordomain.vala
new file mode 100644
index 0000000..c469bf3
--- /dev/null
+++ b/libvaladoc/api/errordomain.vala
@@ -0,0 +1,100 @@
+/* errordomain.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents an error domain declaration.
+ */
+public class Valadoc.Api.ErrorDomain : TypeSymbol {
+       private string? quark_function_name;
+       private string? quark_macro_name;
+       private string? dbus_name;
+       private string? cname;
+
+       public ErrorDomain (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                               SourceComment? comment, string? cname, string? 
quark_macro_name,
+                                               string? quark_function_name, string? dbus_name, void* data)
+       {
+               base (parent, file, name, accessibility, comment, null, null, null, null, false, data);
+
+               this.quark_function_name = quark_function_name;
+               this.quark_macro_name = quark_macro_name;
+               this.dbus_name = dbus_name;
+               this.cname = cname;
+       }
+
+       /**
+        * Returns the name of this errordomain as it is used in C.
+        */
+       public string? get_cname () {
+               return this.cname;
+       }
+
+       /**
+        * Returns the dbus-name.
+        */
+       public string? get_dbus_name () {
+               return dbus_name;
+       }
+
+       /**
+        * Gets the name of the quark() function which represents the error domain
+        */
+       public string get_quark_function_name () {
+               return quark_function_name;
+       }
+
+       /**
+        * Gets the name of the quark macro which represents the error domain
+        */
+       public string get_quark_macro_name () {
+               return quark_macro_name;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.ERROR_DOMAIN; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_error_domain (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               return new SignatureBuilder ()
+                       .append_keyword (accessibility.to_string ())
+                       .append_keyword ("errordomain")
+                       .append_symbol (this)
+                       .get ();
+       }
+}
+
diff --git a/libvaladoc/api/field.vala b/libvaladoc/api/field.vala
new file mode 100644
index 0000000..d7a87a2
--- /dev/null
+++ b/libvaladoc/api/field.vala
@@ -0,0 +1,110 @@
+/* field.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a field.
+ */
+public class Valadoc.Api.Field : Member {
+       private string? cname;
+
+       public Field (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                 SourceComment? comment, string? cname, bool is_static, bool is_volatile,
+                                 void* data)
+       {
+               base (parent, file, name, accessibility, comment, data);
+
+               this.is_static = !(parent is Namespace) && is_static;
+               this.is_volatile = is_volatile;
+
+               this.cname = cname;
+       }
+
+       /**
+        * Returns the name of this field as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * The field type.
+        *
+        * @return The field type or null for void
+        */
+       public TypeReference? field_type {
+               set;
+               get;
+       }
+
+       /**
+        * Specifies whether the field is static.
+        */
+       public bool is_static {
+               private set;
+               get;
+       }
+
+       /**
+        * Specifies whether the field is volatile.
+        */
+       public bool is_volatile {
+               private set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               signature.append_keyword (accessibility.to_string ());
+               if (is_static) {
+                       signature.append_keyword ("static");
+               }
+               if (is_volatile) {
+                       signature.append_keyword ("volatile");
+               }
+
+               signature.append_content (field_type.signature);
+               signature.append_symbol (this);
+               return signature.get ();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.FIELD; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_field (this);
+       }
+}
+
diff --git a/libvaladoc/api/formalparameter.vala b/libvaladoc/api/formalparameter.vala
new file mode 100644
index 0000000..58c4c42
--- /dev/null
+++ b/libvaladoc/api/formalparameter.vala
@@ -0,0 +1,155 @@
+/* formalparameter.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a formal parameter in method, signal and delegate signatures.
+ */
+public class Valadoc.Api.FormalParameter : Symbol {
+       public Content.Run default_value {
+               get;
+               set;
+       }
+
+       /**
+        * Used to translate imported C-documentation
+        */
+       internal string? implicit_array_length_cparameter_name {
+               get;
+               set;
+       }
+
+       /**
+        * Used to translate imported C-documentation
+        */
+       internal string? implicit_closure_cparameter_name {
+               get;
+               set;
+       }
+
+       /**
+        * Used to translate imported C-documentation
+        */
+       internal string? implicit_destroy_cparameter_name {
+               get;
+               set;
+       }
+
+       private FormalParameterType type;
+
+       public FormalParameter (Node parent, SourceFile file, string? name, SymbolAccessibility 
accessibility, FormalParameterType type, bool ellipsis, void* data) {
+               base (parent, file, name, accessibility, data);
+               assert ((name == null && ellipsis) || (name != null && !ellipsis));
+
+               this.ellipsis = ellipsis;
+               this.type = type;
+       }
+
+       /**
+        * Specifies whether the parameter direction is out
+        */
+       public bool is_out {
+               get {
+                       return type == FormalParameterType.OUT;
+               }
+       }
+
+       /**
+        * Specifies whether the parameter direction is ref
+        */
+       public bool is_ref {
+               get {
+                       return type == FormalParameterType.REF;
+               }
+       }
+
+       /**
+        * Specifies whether the parameter has a default value
+        */
+       public bool has_default_value {
+               get {
+                       return default_value != null;
+               }
+       }
+
+       /**
+        * The parameter type.
+        *
+        * @return The parameter type or null for void
+        */
+       public TypeReference? parameter_type {
+               set;
+               get;
+       }
+
+       /**
+        * Specifies whether the methods accepts a variable number of arguments
+        */
+       public bool ellipsis {
+               private set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.FORMAL_PARAMETER; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_formal_parameter (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               if (ellipsis) {
+                       signature.append ("...");
+               } else {
+                       if (is_out) {
+                               signature.append_keyword ("out");
+                       } else if (is_ref) {
+                               signature.append_keyword ("ref");
+                       }
+
+                       signature.append_content (parameter_type.signature);
+                       signature.append (name);
+
+                       if (has_default_value) {
+                               signature.append ("=");
+                               signature.append_content (default_value);
+                       }
+               }
+
+               return signature.get ();
+       }
+}
+
diff --git a/libvaladoc/api/formalparametertype.vala b/libvaladoc/api/formalparametertype.vala
new file mode 100644
index 0000000..d95cc0f
--- /dev/null
+++ b/libvaladoc/api/formalparametertype.vala
@@ -0,0 +1,44 @@
+/* formalparametertype.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>
+ */
+
+public enum Valadoc.Api.FormalParameterType {
+       IN,
+       OUT,
+       REF;
+
+       public string to_string () {
+               switch (this) {
+               case FormalParameterType.OUT:
+                       return "out";
+
+               case FormalParameterType.REF:
+                       return "ref";
+
+               case FormalParameterType.IN:
+                       return "";
+
+               }
+
+               assert_not_reached ();
+       }
+}
+
diff --git a/libvaladoc/api/girsourcecomment.vala b/libvaladoc/api/girsourcecomment.vala
new file mode 100644
index 0000000..d6ffa5a
--- /dev/null
+++ b/libvaladoc/api/girsourcecomment.vala
@@ -0,0 +1,57 @@
+/* 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>
+ */
+
+
+/**
+ * A documentation comment used by valadoc
+ */
+public class Valadoc.Api.GirSourceComment : SourceComment {
+       private Vala.Map<string, SourceComment> parameters = new Vala.HashMap<string, SourceComment> 
(str_hash, str_equal);
+
+       public string? instance_param_name { set; get; }
+       public SourceComment? return_comment { set; get; }
+       public SourceComment? deprecated_comment { set; get; }
+       public SourceComment? version_comment { get; set; }
+       public SourceComment? stability_comment { get; set; }
+
+
+       public Vala.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/libvaladoc/api/interface.vala b/libvaladoc/api/interface.vala
new file mode 100644
index 0000000..ede696c
--- /dev/null
+++ b/libvaladoc/api/interface.vala
@@ -0,0 +1,213 @@
+/* interface.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a interface declaration in the source code.
+ */
+public class Valadoc.Api.Interface : TypeSymbol {
+       private string? interface_macro_name;
+       private string? dbus_name;
+       private string? cname;
+
+
+       public Interface (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                         SourceComment? comment, string? cname, string? type_macro_name, 
string? is_type_macro_name,
+                                         string? type_cast_macro_name, string? type_function_name, string 
interface_macro_name,
+                                         string? dbus_name, void* data)
+       {
+               base (parent, file, name, accessibility, comment, type_macro_name, is_type_macro_name,
+                         type_cast_macro_name, type_function_name, false, data);
+
+               this.interface_macro_name = interface_macro_name;
+               this.dbus_name = dbus_name;
+               this.cname = cname;
+       }
+
+       /**
+        * A list of preconditioned interfaces
+        */
+       private Vala.ArrayList<TypeReference> interfaces = new Vala.ArrayList<TypeReference> ();
+
+       /**
+        * Add a newpreconditioned interface to the list
+        */
+       public void add_interface (TypeReference iface) {
+               interfaces.add (iface);
+       }
+
+       /**
+        * Returns a list of newly preconditioned interfaces
+        */
+       public Vala.Collection<TypeReference> get_implemented_interface_list () {
+               return this.interfaces;
+       }
+
+
+       /**
+        * A list of all preconditioned interfaces
+        */
+       private Vala.Collection<TypeReference> _full_implemented_interfaces = null;
+
+       /**
+        * Returns a list of all preconditioned interfaces
+        */
+       public Vala.Collection<TypeReference> get_full_implemented_interface_list () {
+               if (_full_implemented_interfaces == null) {
+                       _full_implemented_interfaces = new Vala.ArrayList<TypeReference> ();
+                       _full_implemented_interfaces.add_all (this.interfaces);
+
+                       if (base_type != null) {
+                               _full_implemented_interfaces.add_all (((Class) 
base_type.data_type).get_full_implemented_interface_list ());
+                       }
+               }
+
+               return _full_implemented_interfaces;
+       }
+
+       /**
+        * Returns the name of this interface as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * Returns the dbus-name.
+        */
+       public string? get_dbus_name () {
+               return dbus_name;
+       }
+
+       /**
+        * Gets the name of the GType macro which returns the interface struct.
+        */
+       public string get_interface_macro_name () {
+               return interface_macro_name;
+       }
+
+       /**
+        * A preconditioned class or null
+        */
+       public TypeReference? base_type {
+               set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.INTERFACE; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_interface (this);
+       }
+
+       /**
+        * A list of all known related (sub-)interfaces
+        */
+       private Vala.Set<Interface> _known_related_interfaces = new Vala.HashSet<Interface> ();
+
+       /**
+        * A list of all known implementations of this interface
+        */
+       private Vala.Set<Class> _known_implementations = new Vala.HashSet<Class> ();
+
+       /**
+        * Returns a list of all known implementations of this interface
+        */
+       public Vala.Collection<Class> get_known_implementations () {
+               return _known_implementations;
+       }
+
+       /**
+        * Returns a list of all known related (sub-)interfaces
+        */
+       public Vala.Collection<Interface> get_known_related_interfaces () {
+               return _known_related_interfaces;
+       }
+
+       public void register_related_interface (Interface iface) {
+               _known_related_interfaces.add (iface);
+       }
+
+       public void register_implementation (Class cl) {
+               _known_implementations.add (cl);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               signature.append_keyword (accessibility.to_string ());
+               signature.append_keyword ("interface");
+               signature.append_symbol (this);
+
+               var type_parameters = get_children_by_type (NodeType.TYPE_PARAMETER, false);
+               if (type_parameters.size > 0) {
+                       signature.append ("<", false);
+                       bool first = true;
+                       foreach (Item param in type_parameters) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_content (param.signature, false);
+                               first = false;
+                       }
+                       signature.append (">", false);
+               }
+
+               bool first = true;
+               if (base_type != null) {
+                       signature.append (":");
+
+                       signature.append_content (base_type.signature);
+                       first = false;
+               }
+
+               if (interfaces.size > 0) {
+                       if (first) {
+                               signature.append (":");
+                       }
+
+                       foreach (Item implemented_interface in interfaces) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_content (implemented_interface.signature);
+                               first = false;
+                       }
+               }
+
+               return signature.get ();
+       }
+}
+
diff --git a/libvaladoc/api/item.vala b/libvaladoc/api/item.vala
new file mode 100644
index 0000000..60967a7
--- /dev/null
+++ b/libvaladoc/api/item.vala
@@ -0,0 +1,70 @@
+/* item.vala
+ *
+ * Copyright (C) 2008  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;
+
+/**
+ * Represents a node in the api tree.
+ */
+public abstract class Valadoc.Api.Item : Object {
+       private Inline _signature;
+
+       public void* data {
+               private set;
+               get;
+       }
+
+       /**
+        * The parent of this item.
+        */
+       public Item parent {
+               protected set;
+               get;
+       }
+
+       public Item (void* data) {
+               this.data = data;
+       }
+
+       internal virtual void parse_comments (Settings settings, DocumentationParser parser) {
+       }
+
+       internal virtual void check_comments (Settings settings, DocumentationParser parser) {
+       }
+
+
+       /**
+        * The signature of this item.
+        */
+       public Inline signature {
+               get {
+                       if (_signature == null) {
+                               _signature = build_signature ();
+                       }
+                       return _signature;
+               }
+       }
+
+       protected abstract Inline build_signature ();
+}
+
diff --git a/libvaladoc/api/member.vala b/libvaladoc/api/member.vala
new file mode 100644
index 0000000..fcabbea
--- /dev/null
+++ b/libvaladoc/api/member.vala
@@ -0,0 +1,62 @@
+/* member.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public abstract class Valadoc.Api.Member : Symbol {
+       private SourceComment? source_comment;
+
+       public Member (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                  SourceComment? comment, void* data)
+       {
+               base (parent, file, name, accessibility, data);
+
+               this.source_comment = comment;
+       }
+
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void parse_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       return ;
+               }
+
+               if (source_comment != null) {
+                       documentation = parser.parse (this, source_comment);
+               }
+
+               base.parse_comments (settings, parser);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void check_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       parser.check (this, documentation);
+               }
+
+               base.check_comments (settings, parser);
+       }
+}
diff --git a/libvaladoc/api/method.vala b/libvaladoc/api/method.vala
new file mode 100644
index 0000000..bccbac5
--- /dev/null
+++ b/libvaladoc/api/method.vala
@@ -0,0 +1,265 @@
+/* method.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a function or a method.
+ */
+public class Valadoc.Api.Method : Member, Callable {
+       private string? finish_function_cname;
+       private string? dbus_result_name;
+       private string? dbus_name;
+       private string? cname;
+
+       private MethodBindingType binding_type;
+
+       /**
+        * {@inheritDoc}
+        */
+       internal string? implicit_array_length_cparameter_name {
+               get;
+               set;
+       }
+
+
+       public Method (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                  SourceComment? comment, string? cname, string? dbus_name, string? 
dbus_result_name,
+                                  string? finish_function_cname, MethodBindingType binding_type, bool 
is_yields,
+                                  bool is_dbus_visible, bool is_constructor, void* data)
+       {
+               base (parent, file, name, accessibility, comment, data);
+
+               this.finish_function_cname = finish_function_cname;
+               this.dbus_result_name = dbus_result_name;
+               this.dbus_name = dbus_name;
+               this.cname = cname;
+
+               this.binding_type = binding_type;
+               this.is_dbus_visible = is_dbus_visible;
+               this.is_constructor = is_constructor;
+               this.is_yields = is_yields;
+       }
+
+       /**
+        * Returns the name of this method as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * Returns the name of the finish function as it is used in C.
+        */
+       public string? get_finish_function_cname () {
+               return finish_function_cname;
+       }
+
+       /**
+        * Returns the dbus-name.
+        */
+       public string get_dbus_name () {
+               return dbus_name;
+       }
+
+       public string get_dbus_result_name () {
+               return dbus_result_name;
+       }
+
+       /**
+        * Specifies the virtual or abstract method this method overrides.
+        */
+       public weak Method? base_method {
+               set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public TypeReference? return_type {
+               set;
+               get;
+       }
+
+       /**
+        * Specifies whether this method is asynchronous
+        */
+       public bool is_yields {
+               private set;
+               get;
+       }
+
+       /**
+        * Specifies whether this method is abstract
+        */
+       public bool is_abstract {
+               get {
+                       return binding_type == MethodBindingType.ABSTRACT;
+               }
+       }
+
+       /**
+        * Specifies whether this method is virtual
+        */
+       public bool is_virtual {
+               get {
+                       return binding_type == MethodBindingType.VIRTUAL;
+               }
+       }
+
+       /**
+        * Specifies whether this method overrides another one
+        */
+       public bool is_override {
+               get {
+                       return binding_type == MethodBindingType.OVERRIDE;
+               }
+       }
+
+       /**
+        * Specifies whether this method is static
+        */
+       public bool is_static {
+               get {
+                       return !is_constructor && binding_type == MethodBindingType.STATIC
+                               && parent is Namespace == false;
+               }
+       }
+
+       /**
+        * Specifies whether this method is a creation method
+        */
+       public bool is_constructor {
+               private set;
+               get;
+       }
+
+       /**
+        * Specifies whether this method is inline
+        */
+       public bool is_inline {
+               get {
+                       return binding_type == MethodBindingType.INLINE;
+               }
+       }
+
+       /**
+        * Specifies whether this method is visible for dbus
+        */
+       public bool is_dbus_visible {
+               private set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               signature.append_keyword (accessibility.to_string ());
+
+               if (!is_constructor) {
+                       if (is_static) {
+                               signature.append_keyword ("static");
+                       } else if (is_abstract) {
+                               signature.append_keyword ("abstract");
+                       } else if (is_override) {
+                               signature.append_keyword ("override");
+                       } else if (is_virtual) {
+                               signature.append_keyword ("virtual");
+                       }
+                       if (is_inline) {
+                               signature.append_keyword ("inline");
+                       }
+                       if (is_yields) {
+                               signature.append_keyword ("async");
+                       }
+
+                       signature.append_content (return_type.signature);
+               }
+
+               signature.append_symbol (this);
+
+               var type_parameters = get_children_by_type (NodeType.TYPE_PARAMETER, false);
+               if (type_parameters.size > 0) {
+                       signature.append ("<", false);
+                       bool first = true;
+                       foreach (Item param in type_parameters) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_content (param.signature, false);
+                               first = false;
+                       }
+                       signature.append (">", false);
+               }
+
+               signature.append ("(");
+
+               bool first = true;
+               foreach (Node param in get_children_by_type (NodeType.FORMAL_PARAMETER, false)) {
+                       if (!first) {
+                               signature.append (",", false);
+                       }
+                       signature.append_content (param.signature, !first);
+                       first = false;
+               }
+
+               signature.append (")", false);
+
+               var exceptions = get_children_by_types ({NodeType.ERROR_DOMAIN, NodeType.CLASS});
+               if (exceptions.size > 0) {
+                       signature.append_keyword ("throws");
+                       first = true;
+                       foreach (Node param in exceptions) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_type (param);
+                               first = false;
+                       }
+               }
+
+               return signature.get ();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get {
+                       return is_constructor ? NodeType.CREATION_METHOD :
+                              is_static ? NodeType.STATIC_METHOD : NodeType.METHOD;
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_method (this);
+       }
+}
+
diff --git a/libvaladoc/api/methodbindingtype.vala b/libvaladoc/api/methodbindingtype.vala
new file mode 100644
index 0000000..c340c30
--- /dev/null
+++ b/libvaladoc/api/methodbindingtype.vala
@@ -0,0 +1,55 @@
+/* methodbindingtype.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:
+ *     Brosch Florian <flo brosch gmail com>
+ */
+
+
+public enum Valadoc.MethodBindingType {
+       UNMODIFIED,
+       OVERRIDE,
+       ABSTRACT,
+       VIRTUAL,
+       INLINE,
+       STATIC;
+
+       public string to_string () {
+               switch (this) {
+               case OVERRIDE:
+                       return "override";
+
+               case ABSTRACT:
+                       return "abstract";
+
+               case VIRTUAL:
+                       return "virtual";
+
+               case INLINE:
+                       return "inline";
+
+               case STATIC:
+                       return "static";
+
+               case UNMODIFIED:
+                       return "";
+               }
+
+               assert_not_reached ();
+       }
+}
diff --git a/libvaladoc/api/namespace.vala b/libvaladoc/api/namespace.vala
new file mode 100644
index 0000000..7e35166
--- /dev/null
+++ b/libvaladoc/api/namespace.vala
@@ -0,0 +1,96 @@
+/* namespace.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a namespace declaration.
+ */
+public class Valadoc.Api.Namespace : Symbol {
+       private SourceComment? source_comment;
+
+       public Namespace (Api.Node parent, SourceFile file, string? name, SourceComment? comment, void* data) 
{
+               base (parent, file, name, SymbolAccessibility.PUBLIC, data);
+
+               this.source_comment = comment;
+       }
+
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void parse_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       return ;
+               }
+
+               if (source_comment != null) {
+                       documentation = parser.parse (this, source_comment);
+               }
+
+               base.parse_comments (settings, parser);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void check_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       parser.check (this, documentation);
+               }
+
+               base.check_comments (settings, parser);
+       }
+
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               return new SignatureBuilder ()
+                       .append_keyword (accessibility.to_string ())
+                       .append_keyword ("namespace")
+                       .append_symbol (this)
+                       .get ();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type { get { return NodeType.NAMESPACE; } }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_namespace (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override bool is_browsable (Settings settings) {
+               return has_visible_children (settings);
+       }
+}
+
diff --git a/libvaladoc/api/node.vala b/libvaladoc/api/node.vala
new file mode 100644
index 0000000..f1bbd2c
--- /dev/null
+++ b/libvaladoc/api/node.vala
@@ -0,0 +1,723 @@
+/* node.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ * Copyright (C) 20011 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+/**
+ * Represents a node in the api tree.
+ */
+public abstract class Valadoc.Api.Node : Item, Browsable, Documentation {
+       protected bool do_document = false;
+       private SourceFile file;
+
+       /**
+        * The name of the node
+        */
+       public string? name {
+               private set;
+               get;
+       }
+
+       public SourceFile get_source_file () {
+               return file;
+       }
+
+       /**
+        * Returns the type of this node
+        */
+       public abstract NodeType node_type { get; }
+
+       private Vala.Map<string, Node> per_name_children;
+       private Vala.Map<NodeType, Vala.List<Node>> per_type_children;
+
+
+       public Node (Node? parent, SourceFile? file, string? name, void* data) {
+               base (data);
+
+               per_name_children = new Vala.HashMap<string, Node> (str_hash, str_equal);
+               per_type_children = new Vala.HashMap<NodeType, Vala.List<Node>> ();
+
+               if (name != null && (is_keyword (name) || name[0].isdigit ())) {
+                       this.name = "@" + name;
+               } else {
+                       this.name = name;
+               }
+
+               this.parent = parent;
+               this.file = file;
+       }
+
+       /**
+        * Visits this node with the specified Visitor.
+        *
+        * @param visitor the visitor to be called while traversing
+        */
+       public abstract void accept (Visitor visitor);
+
+       /**
+        * {@inheritDoc}
+        */
+       // TODO: rename to is_visible
+       public abstract bool is_browsable (Settings settings);
+
+       /**
+        * {@inheritDoc}
+        */
+       public string? get_filename () {
+               if (file == null) {
+                       return null;
+               }
+
+               return file.relative_path;
+       }
+
+       public void add_child (Symbol child) {
+               if (child.name != null) {
+                       if (child.name[0] == '@') {
+                               per_name_children.set (child.name.next_char (), child);
+                       } else {
+                               per_name_children.set (child.name, child);
+                       }
+               } else {
+                       // Special case for the root namespace
+                       per_name_children.set ("", child);
+               }
+
+               Vala.List<Node> children = per_type_children.get (child.node_type);
+               if (children == null) {
+                       children = new Vala.ArrayList<Node> ();
+                       per_type_children.set (child.node_type, children);
+               }
+
+               children.add (child);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void parse_comments (Settings settings, DocumentationParser parser) {
+               do_document = true;
+
+               foreach (Node node in per_name_children.get_values ()) {
+                       if (node.is_browsable (settings)) {
+                               node.parse_comments (settings, parser);
+                       }
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void check_comments (Settings settings, DocumentationParser parser) {
+
+               foreach (Node node in per_name_children.get_values ()) {
+                       if (node.is_browsable (settings)) {
+                               node.check_comments (settings, parser);
+                       }
+               }
+       }
+
+
+       /**
+        * Specifies whether this node has at least one visible child with the given type
+        *
+        * @param type a node type
+        */
+       public bool has_visible_children_by_type (NodeType type, Settings settings) {
+               Vala.List<Node>? all_children = per_type_children.get (type);
+               if (all_children != null) {
+                       foreach (Node node in all_children) {
+                               if (node.is_browsable (settings)) {
+                                       return true;
+                               }
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Specifies whether this node has at least one visible child with the given types
+        *
+        * @param types a list of node types
+        */
+       public bool has_visible_children_by_types (NodeType[] types, Settings settings) {
+               foreach (NodeType type in types) {
+                       if (has_visible_children_by_type (type, settings)) {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Specifies whether this node has at least one visible child
+        */
+       public bool has_visible_children (Settings settings) {
+               return has_visible_children_by_types (per_type_children.get_keys ().to_array (), settings);
+       }
+
+       /**
+        * Specifies whether this node has at least one child with the given type
+        *
+        * @param type a node type
+        */
+       public bool has_children_by_type (NodeType type) {
+               Vala.List<Node>? all_children = per_type_children.get (type);
+               return all_children != null && !all_children.is_empty;
+       }
+
+       /**
+        * Specifies whether this node has at least one child with the given types
+        *
+        * @param types a list of node types
+        */
+       public bool has_children (NodeType[] types) {
+               foreach (NodeType type in types) {
+                       if (has_children_by_type (type)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Returns a list of all children with the given type.
+        *
+        * @param type a node type
+        * @param filtered specifies whether nodes which are not browsable should appear in the list
+        */
+       public Vala.List<Node> get_children_by_type (NodeType type, bool filtered = true) {
+               var children = new Vala.ArrayList<Node> ();
+
+               Vala.List<Node> all_children = per_type_children.get (type);
+               if (all_children != null) {
+                       foreach (Node node in all_children) {
+                               if (node.do_document || !filtered) {
+                                       children.add (node);
+                               }
+                       }
+               }
+
+               return children;
+       }
+
+       /**
+        * Returns a list of all children with the given types.
+        *
+        * @param types a list of node types
+        * @param filtered specifies whether nodes which are not browsable should appear in the list
+        */
+       public Vala.List<Node> get_children_by_types (NodeType[] types, bool filtered = true) {
+               var children = new Vala.ArrayList<Node> ();
+
+               foreach (NodeType type in types) {
+                       children.add_all (get_children_by_type (type, filtered));
+               }
+
+               return children;
+       }
+
+       /**
+        * Visits all children of this node with the given type with the specified Visitor.
+        *
+        * @param type a node type
+        * @param visitor the visitor to be called while traversing
+        * @param filtered specifies whether nodes which are not browsable should appear in the list
+        */
+       public void accept_children_by_type (NodeType type, Visitor visitor, bool filtered = true) {
+               Vala.List<Node> all_children = per_type_children.get (type);
+               if (all_children != null) {
+                       foreach (Node node in all_children) {
+                               if (node.do_document || !filtered) {
+                                       node.accept (visitor);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Visits all children of this node with the given types with the specified Visitor.
+        *
+        * @param types a list of node types
+        * @param visitor the visitor to be called while traversing
+        * @param filtered specifies whether nodes which are not browsable should appear in the list
+        */
+       public void accept_children (NodeType[] types, Visitor visitor, bool filtered = true) {
+               foreach (NodeType type in types) {
+                       accept_children_by_type (type, visitor, filtered);
+               }
+       }
+
+       /**
+        * Visits all children of this node with the specified Visitor.
+        *
+        * @param visitor the visitor to be called while traversing
+        * @param filtered specifies whether nodes which are not browsable should appear in the list
+        */
+       public void accept_all_children (Visitor visitor, bool filtered = true) {
+               foreach (Vala.List<Node> children in per_type_children.get_values ()) {
+                       foreach (Node node in children) {
+                               if (node.do_document || !filtered) {
+                                       node.accept (visitor);
+                               }
+                       }
+               }
+       }
+
+       public Node? find_by_name (string name) {
+               if (name[0] == '@') {
+                       return per_name_children.get (name.next_char ());
+               } else {
+                       return per_name_children.get (name);
+               }
+       }
+
+       private Namespace? _nspace = null;
+       private Package? _package = null;
+       private string _full_name = null;
+
+       /**
+        * The corresponding namespace
+        */
+       public Namespace? nspace {
+               get {
+                       if (this._nspace == null) {
+                               Api.Item ast = this;
+                               while (ast is Valadoc.Api.Namespace == false) {
+                                       ast = ast.parent;
+                                       if (ast == null) {
+                                               return null;
+                                       }
+                               }
+                               this._nspace = (Valadoc.Api.Namespace)ast;
+                       }
+                       return this._nspace;
+               }
+       }
+
+       /**
+        * The corresponding package such as a vapi or gir file
+        */
+       public Package? package {
+               get {
+                       if (this._package == null) {
+                               Api.Item ast = this;
+                               while (ast is Valadoc.Api.Package == false) {
+                                       ast = ast.parent;
+                                       if (ast == null) {
+                                               return null;
+                                       }
+                               }
+                               this._package = (Valadoc.Api.Package)ast;
+                       }
+                       return this._package;
+               }
+       }
+
+       public Content.Comment? documentation {
+               internal set;
+               get;
+       }
+
+       /**
+        * Returns canonicalized absolute name (GLib.FileStream for instance)
+        */
+       public string? get_full_name () {
+               if (this._full_name == null) {
+                       if (this.name == null) {
+                               return null;
+                       }
+
+                       GLib.StringBuilder full_name = new GLib.StringBuilder (this.name);
+
+                       if (this.parent != null) {
+                               for (Item pos = this.parent; pos is Package == false ; pos = pos.parent) {
+                                       string name = ((Node)pos).name;
+                                       if (name != null) {
+                                               full_name.prepend_unichar ('.');
+                                               full_name.prepend (name);
+                                       }
+                               }
+                       }
+                       this._full_name = full_name.str;
+               }
+               return this._full_name;
+       }
+
+       /**
+        * A comparison function used to sort nodes in alphabetical order
+        */
+       public int compare_to (Node node) {
+               return strcmp (name, node.name);
+       }
+
+       private bool is_keyword (string name) {
+               switch (name[0]) {
+               case 'a':
+                       switch (name[1]) {
+                       case 'b':
+                               return name == "abstract";
+
+                       case 's':
+                               if (name[2] == '\0') {
+                                       return true;
+                               }
+
+                               return name == "async";
+                       }
+                       break;
+
+               case 'b':
+                       switch (name[1]) {
+                       case 'a':
+                               return name == "base";
+
+                       case 'r':
+                               return name == "break";
+                       }
+                       break;
+
+               case 'c':
+                       switch (name[1]) {
+                       case 'a':
+                               switch (name[2]) {
+                               case 's':
+                                       return name == "case";
+
+                               case 't':
+                                       return name == "catch";
+                               }
+                               break;
+
+                       case 'l':
+                               return name == "class";
+
+                       case 'o':
+                               if (name[2] != 'n') {
+                                       return false;
+                               }
+
+                               switch (name[3]) {
+                               case 's':
+                                       if (name[4] == 't') {
+                                               switch (name[5]) {
+                                               case '\0':
+                                                       return true;
+
+                                               case 'r':
+                                                       return name == "construct";
+                                               }
+                                       }
+                                       break;
+
+                               case 't':
+                                       return name == "continue";
+                               }
+                               break;
+                       }
+                       break;
+
+               case 'd':
+                       switch (name[1]) {
+                       case 'e':
+                               switch (name[2]) {
+                               case 'f':
+                                       return name == "default";
+
+                               case 'l':
+                                       if (name[3] != 'e') {
+                                               return false;
+                                       }
+
+                                       switch (name[4]) {
+                                       case 'g':
+                                               return name == "delegate";
+
+                                       case 't':
+                                               return name == "delete";
+                                       }
+                                       break;
+                               }
+                               break;
+
+                       case 'o':
+                               return name[2] == '\0';
+
+                       case 'y':
+                               return name == "dynamic";
+                       }
+                       break;
+
+               case 'e':
+                       switch (name[1]) {
+                       case 'l':
+                               return name == "else";
+
+                       case 'n':
+                               switch (name[2]) {
+                               case 's':
+                                       return name == "ensures";
+
+                               case 'u':
+                                       return name == "enum";
+                               }
+                               break;
+
+                       case 'r':
+                               return name == "errordomain";
+
+                       case 'x':
+                               return name == "extern";
+                       }
+                       break;
+
+               case 'f':
+                       switch (name[1]) {
+                       case 'a':
+                               return name == "false";
+
+                       case 'i':
+                               return name == "finally";
+
+                       case 'o':
+                               if (name[2] != 'r') {
+                                       return false;
+                               }
+
+                               switch (name[3]) {
+                               case '\0':
+                                       return true;
+
+                               case 'e':
+                                       return name == "foreach";
+                               }
+                               break;
+                       }
+                       break;
+
+               case 'g':
+                       return name == "get";
+
+               case 'i':
+                       switch (name[1]) {
+                       case 'f':
+                               return name[2] == '\0';
+
+                       case 'n':
+                               switch (name[2]) {
+                               case '\0':
+                                       return true;
+
+                               case 'l':
+                                       return name == "inline";
+
+                               case 't':
+                                       return name == "interface" || name == "internal";
+                               }
+                               break;
+
+                       case 's':
+                               return name[2] == '\0';
+                       }
+                       break;
+
+               case 'l':
+                       return name == "lock";
+
+               case 'n':
+                       switch (name[1]) {
+                       case 'a':
+                               return name == "namespace";
+
+                       case 'e':
+                               return name == "new";
+
+                       case 'u':
+                               return name == "null";
+                       }
+                       break;
+
+               case 'o':
+                       switch (name[1]) {
+                       case 'u':
+                               return name == "out";
+
+                       case 'v':
+                               return name == "override";
+
+                       case 'w':
+                               return name == "owned";
+                       }
+                       break;
+
+               case 'p':
+                       switch (name[1]) {
+                       case 'a':
+                               return name == "params";
+
+                       case 'r':
+                               switch (name[2]) {
+                               case 'i':
+                                       return name == "private";
+
+                               case 'o':
+                                       return name == "protected";
+                               }
+                               break;
+                       case 'u':
+                               return name == "public";
+                       }
+                       break;
+
+               case 'r':
+                       if (name[1] != 'e') {
+                               return false;
+                       }
+
+                       switch (name[2]) {
+                       case 'f':
+                               return name[3] == '\0';
+
+                       case 'q':
+                               return name == "requires";
+
+                       case 't':
+                               return name == "return";
+                       }
+                       break;
+
+               case 's':
+                       switch (name[1]) {
+                       case 'e':
+                               switch (name[2]) {
+                               case 'a':
+                                       return name == "sealed";
+
+                               case 't':
+                                       return name[3] == '\0';
+                               }
+                               break;
+
+                       case 'i':
+                               switch (name[2]) {
+                               case 'g':
+                                       return name == "signal";
+                               case 'z':
+                                       return name == "sizeof";
+                               }
+                               break;
+
+                       case 't':
+                               switch (name[2]) {
+                               case 'a':
+                                       return name == "static";
+
+                               case 'r':
+                                       return name == "struct";
+                               }
+                               break;
+
+                       case 'w':
+                               return name == "switch";
+                       }
+                       break;
+
+               case 't':
+                       switch (name[1]) {
+                       case 'h':
+                               switch (name[2]) {
+                               case 'i':
+                                       return name == "this";
+
+                               case 'r':
+                                       if (name[3] == 'o' && name[4] == 'w') {
+                                               return name[5] == '\0' || (name[5] == 's' && name[6] == '\0');
+                                       }
+                                       break;
+                               }
+                               break;
+
+                       case 'r':
+                               switch (name[2]) {
+                               case 'u':
+                                       return name == "true";
+
+                               case 'y':
+                                       return name[3] == '\0';
+                               }
+                               break;
+
+                       case 'y':
+                               return name == "typeof";
+                       }
+                       break;
+
+               case 'u':
+                       switch (name[1]) {
+                       case 'n':
+                               return name == "unowned";
+
+                       case 's':
+                               return name == "using";
+                       }
+                       break;
+
+               case 'v':
+                       switch (name[1]) {
+                       case 'a':
+                               return name == "var";
+
+                       case 'i':
+                               return name == "virtual";
+
+                       case 'o':
+                               switch (name[2]) {
+                               case 'i':
+                                       return name == "void";
+
+                               case 'l':
+                                       return name == "volatile";
+                               }
+                               break;
+                       }
+                       break;
+
+               case 'w':
+                       switch (name[1]) {
+                       case 'e':
+                               return name == "weak";
+
+                       case 'h':
+                               return name == "while";
+                       }
+                       break;
+
+               case 'y':
+                       return name == "yield";
+               }
+
+               return false;
+       }
+}
+
diff --git a/libvaladoc/api/nodetype.vala b/libvaladoc/api/nodetype.vala
new file mode 100644
index 0000000..dc515fa
--- /dev/null
+++ b/libvaladoc/api/nodetype.vala
@@ -0,0 +1,117 @@
+/* node.vala
+ *
+ * Copyright (C) 2008-2009     Didier Villevalois
+ * Copyright (C) 2007-20012    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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+/**
+ * Specifies the context of a node.
+ */
+public enum Valadoc.Api.NodeType {
+       CLASS,
+       CONSTANT,
+       CREATION_METHOD,
+       DELEGATE,
+       ENUM,
+       ENUM_VALUE,
+       ERROR_CODE,
+       ERROR_DOMAIN,
+       FIELD,
+       FORMAL_PARAMETER,
+       INTERFACE,
+       METHOD,
+       NAMESPACE,
+       PACKAGE,
+       PROPERTY,
+       PROPERTY_ACCESSOR,
+       SIGNAL,
+       STATIC_METHOD,
+       STRUCT,
+       TYPE_PARAMETER;
+
+       public string to_string () {
+               switch (this) {
+               case CLASS:
+                       return "CLASS";
+
+               case CONSTANT:
+                       return "CONSTANT";
+
+               case CREATION_METHOD:
+                       return "CREATION_METHOD";
+
+               case DELEGATE:
+                       return "DELEGATE";
+
+               case ENUM:
+                       return "ENUM";
+
+               case ENUM_VALUE:
+                       return "ENUM_VALUE";
+
+               case ERROR_CODE:
+                       return "ERROR_CODE";
+
+               case ERROR_DOMAIN:
+                       return "ERROR_DOMAIN";
+
+               case FIELD:
+                       return "FIELD";
+
+               case FORMAL_PARAMETER:
+                       return "FORMAL_PARAMETER";
+
+               case INTERFACE:
+                       return "INTERFACE";
+
+               case METHOD:
+                       return "METHOD";
+
+               case NAMESPACE:
+                       return "NAMESPACE";
+
+               case PACKAGE:
+                       return "PACKAGE";
+
+               case PROPERTY:
+                       return "PROPERTY";
+
+               case PROPERTY_ACCESSOR:
+                       return "PROPERTY_ACCESSOR";
+
+               case SIGNAL:
+                       return "SIGNAL";
+
+               case STATIC_METHOD:
+                       return "STATIC_METHOD";
+
+               case STRUCT:
+                       return "STRUCT";
+
+               case TYPE_PARAMETER:
+                       return "TYPE_PARAMETER";
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+}
+
diff --git a/libvaladoc/api/ownership.vala b/libvaladoc/api/ownership.vala
new file mode 100644
index 0000000..eb4f5b0
--- /dev/null
+++ b/libvaladoc/api/ownership.vala
@@ -0,0 +1,47 @@
+/* ownership.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>
+ */
+
+
+public enum Valadoc.Api.Ownership {
+       DEFAULT,
+       UNOWNED,
+       OWNED,
+       WEAK;
+
+       public string to_string () {
+               switch (this) {
+               case Ownership.UNOWNED:
+                       return "unowned";
+
+               case Ownership.OWNED:
+                       return "owned";
+
+               case Ownership.WEAK:
+                       return "weak";
+
+               case Ownership.DEFAULT:
+                       return "";
+               }
+
+               assert_not_reached ();
+       }
+}
diff --git a/libvaladoc/api/package.vala b/libvaladoc/api/package.vala
new file mode 100644
index 0000000..e2d9603
--- /dev/null
+++ b/libvaladoc/api/package.vala
@@ -0,0 +1,139 @@
+/* package.vala
+ *
+ * Copyright (C) 2008-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.Importer;
+
+public class Valadoc.Api.Package : Node {
+
+       /**
+        * Specifies whether this package is a dependency
+        */
+       public bool is_package {
+                private set;
+                get;
+       }
+
+       internal void set_dependency_list (Vala.ArrayList<Package> list) {
+               this._dependencies = list;
+       }
+
+       private Vala.ArrayList<Package> _dependencies;
+
+       /**
+        * Returns a list with all dependencies
+        */
+       public Vala.Collection<Package> get_full_dependency_list () {
+               Vala.ArrayList<Package> list = new Vala.ArrayList<Package> ();
+
+               if (this._dependencies == null) {
+                       return list;
+               }
+
+               foreach (Package pkg in this._dependencies) {
+                       if (list.contains ( pkg ) == false) {
+                               list.add (pkg);
+                       }
+
+                       var pkg_list = pkg.get_full_dependency_list ();
+                       foreach (Package pkg2 in pkg_list) {
+                               if (list.contains (pkg2) == false) {
+                                       list.add (pkg2);
+                               }
+                       }
+               }
+               return list;
+       }
+
+       public Vala.Collection<Package> get_dependency_list () {
+               if (this._dependencies == null) {
+                       return new Vala.ArrayList<Package> ();
+               }
+
+               return this._dependencies;
+       }
+
+       public Package (string name, bool is_package, void* data) {
+               base (null, null, name, data);
+
+               this.is_package = is_package;
+               this.parent = null;
+       }
+
+       // <version, symbols>
+       private Vala.HashMap<string?, Vala.ArrayList<Symbol>> deprecated;
+
+       internal void register_deprecated_symbol (Symbol symbol, string? version) {
+               if (deprecated == null) {
+                       deprecated = new Vala.HashMap<string?, Vala.ArrayList<Symbol>> (str_hash, str_equal);
+               }
+
+               Vala.ArrayList<Symbol> list = deprecated.get (version);
+               if (list == null) {
+                       list = new Vala.ArrayList<Symbol> ();
+                       deprecated.set (version, list);
+               }
+
+               list.add (symbol);
+       }
+
+       public Vala.Map<string?, Vala.Collection<Symbol>> get_deprecated_symbols () {
+               if (deprecated == null) {
+                       return new Vala.HashMap<string?, Vala.Collection<Symbol>> (str_hash, str_equal);
+               }
+
+               return deprecated;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override bool is_browsable (Settings settings) {
+               return !(this.is_package && settings.with_deps == false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.PACKAGE; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_package (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               return new SignatureBuilder ()
+                       .append_keyword ("package")
+                       .append (name)
+                       .get ();
+       }
+}
+
diff --git a/libvaladoc/api/pointer.vala b/libvaladoc/api/pointer.vala
new file mode 100644
index 0000000..954acd9
--- /dev/null
+++ b/libvaladoc/api/pointer.vala
@@ -0,0 +1,54 @@
+/* pointer.vala
+ *
+ * Copyright (C) 2008  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;
+
+/**
+ * Represents a pointer declaration.
+ */
+public class Valadoc.Api.Pointer : Item {
+
+       /**
+        * The type the pointer is referring to.
+        */
+       public Item data_type {
+               set;
+               get;
+       }
+
+       public Pointer (Item parent, void* data) {
+               base (data);
+
+               this.parent = parent;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               return new SignatureBuilder ()
+                       .append_content (data_type.signature)
+                       .append ("*", false)
+                       .get ();
+       }
+}
diff --git a/libvaladoc/api/property.vala b/libvaladoc/api/property.vala
new file mode 100644
index 0000000..235292f
--- /dev/null
+++ b/libvaladoc/api/property.vala
@@ -0,0 +1,201 @@
+/* property.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a property declaration.
+ */
+public class Valadoc.Api.Property : Member {
+       private PropertyBindingType binding_type;
+       private string? dbus_name;
+       private string? cname;
+
+       public Property (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                        SourceComment? comment, string? cname, string? dbus_name, bool 
is_dbus_visible,
+                                        PropertyBindingType binding_type, void* data)
+       {
+               base (parent, file, name, accessibility, comment, data);
+
+               this.is_dbus_visible = is_dbus_visible;
+               this.binding_type = binding_type;
+
+               this.dbus_name = dbus_name;
+               this.cname = cname;
+       }
+
+       /**
+        * Returns the name of this method as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * Returns the dbus-name.
+        */
+       public string get_dbus_name () {
+               return dbus_name;
+       }
+
+       /**
+        * The property type.
+        *
+        * @return The property type or null for void
+        */
+       public TypeReference? property_type {
+               set;
+               get;
+       }
+
+       /**
+        * Specifies whether the property is virtual.
+        */
+       public bool is_virtual {
+               get {
+                       return binding_type == PropertyBindingType.VIRTUAL;
+               }
+       }
+
+       /**
+        * Specifies whether the property is abstract.
+        */
+       public bool is_abstract {
+               get {
+                       return binding_type == PropertyBindingType.ABSTRACT;
+               }
+       }
+
+       /**
+        * Specifies whether the property is override.
+        */
+       public bool is_override {
+               get {
+                       return binding_type == PropertyBindingType.OVERRIDE;
+               }
+       }
+
+       /**
+        * Specifies whether the property is visible.
+        */
+       public bool is_dbus_visible {
+               private set;
+               get;
+       }
+
+       public PropertyAccessor? setter {
+               set;
+               get;
+       }
+
+       public PropertyAccessor? getter {
+               set;
+               get;
+       }
+
+       /**
+        * Specifies the virtual or abstract property this property overrides.
+        */
+       public Property base_property {
+               set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void parse_comments (Settings settings, DocumentationParser parser) {
+               if (getter != null && getter.is_browsable (settings)) {
+                       getter.parse_comments (settings, parser);
+               }
+
+               if (setter != null && setter.is_browsable (settings)) {
+                       setter.parse_comments (settings, parser);
+               }
+
+               base.parse_comments (settings, parser);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void check_comments (Settings settings, DocumentationParser parser) {
+               if (getter != null && getter.is_browsable (settings)) {
+                       getter.check_comments (settings, parser);
+               }
+
+               if (setter != null && setter.is_browsable (settings)) {
+                       setter.check_comments (settings, parser);
+               }
+
+               base.check_comments (settings, parser);
+       }
+
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               signature.append_keyword (accessibility.to_string ());
+               if (is_abstract) {
+                       signature.append_keyword ("abstract");
+               } else if (is_override) {
+                       signature.append_keyword ("override");
+               } else if (is_virtual) {
+                       signature.append_keyword ("virtual");
+               }
+
+               signature.append_content (property_type.signature);
+               signature.append_symbol (this);
+               signature.append ("{");
+
+               if (setter != null && setter.do_document) {
+                       signature.append_content (setter.signature);
+               }
+
+               if (getter != null && getter.do_document) {
+                       signature.append_content (getter.signature);
+               }
+
+               signature.append ("}");
+
+               return signature.get ();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.PROPERTY; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_property (this);
+       }
+}
+
diff --git a/libvaladoc/api/propertyaccessor.vala b/libvaladoc/api/propertyaccessor.vala
new file mode 100644
index 0000000..173edd8
--- /dev/null
+++ b/libvaladoc/api/propertyaccessor.vala
@@ -0,0 +1,133 @@
+/* propertyaccessor.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a get or set accessor of a property.
+ */
+public class Valadoc.Api.PropertyAccessor : Symbol {
+       private PropertyAccessorType type;
+       private Ownership ownership;
+       private string? cname;
+
+       public PropertyAccessor (Property parent, SourceFile file, string name, SymbolAccessibility 
accessibility,
+                                                        string? cname, PropertyAccessorType type, Ownership 
ownership, void* data)
+       {
+               base (parent, file, name, accessibility, data);
+
+               this.ownership = ownership;
+               this.cname = cname;
+               this.type = type;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.PROPERTY_ACCESSOR; }
+       }
+
+       /**
+        * Returns the name of this property accessor as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+       }
+
+       /**
+        * Specifies whether this accessor may be used to construct the property.
+        */
+       public bool is_construct {
+               get {
+                       return (type & PropertyAccessorType.CONSTRUCT) != 0;
+               }
+       }
+
+       /**
+        * Specifies whether this accessor is a setter.
+        */
+       public bool is_set {
+               get {
+                       return (type & PropertyAccessorType.SET) != 0;
+               }
+       }
+
+       /**
+        * Specifies whether this accessor is a getter.
+        */
+       public bool is_get {
+               get {
+                       return (type & PropertyAccessorType.GET) != 0;
+               }
+       }
+
+       /**
+        * Specifies whether the property is owned.
+        */
+       public bool is_owned {
+               get {
+                       return ownership == Ownership.OWNED;
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               // FIXME
+               if (!do_document) {
+                       return signature.get ();
+               }
+
+               if (((Property) parent).accessibility != accessibility) {
+                       signature.append_keyword (accessibility.to_string ());
+               }
+
+               if (is_set || is_construct) {
+                       if (is_construct) {
+                               signature.append_keyword ("construct");
+                       }
+                       if (is_set) {
+                               signature.append_keyword ("set");
+                       }
+               } else if (is_get) {
+                       if (is_owned) {
+                               signature.append_keyword ("owned");
+                       }
+                       signature.append_keyword ("get");
+               }
+               signature.append (";", false);
+
+               return signature.get ();
+       }
+}
+
diff --git a/libvaladoc/api/propertyaccessortype.vala b/libvaladoc/api/propertyaccessortype.vala
new file mode 100644
index 0000000..8453ca5
--- /dev/null
+++ b/libvaladoc/api/propertyaccessortype.vala
@@ -0,0 +1,43 @@
+/* propertyaccessor.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>
+ */
+
+
+public enum Valadoc.Api.PropertyAccessorType {
+       CONSTRUCT = 1 << 0,
+       SET = 1 << 1,
+       GET = 1 << 2;
+
+       public string to_string () {
+               if ((this & PropertyAccessorType.CONSTRUCT) != 0) {
+                       if ((this & PropertyAccessorType.SET) != 0) {
+                               return "construct set";
+                       }
+                       return "construct";
+               } else if ((this & PropertyAccessorType.SET) != 0) {
+                       return "set";
+               } else if ((this & PropertyAccessorType.GET) != 0) {
+                       return "get";
+               }
+
+               assert_not_reached ();
+       }
+}
diff --git a/libvaladoc/api/propertybindingtype.vala b/libvaladoc/api/propertybindingtype.vala
new file mode 100644
index 0000000..a8ce161
--- /dev/null
+++ b/libvaladoc/api/propertybindingtype.vala
@@ -0,0 +1,48 @@
+/* propertybindingtype.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>
+ */
+
+
+public enum Valadoc.Api.PropertyBindingType {
+       UNMODIFIED,
+       OVERRIDE,
+       ABSTRACT,
+       VIRTUAL;
+
+       public string to_string () {
+               switch (this) {
+               case OVERRIDE:
+                       return "override";
+
+               case ABSTRACT:
+                       return "abstract";
+
+               case VIRTUAL:
+                       return "virtual";
+
+               case UNMODIFIED:
+                       return "";
+               }
+
+               assert_not_reached ();
+       }
+}
+
diff --git a/libvaladoc/api/signal.vala b/libvaladoc/api/signal.vala
new file mode 100644
index 0000000..6e6f885
--- /dev/null
+++ b/libvaladoc/api/signal.vala
@@ -0,0 +1,145 @@
+/* signal.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents an signal.
+ */
+public class Valadoc.Api.Signal : Member, Callable {
+       private string? default_impl_cname;
+       private string? dbus_name;
+       private string? cname;
+
+
+       /**
+        * {@inheritDoc}
+        */
+       internal string? implicit_array_length_cparameter_name {
+               get;
+               set;
+       }
+
+
+       public Signal (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                  SourceComment? comment, string? cname, string? default_impl_cname, string? 
dbus_name, bool is_dbus_visible,
+                                  bool is_virtual, void* data)
+       {
+               base (parent, file, name, accessibility, comment, data);
+
+               this.default_impl_cname = default_impl_cname;
+               this.dbus_name = dbus_name;
+               this.cname = cname;
+
+               this.is_dbus_visible = is_dbus_visible;
+               this.is_virtual = is_virtual;
+       }
+
+       /**
+        * Returns the name of this signal as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       public string? get_default_impl_cname () {
+               return default_impl_cname;
+       }
+
+       /**
+        * Returns the dbus-name.
+        */
+       public string get_dbus_name () {
+               return dbus_name;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public TypeReference? return_type {
+               set;
+               get;
+       }
+
+       /**
+        * Specifies whether this signal is virtual
+        */
+       public bool is_virtual {
+               private set;
+               get;
+       }
+
+       /**
+        * Specifies whether this signal is visible for dbus
+        */
+       public bool is_dbus_visible {
+               private set;
+               get;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               signature.append_keyword (accessibility.to_string ());
+               if (is_virtual) {
+                       signature.append_keyword ("virtual");
+               }
+
+               signature.append_keyword ("signal");
+
+               signature.append_content (return_type.signature);
+               signature.append_symbol (this);
+               signature.append ("(");
+
+               bool first = true;
+               foreach (Node param in get_children_by_type (NodeType.FORMAL_PARAMETER, false)) {
+                       if (!first) {
+                               signature.append (",", false);
+                       }
+                       signature.append_content (param.signature, !first);
+                       first = false;
+               }
+
+               signature.append (")", false);
+
+               return signature.get ();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.SIGNAL; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_signal (this);
+       }
+}
+
diff --git a/libvaladoc/api/signaturebuilder.vala b/libvaladoc/api/signaturebuilder.vala
new file mode 100644
index 0000000..a897dae
--- /dev/null
+++ b/libvaladoc/api/signaturebuilder.vala
@@ -0,0 +1,180 @@
+/* signaturebuilder.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+/**
+ * Builds up a signature from the given items.
+ */
+public class Valadoc.Api.SignatureBuilder {
+       private Run run;
+       private Inline last_appended;
+
+       /**
+        * Creates a new SignatureBuilder
+        */
+       public SignatureBuilder () {
+               run = new Run (Run.Style.NONE);
+       }
+
+       private void append_text (string text) {
+               if (last_appended is Text) {
+                       ((Text) last_appended).content += text;
+               } else {
+                       run.content.add (last_appended = new Text (text));
+               }
+       }
+
+       /**
+        * Adds text onto the end of the builder. 
+        *
+        * @param text a string
+        * @param spaced add a space at the front of the string if necessary
+        * @return this
+        */
+       public SignatureBuilder append (string text, bool spaced = true) {
+               string content = (last_appended != null && spaced ? " " : "") + text;
+               append_text (content);
+               return this;
+       }
+
+       /**
+        * Adds text onto the end of the builder. 
+        *
+        * @param text a string
+        * @param spaced add a space at the front of the string if necessary
+        * @return this
+        */
+       public SignatureBuilder append_attribute (string text, bool spaced = true) {
+               string content = (last_appended != null && spaced ? " " : "") + text;
+               append_text (content);
+               return this;
+       }
+
+       /**
+        * Adds highlighted text onto the end of the builder. 
+        *
+        * @param text a string
+        * @param spaced add a space at the front of the string if necessary
+        * @return this
+        */
+       public SignatureBuilder append_highlighted (string text, bool spaced = true) {
+               string content = (last_appended != null && spaced ? " " : "") + text;
+               Run inner = new Run (Run.Style.ITALIC);
+               inner.content.add (new Text (content));
+               return append_content (inner, spaced);
+       }
+
+       /**
+        * Adds a Inline onto the end of the builder. 
+        *
+        * @param content a content
+        * @param spaced add a space at the front of the inline if necessary
+        * @return this
+        */
+       public SignatureBuilder append_content (Inline content, bool spaced = true) {
+               if (last_appended != null && spaced) {
+                       append_text (" ");
+               }
+               run.content.add (last_appended = content);
+               return this;
+       }
+
+       /**
+        * Adds a keyword onto the end of the builder. 
+        *
+        * @param keyword a keyword
+        * @param spaced add a space at the front of the keyword if necessary
+        * @return this
+        */
+       public SignatureBuilder append_keyword (string keyword, bool spaced = true) {
+               Run inner = new Run (Run.Style.LANG_KEYWORD);
+               inner.content.add (new Text (keyword));
+               return append_content (inner, spaced);
+       }
+
+       /**
+        * Adds a symbol onto the end of the builder. 
+        *
+        * @param node a node
+        * @param spaced add a space at the front of the node if necessary
+        * @return this
+        */
+       public SignatureBuilder append_symbol (Node node, bool spaced = true) {
+               Run inner = new Run (Run.Style.BOLD);
+               inner.content.add (new SymbolLink (node, node.name));
+               return append_content (inner, spaced);
+       }
+
+       /**
+        * Adds a type onto the end of the builder. 
+        *
+        * @param node a node
+        * @param spaced add a space at the front of the node if necessary
+        * @return this
+        */
+       public SignatureBuilder append_type (Node node, bool spaced = true) {
+               Run.Style style = Run.Style.LANG_TYPE;
+               if (node is TypeSymbol && ((TypeSymbol)node).is_basic_type) {
+                       style = Run.Style.LANG_BASIC_TYPE;
+               }
+
+               Run inner = new Run (style);
+               inner.content.add (new SymbolLink (node, node.name));
+               return append_content (inner, spaced);
+       }
+
+       /**
+        * Adds a type name onto the end of the builder. 
+        *
+        * @param name a type name
+        * @param spaced add a space at the front of the type name if necessary
+        * @return this
+        */
+       public SignatureBuilder append_type_name (string name, bool spaced = true) {
+               Run inner = new Run (Run.Style.LANG_TYPE);
+               inner.content.add (new Text (name));
+               return append_content (inner, spaced);
+       }
+
+       /**
+        * Adds a literal onto the end of the builder. 
+        *
+        * @param literal a literal
+        * @param spaced add a space at the front of the literal if necessary
+        * @return this
+        */
+       public SignatureBuilder append_literal (string literal, bool spaced = true) {
+               Run inner = new Run (Run.Style.LANG_LITERAL);
+               inner.content.add (new Text (literal));
+               return append_content (inner, spaced);
+       }
+
+       /**
+        * The content
+        */
+       public new Run get () {
+               return run;
+       }
+}
+
diff --git a/libvaladoc/api/sourcecomment.vala b/libvaladoc/api/sourcecomment.vala
new file mode 100644
index 0000000..2d8eb14
--- /dev/null
+++ b/libvaladoc/api/sourcecomment.vala
@@ -0,0 +1,85 @@
+/* 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>
+ */
+
+
+/**
+ * A documentation comment used by valadoc
+ */
+public class Valadoc.Api.SourceComment {
+       public SourceFile file {
+               private set;
+               get;            
+       }
+
+       /**
+        * The text describing the referenced source code.
+        */
+       public string content {
+               private set;
+               get;
+       }
+
+       /**
+        * The first line number of the referenced source code.
+        */
+       public int first_line {
+               private set;
+               get;
+       }
+
+       /**
+        * The first column number of the referenced source code.
+        */
+       public int first_column {
+               private set;
+               get;
+       }
+
+       /**
+        * The last line number of the referenced source code.
+        */
+       public int last_line {
+               private set;
+               get;
+       }
+
+       /**
+        * The last column number of the referenced source code.
+        */
+       public int last_column {
+               private set;
+               get;
+       }
+
+       public SourceComment (string content, SourceFile file, int first_line, int first_column,
+                                                 int last_line, int last_column)
+       {
+               this.first_column = first_column;
+               this.last_column = last_column;
+               this.first_line = first_line;
+               this.last_line = last_line;
+               this.content = content;
+               this.file = file;
+       }
+}
+
+
diff --git a/libvaladoc/api/sourcefile.vala b/libvaladoc/api/sourcefile.vala
new file mode 100644
index 0000000..9c34011
--- /dev/null
+++ b/libvaladoc/api/sourcefile.vala
@@ -0,0 +1,61 @@
+/* sourcefile.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:
+ *     Brosch Florian <flo brosch gmail com>
+ */
+
+
+/**
+ * Represents a source file
+ */
+public class Valadoc.Api.SourceFile : Object {
+
+       public Package package {
+               private set;
+               get;
+       }
+
+       public string relative_path {
+               private set;
+               get;
+       }
+
+       public string? relative_c_path {
+               private set;
+               get;
+       }
+
+       public string get_name () {
+               return Path.get_basename (relative_path);
+       }
+
+       public void* data {
+               private set;
+               get;
+       }
+
+       public SourceFile (Package package, string relative_path, string? relative_c_path, void* data) {
+               this.relative_c_path = relative_c_path;
+               this.relative_path = relative_path;
+               this.package = package;
+               this.data = data;
+       }
+}
+
+
diff --git a/libvaladoc/api/struct.vala b/libvaladoc/api/struct.vala
new file mode 100644
index 0000000..93bbce7
--- /dev/null
+++ b/libvaladoc/api/struct.vala
@@ -0,0 +1,173 @@
+/* struct.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;
+
+/**
+ * Represents a struct declaration.
+ */
+public class Valadoc.Api.Struct : TypeSymbol {
+       private string? dup_function_cname;
+       private string? copy_function_cname;
+       private string? free_function_cname;
+       private string? destroy_function_cname;
+       private string? type_id;
+       private string? cname;
+
+       public Struct (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                  SourceComment? comment, string? cname, string? type_macro_name,
+                                  string? type_function_name, string? type_id, string? dup_function_cname,
+                                  string? copy_function_cname, string? destroy_function_cname,
+                                  string? free_function_cname, bool is_basic_type, void* data)
+       {
+               base (parent, file, name, accessibility, comment, type_macro_name, null, null,
+                       type_function_name, is_basic_type, data);
+
+               this.dup_function_cname = dup_function_cname;
+               this.copy_function_cname = copy_function_cname;
+               this.free_function_cname = free_function_cname;
+               this.destroy_function_cname = destroy_function_cname;
+
+               this.cname = cname;
+       }
+
+       /**
+        * Specifies the base struct.
+        */
+       public TypeReference? base_type {
+               set;
+               get;
+       }
+
+
+       /**
+        * Returns the name of this struct as it is used in C.
+        */
+       public string? get_cname () {
+               return cname;
+       }
+
+       /**
+        * Returns the C symbol representing the runtime type id for this data type.
+        */
+       public string? get_type_id () {
+               return type_id;
+       }
+
+       /**
+        * Returns the C function name that duplicates instances of this data
+        * type.
+        */
+       public string? get_dup_function_cname () {
+               return dup_function_cname;
+       }
+
+       /**
+        * Returns the C function name that copies instances of this data
+        * type.
+        */
+       public string? get_copy_function_cname () {
+               return copy_function_cname;
+       }
+
+       /**
+        * Returns the C function name that frees instances of this data type.
+        */
+       public string? get_free_function_cname () {
+               return free_function_cname;
+       }
+
+       /**
+        * Returns the C function name that destroys instances of this data type.
+        */
+       public string? get_destroy_function_cname () {
+               return destroy_function_cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override NodeType node_type {
+               get { return NodeType.STRUCT; }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void accept (Visitor visitor) {
+               visitor.visit_struct (this);
+       }
+
+
+       private Vala.Set<Struct> _known_child_structs = new Vala.HashSet<Struct> ();
+
+       /**
+        * Returns a list of all known structs based on this struct
+        */
+       public Vala.Collection<Struct> get_known_child_structs () {
+               return _known_child_structs;
+       }
+
+       public void register_child_struct (Struct stru) {
+               if (this.base_type != null) {
+                       ((Struct) this.base_type.data_type).register_child_struct (stru);
+               }
+
+               _known_child_structs.add (stru);
+       }
+
+
+       /**
+        * {@inheritDoc}
+        */
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               signature.append_keyword (accessibility.to_string ());
+               signature.append_keyword ("struct");
+               signature.append_symbol (this);
+
+               var type_parameters = get_children_by_type (NodeType.TYPE_PARAMETER, false);
+               if (type_parameters.size > 0) {
+                       signature.append ("<", false);
+                       bool first = true;
+                       foreach (Item param in type_parameters) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_content (param.signature, false);
+                               first = false;
+                       }
+                       signature.append (">", false);
+               }
+
+               if (base_type != null) {
+                       signature.append (":");
+
+                       signature.append_content (base_type.signature);
+               }
+
+               return signature.get ();
+       }
+}
+
diff --git a/libvaladoc/api/symbol.vala b/libvaladoc/api/symbol.vala
new file mode 100644
index 0000000..020c28a
--- /dev/null
+++ b/libvaladoc/api/symbol.vala
@@ -0,0 +1,157 @@
+/* symbol.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+/**
+ * Represents a node in the symbol tree.
+ */
+public abstract class Valadoc.Api.Symbol : Node {
+       private Vala.ArrayList<Attribute> attributes;
+
+       public bool is_deprecated {
+               default = false;
+               private set;
+               get;
+       }
+
+       public Symbol (Node parent, SourceFile file, string? name, SymbolAccessibility accessibility,
+                                  void* data)
+       {
+               base (parent, file, name, data);
+
+               this.accessibility = accessibility;
+       }
+
+       public void add_attribute (Attribute att) {
+               if (attributes == null) {
+                       attributes = new Vala.ArrayList<Attribute> ();
+               }
+
+               // register deprecated symbols:
+               if (att.name == "Version") {
+                       AttributeArgument? deprecated = att.get_argument ("deprecated");
+                       AttributeArgument? version = att.get_argument ("deprecated_since");
+                       if ((deprecated != null && deprecated.get_value_as_boolean ()) || version != null) {
+                               string? version_str = (version != null) ? version.get_value_as_string () : 
null;
+
+                               package.register_deprecated_symbol (this, version_str);
+                               is_deprecated = true;
+                       }
+               } else if (att.name == "Deprecated") {
+                       AttributeArgument? version = att.get_argument ("version");
+                       string? version_str = (version != null) ? version.get_value_as_string () : null;
+
+                       package.register_deprecated_symbol (this, version_str);
+                       is_deprecated = true;
+               }
+
+               attributes.add (att);
+       }
+
+       public Vala.Collection<Attribute> get_attributes () {
+               if (attributes == null) {
+                       return new Vala.ArrayList<Attribute> ();
+               } else {
+                       return attributes;
+               }
+       }
+
+       public Attribute? get_attribute (string name) {
+               if (attributes != null) {
+                       foreach (Attribute att in attributes) {
+                               if (att.name == name) {
+                                       return att;
+                               }
+                       }
+               }
+
+               return null;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override bool is_browsable (Settings settings) {
+               if (!settings._private && this.is_private) {
+                       return false;
+               }
+               if (!settings._internal && this.is_internal) {
+                       return false;
+               }
+               if (!settings._protected && this.is_protected) {
+                       return false;
+               }
+
+               Item? pos = parent;
+               while (pos != null && pos is Symbol && pos is Namespace == false) {
+                       if (((Symbol) pos).is_browsable (settings) == false) {
+                               return false;
+                       }
+                       pos = pos.parent;
+               }
+
+               return true;
+       }
+
+       public SymbolAccessibility accessibility {
+               private set;
+               get;
+       }
+
+       /**
+        * Specifies whether this symbol is public.
+        */
+       public bool is_public {
+               get {
+                       return accessibility == SymbolAccessibility.PUBLIC;
+               }
+       }
+
+       /**
+        * Specifies whether this symbol is protected.
+        */
+       public bool is_protected {
+               get {
+                       return accessibility == SymbolAccessibility.PROTECTED;
+               }
+       }
+
+       /**
+        * Specifies whether this symbol is internal.
+        */
+       public bool is_internal {
+               get {
+                       return accessibility == SymbolAccessibility.INTERNAL;
+               }
+       }
+
+       /**
+        * Specifies whether this symbol is private.
+        */
+       public bool is_private {
+               get {
+                       return accessibility == SymbolAccessibility.PRIVATE;
+               }
+       }
+}
+
diff --git a/libvaladoc/api/symbolaccessibility.vala b/libvaladoc/api/symbolaccessibility.vala
new file mode 100644
index 0000000..9b78aa6
--- /dev/null
+++ b/libvaladoc/api/symbolaccessibility.vala
@@ -0,0 +1,51 @@
+/* SymbolAccessibility.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>
+ */
+
+
+/**
+ * The access modifier
+ */
+public enum Valadoc.Api.SymbolAccessibility {
+       PROTECTED,
+       INTERNAL,
+       PRIVATE,
+       PUBLIC;
+
+       public string to_string () {
+               switch (this) {
+               case SymbolAccessibility.PROTECTED:
+                       return "protected";
+
+               case SymbolAccessibility.INTERNAL:
+                       return "internal";
+
+               case SymbolAccessibility.PRIVATE:
+                       return "private";
+
+               case SymbolAccessibility.PUBLIC:
+                       return "public";
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+}
diff --git a/libvaladoc/api/tree.vala b/libvaladoc/api/tree.vala
new file mode 100644
index 0000000..4344c2e
--- /dev/null
+++ b/libvaladoc/api/tree.vala
@@ -0,0 +1,350 @@
+/* tree.vala
+ *
+ * Copyright (C) 2008-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.Importer;
+
+/**
+ * The root of the code tree.
+ */
+public class Valadoc.Api.Tree {
+       private Vala.List<InheritDocContainer> inheritdocs = new Vala.ArrayList<InheritDocContainer> ();
+       private Vala.ArrayList<string> external_c_files = new Vala.ArrayList<string>(str_equal);
+       private Vala.ArrayList<Package> packages = new Vala.ArrayList<Package>();
+       private Package source_package = null;
+       private Settings settings;
+       private ErrorReporter reporter;
+       private Highlighter.Highlighter _highlighter;
+       private CTypeResolver _cresolver = null;
+       private Package _source_package;
+
+
+       private class InheritDocContainer {
+               public unowned Taglets.InheritDoc taglet;
+               public unowned Api.Node taglet_container;
+
+               public InheritDocContainer (Api.Node taglet_container, Taglets.InheritDoc taglet) {
+                       this.taglet_container = taglet_container;
+                       this.taglet = taglet;
+               }
+       }
+
+
+       public void add_package(Package package) {
+               this.packages.add (package);
+       }
+
+       public void* data {
+               set;
+               get;
+       }
+
+       public Highlighter.Highlighter highlighter {
+               get {
+                       if (_highlighter == null) {
+                               _highlighter = new Highlighter.Highlighter ();
+                       }
+
+                       return _highlighter;
+               }
+       }
+
+       /**
+        * The root of the wiki tree.
+        */
+       public WikiPageTree? wikitree {
+               private set;
+               get;
+       }
+
+       /**
+        * Returns a list of C source files.
+        *
+        * @return list of C source files
+        */
+       public Vala.Collection<string> get_external_c_files () {
+               return external_c_files;
+       }
+
+       public void add_external_c_files (string name) {
+               external_c_files.add (name);
+       }
+
+
+       /**
+        * Returns a list of all packages in the tree
+        *
+        * @return list of all packages
+        */
+       public Vala.Collection<Package> get_package_list () {
+               return this.packages;
+       }
+
+       private void add_dependencies_to_source_package () {
+               if ( this.source_package != null ) {
+                       Vala.ArrayList<Package> deplst = new Vala.ArrayList<Package> ();
+                       foreach (Package pkg in this.packages) {
+                               if (pkg != this.source_package) {
+                                       deplst.add (pkg);
+                               }
+                       }
+                       this.source_package.set_dependency_list (deplst);
+               }
+       }
+
+       /**
+        * Visits this node with the specified Visitor.
+        *
+        * @param visitor the visitor to be called while traversing
+        */
+       public void accept (Visitor visitor) {
+               visitor.visit_tree (this);
+       }
+
+       /**
+        * Visits all children of this node with the given types with the specified Visitor.
+        *
+        * @param visitor the visitor to be called while traversing
+        */
+       public void accept_children (Visitor visitor) {
+               foreach (Node node in packages) {
+                       node.accept (visitor);
+               }
+       }
+
+       private Node? search_relative_to (Node element, string[] path) {
+               Api.Node? node = element;
+
+               foreach (string name in path) {
+                       node = node.find_by_name (name);
+                       if (node == null) {
+                               break;
+                       }
+               }
+
+               if (node == null && element.parent != null) {
+                       node = search_relative_to ((Node) element.parent, path);
+               }
+
+               return node;
+       }
+
+       public Node? search_symbol_path (Node? element, string[] path) {
+               Api.Node? node = null;
+
+               // relative to element
+               if (element != null) {
+                       node = search_relative_to (element, path);
+                       if (node != null) {
+                               return node;
+                       }
+               }
+
+
+               // absolute
+               foreach (Package package in packages) {
+                       // search in root namespace
+
+                       Node? global = package.find_by_name ("");
+                       if (global != null) {
+                               node = search_relative_to (global, path);
+                               if (node != null) {
+                                       return node;
+                               }
+                       }
+               }
+
+               return null;
+       }
+
+       public TypeSymbol? search_symbol_type_cstr (string cname) {
+               if (_cresolver == null) {
+                       _cresolver = new CTypeResolver (this);
+               }
+
+               return _cresolver.resolve_symbol_type (cname);          
+       }
+
+       public Node? search_symbol_cstr (Node? element, string cname) {
+               if (_cresolver == null) {
+                       _cresolver = new CTypeResolver (this);
+               }
+
+               return _cresolver.resolve_symbol (element, cname);
+       }
+
+       public Node? search_symbol_str (Node? element, string symname) {
+               string[] path = split_name (symname);
+
+               var node = search_symbol_path (element, path);
+               if (node != null) {
+                       return node;
+               }
+
+               if (path.length >= 2 && path[path.length-2] == path[path.length-2]) {
+                       path[path.length-2] = path[path.length-2]+"."+path[path.length-1];
+                       path.resize (path.length-1);
+                       return search_symbol_path (element, path);
+               }
+
+               return null;
+       }
+
+       private string[] split_name (string full_name) {
+               string[] params = (full_name).split (".", -1);
+               int i = 0; while (params[i] != null) i++;
+               params.length = i;
+               return params;
+       }
+
+       public Tree (ErrorReporter reporter, Settings settings, void* data = null) {
+               this.settings = settings;
+               this.reporter = reporter;
+               this.data = data;
+       }
+
+       // copied from valacodecontext.vala
+       private string? get_file_path (string basename, string[] directories) {
+               string filename = null;
+
+               if (directories != null) {
+                       foreach (string dir in directories) {
+                               filename = Path.build_filename (dir, basename);
+                               if (FileUtils.test (filename, FileTest.EXISTS)) {
+                                       return filename;
+                               }
+                       }
+               }
+
+               foreach (string dir in Environment.get_system_data_dirs ()) {
+                       filename = Path.build_filename (dir, basename);
+                       if (FileUtils.test (filename, FileTest.EXISTS)) {
+                               return filename;
+                       }
+               }
+
+               return null;
+       }
+
+       public bool create_tree ( ) {
+               this.add_dependencies_to_source_package ();
+               return true;
+       }
+
+       private Package? get_source_package () {
+               if (_source_package == null) {
+                       foreach (Package pkg in packages) {
+                               if (!pkg.is_package) {
+                                       _source_package = pkg;
+                                       break;
+                               }
+                       }
+               }
+
+               return _source_package;
+       }
+
+       private void parse_wiki (DocumentationParser docparser) {
+               this.wikitree = new WikiPageTree ();
+               var pkg = get_source_package ();
+               if (pkg != null) {
+                       wikitree.parse (settings, docparser, pkg, reporter);
+               }
+       }
+
+       private void check_wiki (DocumentationParser docparser) {
+               Package pkg = get_source_package ();
+               if (pkg != null) {
+                       wikitree.check (settings, docparser, pkg);
+               }
+       }
+
+       public void parse_comments (DocumentationParser docparser) {
+               parse_wiki (docparser);
+
+               foreach (Package pkg in this.packages) {
+                       if (pkg.is_browsable (settings)) {
+                               pkg.parse_comments (settings, docparser);
+                       }
+               }
+       }
+
+       public void check_comments (DocumentationParser docparser) {
+               check_wiki (docparser);
+
+               foreach (Package pkg in this.packages) {
+                       if (pkg.is_browsable (settings)) {
+                               pkg.check_comments (settings, docparser);
+                               postprocess_inheritdoc (docparser);
+                       }
+               }
+       }
+
+       internal void register_inheritdoc (Api.Node container, Taglets.InheritDoc taglet) {
+               inheritdocs.add (new InheritDocContainer (container, taglet));
+       }
+
+       private void postprocess_inheritdoc (DocumentationParser docparser) {
+               while (!this.inheritdocs.is_empty) {
+                       InheritDocContainer container = this.inheritdocs.remove_at (0);
+
+                       docparser.transform_inheritdoc (container.taglet_container, container.taglet);
+               }
+       }
+
+
+       /**
+        * Import documentation from various sources
+        *
+        * @param importers a list of importers
+        * @param packages sources
+        * @param import_directories List of directories where to find the files
+        */
+       public void import_comments (DocumentationImporter[] importers, string[] packages,
+                                                                         string[] import_directories)
+       {
+               Vala.HashSet<string> processed = new Vala.HashSet<string> ();
+               foreach (string pkg_name in packages) {
+                       bool imported = false;
+                       foreach (DocumentationImporter importer in importers) {
+                               string? path = get_file_path ("%s.%s".printf (pkg_name, 
importer.file_extension),
+                                                                                         import_directories);
+                               if (path == null) {
+                                       continue;
+                               }
+
+                               path = realpath (path);
+                               imported = true;
+
+                               if (!processed.contains (path)) {
+                                       importer.process (path);
+                                       processed.add (path);
+                               }
+                       }
+
+                       if (imported == false) {
+                               reporter.simple_error (null, "'%s' not found in specified import 
directories", pkg_name);
+                       }
+               }
+       }
+}
+
diff --git a/libvaladoc/api/typeparameter.vala b/libvaladoc/api/typeparameter.vala
new file mode 100644
index 0000000..9cfe864
--- /dev/null
+++ b/libvaladoc/api/typeparameter.vala
@@ -0,0 +1,61 @@
+/* typeparameter.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * Represents a generic type parameter in the source code.
+ */
+public class Valadoc.Api.TypeParameter : Symbol {
+
+       public TypeParameter (Node parent, SourceFile file, string name, void* data) {
+               base (parent, file, name, SymbolAccessibility.PUBLIC, data);
+       }
+
+       /**
+        * {@inheritDoc}
+        */ 
+       protected override Inline build_signature () {
+               return new SignatureBuilder ()
+                       .append_symbol (this)
+                       .get ();
+       }
+
+       /**
+        * {@inheritDoc}
+        */ 
+       public override NodeType node_type { get { return NodeType.TYPE_PARAMETER; } }
+
+       /**
+        * {@inheritDoc}
+        */ 
+       public override void accept (Visitor visitor) {
+               visitor.visit_type_parameter (this);
+       }
+
+       public override bool is_browsable (Settings settings) {
+               return false;
+       }
+
+}
+
diff --git a/libvaladoc/api/typereference.vala b/libvaladoc/api/typereference.vala
new file mode 100644
index 0000000..3fd975c
--- /dev/null
+++ b/libvaladoc/api/typereference.vala
@@ -0,0 +1,167 @@
+/* typereference.vala
+ *
+ * Copyright (C) 2008-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;
+
+/**
+ * A reference to a data type.
+ */
+public class Valadoc.Api.TypeReference : Item {
+       private Vala.ArrayList<TypeReference> type_arguments = new Vala.ArrayList<TypeReference> ();
+       private string? dbus_type_signature;
+       private Ownership ownership;
+
+       public TypeReference (Item parent, Ownership ownership, bool pass_ownership, bool is_dynamic,
+                                                 bool is_nullable, string? dbus_type_signature, void* data)
+       {
+               base (data);
+
+               this.dbus_type_signature = dbus_type_signature;
+               this.pass_ownership = pass_ownership;
+               this.is_nullable = is_nullable;
+               this.is_dynamic = is_dynamic;
+               this.ownership = ownership;
+               this.parent = parent;
+       }
+
+       /**
+        * Returns a copy of the list of generic type arguments.
+        *
+        * @return type argument list
+        */
+       public Vala.Collection<TypeReference> get_type_arguments () {
+               return this.type_arguments;
+       }
+
+       public void add_type_argument (TypeReference type_ref) {
+               type_arguments.add (type_ref);
+       }
+
+       /**
+        * The referred data type.
+        */
+       public Item? data_type {
+               set;
+               get;
+       }
+
+       public bool pass_ownership {
+               private set;
+               get;
+       }
+
+       /**
+        * Specifies that the expression is owned.
+        */
+       public bool is_owned {
+               get {
+                       return ownership == Ownership.OWNED;
+               }
+       }
+
+       /**
+        * Specifies that the expression is weak.
+        */
+       public bool is_weak {
+               get {
+                       return ownership == Ownership.WEAK;
+               }
+       }
+
+       /**
+        * Specifies that the expression is unwoned.
+        */
+       public bool is_unowned {
+               get {
+                       return ownership == Ownership.UNOWNED;
+               }
+       }
+
+
+       /**
+        * Specifies that the expression is dynamic.
+        */
+       public bool is_dynamic {
+               private set;
+               get;
+       }
+
+       /**
+        * Specifies that the expression may be null.
+        */
+       public bool is_nullable {
+               private set;
+               get;
+       }
+
+       public string? get_dbus_type_signature () {
+               return dbus_type_signature;
+       }
+
+       /**
+        * {@inheritDoc}
+        */ 
+       protected override Inline build_signature () {
+               var signature = new SignatureBuilder ();
+
+               if (is_dynamic) {
+                       signature.append_keyword ("dynamic");
+               }
+
+               if (is_weak) {
+                       signature.append_keyword ("weak");
+               } else if (is_owned) {
+                       signature.append_keyword ("owned");
+               } else if (is_unowned) {
+                       signature.append_keyword ("unowned");
+               }
+
+               if (data_type == null) {
+                       signature.append_keyword ("void");
+               } else if (data_type is Symbol) {
+                       signature.append_type ((Symbol) data_type);
+               } else {
+                       signature.append_content (data_type.signature);
+               }
+
+               if (type_arguments.size > 0) {
+                       signature.append ("<", false);
+                       bool first = true;
+                       foreach (Item param in type_arguments) {
+                               if (!first) {
+                                       signature.append (",", false);
+                               }
+                               signature.append_content (param.signature, false);
+                               first = false;
+                       }
+                       signature.append (">", false);
+               }
+
+               if (is_nullable) {
+                       signature.append ("?", false);
+               }
+
+               return signature.get ();
+       }
+}
+
diff --git a/libvaladoc/api/typesymbol.vala b/libvaladoc/api/typesymbol.vala
new file mode 100644
index 0000000..c7274ba
--- /dev/null
+++ b/libvaladoc/api/typesymbol.vala
@@ -0,0 +1,112 @@
+/* typesymbol.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+/**
+ * Represents a runtime data type.
+ */
+public abstract class Valadoc.Api.TypeSymbol : Symbol {
+       private SourceComment? source_comment;
+       private string? type_macro_name;
+       private string? is_type_macro_name;
+       private string? type_cast_macro_name;
+       private string? type_function_name;
+
+       public TypeSymbol (Node parent, SourceFile file, string name, SymbolAccessibility accessibility,
+                                          SourceComment? comment, string? type_macro_name, string? 
is_type_macro_name,
+                                          string? type_cast_macro_name, string? type_function_name, bool 
is_basic_type,
+                                          void* data)
+       {
+               base (parent, file, name, accessibility, data);
+
+               this.type_cast_macro_name = type_cast_macro_name;
+               this.is_type_macro_name = is_type_macro_name;
+               this.type_function_name = type_function_name;
+               this.type_macro_name = type_macro_name;
+
+               this.is_basic_type = is_basic_type;
+               this.source_comment = comment;
+       }
+
+       /**
+        * Specifies whether this symbol is a basic type (string, int, char, etc)
+        */
+       public bool is_basic_type {
+               private set;
+               get;
+       }
+
+       /**
+        * Gets the name of the GType macro which represents the type symbol
+        */
+       public string get_type_macro_name () {
+               return type_macro_name;
+       }
+
+       /**
+        * Gets the name of the GType macro which casts a type instance to the given type.
+        */
+       public string get_type_cast_macro_name () {
+               return type_cast_macro_name;
+       }
+
+       /**
+        * Gets the name of the GType macro which determines whether a type instance is of a given type.
+        */
+       public string get_is_type_macro_name () {
+               return is_type_macro_name;
+       }
+
+       /**
+        * Gets the name of the get_type() function which represents the type symbol
+        */
+       public string get_type_function_name () {
+               return type_function_name;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void parse_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       return ;
+               }
+
+               if (source_comment != null) {
+                       documentation = parser.parse (this, source_comment);
+               }
+
+               base.parse_comments (settings, parser);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       internal override void check_comments (Settings settings, DocumentationParser parser) {
+               if (documentation != null) {
+                       parser.check (this, documentation);
+               }
+
+               base.check_comments (settings, parser);
+       }
+}
diff --git a/libvaladoc/api/visitor.vala b/libvaladoc/api/visitor.vala
new file mode 100644
index 0000000..bf66a45
--- /dev/null
+++ b/libvaladoc/api/visitor.vala
@@ -0,0 +1,171 @@
+/* visitor.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+/**
+ * Abstract visitor for traversing API.
+ */
+public abstract class Valadoc.Api.Visitor : GLib.Object {
+       /**
+        * Visit operation called for api trees.
+        *
+        * @param item a tree
+        */
+       public virtual void visit_tree (Tree item) {
+       }
+
+       /**
+        * Visit operation called for packages like gir-files and vapi-files.
+        *
+        * @param item a package
+        */
+       public virtual void visit_package (Package item) {
+       }
+
+       /**
+        * Visit operation called for namespaces
+        *
+        * @param item a namespace
+        */
+       public virtual void visit_namespace (Namespace item) {
+       }
+
+       /**
+        * Visit operation called for interfaces.
+        *
+        * @param item a interface
+        */
+       public virtual void visit_interface (Interface item) {
+       }
+
+       /**
+        * Visit operation called for classes.
+        *
+        * @param item a class
+        */
+       public virtual void visit_class (Class item) {
+       }
+
+       /**
+        * Visit operation called for structs.
+        *
+        * @param item a struct
+        */
+       public virtual void visit_struct (Struct item) {
+       }
+
+       /**
+        * Visit operation called for properties.
+        *
+        * @param item a property
+        */
+       public virtual void visit_property (Property item) {
+       }
+
+       /**
+        * Visit operation called for fields.
+        *
+        * @param item a field
+        */
+       public virtual void visit_field (Field item) {
+       }
+
+       /**
+        * Visit operation called for constants.
+        *
+        * @param item a constant
+        */
+       public virtual void visit_constant (Constant item) {
+       }
+
+       /**
+        * Visit operation called for delegates.
+        *
+        * @param item a delegate
+        */
+       public virtual void visit_delegate (Delegate item) {
+       }
+
+       /**
+        * Visit operation called for signals.
+        *
+        * @param item a signal
+        */
+       public virtual void visit_signal (Signal item) {
+       }
+
+       /**
+        * Visit operation called for methods.
+        *
+        * @param item a method
+        */
+       public virtual void visit_method (Method item) {
+       }
+
+       /**
+        * Visit operation called for type parameters.
+        *
+        * @param item a type parameter
+        */
+       public virtual void visit_type_parameter (TypeParameter item) {
+       }
+
+       /**
+        * Visit operation called for formal parameters.
+        *
+        * @param item a formal parameter
+        */
+       public virtual void visit_formal_parameter (FormalParameter item) {
+       }
+
+       /**
+        * Visit operation called for error domains.
+        *
+        * @param item a error domain
+        */
+       public virtual void visit_error_domain (ErrorDomain item) {
+       }
+
+       /**
+        * Visit operation called for error codes.
+        *
+        * @param item a error code
+        */
+       public virtual void visit_error_code (ErrorCode item) {
+       }
+
+       /**
+        * Visit operation called for enums.
+        *
+        * @param item a enum
+        */
+       public virtual void visit_enum (Enum item) {
+       }
+
+       /**
+        * Visit operation called for enum values.
+        *
+        * @param item a enum value
+        */
+       public virtual void visit_enum_value (EnumValue item) {
+       }
+}
diff --git a/libvaladoc/charts/chart.vala b/libvaladoc/charts/chart.vala
new file mode 100644
index 0000000..a6307d7
--- /dev/null
+++ b/libvaladoc/charts/chart.vala
@@ -0,0 +1,73 @@
+/* chart.vala
+ *
+ * Copyright (C) 2008  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>
+ */
+
+
+public class Valadoc.Charts.Chart : Api.Visitor {
+       protected Gvc.Context context;
+       protected Gvc.Graph graph;
+       protected Factory factory;
+
+       static construct {
+               #if !WITH_CGRAPH
+               Gvc.init ();
+               #endif
+       }
+
+       public Chart (Factory factory, Api.Node node) {
+               graph = factory.create_graph (node);
+               this.factory = factory;
+               node.accept (this);
+       }
+
+       public void save (string file_name, string file_type = "png") {
+               if (context == null) {
+                       context = factory.create_context (graph);
+               }
+               context.render_filename (graph, file_type, file_name);
+       }
+
+       public void write (GLib.FileStream file, string file_type) {
+               if (context == null) {
+                       context = factory.create_context (graph);
+               }
+               context.render (graph, file_type, file);
+       }
+
+       public uint8[]? write_buffer (string file_type) {
+               if (context == null) {
+                       context = factory.create_context (graph);
+               }
+
+               uint8[]? data;
+
+               /* This will return null in data if it fails. */
+               context.render_data (graph, file_type, out data);
+               return data;
+       }
+
+       ~Chart () {
+               if (context != null) {
+                       context.free_layout (graph);
+               }
+       }
+}
+
diff --git a/libvaladoc/charts/chartfactory.vala b/libvaladoc/charts/chartfactory.vala
new file mode 100644
index 0000000..ab1ea73
--- /dev/null
+++ b/libvaladoc/charts/chartfactory.vala
@@ -0,0 +1,53 @@
+/* chartfactory.vala
+ *
+ * Copyright (C) 2008  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>
+ */
+
+
+public abstract class Valadoc.Charts.Factory : Object {
+       protected Gvc.Node create_type (Gvc.Graph graph, Api.Node item) {
+#if WITH_CGRAPH
+               return graph.create_node (item.get_full_name (), 1);
+#else
+               return graph.create_node (item.get_full_name ());
+#endif
+       }
+
+       public abstract Gvc.Graph create_graph (Api.Node item);
+
+       public abstract Gvc.Context create_context (Gvc.Graph graph);
+
+       public abstract Gvc.Node create_class (Gvc.Graph graph, Api.Class item);
+
+       public abstract Gvc.Node create_struct (Gvc.Graph graph, Api.Struct item);
+
+       public abstract Gvc.Node create_interface (Gvc.Graph graph, Api.Interface item);
+
+       public abstract Gvc.Node create_enum (Gvc.Graph graph, Api.Enum item);
+
+       public abstract Gvc.Node create_delegate (Gvc.Graph graph, Api.Delegate item);
+
+       public abstract Gvc.Node create_errordomain (Gvc.Graph graph, Api.ErrorDomain item);
+
+       public abstract Gvc.Node create_namespace (Gvc.Graph graph, Api.Namespace item);
+
+       public abstract Gvc.Edge add_children (Gvc.Graph graph, Gvc.Node parent, Gvc.Node child);
+}
+
diff --git a/libvaladoc/charts/hierarchychart.vala b/libvaladoc/charts/hierarchychart.vala
new file mode 100644
index 0000000..c60882c
--- /dev/null
+++ b/libvaladoc/charts/hierarchychart.vala
@@ -0,0 +1,80 @@
+/* hierarchychart.vala
+ *
+ * Copyright (C) 2008  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>
+ */
+
+
+public class Valadoc.Charts.Hierarchy : Charts.Chart {
+       public Hierarchy (Factory factory, Api.Node node) {
+               base (factory, node);
+       }
+
+       private void draw_implemented_interfaces (Gvc.Node child, Vala.Collection<Api.TypeReference> 
interfaces) {
+               foreach (Api.TypeReference typeref in interfaces) {
+                       var parent = factory.create_interface (graph, (Api.Interface) typeref.data_type);
+                       factory.add_children (graph, parent, child);
+               }
+       }
+
+       private void draw_parent_classes (Api.Class item, Gvc.Node? child = null) {
+               var parent = factory.create_class (graph, item);
+
+               if (child != null) {
+                       factory.add_children (graph, parent, child);
+               }
+
+               if (item.base_type != null) {
+                       draw_parent_classes ((Api.Class) item.base_type.data_type, parent);
+               }
+
+               draw_implemented_interfaces (parent, item.get_implemented_interface_list ());
+       }
+
+       private void draw_parent_structs (Api.Struct item, Gvc.Node? child = null) {
+               var parent = factory.create_struct (graph, item);
+
+               if (child != null) {
+                       factory.add_children (graph, parent, child);
+               }
+
+               if (item.base_type != null) {
+                       draw_parent_structs ((Api.Struct) item.base_type.data_type, parent);
+               }
+       }
+
+       public override void visit_interface (Api.Interface item) {
+               var iface = factory.create_interface (graph, item);
+
+               if (item.base_type != null) {
+                       draw_parent_classes ((Api.Class) item.base_type.data_type, iface);
+               }
+
+               draw_implemented_interfaces (iface, item.get_implemented_interface_list ());
+       }
+
+       public override void visit_class (Api.Class item) {
+               draw_parent_classes (item);
+       }
+
+       public override void visit_struct (Api.Struct item) {
+               draw_parent_structs (item);
+       }
+}
+
diff --git a/libvaladoc/charts/simplechartfactory.vala b/libvaladoc/charts/simplechartfactory.vala
new file mode 100644
index 0000000..a1d080f
--- /dev/null
+++ b/libvaladoc/charts/simplechartfactory.vala
@@ -0,0 +1,87 @@
+/* simplechartfactory.vala
+ *
+ * Copyright (C) 2008  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>
+ */
+
+
+
+public class Valadoc.Charts.SimpleFactory : Charts.Factory {
+       protected virtual Gvc.Node configure_type (Gvc.Node node, Api.Node item) {
+               node.safe_set ("shape", "box", "");
+               node.safe_set ("fontname", "Times", "");
+               node.safe_set ("label", item.get_full_name (), "");
+               return node;
+       }
+
+       public override Gvc.Graph create_graph (Api.Node item) {
+#if WITH_CGRAPH
+               var graph = new Gvc.Graph (item.get_full_name (), Gvc.Agdirected, 0);
+#else
+               var graph = new Gvc.Graph (item.get_full_name (), Gvc.GraphKind.AGDIGRAPH);
+#endif
+               return graph;
+       }
+
+       public override Gvc.Context create_context (Gvc.Graph graph) {
+               var context = new Gvc.Context ();
+               context.layout_jobs (graph);
+               context.layout (graph, "dot");
+               return context;
+       }
+
+       public override Gvc.Node create_class (Gvc.Graph graph, Api.Class item) {
+               var node = configure_type (create_type (graph, item), item);
+               node.safe_set ("style", "bold", "");
+               return node;
+       }
+
+       public override Gvc.Node create_struct (Gvc.Graph graph, Api.Struct item) {
+               var node = configure_type (create_type (graph, item), item);
+               node.safe_set ("style", "bold", "");
+               return node;
+       }
+
+       public override Gvc.Node create_interface (Gvc.Graph graph, Api.Interface item) {
+               return configure_type (create_type (graph, item), item);
+       }
+
+       public override Gvc.Node create_enum (Gvc.Graph graph, Api.Enum item) {
+               return configure_type (create_type (graph, item), item);
+       }
+
+       public override Gvc.Node create_delegate (Gvc.Graph graph, Api.Delegate item) {
+               return configure_type (create_type (graph, item), item);
+       }
+
+       public override Gvc.Node create_errordomain (Gvc.Graph graph, Api.ErrorDomain item) {
+               return configure_type (create_type (graph, item), item);
+       }
+
+       public override Gvc.Node create_namespace (Gvc.Graph graph, Api.Namespace item) {
+               return configure_type (create_type (graph, item), item);
+       }
+
+       public override Gvc.Edge add_children (Gvc.Graph graph, Gvc.Node parent, Gvc.Node child) {
+               var edge = graph.create_edge (parent, child);
+               edge.safe_set ("dir", "back", "");
+               return edge;
+       }
+}
+
diff --git a/libvaladoc/content/block.vala b/libvaladoc/content/block.vala
new file mode 100644
index 0000000..99273ae
--- /dev/null
+++ b/libvaladoc/content/block.vala
@@ -0,0 +1,25 @@
+/* block.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+public interface Valadoc.Content.Block : ContentElement {
+}
+
diff --git a/libvaladoc/content/blockcontent.vala b/libvaladoc/content/blockcontent.vala
new file mode 100644
index 0000000..06e3d05
--- /dev/null
+++ b/libvaladoc/content/blockcontent.vala
@@ -0,0 +1,65 @@
+/* blockcontent.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public abstract class Valadoc.Content.BlockContent : ContentElement {
+       public Vala.List<Block> content { get { return _content; } }
+
+       private Vala.List<Block> _content;
+
+       construct {
+               _content = new Vala.ArrayList<Block> ();
+       }
+
+       internal BlockContent () {
+       }
+
+       public override void configure (Settings settings, ResourceLocator locator) {
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               foreach (Block element in _content) {
+                       element.parent = this;
+                       element.check (api_root, container, file_path, reporter, settings);
+               }
+       }
+
+       public override void accept_children (ContentVisitor visitor) {
+               foreach (Block element in _content) {
+                       element.accept (visitor);
+               }
+       }
+
+       public override bool is_empty () {
+               foreach (Block item in content) {
+                       if (!item.is_empty ()) {
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+}
+
diff --git a/libvaladoc/content/comment.vala b/libvaladoc/content/comment.vala
new file mode 100644
index 0000000..79362f5
--- /dev/null
+++ b/libvaladoc/content/comment.vala
@@ -0,0 +1,105 @@
+/* comment.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Taglets;
+
+public class Valadoc.Content.Comment : BlockContent {
+       public Vala.List<Taglet> taglets { get { return _taglets; } }
+       private Vala.List<Taglet> _taglets;
+
+       private bool checked = false;
+
+
+       internal Comment () {
+               base ();
+               _taglets = new Vala.ArrayList<Taglet> ();
+       }
+
+       public override void configure (Settings settings, ResourceLocator locator) {
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               if (checked == true) {
+                       return ;
+               }
+
+               checked = true;
+
+
+               base.check (api_root, container, file_path, reporter, settings);
+
+               foreach (Taglet element in _taglets) {
+                       element.parent = this;
+                       element.check (api_root, container, file_path, reporter, settings);
+               }
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_comment (this);
+       }
+
+       public override void accept_children (ContentVisitor visitor) {
+               base.accept_children (visitor);
+
+               foreach (Taglet element in _taglets) {
+                       element.accept (visitor);
+               }
+       }
+
+       public Vala.List<Taglet> find_taglets (Api.Node? container, Type taglet_type) {
+               Vala.List<Taglet> selected_taglets = new Vala.ArrayList<Taglet> ();
+
+               // TODO inherit stuff if needed
+
+               foreach (Taglet taglet in _taglets) {
+                       if (taglet.get_type () == taglet_type) {
+                               selected_taglets.add (taglet);
+                       }
+               }
+
+               return selected_taglets;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               assert (new_parent == null);
+
+               Comment comment = new Comment ();
+               comment.parent = new_parent;
+
+               foreach (Block element in content) {
+                       Block copy = element.copy (comment) as Block;
+                       comment.content.add (copy);
+               }
+
+               foreach (Taglet taglet in _taglets) {
+                       Taglet copy = taglet.copy (comment) as Taglet;
+                       comment.taglets.add (copy);
+               }
+
+               return comment;
+       }
+}
+
diff --git a/libvaladoc/content/contentelement.vala b/libvaladoc/content/contentelement.vala
new file mode 100644
index 0000000..13e99e3
--- /dev/null
+++ b/libvaladoc/content/contentelement.vala
@@ -0,0 +1,44 @@
+/* contentelement.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public abstract class Valadoc.Content.ContentElement : Object {
+       public ContentElement parent { get; internal set; }
+
+       public abstract ContentElement copy (ContentElement? new_parent = null);
+
+
+       public virtual void configure (Settings settings, ResourceLocator locator) {
+       }
+
+       public abstract void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings);
+
+       public abstract void accept (ContentVisitor visitor);
+
+       public abstract bool is_empty ();
+
+       public virtual void accept_children (ContentVisitor visitor) {
+       }
+}
+
diff --git a/libvaladoc/content/contentfactory.vala b/libvaladoc/content/contentfactory.vala
new file mode 100644
index 0000000..fc14fe4
--- /dev/null
+++ b/libvaladoc/content/contentfactory.vala
@@ -0,0 +1,122 @@
+/* contentfactory.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.ContentFactory : Object {
+
+       public ContentFactory (Settings settings, ResourceLocator locator, ModuleLoader modules) {
+               _settings = settings;
+               _locator = locator;
+               _modules = modules;
+       }
+
+       private Settings _settings;
+       private ResourceLocator _locator;
+       private ModuleLoader _modules;
+
+       private inline ContentElement configure (ContentElement element) {
+               element.configure (_settings, _locator);
+               return element;
+       }
+
+       public Comment create_comment () {
+               return (Comment) configure (new Comment ());
+       }
+
+       public Embedded create_embedded () {
+               return (Embedded) configure (new Embedded ());
+       }
+
+       public Headline create_headline () {
+               return (Headline) configure (new Headline ());
+       }
+
+       public Link create_link () {
+               return (Link) configure (new Link ());
+       }
+
+       public WikiLink create_wiki_link () {
+               return (WikiLink) configure (new WikiLink ());
+       }
+
+       public List create_list () {
+               return (List) configure (new List ());
+       }
+
+       public ListItem create_list_item () {
+               return (ListItem) configure (new ListItem ());
+       }
+
+       public Page create_page () {
+               return (Page) configure (new Page ());
+       }
+
+       public Paragraph create_paragraph () {
+               return (Paragraph) configure (new Paragraph ());
+       }
+
+       public Warning create_warning () {
+               return (Warning) configure (new Warning ());
+       }
+       public Note create_note () {
+               return (Note) configure (new Note ());
+       }
+
+       public Run create_run (Run.Style style) {
+               return (Run) configure (new Run (style));
+       }
+
+       public SourceCode create_source_code () {
+               return (SourceCode) configure (new SourceCode ());
+       }
+
+       public Table create_table () {
+               return (Table) configure (new Table ());
+       }
+
+       public TableCell create_table_cell () {
+               return (TableCell) configure (new TableCell ());
+       }
+
+       public TableRow create_table_row () {
+               return (TableRow) configure (new TableRow ());
+       }
+
+       public Taglet? create_taglet (string name) {
+               return _modules.create_taglet (name);
+       }
+
+       public Text create_text (string? text = null) {
+               return (Text) configure (new Text (text));
+       }
+
+       public ContentElement set_style_attributes (StyleAttributes element,
+                                                   VerticalAlign? valign,
+                                                   HorizontalAlign? halign,
+                                                   string? style) {
+               element.vertical_align = valign;
+               element.horizontal_align = halign;
+               element.style = style;
+               return element;
+       }
+}
diff --git a/libvaladoc/content/contentrenderer.vala b/libvaladoc/content/contentrenderer.vala
new file mode 100644
index 0000000..bad2bee
--- /dev/null
+++ b/libvaladoc/content/contentrenderer.vala
@@ -0,0 +1,30 @@
+/* contentrenderer.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public abstract class Valadoc.Content.ContentRenderer : ContentVisitor {
+
+       public abstract void render (ContentElement element);
+
+       public abstract void render_children (ContentElement element);
+}
+
diff --git a/libvaladoc/content/contentvisitor.vala b/libvaladoc/content/contentvisitor.vala
new file mode 100644
index 0000000..8ff33d6
--- /dev/null
+++ b/libvaladoc/content/contentvisitor.vala
@@ -0,0 +1,84 @@
+/* contentvisitor.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public abstract class Valadoc.Content.ContentVisitor : Object {
+
+       public virtual void visit_comment (Comment element) {
+       }
+
+       public virtual void visit_embedded (Embedded element) {
+       }
+
+       public virtual void visit_headline (Headline element) {
+       }
+
+       public virtual void visit_link (Link element) {
+       }
+
+       public virtual void visit_wiki_link (WikiLink element) {
+       }
+
+       public virtual void visit_symbol_link (SymbolLink element) {
+       }
+
+       public virtual void visit_list (List element) {
+       }
+
+       public virtual void visit_list_item (ListItem element) {
+       }
+
+       public virtual void visit_paragraph (Paragraph element) {
+       }
+
+       public virtual void visit_warning (Warning element) {
+       }
+
+       public virtual void visit_note (Note element) {
+       }
+
+       public virtual void visit_page (Page element) {
+       }
+
+       public virtual void visit_run (Run element) {
+       }
+
+       public virtual void visit_source_code (SourceCode element) {
+       }
+
+       public virtual void visit_table (Table element) {
+       }
+
+       public virtual void visit_table_cell (TableCell element) {
+       }
+
+       public virtual void visit_table_row (TableRow element) {
+       }
+
+       public virtual void visit_taglet (Taglet element) {
+       }
+
+       public virtual void visit_text (Text element) {
+       }
+}
+
diff --git a/libvaladoc/content/embedded.vala b/libvaladoc/content/embedded.vala
new file mode 100644
index 0000000..2666cd8
--- /dev/null
+++ b/libvaladoc/content/embedded.vala
@@ -0,0 +1,123 @@
+/* embedded.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Embedded : ContentElement, Inline, StyleAttributes {
+       public string url {
+               get;
+               set;
+       }
+
+       public string? caption {
+               get;
+               set;
+       }
+
+       public HorizontalAlign? horizontal_align {
+               get;
+               set;
+       }
+
+       public VerticalAlign? vertical_align {
+               get;
+               set;
+       }
+
+       public string? style {
+               get;
+               set;
+       }
+
+       public Api.Package package;
+
+       private ResourceLocator _locator;
+
+       internal Embedded () {
+               base ();
+       }
+
+       public override void configure (Settings settings, ResourceLocator locator) {
+               _locator = locator;
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // search relative to our file
+               if (!Path.is_absolute (url)) {
+                       string relative_to_file = Path.build_path (Path.DIR_SEPARATOR_S,
+                                                                                                          
Path.get_dirname (file_path),
+                                                                                                          
url);
+                       if (FileUtils.test (relative_to_file, FileTest.EXISTS | FileTest.IS_REGULAR)) {
+                               url = (owned) relative_to_file;
+                               package = container.package;
+                               return ;
+                       }
+               }
+
+               // search relative to the current directory / absoulte path
+               if (!FileUtils.test (url, FileTest.EXISTS | FileTest.IS_REGULAR)) {
+                       string base_name = Path.get_basename (url);
+
+                       foreach (unowned string dir in settings.alternative_resource_dirs) {
+                               string alternative_path = Path.build_path (Path.DIR_SEPARATOR_S,
+                                                                                                             
   dir,
+                                                                                                             
   base_name);
+                               if (FileUtils.test (alternative_path, FileTest.EXISTS | FileTest.IS_REGULAR)) 
{
+                                       url = (owned) alternative_path;
+                                       package = container.package;
+                                       return ;
+                               }
+                       }
+
+                       string node_segment = (container is Api.Package)? "" : container.get_full_name () + 
": ";
+                       reporter.simple_error ("%s: %s{{".printf (file_path, node_segment),
+                                                                  "'%s' does not exist", url);
+               } else {
+                       package = container.package;
+               }
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_embedded (this);
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Embedded embedded = new Embedded ();
+               embedded.parent = new_parent;
+
+               embedded.horizontal_align = horizontal_align;
+               embedded.vertical_align = vertical_align;
+               embedded._locator = _locator;
+               embedded.caption = caption;
+               embedded.package = package;
+               embedded.style = style;
+               embedded.url = url;
+
+               return embedded;
+       }
+}
diff --git a/libvaladoc/content/headline.vala b/libvaladoc/content/headline.vala
new file mode 100644
index 0000000..dcf2e6f
--- /dev/null
+++ b/libvaladoc/content/headline.vala
@@ -0,0 +1,64 @@
+/* headline.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Headline : InlineContent, Block {
+       public int level { get; set; }
+
+       internal Headline () {
+               base ();
+               _level = 0;
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // TODO report error if level == 0 ?
+               // TODO: content.size == 0?
+
+               // Check inline content
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_headline (this);
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Headline headline = new Headline ();
+               headline.parent = new_parent;
+               headline.level = level;
+
+               foreach (Inline element in content) {
+                       Inline copy = element.copy (headline) as Inline;
+                       headline.content.add (copy);
+               }
+
+               return headline;
+       }
+}
+
diff --git a/libvaladoc/content/inline.vala b/libvaladoc/content/inline.vala
new file mode 100644
index 0000000..3a6af75
--- /dev/null
+++ b/libvaladoc/content/inline.vala
@@ -0,0 +1,25 @@
+/* inline.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public interface Valadoc.Content.Inline : ContentElement {
+}
diff --git a/libvaladoc/content/inlinecontent.vala b/libvaladoc/content/inlinecontent.vala
new file mode 100644
index 0000000..8fdb82d
--- /dev/null
+++ b/libvaladoc/content/inlinecontent.vala
@@ -0,0 +1,73 @@
+/* inlinecontent.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public abstract class Valadoc.Content.InlineContent : ContentElement {
+       public Vala.List<Inline> content {
+               get {
+                       return _content;
+               }
+       }
+
+       private Vala.List<Inline> _content;
+
+       construct {
+               _content = new Vala.ArrayList<Inline> ();
+       }
+
+       internal InlineContent () {
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               foreach (Inline element in _content) {
+                       element.parent = this;
+                       element.check (api_root, container, file_path, reporter, settings);
+               }
+       }
+
+       public override void accept_children (ContentVisitor visitor) {
+               foreach (Inline element in _content) {
+                       element.accept (visitor);
+               }
+       }
+
+       public override bool is_empty () {
+               foreach (Inline item in content) {
+                       if (!item.is_empty ()) {
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       internal void replace_node (Inline old, Inline replacement) {
+               int index = _content.index_of (old);
+               assert (index >= 0);
+
+               _content.set (index, replacement);
+       }
+}
+
diff --git a/libvaladoc/content/inlinetaglet.vala b/libvaladoc/content/inlinetaglet.vala
new file mode 100644
index 0000000..ad6c7a7
--- /dev/null
+++ b/libvaladoc/content/inlinetaglet.vala
@@ -0,0 +1,69 @@
+/* taglet.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public abstract class Valadoc.Content.InlineTaglet : ContentElement, Taglet, Inline {
+       protected Settings settings;
+       protected ResourceLocator locator;
+       private ContentElement _content;
+
+       public InlineTaglet () {
+               base ();
+       }
+
+       public abstract Rule? get_parser_rule (Rule run_rule);
+
+       public abstract ContentElement produce_content ();
+
+       private ContentElement get_content () {
+               if (_content == null) {
+                       _content = produce_content ();
+               }
+               return _content;
+       }
+
+       public override void configure (Settings settings, ResourceLocator locator) {
+               this.settings = settings;
+               this.locator = locator;
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               ContentElement element = get_content ();
+               element.parent = this;
+
+               element.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               ContentElement element = get_content ();
+               element.accept (visitor);
+       }
+
+       public override bool is_empty () {
+               // taglets are not empty by default
+               return false;
+       }
+}
+
diff --git a/libvaladoc/content/link.vala b/libvaladoc/content/link.vala
new file mode 100644
index 0000000..4e91aab
--- /dev/null
+++ b/libvaladoc/content/link.vala
@@ -0,0 +1,113 @@
+/* link.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2014 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Link : InlineContent, Inline {
+       public string url {
+               set;
+               get;
+       }
+
+       /**
+        * Used by importers to transform internal URLs
+        */
+       public Importer.InternalIdRegistrar id_registrar {
+               internal set;
+               get;
+       }
+
+
+       internal Link () {
+               base ();
+       }
+
+       public override void configure (Settings settings, ResourceLocator locator) {
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+       
+               // Internal gktdoc-id? (gir-importer)
+               if (id_registrar != null) {
+                       Api.Node? node = id_registrar.map_symbol_id (url);
+                       if (node != null) {
+                               InlineContent _parent = parent as InlineContent;
+                               assert (_parent != null);
+
+                               SymbolLink replacement = new SymbolLink (node);
+                               replacement.content.add_all (content);
+
+                               replacement.check (api_root, container, file_path, reporter, settings);
+                               _parent.replace_node (this, replacement);
+                               return ;
+                       }               
+
+
+                       string _url = id_registrar.map_url_id (url);
+                       if (_url == null) {
+                               string node_segment = (container is Api.Package)? "" : 
container.get_full_name () + ": ";
+                               reporter.simple_warning ("%s: %s[[".printf (file_path, node_segment),
+                                                                                "unknown imported internal 
id '%s'", url);
+
+                               InlineContent _parent = parent as InlineContent;
+                               assert (_parent != null);
+
+                               Run replacement = new Run (Run.Style.ITALIC);
+                               replacement.content.add_all (content);
+                               replacement.check (api_root, container, file_path, reporter, settings);
+
+                               _parent.replace_node (this, replacement);
+                               return ;
+                       }
+
+                       url = _url;
+               }
+
+
+               //TODO: check url
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_link (this);
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Link link = new Link ();
+               link.id_registrar = id_registrar;
+               link.parent = new_parent;
+               link.url = url;
+
+               foreach (Inline element in content) {
+                       Inline copy = element.copy (link) as Inline;
+                       link.content.add (copy);
+               }
+
+               return link;
+       }
+}
diff --git a/libvaladoc/content/list.vala b/libvaladoc/content/list.vala
new file mode 100644
index 0000000..e47ed0b
--- /dev/null
+++ b/libvaladoc/content/list.vala
@@ -0,0 +1,154 @@
+/* list.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.List : ContentElement, Block {
+       public enum Bullet {
+               NONE,
+               UNORDERED,
+               ORDERED,
+               ORDERED_NUMBER,
+               ORDERED_LOWER_CASE_ALPHA,
+               ORDERED_UPPER_CASE_ALPHA,
+               ORDERED_LOWER_CASE_ROMAN,
+               ORDERED_UPPER_CASE_ROMAN;
+
+               public static Bullet? from_string (string? str) {
+                       switch (str) {
+                       case "none":
+                               return Bullet.NONE;
+
+                       case "unordered":
+                               return Bullet.UNORDERED;
+
+                       case "ordered":
+                               return Bullet.ORDERED;
+
+                       case "ordered-number":
+                               return Bullet.ORDERED_NUMBER;
+
+                       case "ordered-lower-case-alpa":
+                               return Bullet.ORDERED_LOWER_CASE_ALPHA;
+
+                       case "ordered-upper-case-alpha":
+                               return Bullet.ORDERED_UPPER_CASE_ALPHA;
+
+                       case "ordered-lower-case-roman":
+                               return Bullet.ORDERED_LOWER_CASE_ROMAN;
+
+                       case "ordered-upper-case-roman":
+                               return Bullet.ORDERED_UPPER_CASE_ROMAN;
+                       }
+
+                       return null;
+               }
+
+               public unowned string to_string () {
+                       switch (this) {
+                       case Bullet.NONE:
+                               return "none";
+
+                       case Bullet.UNORDERED:
+                               return "unordered";
+
+                       case Bullet.ORDERED:
+                               return "ordered";
+
+                       case Bullet.ORDERED_NUMBER:
+                               return "ordered-number";
+
+                       case Bullet.ORDERED_LOWER_CASE_ALPHA:
+                               return "ordered-lower-case-alpa";
+
+                       case Bullet.ORDERED_UPPER_CASE_ALPHA:
+                               return "ordered-upper-case-alpha";
+
+                       case Bullet.ORDERED_LOWER_CASE_ROMAN:
+                               return "ordered-lower-case-roman";
+
+                       case Bullet.ORDERED_UPPER_CASE_ROMAN:
+                               return "ordered-upper-case-roman";
+                       }
+
+                       assert (true);
+                       return "";
+               }
+       }
+
+       public Bullet bullet {
+               get;
+               set;
+       }
+
+       // TODO add initial value (either a number or some letters)
+       public Vala.List<ListItem> items {
+               get {
+                       return _items;
+               }
+       }
+
+       private Vala.List<ListItem> _items;
+
+       internal List () {
+               base ();
+               _bullet = Bullet.NONE;
+               _items = new Vala.ArrayList<ListItem> ();
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check individual list items
+               foreach (ListItem element in _items) {
+                       element.parent = this;
+                       element.check (api_root, container, file_path, reporter, settings);
+               }
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_list (this);
+       }
+
+       public override void accept_children (ContentVisitor visitor) {
+               foreach (ListItem element in _items) {
+                       element.accept (visitor);
+               }
+       }
+
+       public override bool is_empty () {
+               return _items.size == 0;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Content.List list = new Content.List ();
+               list.parent = new_parent;
+               list.bullet = bullet;
+
+               foreach (ListItem item in items) {
+                       ListItem copy = item.copy (list) as ListItem;
+                       list.items.add (copy);
+               }
+
+               return list;
+       }
+}
diff --git a/libvaladoc/content/listitem.vala b/libvaladoc/content/listitem.vala
new file mode 100644
index 0000000..ee3aa45
--- /dev/null
+++ b/libvaladoc/content/listitem.vala
@@ -0,0 +1,57 @@
+/* listitem.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.ListItem : BlockContent {
+
+       internal ListItem () {
+               base ();
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check block content
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_list_item (this);
+       }
+
+       public override void accept_children (ContentVisitor visitor) {
+               base.accept_children (visitor);
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               ListItem item = new ListItem ();
+               item.parent = new_parent;
+
+               foreach (Block block in content) {
+                       Block copy = block.copy (item) as Block;
+                       item.content.add (copy);
+               }
+
+               return item;
+       }
+}
diff --git a/libvaladoc/content/note.vala b/libvaladoc/content/note.vala
new file mode 100644
index 0000000..49b8178
--- /dev/null
+++ b/libvaladoc/content/note.vala
@@ -0,0 +1,53 @@
+/* note.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Note : BlockContent, Block {
+       internal Note () {
+               base ();
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check inline content
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_note (this);
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Note note = new Note ();
+               note.parent = new_parent;
+
+               foreach (Block block in content) {
+                       Block copy = block.copy (note) as Block;
+                       note.content.add (copy);
+               }
+
+               return note;
+       }
+}
+
diff --git a/libvaladoc/content/page.vala b/libvaladoc/content/page.vala
new file mode 100644
index 0000000..caaa7d9
--- /dev/null
+++ b/libvaladoc/content/page.vala
@@ -0,0 +1,63 @@
+/* page.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Page : BlockContent {
+       private bool checked = false;
+
+
+       internal Page () {
+               base ();
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_page (this);
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               if (checked == true) {
+                       return ;
+               }
+
+               checked = true;
+
+
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               assert (new_parent == null);
+
+               Content.Page page = new Content.Page ();
+               page.parent = new_parent;
+
+               foreach (Block block in content) {
+                       Block copy = block.copy (page) as Block;
+                       page.content.add (copy);
+               }
+
+               return page;
+       }
+}
+
diff --git a/libvaladoc/content/paragraph.vala b/libvaladoc/content/paragraph.vala
new file mode 100644
index 0000000..548c03f
--- /dev/null
+++ b/libvaladoc/content/paragraph.vala
@@ -0,0 +1,72 @@
+/* paragraph.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Paragraph : InlineContent, Block, StyleAttributes {
+       public HorizontalAlign? horizontal_align {
+               get;
+               set;
+       }
+
+       public VerticalAlign? vertical_align {
+               get;
+               set;
+       }
+
+       public string? style {
+               get;
+               set;
+       }
+
+       internal Paragraph () {
+               base ();
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check inline content
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_paragraph (this);
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Paragraph p = new Paragraph ();
+               p.parent = new_parent;
+
+               p.horizontal_align = horizontal_align;
+               p.vertical_align = vertical_align;
+               p.style = style;
+
+               foreach (Inline element in content) {
+                       Inline copy = element.copy (p) as Inline;
+                       p.content.add (copy);
+               }
+
+               return p;
+       }
+}
+
diff --git a/libvaladoc/content/resourcelocator.vala b/libvaladoc/content/resourcelocator.vala
new file mode 100644
index 0000000..e6f2785
--- /dev/null
+++ b/libvaladoc/content/resourcelocator.vala
@@ -0,0 +1,27 @@
+/* resourcelocator.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public interface Valadoc.ResourceLocator : Object {
+       public abstract string resolve (string path);
+}
+
diff --git a/libvaladoc/content/run.vala b/libvaladoc/content/run.vala
new file mode 100644
index 0000000..c2228b7
--- /dev/null
+++ b/libvaladoc/content/run.vala
@@ -0,0 +1,206 @@
+/* run.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Run : InlineContent, Inline {
+       public enum Style {
+               NONE,
+               BOLD,
+               ITALIC,
+               UNDERLINED,
+               MONOSPACED,
+               STROKE,
+               LANG_KEYWORD,
+               LANG_LITERAL,
+               LANG_BASIC_TYPE,
+               LANG_TYPE,
+               LANG_PREPROCESSOR,
+               LANG_COMMENT,
+               LANG_ESCAPE,
+               
+               XML_ESCAPE,
+               XML_ELEMENT,
+               XML_ATTRIBUTE,
+               XML_ATTRIBUTE_VALUE,
+               XML_COMMENT,
+               XML_CDATA;
+
+               public static Style? from_string (string str) {
+                       switch (str) {
+                       case "none":
+                               return Style.NONE;
+
+                       case "bold":
+                               return Style.BOLD;
+
+                       case "italic":
+                               return Style.ITALIC;
+
+                       case "underlined":
+                               return Style.UNDERLINED;
+
+                       case "monospaced":
+                               return Style.MONOSPACED;        
+
+                       case "stroke":
+                               return Style.STROKE;
+
+                       case "lang-escape":
+                               return Style.LANG_ESCAPE;
+
+                       case "lang-keyword":
+                               return Style.LANG_KEYWORD;
+
+                       case "lang-literal":
+                               return Style.LANG_LITERAL;
+
+                       case "lang-basic-type":
+                               return Style.LANG_BASIC_TYPE;
+
+                       case "lang-type":
+                               return Style.LANG_TYPE;
+
+                       case "lang-preprocessor":
+                               return Style.LANG_PREPROCESSOR;
+
+                       case "lang-comment":
+                               return Style.LANG_COMMENT;
+
+                       case "xml-escape":
+                               return Style.XML_ESCAPE;
+
+                       case "xml-element":
+                               return Style.XML_ELEMENT;
+
+                       case "xml-attribute":
+                               return Style.XML_ATTRIBUTE;
+
+                       case "xml-attribute-value":
+                               return Style.XML_ATTRIBUTE_VALUE;
+
+                       case "xml-comment":
+                               return Style.XML_COMMENT;
+
+                       case "xml-cdata":
+                               return Style.XML_CDATA;
+                       }
+
+                       return null;
+               }
+
+               public unowned string to_string () {
+                       switch (this) {
+                       case Style.NONE:
+                               return "none";
+
+                       case Style.BOLD:
+                               return "bold";
+
+                       case Style.ITALIC:
+                               return "italic";
+
+                       case Style.UNDERLINED:
+                               return "underlined";
+
+                       case Style.MONOSPACED:
+                               return "monospaced";
+
+                       case Style.STROKE:
+                               return "stroke";
+
+                       case Style.LANG_ESCAPE:
+                               return "lang-escape";
+
+                       case Style.LANG_KEYWORD:
+                               return "lang-keyword";
+
+                       case Style.LANG_LITERAL:
+                               return "lang-literal";
+
+                       case Style.LANG_BASIC_TYPE:
+                               return "lang-basic-type";
+
+                       case Style.LANG_TYPE:
+                               return "lang-type";
+
+                       case Style.LANG_PREPROCESSOR:
+                               return "lang-preprocessor";
+
+                       case Style.LANG_COMMENT:
+                               return "lang-comment";
+
+                       case Style.XML_ESCAPE:
+                               return "xml-escape";
+
+                       case Style.XML_ELEMENT:
+                               return "xml-element";
+
+                       case Style.XML_ATTRIBUTE:
+                               return "xml-attribute";
+
+                       case Style.XML_ATTRIBUTE_VALUE:
+                               return "xml-attribute-value";
+
+                       case Style.XML_COMMENT:
+                               return "xml-comment";
+
+                       case Style.XML_CDATA:
+                               return "xml-cdata";
+                       }
+
+                       assert (true);
+                       return "";
+               }
+       }
+
+       public Style style { get; set; }
+
+       internal Run (Style style) {
+               base ();
+               _style = style;
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check inline content
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_run (this);
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Run run = new Run (style);
+               run.parent = new_parent;
+
+               foreach (Inline element in content) {
+                       Inline copy = element.copy (run) as Inline;
+                       run.content.add (copy);
+               }
+
+               return run;
+       }
+}
+
diff --git a/libvaladoc/content/sourcecode.vala b/libvaladoc/content/sourcecode.vala
new file mode 100644
index 0000000..a9c4935
--- /dev/null
+++ b/libvaladoc/content/sourcecode.vala
@@ -0,0 +1,239 @@
+/* sourcecode.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.SourceCode : ContentElement, Inline {
+       public enum Language {
+               GENIE,
+               VALA,
+               XML,
+               C;
+
+               public static Language? from_path (string path) {
+                       int pos = path.last_index_of (".");
+                       if (pos < 0) {
+                               return null;
+                       }
+
+                       string ext = path.substring (pos + 1);
+                       return from_string (ext, true);
+               }
+
+               public static Language? from_string (string str, bool is_extension = false) {
+                       switch (str) {
+                       case "genie":
+                               if (is_extension) {
+                                       return null;
+                               }
+                               return Language.GENIE;
+
+                       case "gs":
+                               return Language.GENIE;
+
+                       case "xml":
+                               return Language.XML;
+
+                       case "vala":
+                               return Language.VALA;
+
+                       case "c":
+                       case "h":
+                               return Language.C;
+                       }
+
+                       return null;
+               }
+
+               public unowned string to_string () {
+                       switch (this) {
+                       case Language.GENIE:
+                               return "genie";
+
+                       case Language.VALA:
+                               return "vala";
+
+                       case Language.XML:
+                               return "xml";
+
+                       case Language.C:
+                               return "c";
+                       }
+
+                       assert (true);
+                       return "";
+               }
+       }
+
+
+       public string code {
+               get;
+               set;
+       }
+
+       public Run? highlighted_code {
+               get;
+               private set;
+       }
+
+       public Language? language {
+               get;
+               set;
+       }
+
+       internal SourceCode () {
+               base ();
+               _language = Language.VALA;
+       }
+
+       private string? get_path (string path, Api.Node container, string source_file_path,
+                                                         ErrorReporter reporter)
+       {
+               // search relative to our file
+               if (!Path.is_absolute (path)) {
+                       string relative_to_file = Path.build_path (Path.DIR_SEPARATOR_S,
+                                                                                                          
Path.get_dirname (source_file_path),
+                                                                                                          
path);
+                       if (FileUtils.test (relative_to_file, FileTest.EXISTS | FileTest.IS_REGULAR)) {
+                               return (owned) relative_to_file;
+                       }
+               }
+
+               // search relative to the current directory / absoulte path
+               if (!FileUtils.test (path, FileTest.EXISTS | FileTest.IS_REGULAR)) {
+                       string node_segment = (container is Api.Package)? "" : container.get_full_name () + 
": ";
+                       code = "File '%s' does not exist".printf (path);
+                       reporter.simple_warning ("%s: %s{{{".printf (source_file_path, node_segment),
+                                                                        "%s", code);
+                       return null;
+               }
+
+               return path;
+       }
+
+       private void load_source_code (string _path, Api.Node container, string source_file_path,
+                                                                  ErrorReporter reporter)
+       {
+               string? path = get_path (_path, container, source_file_path, reporter);
+               if (path == null) {
+                       return ;
+               }
+
+               try {
+                       string content = null;
+                       FileUtils.get_contents (path, out content);
+                       _language = Language.from_path (path);
+                       code = (owned) content;
+               } catch (FileError err) {
+                       string node_segment = (container is Api.Package)? "" : container.get_full_name () + 
": ";
+                       reporter.simple_error ("%s: %s{{{".printf (source_file_path, node_segment),
+                                                                  "Can't read file '%s': %s", path, 
err.message);
+               }
+       }
+
+       private inline bool is_empty_string (string line) {
+               for (int i = 0; line[i] != '\0'; i++) {
+                       if (line[i].isspace () == false) {
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       private string strip_code (string code) {
+               string[] lines = code.split ("\n");
+               for (int i = lines.length - 1; i >= 0 && is_empty_string (lines[i]); i--) {
+                       lines[i] = null;
+               }
+
+               string** _lines = lines;
+               for (int i = 0; lines[i] != null && is_empty_string (lines[i]); i++) {
+                       _lines = &lines[i + 1];
+               }
+
+               return string.joinv ("\n", (string[]) _lines);
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               string[] splitted = code.split ("\n", 2);
+               if (splitted[0].strip () == "") {
+                       code = splitted[1] ?? "";
+               } else if (splitted[0].has_prefix ("#!")) {
+                       unowned string start = (string) (((char*) splitted[0]) + 2);
+                       if (start.has_prefix ("include:")) {
+                               start = (string) (((char*) start) + 8);
+                               string path = start.strip ();
+                               load_source_code (path, container, file_path, reporter);
+                       } else {
+                               string name = start._strip ().down ();
+                               _language = Language.from_string (name);
+                               code = splitted[1] ?? "";
+                               if (_language == null && name != "none") {
+                                       string node_segment = (container is Api.Package)? "" : 
container.get_full_name () + ": ";
+                                       reporter.simple_warning ("%s: %s{{{".printf (file_path, node_segment),
+                                               "Unsupported programming language '%s'", name);
+                               }
+                       }
+               }
+
+               code = strip_code (code);
+
+               if (_language == Language.VALA) {
+                       highlighted_code = api_root.highlighter.highlight_vala (code);
+               } else if (_language == Language.XML) {
+                       highlighted_code = api_root.highlighter.highlight_xml (code);
+               } else if (_language == Language.C) {
+                       highlighted_code = api_root.highlighter.highlight_c (code);
+               } else {
+                       highlighted_code = new Run (Run.Style.MONOSPACED);
+                       highlighted_code.content.add (new Text (code));
+               }
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_source_code (this);
+       }
+
+       public override void accept_children (ContentVisitor visitor) {
+               if (highlighted_code != null) {
+                       highlighted_code.accept (visitor);
+               }
+       }
+
+       public override bool is_empty () {
+               // empty source blocks are visible as well
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               SourceCode source_code = new SourceCode ();
+               source_code.parent = new_parent;
+
+               source_code.language = language;
+               source_code.code = code;
+
+               return source_code;
+       }
+}
diff --git a/libvaladoc/content/styleattributes.vala b/libvaladoc/content/styleattributes.vala
new file mode 100644
index 0000000..69fdb83
--- /dev/null
+++ b/libvaladoc/content/styleattributes.vala
@@ -0,0 +1,114 @@
+/* styleattributes.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public enum Valadoc.Content.HorizontalAlign {
+       LEFT,
+       RIGHT,
+       CENTER;
+
+       public static HorizontalAlign? from_string (string str) {
+               switch (str) {
+               case "left":
+                       return HorizontalAlign.LEFT;
+
+               case "right":
+                       return HorizontalAlign.RIGHT;
+
+               case "center":
+                       return HorizontalAlign.CENTER;
+               }
+
+               return null;
+       }
+
+       public unowned string to_string () {
+               switch (this) {
+               case HorizontalAlign.LEFT:
+                       return "left";
+
+               case HorizontalAlign.RIGHT:
+                       return "right";
+
+               case HorizontalAlign.CENTER:
+                       return "center";
+               }
+
+               assert (true);
+               return "";
+       }
+}
+
+public enum Valadoc.Content.VerticalAlign {
+       TOP,
+       MIDDLE,
+       BOTTOM;
+
+       public static VerticalAlign? from_string (string str) {
+               switch (str) {
+               case "top":
+                       return VerticalAlign.TOP;
+
+               case "middle":
+                       return VerticalAlign.MIDDLE;
+
+               case "bottom":
+                       return VerticalAlign.BOTTOM;
+               }
+
+               return null;
+       }
+
+       public unowned string to_string () {
+               switch (this) {
+               case VerticalAlign.TOP:
+                       return "top";
+
+               case VerticalAlign.MIDDLE:
+                       return "middle";
+
+               case VerticalAlign.BOTTOM:
+                       return "bottom";
+               }
+
+               assert (true);
+               return "";
+       }
+}
+
+public interface Valadoc.Content.StyleAttributes : ContentElement {
+       public abstract HorizontalAlign? horizontal_align {
+               get;
+               set;
+       }
+
+       public abstract VerticalAlign? vertical_align {
+               get;
+               set;
+       }
+
+       public abstract string? style {
+               get;
+               set;
+       }
+}
+
diff --git a/libvaladoc/content/symbollink.vala b/libvaladoc/content/symbollink.vala
new file mode 100644
index 0000000..7ea01b8
--- /dev/null
+++ b/libvaladoc/content/symbollink.vala
@@ -0,0 +1,70 @@
+/* symbollink.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2014 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.SymbolLink : InlineContent, Inline {
+       public Api.Node symbol {
+               get;
+               set;
+       }
+
+       public string given_symbol_name {
+               get;
+               set;
+       }
+
+       internal SymbolLink (Api.Node? symbol = null, string? given_symbol_name = null) {
+               base ();
+               _symbol = symbol;
+               _given_symbol_name = given_symbol_name;
+       }
+
+       public override void configure (Settings settings, ResourceLocator locator) {
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_symbol_link (this);
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               SymbolLink link = new SymbolLink (symbol, _given_symbol_name);
+               link.parent = new_parent;
+
+               foreach (Inline element in content) {
+                       Inline copy = element.copy (link) as Inline;
+                       link.content.add (copy);
+               }
+
+               return link;
+       }
+}
+
diff --git a/libvaladoc/content/table.vala b/libvaladoc/content/table.vala
new file mode 100644
index 0000000..baae1a0
--- /dev/null
+++ b/libvaladoc/content/table.vala
@@ -0,0 +1,77 @@
+/* table.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Table : ContentElement, Block {
+       public Vala.List<TableRow> rows {
+               get {
+                       return _rows;
+               }
+       }
+
+       private Vala.List<TableRow> _rows;
+
+       internal Table () {
+               base ();
+               _rows = new Vala.ArrayList<TableRow> ();
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check the table consistency in term of row/column number
+
+               // Check individual rows
+               foreach (var row in _rows) {
+                       row.parent = this;
+                       row.check (api_root, container, file_path, reporter, settings);
+               }
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_table (this);
+       }
+
+       public override void accept_children (ContentVisitor visitor) {
+               foreach (TableRow element in _rows) {
+                       element.accept (visitor);
+               }
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Table table = new Table ();
+               table.parent = new_parent;
+
+               foreach (var row in _rows) {
+                       TableRow copy = row.copy (table) as TableRow;
+                       table.rows.add (copy);
+               }
+
+               return table;
+       }
+}
+
diff --git a/libvaladoc/content/tablecell.vala b/libvaladoc/content/tablecell.vala
new file mode 100644
index 0000000..9bc1208
--- /dev/null
+++ b/libvaladoc/content/tablecell.vala
@@ -0,0 +1,91 @@
+/* tablecell.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.TableCell : InlineContent, StyleAttributes {
+       public HorizontalAlign? horizontal_align {
+               get;
+               set;
+       }
+
+       public VerticalAlign? vertical_align {
+               get;
+               set;
+       }
+
+       public string? style {
+               get;
+               set;
+       }
+
+       public int colspan {
+               get;
+               set;
+       }
+
+       public int rowspan {
+               get;
+               set;
+       }
+
+       internal TableCell () {
+               base ();
+               _colspan = 1;
+               _rowspan = 1;
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+               ErrorReporter reporter, Settings settings)
+       {
+               // Check inline content
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_table_cell (this);
+       }
+
+       public override bool is_empty () {
+               // empty cells are displayed as well
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               TableCell cell = new TableCell ();
+               cell.parent = new_parent;
+
+               cell.horizontal_align = horizontal_align;
+               cell.vertical_align = vertical_align;
+               cell.colspan = colspan;
+               cell.rowspan = rowspan;
+               cell.style = style;
+
+               foreach (Inline element in content) {
+                       Inline copy = element.copy (cell) as Inline;
+                       cell.content.add (copy);
+               }
+
+               return cell;
+       }
+}
+
diff --git a/libvaladoc/content/tablerow.vala b/libvaladoc/content/tablerow.vala
new file mode 100644
index 0000000..97b024b
--- /dev/null
+++ b/libvaladoc/content/tablerow.vala
@@ -0,0 +1,75 @@
+/* tablerow.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.TableRow : ContentElement {
+       public Vala.List<TableCell> cells {
+               get {
+                       return _cells;
+               }
+       }
+
+       private Vala.List<TableCell> _cells;
+
+       internal TableRow () {
+               base ();
+               _cells = new Vala.ArrayList<TableCell> ();
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check individual cells
+               foreach (var cell in _cells) {
+                       cell.parent = this;
+                       cell.check (api_root, container, file_path, reporter, settings);
+               }
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_table_row (this);
+       }
+
+       public override void accept_children (ContentVisitor visitor) {
+               foreach (TableCell element in _cells) {
+                       element.accept (visitor);
+               }
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               TableRow row = new TableRow ();
+               row.parent = new_parent;
+
+               foreach (TableCell cell in _cells) {
+                       TableCell copy = cell.copy (row) as TableCell;
+                       row.cells.add (copy);
+               }
+
+               return row;
+       }
+}
+
diff --git a/libvaladoc/content/taglet.vala b/libvaladoc/content/taglet.vala
new file mode 100644
index 0000000..d2efb43
--- /dev/null
+++ b/libvaladoc/content/taglet.vala
@@ -0,0 +1,36 @@
+/* taglet.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public interface Valadoc.Content.Taglet : ContentElement {
+
+       public abstract Rule? get_parser_rule (Rule run_rule);
+
+       public virtual Vala.List<ContentElement>? get_inheritable_documentation () {
+               return null;
+       }
+
+       public virtual bool inheritable (Taglet taglet) {
+               return false;
+       }
+}
+
diff --git a/libvaladoc/content/text.vala b/libvaladoc/content/text.vala
new file mode 100644
index 0000000..ab42864
--- /dev/null
+++ b/libvaladoc/content/text.vala
@@ -0,0 +1,61 @@
+/* text.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Text : ContentElement, Inline {
+       public string content {
+               get;
+               set;
+       }
+
+       construct {
+               _content = "";
+       }
+
+       internal Text (string? text = null) {
+               if (text != null) {
+                       _content = text;
+               }
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_text (this);
+       }
+
+
+       public override bool is_empty () {
+               return content == "";
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Text text = new Text (content);
+               text.parent = new_parent;
+               return text;
+       }
+}
+
diff --git a/libvaladoc/content/warning.vala b/libvaladoc/content/warning.vala
new file mode 100644
index 0000000..e441732
--- /dev/null
+++ b/libvaladoc/content/warning.vala
@@ -0,0 +1,53 @@
+/* warning.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.Warning : BlockContent, Block {
+       internal Warning () {
+               base ();
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check inline content
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_warning (this);
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Warning warning = new Warning ();
+               warning.parent = new_parent;
+
+               foreach (Block block in content) {
+                       Block copy = block.copy (warning) as Block;
+                       warning.content.add (copy);
+               }
+
+               return warning;
+       }
+}
+
diff --git a/libvaladoc/content/wikilink.vala b/libvaladoc/content/wikilink.vala
new file mode 100644
index 0000000..cb62887
--- /dev/null
+++ b/libvaladoc/content/wikilink.vala
@@ -0,0 +1,76 @@
+/* link.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Content.WikiLink : InlineContent, Inline {
+       public WikiPage page {
+               internal set;
+               get;
+       }
+
+       public string name {
+               get;
+               set;
+       }
+
+       internal WikiLink () {
+               base ();
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               base.check (api_root, container, file_path, reporter, settings);
+
+               page = api_root.wikitree.search (name);
+               if (page == null) {
+                       string node_segment = (container is Api.Package)? "" : container.get_full_name () + 
": ";
+                       reporter.simple_warning ("%s: %s[[".printf (file_path, node_segment),
+                                                                        "'%s' does not exist", name);
+                       return ;
+               }
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_wiki_link (this);
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               WikiLink link = new WikiLink ();
+               link.parent = new_parent;
+
+               link.page = page;
+               link.name = name;
+
+               foreach (Inline element in content) {
+                       Inline copy = element.copy (link) as Inline;
+                       link.content.add (copy);
+               }
+
+               return link;
+       }
+}
diff --git a/libvaladoc/ctyperesolver.vala b/libvaladoc/ctyperesolver.vala
new file mode 100644
index 0000000..2909df6
--- /dev/null
+++ b/libvaladoc/ctyperesolver.vala
@@ -0,0 +1,401 @@
+/* ctyperesolver.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.Api;
+
+/**
+ * Resolves symbols by C-names
+ */
+public class Valadoc.CTypeResolver : Visitor {
+       private Vala.Map<string, Api.TypeSymbol> types = new Vala.HashMap<string, Api.TypeSymbol> (str_hash, 
str_equal);
+       private Vala.Map<string, Api.Node> nodes = new Vala.HashMap<string, Api.Node> (str_hash, str_equal);
+       private Api.Tree tree;
+
+       public CTypeResolver (Api.Tree tree) {
+               tree.accept (this);
+               this.tree = tree;
+       }
+
+       private string convert_array_to_camelcase (string[] elements) {
+               StringBuilder builder = new StringBuilder ();
+
+               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_to_g (string name) {
+               if (is_capitalized_and_underscored (name)) {
+                       string[] segments = name.split ("_");
+                       unowned string last_segment = segments[segments.length - 1];
+                       if (last_segment != "ERROR") {
+                               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;
+       }
+
+       public Api.TypeSymbol? resolve_symbol_type (string name) {
+               TypeSymbol? symbol = types.get (name);
+               if (symbol != null) {
+                       return symbol;
+               }
+
+               if (is_capitalized_and_underscored (name)) {
+                       string[] segments = name.split ("_");
+
+                       if (segments[segments.length - 1] == "TYPE") {
+                               segments.resize (segments.length - 1);
+                               return types.get (convert_array_to_camelcase (segments));
+                       } else if (segments.length > 2 && segments[1] == "TYPE") {
+                               string[] _segments = segments[1:segments.length];
+                               _segments[0] = segments[0];
+                               return types.get (convert_array_to_camelcase (_segments));
+                       }
+               }
+
+               return null;
+       }
+
+       /**
+        * Resolves symbols by C-names
+        *
+        * @param _name a C-name
+        * @return the resolved node or null
+        */
+       public Api.Node? resolve_symbol (Api.Node? element, string _name) {
+               string name = _name.replace ("->", ".").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;
+               }
+
+               string? alternative = translate_cname_to_g (name);
+               if (alternative != null) {
+                       return nodes.get (alternative);
+               }
+
+               if (element != null && name.has_prefix (":")) {
+                       if (element is Class && ((Class) element).get_cname () != null) {
+                               return nodes.get (((Class) element).get_cname () + "." + name);
+                       } else if (element is Struct && ((Struct) element).get_cname () != null) {
+                               return nodes.get (((Struct) element).get_cname () + "." + name);
+                       }
+               }
+
+               if (name == "dgettext") {
+                       return nodes.get ("g_dgettext");
+               } else if (name == "printf") {
+                       return this.tree.search_symbol_str (null, "GLib.FileStream.printf");
+               }
+
+               int dotpos = name.index_of_char ('.');
+               if (dotpos > 0) {
+                       string fst = name.substring (0, dotpos);
+                       string snd = name.substring (dotpos + 1);
+                       return nodes.get (fst + ":" + snd);
+               }
+
+               return null;
+       }
+
+       private void register_symbol_type (string? name, Api.TypeSymbol symbol) {
+               if (name != null) {
+                       types.set (name, symbol);
+               }
+       }
+
+       private void register_symbol (string? name, Api.Node node) {
+               if (name != null) {
+                       nodes.set (name.replace ("-", "_"), node);
+               }
+       }
+
+       private string? get_parent_type_cname (Item item) {
+               string parent_cname = null;
+               if (item.parent is Class) {
+                       parent_cname = ((Class) item.parent).get_cname ();
+               } else if (item.parent is Interface) {
+                       parent_cname = ((Interface) item.parent).get_cname ();
+               } else if (item.parent is Struct) {
+                       parent_cname = ((Struct) item.parent).get_cname ();
+               } else if (item.parent is ErrorDomain) {
+                       parent_cname = ((ErrorDomain) item.parent).get_cname ();
+               } else if (item.parent is Api.Enum) {
+                       parent_cname = ((Api.Enum) item.parent).get_cname ();
+               } else {
+                       assert (true);
+               }
+               return parent_cname;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_tree (Api.Tree item) {
+               item.accept_children (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_package (Package item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_namespace (Namespace item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_interface (Interface item) {
+               register_symbol (item.get_cname (), item);
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_class (Class item) {
+               register_symbol_type (item.get_type_id (), item);
+               register_symbol (item.get_cname (), item);
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_struct (Struct item) {
+               register_symbol_type (item.get_type_id (), item);
+               register_symbol (item.get_cname (), item);
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_property (Property item) {
+               string parent_cname = get_parent_type_cname (item);
+               assert (parent_cname != null);
+
+               string cname = item.get_cname ();
+               register_symbol (parent_cname+":"+cname, item);
+
+
+               Vala.Collection<Interface> interfaces = null;
+               Vala.Collection<Class> classes = null;
+
+               if (item.parent is Interface) {
+                       interfaces = ((Api.Interface) item.parent).get_known_related_interfaces ();
+                       classes = ((Api.Interface) item.parent).get_known_implementations ();
+               } else if (item.parent is Class) {
+                       interfaces = ((Api.Class) item.parent).get_known_derived_interfaces ();
+                       classes = ((Api.Class) item.parent).get_known_child_classes ();
+               }
+
+               foreach (Interface iface in interfaces) {
+                       register_symbol (iface.get_cname () + ":" + cname, item);
+               }
+
+               foreach (Class cl in classes) {
+                       register_symbol (cl.get_cname () + ":" + cname, item);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_field (Field item) {
+               if (item.parent is Namespace || item.is_static) {
+                       register_symbol (item.get_cname (), item);
+               } else {
+                       string parent_cname = get_parent_type_cname (item);
+                       if (parent_cname != null) {
+                               register_symbol (parent_cname + "." + item.get_cname (), item);
+                       }
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_constant (Constant item) {
+               register_symbol (item.get_cname (), item);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_delegate (Delegate item) {
+               register_symbol (item.get_cname (), item);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_signal (Api.Signal item) {
+               string parent_cname = get_parent_type_cname (item);
+               assert (parent_cname != null);
+
+               string? default_impl_cname = item.get_default_impl_cname ();
+               string cname = item.get_cname ();
+               register_symbol (parent_cname+"::"+cname, item);
+
+               if (item.is_virtual) {
+                       // only supported by classes
+                       register_symbol (parent_cname + "Class." + item.name, item);
+               }
+
+               Vala.Collection<Interface> interfaces = null;
+               Vala.Collection<Class> classes = null;
+
+               if (item.parent is Interface) {
+                       interfaces = ((Api.Interface) item.parent).get_known_related_interfaces ();
+                       classes = ((Api.Interface) item.parent).get_known_implementations ();
+               } else if (item.parent is Class) {
+                       interfaces = ((Api.Class) item.parent).get_known_derived_interfaces ();
+                       classes = ((Api.Class) item.parent).get_known_child_classes ();
+               }
+
+               foreach (Interface iface in interfaces) {
+                       register_symbol (iface.get_cname () + "::" + cname, item);
+               }
+
+               foreach (Class cl in classes) {
+                       register_symbol (cl.get_cname () + "::" + cname, item);
+               }
+
+               if (default_impl_cname != null) {
+                       register_symbol (default_impl_cname, item);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_method (Method item) {
+               if (item.is_abstract || item.is_virtual || item.is_override) {
+                       string parent_cname = get_parent_type_cname (item);
+
+                       if (item.parent is Class) {
+                               register_symbol (parent_cname + "Class." + item.name, item);
+                       } else {
+                               register_symbol (parent_cname + "Iface." + item.name, item);
+                       }
+
+                       // Allow to resolve invalid links:
+                       register_symbol (parent_cname + "." + item.name, item);
+               }
+
+               register_symbol (item.get_cname (), item);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_error_domain (ErrorDomain item) {
+               register_symbol (item.get_cname (), item);
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_error_code (ErrorCode item) {
+               register_symbol (item.get_cname (), item);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_enum (Api.Enum item) {
+               register_symbol (item.get_cname (), item);
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_enum_value (Api.EnumValue item) {
+               register_symbol (item.get_cname (), item);
+       }
+}
+
+
diff --git a/libvaladoc/devhelp-markupwriter.vala b/libvaladoc/devhelp-markupwriter.vala
new file mode 100644
index 0000000..d868080
--- /dev/null
+++ b/libvaladoc/devhelp-markupwriter.vala
@@ -0,0 +1,94 @@
+/* devhelp-markupwriter.vala
+ *
+ * Copyright (C) 2008-2009 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>
+ */
+
+
+public class Valadoc.Devhelp.MarkupWriter : Valadoc.MarkupWriter {
+
+       public MarkupWriter (FileStream stream, bool xml_declaration = true) {
+               // avoid broken implicit copy
+               unowned FileStream _stream = stream;
+
+               base ((str) => { _stream.printf (str); }, xml_declaration);
+       }
+
+       protected override bool inline_element (string name) {
+               return name != "book";
+       }
+
+       protected override bool content_inline_element (string name) {
+               return name == "keyword"
+                       || name == "sub";
+       }
+
+       public MarkupWriter start_book (string title, string lang, string link, string name, string version, 
string author) {
+               this.start_tag ("book", {"xmlns", "http://www.devhelp.net/book";,
+                                                                "title", title,
+                                                                "language", lang,
+                                                                "name", name,
+                                                                "version", version,
+                                                                "author", author,
+                                                                "link", link});
+               return this;
+       }
+
+       public MarkupWriter end_book () {
+               this.end_tag ("book");
+               return this;
+       }
+
+       public MarkupWriter start_functions () {
+               this.start_tag ("functions");
+               return this;
+       }
+
+       public MarkupWriter end_functions () {
+               this.end_tag ("functions");
+               return this;
+       }
+
+       public MarkupWriter start_chapters () {
+               this.start_tag ("chapters");
+               return this;
+       }
+
+       public MarkupWriter end_chapters () {
+               this.end_tag ("chapters");
+               return this;
+       }
+
+       public MarkupWriter start_sub (string name, string link) {
+               this.start_tag ("sub", {"name", name, "link", link});
+               return this;
+       }
+
+       public MarkupWriter end_sub () {
+               this.end_tag ("sub");
+               return this;
+       }
+
+       public MarkupWriter keyword (string name, string type, string link) {
+               this.start_tag ("keyword", {"type", type, "name", name, "link", link});
+               this.end_tag ("keyword");
+               return this;
+       }
+}
+
diff --git a/libvaladoc/doclet.vala b/libvaladoc/doclet.vala
new file mode 100644
index 0000000..d099bf5
--- /dev/null
+++ b/libvaladoc/doclet.vala
@@ -0,0 +1,51 @@
+/* doclet.vala
+ *
+ * Copyright (C) 2008-2009 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:
+ *     Brosch Florian <flo brosch gmail com>
+ */
+
+
+/**
+ * A plugin register function for doclets
+ *
+ * @see ModuleLoader
+ */
+[CCode (has_target = false)]
+public delegate Type Valadoc.DocletRegisterFunction (ModuleLoader module_loader);
+
+
+
+/**
+ * Provides a mechanism to inspect the API & documentation of programs and libraries
+ */
+public interface Valadoc.Doclet : GLib.Object {
+
+       /**
+        * Allows the doclet to inspect the given {@link Api.Tree}
+        *
+        * @param settings various configurations
+        * @param tree the tree to inspect
+        * @param reporter the reporter to use
+        * @see Content.ContentVisitor
+        * @see Api.Visitor
+        */
+       public abstract void process (Settings settings, Api.Tree tree, ErrorReporter reporter);
+}
+
+
diff --git a/libvaladoc/documentation/commentscanner.vala b/libvaladoc/documentation/commentscanner.vala
new file mode 100644
index 0000000..ad01601
--- /dev/null
+++ b/libvaladoc/documentation/commentscanner.vala
@@ -0,0 +1,69 @@
+/* commentscanner.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+public class Valadoc.CommentScanner : WikiScanner {
+
+       public CommentScanner (Settings settings) {
+               base (settings);
+       }
+
+       private bool in_line_start;
+       private bool past_star;
+       private int start_column;
+
+       public override void reset () {
+               base.reset ();
+
+               in_line_start = true;
+               past_star = false;
+               start_column = 0;
+       }
+
+       public override int get_line_start_column () {
+               return start_column;
+       }
+
+       protected override void accept (unichar c) throws ParserError {
+               if (in_line_start) {
+                       start_column++;
+                       if (c == '*') {
+                               past_star = true;
+                       } else if (past_star) {
+                               past_star = false;
+                               if (c == '\n') {
+                                       base.accept (c);
+                                       in_line_start = true;
+                                       start_column = 0;
+                               } else {
+                                       in_line_start = false;
+                               }
+                       }
+               } else {
+                       base.accept (c);
+                       if (c == '\n') {
+                               in_line_start = true;
+                               start_column = 0;
+                       }
+               }
+       }
+}
+
diff --git a/libvaladoc/documentation/documentation.vala b/libvaladoc/documentation/documentation.vala
new file mode 100644
index 0000000..da36684
--- /dev/null
+++ b/libvaladoc/documentation/documentation.vala
@@ -0,0 +1,38 @@
+/* documentation.vala
+ *
+ * Copyright (C) 2008-2009 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>
+ */
+
+
+public interface Valadoc.Documentation : Object {
+
+       /**
+        * The corresponding package
+        */
+       public abstract Api.Package? package {
+               get;
+       }
+
+       /**
+        * The corresponding file name
+        */
+       public abstract string? get_filename ();
+}
+
diff --git a/libvaladoc/documentation/documentationparser.vala 
b/libvaladoc/documentation/documentationparser.vala
new file mode 100644
index 0000000..878f8a1
--- /dev/null
+++ b/libvaladoc/documentation/documentationparser.vala
@@ -0,0 +1,896 @@
+/* documentationparser.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+using Valadoc.Importer;
+
+public class Valadoc.DocumentationParser : Object, ResourceLocator {
+       private Vala.HashMap<Api.SourceFile, GirMetaData> metadata;
+       private Importer.InternalIdRegistrar id_registrar;
+
+
+       public DocumentationParser (Settings settings, ErrorReporter reporter,
+                                                               Api.Tree tree, ModuleLoader modules)
+       {
+               _settings = settings;
+               _reporter = reporter;
+               _tree = tree;
+               _modules = modules;
+
+               _factory = new ContentFactory (_settings, this, _modules);
+
+               _wiki_scanner = new WikiScanner (_settings);
+               _wiki_parser = new Parser (_settings, _wiki_scanner, _reporter);
+               _wiki_scanner.set_parser (_wiki_parser);
+
+               _comment_scanner = new CommentScanner (_settings);
+               _comment_parser = new Parser (_settings, _comment_scanner, _reporter);
+               _comment_scanner.set_parser (_comment_parser);
+
+               gtkdoc_parser = new Gtkdoc.Parser (settings, reporter, tree, modules);
+               gtkdoc_markdown_parser = new Gtkdoc.MarkdownParser (settings, reporter, tree, modules);
+
+
+               metadata = new Vala.HashMap<Api.SourceFile, GirMetaData> ();
+               id_registrar = new Importer.InternalIdRegistrar ();
+
+               init_valadoc_rules ();
+       }
+
+       private Gtkdoc.Parser gtkdoc_parser;
+       private Gtkdoc.MarkdownParser gtkdoc_markdown_parser;
+
+       private Settings _settings;
+       private ErrorReporter _reporter;
+       private Api.Tree _tree;
+       private ModuleLoader _modules;
+
+       private ContentFactory _factory;
+       private WikiScanner _wiki_scanner;
+       private CommentScanner _comment_scanner;
+       private Parser _wiki_parser;
+       private Parser _comment_parser;
+       
+       private Parser _parser;
+       private Scanner _scanner;
+
+       public Comment? parse (Api.Node element, Api.SourceComment comment) {
+               if (comment is Api.GirSourceComment) {
+                       Api.GirSourceComment gir_comment = (Api.GirSourceComment) comment;
+                       GirMetaData metadata = get_metadata_for_comment (gir_comment);
+
+                       if (metadata.is_docbook) {
+                               Comment doc_comment = gtkdoc_parser.parse (element, gir_comment, metadata, 
id_registrar);
+                               return doc_comment;
+                       } else {
+                               Comment doc_comment = gtkdoc_markdown_parser.parse (element, gir_comment, 
metadata, id_registrar);
+                               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)
+       {
+               try {
+                       Comment doc_comment = parse_comment (content, filename, first_line, first_column);
+                       return doc_comment;
+               } catch (ParserError error) {
+                       return null;
+               }
+       }
+
+       public Page? parse_wikipage (Api.Package pkg, WikiPage page) {
+               if (page.documentation != null) {
+                       return page.documentation;
+               }
+
+               if (page.documentation_str == null) {
+                       return null;
+               }
+
+               try {
+                       Page documentation = parse_wiki (page.documentation_str, page.get_filename ());
+                       return documentation;
+               } catch (ParserError error) {
+                       return null;
+               }
+       }
+
+       private Comment parse_comment (string content, string filename, int first_line, int first_column)
+                                                                  throws ParserError
+       {
+               _parser = _comment_parser;
+               _scanner = _comment_scanner;
+               _stack.clear ();
+               _comment_parser.parse (content, filename, first_line, first_column);
+               return (Comment) pop ();
+       }
+
+       private Page parse_wiki (string content, string filename) throws ParserError {
+               _parser = _wiki_parser;
+               _scanner = _wiki_scanner;
+               _stack.clear ();
+               _wiki_parser.parse (content, filename, 0, 0);
+               return (Page) pop ();
+       }
+
+       public void check (Api.Node element, Comment comment) {
+               comment.check (_tree, element, element.get_source_file ().relative_path, _reporter, 
_settings);
+       }
+
+       public void check_wikipage (Api.Package package, WikiPage page) {
+               page.documentation.check (_tree, package, page.path, _reporter, _settings);
+       }
+
+       public void transform_inheritdoc (Api.Node taglet_owner, Taglets.InheritDoc taglet) {
+               if (taglet.inherited == null) {
+                       return ;
+               }
+
+
+               taglet.inherited.parse_comments (_settings, this);
+               if (taglet.inherited.documentation == null) {
+                       return ;
+               }
+
+
+               taglet.inherited.check_comments (_settings, this);
+
+               taglet.transform (_tree, taglet_owner, taglet_owner.get_source_file ().get_name (), 
_reporter, _settings);
+       }
+
+       private GirMetaData get_metadata_for_comment (Api.GirSourceComment gir_comment) {
+               GirMetaData metadata = metadata.get (gir_comment.file);
+               if (metadata != null) {
+                       return metadata;
+               }
+
+               metadata = new GirMetaData (gir_comment.file.relative_path, _settings.metadata_directories, 
_reporter);
+               if (metadata.index_sgml != null) {
+                       id_registrar.read_index_sgml_file (metadata.index_sgml, metadata.index_sgml_online, 
_reporter);
+               }
+
+               this.metadata.set (gir_comment.file, metadata);
+               return metadata;
+       }
+
+       public string resolve (string path) {
+               return path;
+       }
+
+       private Vala.ArrayList<Object> _stack = new Vala.ArrayList<Object> ();
+
+       private void push (Object element) {
+               _stack.add (element);
+       }
+
+       private Object peek (int offset = -1) {
+               assert (_stack.size >= - offset);
+               return _stack.get (_stack.size + offset);
+       }
+
+       private Object pop () {
+               Object node = peek ();
+               _stack.remove_at (_stack.size - 1);
+               return node;
+       }
+
+       private Rule multiline_block_run;
+       private Rule multiline_run;
+       private int current_level = 0;
+       private int[] levels = new int[0];
+
+       private void new_list_item (Content.List.Bullet bullet) throws ParserError {
+               var new_item = _factory.create_list_item ();
+
+               Content.List list = null;
+               if (levels.length >= 1) {
+                       if (current_level > levels[levels.length - 1]) {
+                               list = _factory.create_list ();
+                               list.bullet = bullet;
+
+                               var current_item = peek () as ListItem;
+                               current_item.content.add (list);
+                               push (list);
+
+                               levels += current_level;
+                       } else {
+                               bool poped_some_lists = false;
+                               while (current_level < levels[levels.length - 1]) {
+                                       // Pop current item and list
+                                       pop ();
+                                       pop ();
+                                       levels.resize (levels.length - 1);
+                                       poped_some_lists = true;
+                               }
+                               list = peek (-2) as Content.List;
+
+                               if (!poped_some_lists && bullet == Content.List.Bullet.NONE) {
+                                       ((Paragraph) ((ListItem) peek ()).content[0]).content.add 
(_factory.create_text (" "));
+                                       return;
+                               } else if (list.bullet != bullet) {
+                                       _parser.error (null, "Invalid bullet type '%s': expected '%s'"
+                                               .printf (bullet_type_string (bullet), bullet_type_string 
(list.bullet)));
+                                       return;
+                               }
+
+                               pop ();
+                       }
+               } else {
+                       list = _factory.create_list ();
+                       list.bullet = bullet;
+
+                       ((BlockContent) peek ()).content.add (list);
+                       push (list);
+
+                       levels = new int[0];
+                       levels += current_level;
+               }
+
+               list.items.add (new_item);
+               push (new_item);
+       }
+
+       private string bullet_type_string (Content.List.Bullet bullet) {
+               switch (bullet) {
+               case Content.List.Bullet.NONE:
+                       return ".";
+               case Content.List.Bullet.UNORDERED:
+                       return "*";
+               case Content.List.Bullet.ORDERED_NUMBER:
+                       return "1.";
+               case Content.List.Bullet.ORDERED_LOWER_CASE_ALPHA:
+                       return "a.";
+               case Content.List.Bullet.ORDERED_UPPER_CASE_ALPHA:
+                       return "A.";
+               case Content.List.Bullet.ORDERED_LOWER_CASE_ROMAN:
+                       return "i.";
+               case Content.List.Bullet.ORDERED_UPPER_CASE_ROMAN:
+                       return "I.";
+               }
+               return "";
+       }
+
+       private void finish_list () {
+               while (peek () is ListItem) {
+                       pop ();
+                       pop ();
+                       levels.resize (levels.length - 1);
+               }
+       }
+
+       private void add_content_string (string str) {
+               var text = peek () as Text;
+               if (text == null) {
+                       push (text = _factory.create_text ());
+               }
+               text.content += str;
+       }
+
+       private void add_content_space () {
+               // avoid double spaces
+               var head = peek ();
+               Text text_node = null;
+
+               if (head is Text) {
+                       text_node = (Text) head;
+               } else if (head is InlineContent && ((InlineContent) head).content.size > 0
+                       && ((InlineContent) head).content.last () is Text)
+               {
+                       text_node = (Text) ((InlineContent) head).content.last ();
+               } else {
+                       text_node = _factory.create_text ();
+                       ((InlineContent) peek ()).content.add (text_node);
+               }
+
+               if (!text_node.content.has_suffix (" ")) {
+                       text_node.content += " ";
+               }
+       }
+
+       private void init_valadoc_rules () {
+               // Inline rules
+
+               StubRule run = new StubRule ();
+               run.set_name ("Run");
+
+               TokenType.Action add_text = (token) => {
+                       add_content_string (token.to_string ());
+               };
+
+               TokenType space = TokenType.SPACE.action ((token) => { add_content_space (); });
+               TokenType word = TokenType.any_word ().action (add_text);
+
+               Rule optional_invisible_spaces =
+                       Rule.option ({
+                               Rule.many ({ TokenType.SPACE })
+                       });
+
+               Rule optional_spaces = 
+                       Rule.option ({
+                               Rule.many ({
+                                       TokenType.SPACE.action ((token) => { add_content_space (); })
+                               })
+                       });
+
+
+               Rule text =
+                       Rule.many ({
+                               Rule.one_of ({
+                                       TokenType.BREAK.action ((token) => { add_content_string ("\n"); }),
+                                       TokenType.CLOSED_BRACE.action (add_text),
+                                       TokenType.MINUS.action (add_text),
+                                       TokenType.ALIGN_BOTTOM.action (add_text),
+                                       TokenType.ALIGN_TOP.action (add_text),
+                                       TokenType.GREATER_THAN.action (add_text),
+                                       TokenType.LESS_THAN.action (add_text),
+                                       TokenType.DOUBLE_PIPE.action (add_text),
+                                       TokenType.PIPE.action (add_text),
+                                       TokenType.ALIGN_RIGHT.action (add_text),
+                                       TokenType.ALIGN_CENTER.action (add_text),
+                                       TokenType.EQUAL_1.action (add_text),
+                                       TokenType.EQUAL_2.action (add_text),
+                                       TokenType.EQUAL_3.action (add_text),
+                                       TokenType.EQUAL_4.action (add_text),
+                                       TokenType.EQUAL_5.action (add_text),
+                                       word
+                               }),
+                               Rule.option ({ space })
+                       })
+                       .set_name ("Text")
+                       .set_start (() => { push (_factory.create_text ()); });
+
+               Rule run_with_spaces =
+                       Rule.seq ({
+                               Rule.many ({
+                                       Rule.one_of ({
+                                               optional_invisible_spaces,
+                                               run
+                                       })
+                               })
+                       })
+                       .set_name ("RunWithSpaces");
+
+               multiline_run = Rule.many ({
+                               run_with_spaces,
+                               TokenType.EOL.action (() => { add_content_space (); })
+                       })
+                       .set_name ("MultiLineRun");
+
+               Rule inline_taglet =
+                       Rule.seq ({
+                               TokenType.OPEN_BRACE,
+                               Rule.option ({
+                                       TokenType.AROBASE,
+                                       TokenType.any_word ().action ((token) => {
+                                               var taglet = _factory.create_taglet (token.to_string ());
+                                               if (!(taglet is Inline)) {
+                                                       _parser.error (null, "Invalid taglet in this context: 
%s".printf (token.to_string ()));
+                                               }
+                                               push (taglet);
+                                               Rule? taglet_rule = taglet.get_parser_rule (multiline_run);
+                                               if (taglet_rule != null) {
+                                                       _parser.push_rule (Rule.seq ({ TokenType.SPACE, 
taglet_rule }));
+                                               }
+                                       }),
+                                       TokenType.CLOSED_BRACE
+                               })
+                               .set_skip (() => { add_content_string ("{"); })
+                       })
+                       .set_name ("InlineTaglet");
+
+               //TODO: Find a nicer way to allow empty tags (''run?'' won't work)
+               Rule bold =
+                       Rule.seq ({
+                               TokenType.SINGLE_QUOTE_2, 
+                               Rule.one_of ({
+                                       TokenType.SINGLE_QUOTE_2,
+                                       Rule.seq ({ optional_spaces, run, TokenType.SINGLE_QUOTE_2 })
+                               })
+                       })
+                       .set_name ("Bold")
+                       .set_start (() => { push (_factory.create_run (Run.Style.BOLD)); });
+
+               Rule italic =
+                       Rule.seq ({
+                               TokenType.SLASH_2,
+                               Rule.one_of ({
+                                       TokenType.SLASH_2,
+                                       Rule.seq ({ optional_spaces, run, TokenType.SLASH_2 })
+                               })
+                       })
+                       .set_name ("Italic")
+                       .set_start (() => { push (_factory.create_run (Run.Style.ITALIC)); });
+
+               Rule underlined =
+                       Rule.seq ({
+                               TokenType.UNDERSCORE_2,
+                               Rule.one_of ({
+                                       TokenType.UNDERSCORE_2,
+                                       Rule.seq ({ optional_spaces, run, TokenType.UNDERSCORE_2 })
+                               })
+                       })
+                       .set_name ("Underlined")
+                       .set_start (() => { push (_factory.create_run (Run.Style.UNDERLINED)); });
+
+               Rule monospace =
+                       Rule.seq ({
+                               TokenType.BACK_QUOTE_2,
+                               Rule.one_of ({
+                                       TokenType.BACK_QUOTE_2,
+                                       Rule.seq ({ optional_spaces, run, TokenType.BACK_QUOTE_2 })
+                               })
+                       })
+                       .set_name ("Monospace")
+                       .set_start (() => { push (_factory.create_run (Run.Style.MONOSPACED)); });
+
+               Rule embedded =
+                       Rule.seq ({
+                               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 (() => { ((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 (() => { ((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 (() => { ((WikiScanner) 
_scanner).set_url_escape_mode (true); }),
+                               TokenType.any_word ().action ((token) => {
+                                       var url = token.to_string ();
+                                       if (url.has_suffix (".valadoc")) {
+                                               var link = _factory.create_wiki_link ();
+                                               link.name = url;
+                                               push (link);
+                                       } else {
+                                               var link = _factory.create_link ();
+                                               link.url = url;
+                                               push (link);
+                                       }
+                               }),
+                               Rule.option ({
+                                       TokenType.PIPE.action (() => { ((WikiScanner) 
_scanner).set_url_escape_mode (false); }),
+                                       run
+                               }),
+                               TokenType.DOUBLE_CLOSED_BRACKET.action (() => { ((WikiScanner) 
_scanner).set_url_escape_mode (false); })
+                       })
+                       .set_name ("Link");
+               Rule source_code =
+                       Rule.seq ({
+                               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) => { ((WikiScanner) 
_scanner).set_code_escape_mode (false); })
+                       })
+                       .set_name ("SourceCode")
+                       .set_start (() => { push (_factory.create_source_code ()); });
+
+               Rule.Action append_head_to_head2 = () => {
+                               var head = (Inline) pop ();
+                               ((InlineContent) peek ()).content.add (head);
+                       };
+
+               Rule run_subrules =
+                       Rule.one_of ({
+                               Rule.seq ({
+                                       text
+                               })
+                               .set_reduce (append_head_to_head2),
+                               Rule.seq ({
+                                       Rule.one_of ({
+                                               inline_taglet, bold, italic, underlined, monospace, embedded, 
link, source_code
+                                       })
+                                       .set_reduce (append_head_to_head2),
+                                       optional_spaces
+                               })
+                       });
+
+               Rule run_arobase =
+                       Rule.seq ({
+                               TokenType.AROBASE.action (add_text)
+                       })
+                       .set_reduce (append_head_to_head2);
+
+               run.set_rule (
+                       Rule.seq ({
+                               run_subrules,
+                               optional_spaces,
+                               Rule.option ({
+                                       Rule.many ({
+                                               Rule.one_of ({
+                                                       run_arobase,
+                                                       run_subrules,
+                                                       optional_spaces
+                                               })
+                                       })
+                               })
+                       })
+                       .set_name ("Run")
+               );
+
+
+               // Block rules
+
+               Rule paragraph =
+                       Rule.seq ({
+                               Rule.option ({
+                                       Rule.one_of ({
+                                               TokenType.ALIGN_CENTER.action (() => { ((Paragraph) peek 
()).horizontal_align = HorizontalAlign.CENTER; }),
+                                               TokenType.ALIGN_RIGHT.action (() => { ((Paragraph) peek 
()).horizontal_align = HorizontalAlign.RIGHT; })
+                                       })
+                               }),
+                               Rule.many ({
+                                       run,
+                                       TokenType.EOL.action (() => { add_content_space (); })
+                               })
+                       })
+                       .set_name ("Paragraph")
+                       .set_start (() => { push (_factory.create_paragraph ()); })
+                       .set_reduce (() => {
+                               var head = (Paragraph) pop ();
+                               ((BlockContent) peek ()).content.add (head);
+
+                               Text last_element = head.content.last () as Text;
+                               if (last_element != null) {
+                                       last_element.content._chomp ();
+                               }
+                       });
+
+               Rule warning =
+                       Rule.seq ({
+                               TokenType.str ("Warning:"),
+                               optional_invisible_spaces,
+                               Rule.many ({
+                                       Rule.seq({optional_invisible_spaces, run}),
+                                       TokenType.EOL.action (() => { add_content_space (); })
+                               })
+                       })
+                       .set_name ("Warning")
+                       .set_start (() => { push (_factory.create_paragraph ()); })
+                       .set_reduce (() => {
+                               var head = _factory.create_warning ();
+                               head.content.add ((Paragraph) pop ());
+                               ((BlockContent) peek ()).content.add (head);
+
+                               Text last_element = head.content.last () as Text;
+                               if (last_element != null) {
+                                       last_element.content._chomp ();
+                               }
+                       });
+
+               Rule note =
+                       Rule.seq ({
+                               TokenType.str ("Note:"),
+                               optional_invisible_spaces,
+                               Rule.many ({
+                                       Rule.seq({optional_invisible_spaces, run}),
+                                       TokenType.EOL.action (() => { add_content_space (); })
+                               })
+                       })
+                       .set_name ("Note")
+                       .set_start (() => { push (_factory.create_paragraph ()); })
+                       .set_reduce (() => {
+                               var head = _factory.create_note ();
+                               head.content.add ((Paragraph) pop ());
+                               ((BlockContent) peek ()).content.add (head);
+
+                               Text last_element = head.content.last () as Text;
+                               if (last_element != null) {
+                                       last_element.content._chomp ();
+                               }
+                       });
+
+               Rule indented_item =
+                       Rule.seq ({
+                               Rule.many ({
+                                       TokenType.SPACE.action ((token) => { current_level++; })
+                               }),
+                               Rule.option ({
+                                       Rule.one_of ({
+                                               TokenType.str (".").action ((token) => { new_list_item 
(Content.List.Bullet.NONE); }),
+                                               TokenType.str ("*").action ((token) => { new_list_item 
(Content.List.Bullet.UNORDERED); }),
+                                               TokenType.str ("#").action ((token) => { new_list_item 
(Content.List.Bullet.ORDERED); }),
+                                               TokenType.str ("1.").action ((token) => { new_list_item 
(Content.List.Bullet.ORDERED_NUMBER); }),
+                                               TokenType.str ("a.").action ((token) => { new_list_item 
(Content.List.Bullet.ORDERED_LOWER_CASE_ALPHA); }),
+                                               TokenType.str ("A.").action ((token) => { new_list_item 
(Content.List.Bullet.ORDERED_UPPER_CASE_ALPHA); }),
+                                               TokenType.str ("i.").action ((token) => { new_list_item 
(Content.List.Bullet.ORDERED_LOWER_CASE_ROMAN); }),
+                                               TokenType.str ("I.").action ((token) => { new_list_item 
(Content.List.Bullet.ORDERED_UPPER_CASE_ROMAN); })
+                                       }),
+                                       optional_invisible_spaces
+                               })
+                               .set_skip (() => { new_list_item (Content.List.Bullet.NONE); }),
+                               Rule.seq ({ run })
+                               .set_start (() => {
+                                       var content = _factory.create_paragraph ();
+                                       ((ListItem) peek ()).content.add (content);
+                                       push (content);
+                               })
+                               .set_reduce (() => { pop (); }),
+                               TokenType.EOL
+                       })
+                       .set_name ("IndentedItem")
+                       .set_start (() => { current_level = 0; })
+                       .set_reduce (() => {
+                               var content_list = ((ListItem) peek ()).content;
+                               if (content_list.size > 0 && content_list.last () is Text) {
+                                       ((Text) content_list.last ()).content._chomp ();
+                               }
+                       });
+
+               Rule indented_blocks =
+                       Rule.many ({
+                               indented_item
+                       })
+                       .set_name ("IndentedBlocks")
+                       .set_reduce (() => { finish_list (); });
+
+               Rule table_cell_attributes =
+                       Rule.seq ({
+                               TokenType.LESS_THAN,
+                               Rule.option ({
+                                       Rule.one_of ({
+                                               Rule.seq ({
+                                                       Rule.option ({
+                                                               Rule.one_of ({
+                                                                       TokenType.ALIGN_RIGHT.action ((token) 
=> { ((TableCell) peek ()).horizontal_align = HorizontalAlign.RIGHT; }),
+                                                                       TokenType.ALIGN_CENTER.action 
((token) => { ((TableCell) peek ()).horizontal_align = HorizontalAlign.CENTER; })
+                                                               })
+                                                       }),
+                                                       Rule.option ({
+                                                               Rule.one_of ({
+                                                                       TokenType.ALIGN_TOP.action ((token) 
=> { ((TableCell) peek ()).vertical_align = VerticalAlign.TOP; }),
+                                                                       TokenType.ALIGN_BOTTOM.action 
((token) => { ((TableCell) peek ()).vertical_align = VerticalAlign.BOTTOM; })
+                                                               })
+                                                       })
+                                               }),
+                                               TokenType.any_word ().action ((token) => { ((TableCell) peek 
()).style = token.to_string (); })
+                                       })
+                               }),
+                               Rule.option ({
+                                       Rule.one_of ({
+                                               Rule.seq ({
+                                                       TokenType.PIPE,
+                                                       TokenType.any_number ().action ((token) => { 
((TableCell) peek ()).rowspan = token.to_int (); })
+                                               }),
+                                               Rule.seq ({
+                                                       TokenType.MINUS,
+                                                       TokenType.any_number ().action ((token) => { 
((TableCell) peek ()).colspan = token.to_int (); })
+                                               })
+                                       })
+                               }),
+                               TokenType.GREATER_THAN
+                       })
+                       .set_name ("CellAttributes");
+               Rule table_cell =
+                       Rule.seq ({
+                               Rule.seq ({
+                                       Rule.option ({
+                                               table_cell_attributes
+                                       }),
+                                       optional_invisible_spaces,
+                                       run
+                               }),
+                               TokenType.DOUBLE_PIPE
+                       })
+                       .set_name ("Cell")
+                       .set_start (() => { push (_factory.create_table_cell ()); })
+                       .set_reduce (() => {
+                               var head = (TableCell) pop ();
+                               ((TableRow) peek ()).cells.add (head);
+
+                               if (head.content.size > 0 && head.content.last () is Text) {
+                                       ((Text) head.content.last ()).content._chomp ();
+                               }
+                       });
+               Rule table_row =
+                       Rule.seq ({
+                               TokenType.DOUBLE_PIPE,
+                               Rule.many ({
+                                       table_cell
+                               }),
+                               TokenType.EOL
+                       })
+                       .set_name ("Row")
+                       .set_start (() => { push (_factory.create_table_row ()); })
+                       .set_reduce (() => {
+                               var head = (TableRow) pop ();
+                               ((Table) peek ()).rows.add (head);
+                       });
+               Rule table =
+                       Rule.seq ({
+                               Rule.many ({
+                                       table_row
+                               })
+                       })
+                       .set_name ("Table")
+                       .set_start (() => { push (_factory.create_table ()); })
+                       .set_reduce (() => {
+                               var head = (Block) pop ();
+                               ((BlockContent) peek ()).content.add (head);
+                       });
+
+               Rule headline =
+                       Rule.one_of ({
+                               Rule.seq ({
+                                       TokenType.EQUAL_1.action ((token) => { ((Headline) peek ()).level = 
1; }),
+                                       optional_invisible_spaces,
+                                       run,
+                                       optional_invisible_spaces,
+                                       TokenType.EQUAL_1,
+                                       TokenType.EOL
+                               }),
+                               Rule.seq ({
+                                       TokenType.EQUAL_2.action ((token) => { ((Headline) peek ()).level = 
2; }),
+                                       optional_invisible_spaces,
+                                       run,
+                                       optional_invisible_spaces,
+                                       TokenType.EQUAL_2,
+                                       TokenType.EOL
+                               }),
+                               Rule.seq ({
+                                       TokenType.EQUAL_3.action ((token) => { ((Headline) peek ()).level = 
3; }),
+                                       optional_invisible_spaces,
+                                       run,
+                                       optional_invisible_spaces,
+                                       TokenType.EQUAL_3,
+                                       TokenType.EOL
+                               }),
+                               Rule.seq ({
+                                       TokenType.EQUAL_4.action ((token) => { ((Headline) peek ()).level = 
4; }),
+                                       optional_invisible_spaces,
+                                       run,
+                                       optional_invisible_spaces,
+                                       TokenType.EQUAL_4,
+                                       TokenType.EOL
+                               }),
+                               Rule.seq ({
+                                       TokenType.EQUAL_5.action ((token) => { ((Headline) peek ()).level = 
5; }),
+                                       optional_invisible_spaces,
+                                       run,
+                                       optional_invisible_spaces,
+                                       TokenType.EQUAL_5,
+                                       TokenType.EOL
+                               })
+                       })
+                       .set_name ("Headline")
+                       .set_start (() => { push (_factory.create_headline ()); })
+                       .set_reduce (() => {
+                               var head = (Block) pop ();
+                               ((BlockContent) peek ()).content.add (head);
+                       });
+
+               Rule blocks =
+                       Rule.one_of ({
+                               indented_blocks,
+                               table,
+                               headline,
+                               warning,
+                               note,
+                               paragraph
+                       })
+                       .set_name ("Blocks");
+
+               Rule page =
+                       Rule.seq ({
+                               blocks,
+                               Rule.option ({
+                                       Rule.many ({
+                                               TokenType.EOL,
+                                               Rule.option ({ blocks })
+                                       })
+                               })
+                       })
+                       .set_name ("Page")
+                       .set_start (() => { push (_factory.create_page ()); });
+
+               Rule description =
+                       Rule.seq ({
+                               blocks,
+                               Rule.option ({
+                                       Rule.many ({
+                                               TokenType.EOL,
+                                               Rule.option ({ blocks })
+                                       })
+                               })
+                       })
+                       .set_name ("Description");
+
+               multiline_block_run =
+                       Rule.seq ({
+                               multiline_run
+                       })
+                       .set_start (() => { push (_factory.create_paragraph ()); })
+                       .set_reduce (() => {
+                               Paragraph p = (Paragraph) pop ();
+                               ((BlockContent) peek ()).content.add (p);
+                       })
+                       .set_name ("BlockMultilineRun");
+
+               Rule taglet =
+                       Rule.seq ({
+                               TokenType.AROBASE,
+                               TokenType.any_word ().action ((token) => {
+
+                                       string tag_name = token.to_string ();
+                                       var taglet = _factory.create_taglet (tag_name);
+                                       if (!(taglet is Block)) {
+                                               _parser.error (token, "Invalid taglet in this context");
+                                       }
+                                       push (taglet);
+
+                                       Rule? taglet_rule;
+                                       if (taglet is BlockContent) {
+                                               taglet_rule = taglet.get_parser_rule (multiline_block_run);   
                                  
+                                       } else {
+                                               taglet_rule = taglet.get_parser_rule (multiline_run);
+                                       }
+
+                                       if (taglet_rule != null) {
+                                               _parser.push_rule (Rule.seq ({ TokenType.SPACE, taglet_rule 
}));
+                                       }
+                               }),
+                               Rule.option ({
+                                       Rule.many ({ TokenType.EOL })
+                               })
+                       })
+                       .set_name ("Taglet")
+                       .set_reduce (() => {
+                               var head = (Taglet) pop ();
+                               ((Comment) peek ()).taglets.add (head);
+                       });
+
+               Rule comment =
+                       Rule.seq ({
+                               TokenType.EOL,
+                               Rule.option ({
+                                       description
+                               }),
+                               Rule.option ({
+                                       Rule.many ({ taglet })
+                               })
+                       })
+                       .set_name ("Comment")
+                       .set_start (() => { push (_factory.create_comment ()); });
+
+               _comment_parser.set_root_rule (comment);
+               _wiki_parser.set_root_rule (page);
+       }
+
+#if DEBUG
+       private void dump_stack (string title) {
+               message ("=== Dumping stack: %s ===", title);
+               foreach (Object object in _stack) {
+                       message ("%s", object.get_type ().name ());
+               }
+       }
+#endif
+}
diff --git a/libvaladoc/documentation/girmetadata.vala b/libvaladoc/documentation/girmetadata.vala
new file mode 100644
index 0000000..7d1b78e
--- /dev/null
+++ b/libvaladoc/documentation/girmetadata.vala
@@ -0,0 +1,154 @@
+/* girmetadata.vala
+ *
+ * Copyright (C) 2012-2014 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:
+ *     Brosch Florian <flo brosch gmail com>
+ */
+
+
+/**
+ * Metadata reader for GIR files
+ */
+public class Valadoc.GirMetaData : Object {
+       private string? metadata_path = null;
+       private string? resource_dir = null;
+
+
+       public bool is_docbook { private set; get; default = false; }
+       public string index_sgml { private set; get; default = null; }
+       public string index_sgml_online { private set; get; default = null; }
+
+       /**
+        * Used to manipulate paths to resources inside gir-files
+        */
+       public string get_resource_path (string resource) {
+               if (resource_dir == null || metadata_path == null) {
+                       return resource;
+               }
+
+               if (Path.is_absolute (resource_dir)) {
+                       return Path.build_filename (resource_dir, resource);
+               }
+
+               return Path.build_filename (Path.get_dirname (metadata_path), resource_dir, resource);
+       }
+
+       private string? get_metadata_file_name (string gir_file_path) {
+               string metadata_file_name = Path.get_basename (gir_file_path);
+               int last_dot_pos = metadata_file_name.last_index_of (".");
+               if (last_dot_pos < 0) {
+                       return null;
+               }
+
+               metadata_file_name = metadata_file_name.substring (0, last_dot_pos);
+               return metadata_file_name + ".valadoc.metadata";
+       }
+
+       private string? get_metadata_path (string gir_file_path, string[] metadata_dirs) {
+               string? metadata_file_name = get_metadata_file_name (gir_file_path);
+               if (metadata_file_name == null) {
+                       return null;
+               }
+
+               // search for metatada at the same location as the gir file
+               string metadata_path = Path.build_filename (Path.get_dirname (gir_file_path), 
metadata_file_name);
+               if (FileUtils.test (metadata_path, FileTest.IS_REGULAR)) {
+                       return metadata_path;
+               }
+
+               foreach (string metadata_dir in metadata_dirs) {
+                       metadata_path = Path.build_filename (metadata_dir, metadata_file_name);
+                       if (FileUtils.test (metadata_path, FileTest.IS_REGULAR)) {
+                               return metadata_path;
+                       }
+               }
+
+               return null;
+       }
+
+       private void load_general_metadata (KeyFile key_file, ErrorReporter reporter) throws KeyFileError {
+               foreach (string key in key_file.get_keys ("General")) {
+                       switch (key) {
+                       case "resources":
+                               this.resource_dir = key_file.get_string ("General", "resources");
+                               break;
+
+                       case "is_docbook":
+                               this.is_docbook = key_file.get_boolean ("General", "is_docbook");
+                               break;
+
+                       case "index_sgml":
+                               string tmp = key_file.get_string ("General", "index_sgml");
+                               this.index_sgml = Path.build_filename (Path.get_dirname (metadata_path), tmp);
+                               break;
+
+                       case "index_sgml_online":
+                               this.index_sgml_online = key_file.get_string ("General", "index_sgml_online");
+                               break;
+
+                       default:
+                               reporter.simple_warning (metadata_path, "Unknown key 'General.%s'", key);
+                               break;
+                       }
+               }
+       }
+
+       public GirMetaData (string gir_file_path, string[] metadata_dirs, ErrorReporter reporter) {
+               if (!FileUtils.test (gir_file_path, FileTest.IS_REGULAR)) {
+                       return ;
+               }
+
+               metadata_path = get_metadata_path (gir_file_path, metadata_dirs);
+               if (metadata_path == null) {
+                       return ;
+               }
+
+               KeyFile key_file;
+
+               try {
+                       key_file = new KeyFile ();
+                       key_file.load_from_file (metadata_path, KeyFileFlags.NONE);
+               } catch (KeyFileError e) {
+                       reporter.simple_error (metadata_path, "%s", e.message);
+                       return ;
+               } catch (FileError e) {
+                       reporter.simple_error (metadata_path, "%s", e.message);
+                       return ;
+               }
+
+               try {
+                       foreach (string group in key_file.get_groups ()) {
+                               switch (group) {
+                               case "General":
+                                       load_general_metadata (key_file, reporter);
+                                       break;
+
+                               default:
+                                       reporter.simple_warning (metadata_path, "Unknown group '%s'", group);
+                                       break;
+                               }
+                       }
+               } catch (KeyFileError e) {
+                       reporter.simple_error (null, "Unable to read file '%s': %s", metadata_path, 
e.message);
+               }
+
+
+               // Load internal link lut:
+       }
+}
+
diff --git a/libvaladoc/documentation/gtkdoccommentparser.vala 
b/libvaladoc/documentation/gtkdoccommentparser.vala
new file mode 100644
index 0000000..ede991c
--- /dev/null
+++ b/libvaladoc/documentation/gtkdoccommentparser.vala
@@ -0,0 +1,1663 @@
+/* gtkcommentparser.vala
+ *
+ * Copyright (C) 2011-2014  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;
+
+public class Valadoc.Gtkdoc.Parser : Object, ResourceLocator {
+       private Scanner scanner = new Scanner ();
+       private Token current;
+
+       private Vala.List<string> stack = new Vala.ArrayList<string> (str_equal);
+       private Vala.List<Vala.List<Block>> footnotes = new Vala.ArrayList<Vala.ArrayList<Block>> ();
+
+       private ContentFactory factory;
+       private ErrorReporter reporter;
+       private Settings settings;
+       private Api.Tree tree;
+       private Api.Node? element;
+
+       private bool show_warnings;
+       private Api.SourceComment comment;
+       private unowned string instance_param_name;
+
+       private string[]? comment_lines;
+
+       private Regex? is_numeric_regex = null;
+       private Regex? normalize_regex = null;
+       private Regex regex_source_lang = null;
+
+       private Importer.InternalIdRegistrar id_registrar = null;
+       private GirMetaData? current_metadata = null;
+
+       private inline string fix_resource_path (string path) {
+               return this.current_metadata.get_resource_path (path);
+       }
+
+       private void reset (Api.SourceComment comment) {
+               this.scanner.reset (comment.content);
+               this.show_warnings = !comment.file.package.is_package;
+               this.comment_lines = null;
+               this.footnotes.clear ();
+               this.comment = comment;
+               this.current = null;
+               this.stack.clear ();
+       }
+
+       private string normalize (string text) {
+               try {
+                       return normalize_regex.replace (text, -1, 0, " ");
+               } catch (RegexError e) {
+                       assert_not_reached ();
+               }
+       }
+
+       private bool is_numeric (string str) {
+               return is_numeric_regex.match (str);
+       }
+
+       private void report_unexpected_token (Token got, string expected) {
+               report_warning (got, "Unexpected Token: %s (Expected: %s)".printf (got.to_string (), 
expected));
+       }
+
+       private void report_warning (Token got, string message) {
+               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],
+                                                          message);
+       }
+
+       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;
+
+               try {
+                       is_numeric_regex = new Regex 
("^[+-]?([0-9]*\\.?[0-9]+|[0-9]+\\.?[0-9]*)([eE][+-]?[0-9]+)?$",
+                               RegexCompileFlags.OPTIMIZE);
+                       normalize_regex = new Regex ("( |\n|\t)+", RegexCompileFlags.OPTIMIZE);
+                       regex_source_lang = new Regex ("^<!--[ \t]+language=\"([A-Za-z]*)\"[ \t]+-->");
+               } catch (RegexError e) {
+                       assert_not_reached ();
+               }
+       }
+
+       private Note? _parse_note (Api.SourceComment comment) {
+               Comment? cmnt = parse_root_content (comment);
+               if (cmnt == null) {
+                       return null;
+               }
+
+               Note note = factory.create_note ();
+               note.content.add_all (cmnt.content);
+
+               return note;
+       }
+
+       private void add_note (ref Comment? comment, Note? note) {
+               if (note == null) {
+                       return ;
+               }
+
+               if (comment == null) {
+                       comment = factory.create_comment ();
+               }
+
+               if (comment.content.size == 0) {
+                       comment.content.add (factory.create_paragraph ());
+               }
+
+               comment.content.insert (1, note);
+       }
+
+       private void add_taglet (ref Comment? comment, Taglet? taglet) {
+               if (taglet == null) {
+                       return ;
+               }
+
+               if (comment == null) {
+                       comment = factory.create_comment ();
+               }
+
+               comment.taglets.add (taglet);
+       }
+
+       public Comment? parse (Api.Node element, Api.GirSourceComment gir_comment, GirMetaData gir_metadata, 
Importer.InternalIdRegistrar id_registrar) {
+               this.instance_param_name = gir_comment.instance_param_name;
+               this.current_metadata = gir_metadata;
+               this.id_registrar = id_registrar;
+               this.element = element;
+
+
+               Comment? cmnt = parse_root_content (gir_comment);
+               if (cmnt != null) {
+                       ImporterHelper.extract_short_desc (cmnt, factory);
+               }
+
+
+               // deprecated:
+               if (gir_comment.deprecated_comment != null) {
+                       Note? note = _parse_note (gir_comment.deprecated_comment);
+                       add_note (ref cmnt, note);
+               }
+
+
+               // version:
+               if (gir_comment.version_comment != null) {
+                       Note? note = _parse_note (gir_comment.version_comment);
+                       add_note (ref cmnt, note);
+               }
+
+               // stability:
+               if (gir_comment.stability_comment != null) {
+                       Note? note = _parse_note (gir_comment.stability_comment);
+                       add_note (ref cmnt, note);
+               }
+
+
+               // return:
+               if (gir_comment.return_comment != null) {
+                       Taglet? taglet = parse_block_taglet (gir_comment.return_comment, "return");
+                       add_taglet (ref cmnt, taglet);
+               }
+
+
+               // parameters:
+               Vala.MapIterator<string, Api.SourceComment> iter = gir_comment.parameter_iterator ();
+               for (bool has_next = iter.next (); has_next; has_next = iter.next ()) {
+                       Taglets.Param? taglet = parse_block_taglet (iter.get_value (), "param") as 
Taglets.Param;
+                       string param_name = iter.get_key ();
+
+                       taglet.is_c_self_param = (param_name == gir_comment.instance_param_name);
+                       taglet.parameter_name = param_name;
+                       add_taglet (ref cmnt, taglet);
+               }
+
+
+               bool first = true;
+               foreach (Vala.List<Block> note in this.footnotes) {
+                       if (first == true && note.size > 0) {
+                               Paragraph p = note.first () as Paragraph;
+                               if (p == null) {
+                                       p = factory.create_paragraph ();
+                                       cmnt.content.add (p);
+                               }
+
+                               p.content.insert (0, factory.create_text ("\n"));
+                       }
+                       cmnt.content.add_all (note);
+                       first = false;
+               }
+
+               return cmnt;
+       }
+
+       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;
+               }
+
+               BlockContent? taglet = factory.create_taglet (taglet_name) as BlockContent;
+               assert (taglet != null);
+               Paragraph paragraph = factory.create_paragraph ();
+               paragraph.content.add (ic);
+               taglet.content.add (paragraph);
+               return taglet as Taglet;
+       }
+
+       private Comment? parse_root_content (Api.SourceComment 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;
+               }
+
+               ImporterHelper.extract_short_desc (comment, factory);
+
+               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)
+                       || current.type != TokenType.XML_OPEN)
+               {
+                       return false;
+               }
+
+               stack.insert (0, tagname);
+               return true;
+       }
+
+       private bool check_xml_close_tag (string tagname) {
+               if ((current.type == TokenType.XML_CLOSE && current.content != tagname)
+                       || current.type != TokenType.XML_CLOSE)
+               {
+                       return false;
+               }
+
+               assert (stack.remove_at (0) == tagname);
+
+               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, bool is_internal) {
+               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 ();
+               if (is_internal) {
+                       link.id_registrar = id_registrar;
+               }
+               link.url = url;
+
+               if (builder.len == 0) {
+                       link.content.add (factory.create_text (url));
+               } else {
+                       link.content.add (factory.create_text (normalize (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.WORD && current.content == "struct") {
+                       next ();
+
+                       if (next ().type == TokenType.SPACE) {
+                               next ();
+                       }
+               }
+
+
+               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");
+               if (id != null) {
+                       id_registrar.register_symbol (id, element);
+               }
+               next ();
+
+               if (!check_xml_close_tag ("anchor")) {
+                       this.report_unexpected_token (current, "</anchor>");
+                       return;
+               }
+
+               next ();
+       }
+
+       private Link? parse_xref () {
+               if (!check_xml_open_tag ("xref")) {
+                       this.report_unexpected_token (current, "<xref>");
+                       return null;
+               }
+
+               string linkend = current.attributes.get ("linkend");
+               next ();
+
+               Link link = factory.create_link ();
+               link.content.add (factory.create_text (linkend));
+               link.id_registrar = id_registrar;
+               link.url = linkend;
+
+               if (!check_xml_close_tag ("xref")) {
+                       this.report_unexpected_token (current, "</xref>");
+                       return link;
+               }
+
+               next ();
+               return link;
+       }
+
+       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 ();
+       
+               item.content.add_all (parse_mixed_content ());
+
+               if (!check_xml_close_tag ("listitem")) {
+                       this.report_unexpected_token (current, "</listitem>");
+                       return item;
+               }
+
+               next ();
+               return item;
+       }
+
+       private BlockContent? parse_docbook_information_box_template (string tagname, BlockContent container) 
{
+               if (!check_xml_open_tag (tagname)) {
+                       this.report_unexpected_token (current, "<%s>".printf (tagname));
+                       return null;
+               }
+
+               next ();
+               parse_docbook_spaces ();
+
+               Token tmp = null;
+               while (current.type != TokenType.XML_CLOSE && current.type != TokenType.EOF) {
+                       tmp = current;
+                       var ic = parse_inline_content ();
+                       if (ic != null && ic.content.size > 0) {
+                               Paragraph p = factory.create_paragraph ();
+                               p.content.add (ic);
+                               container.content.add (p);
+                       }
+
+                       var bc = parse_block_content ();
+                       if (bc != null && bc.size > 0) {
+                               container.content.add_all (bc);
+                       }
+               }
+
+               parse_docbook_spaces ();
+
+               if (!check_xml_close_tag (tagname)) {
+                       this.report_unexpected_token (current, "</%s>".printf (tagname));
+                       return container;
+               }
+
+               next ();
+               return container;
+       }
+
+       private Note? parse_docbook_important () {
+               return (Note?) parse_docbook_information_box_template ("important", factory.create_note ());
+       }
+
+       private Note? parse_docbook_note () {
+               return (Note?) parse_docbook_information_box_template ("note", factory.create_note ());
+       }
+
+       private Warning? parse_docbook_warning () {
+               return (Warning?) parse_docbook_information_box_template ("warning", factory.create_warning 
());
+       }
+
+       private inline Vala.Collection<Block>? parse_docbook_orderedlist () {
+               return parse_docbook_itemizedlist ("orderedlist", Content.List.Bullet.ORDERED);
+       }
+
+       private Vala.Collection<Block>? parse_docbook_itemizedlist (string tag_name = "itemizedlist",
+                                                                                  Content.List.Bullet 
bullet_type = Content.List.Bullet.UNORDERED)
+       {
+               if (!check_xml_open_tag (tag_name)) {
+                       this.report_unexpected_token (current, "<%s>".printf (tag_name));
+                       return null;
+               }
+               next ();
+
+
+               Vala.Collection<Block> content = new Vala.ArrayList<Block> ();
+               parse_docbook_spaces ();
+
+               if (current.type == TokenType.XML_OPEN && current.content == "title") {
+                       append_block_content_not_null (content, parse_docbook_title ());
+                       parse_docbook_spaces ();
+               }
+
+               Content.List list = factory.create_list ();
+               list.bullet = bullet_type;
+               content.add (list);
+
+               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 (tag_name)) {
+                       this.report_unexpected_token (current, "</%s>".printf (tag_name));
+                       return content;
+               }
+
+               next ();
+               return content;
+       }
+
+       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 Vala.Collection<Block> parse_mixed_content () {
+               Vala.Collection<Block> content = new Vala.ArrayList<Block> ();
+               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;
+                       }
+
+                       Vala.Collection<Block> lst = parse_block_content ();
+                       if (lst != null && lst.size > 0) {
+                               content.add_all (lst);
+                               continue;
+                       }
+               }
+
+               return content;
+       }
+
+       private inline Vala.Collection<Block>? parse_docbook_simpara () {
+               return parse_docbook_para ("simpara");
+       }
+
+       private Vala.Collection<Block>? parse_docbook_para (string tag_name = "para") {
+               if (!check_xml_open_tag (tag_name)) {
+                       this.report_unexpected_token (current, "<%s>".printf (tag_name));
+                       return null;
+               }
+
+               next ();
+
+               Vala.Collection<Block> content = parse_mixed_content ();
+
+               // ignore missing </para> to match gtkdocs behaviour
+               if (!check_xml_close_tag (tag_name) && current.type != TokenType.EOF) {
+                       this.report_unexpected_token (current, "</%s>".printf (tag_name));
+                       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 ();
+               Token source_token = current;
+
+               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 code = factory.create_source_code ();
+               MatchInfo info;
+
+               unowned string source = builder.str;
+               if (regex_source_lang.match (source, 0, out info)) {
+                       string lang_name = info.fetch (1).down ();
+                       SourceCode.Language? lang = SourceCode.Language.from_string (lang_name);
+                       code.language = lang;
+
+                       if (lang == null) {
+                               report_warning (source_token, "Unknown language `%s' in source code block 
|[<!-- language=\"\"".printf (lang_name));
+                       }
+
+                       source = source.offset (source.index_of_char ('>') + 1);
+               } else {
+                       code.language = (Highlighter.XmlScanner.is_xml (source))
+                               ? SourceCode.Language.XML
+                               : SourceCode.Language.C;
+               }
+               code.code = source;
+
+               Paragraph p = factory.create_paragraph ();
+               p.content.add (code);
+
+               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 Paragraph? parse_docbook_graphic () {
+               var tmp = parse_docbook_inlinegraphic ("graphic");
+               if (tmp == null) {
+                       return null;
+               }
+
+               Paragraph? p = factory.create_paragraph ();
+               p.content.add (tmp);
+               return p;
+       }
+
+       private Embedded? parse_docbook_inlinegraphic (string tag_name = "inlinegraphic") {
+               if (!check_xml_open_tag (tag_name)) {
+                       this.report_unexpected_token (current, "<%s>".printf (tag_name));
+                       return null;
+               }
+
+               Embedded e = factory.create_embedded ();
+               e.url = fix_resource_path (current.attributes.get ("fileref"));
+
+               next ();
+               parse_docbook_spaces ();
+
+               if (!check_xml_close_tag (tag_name)) {
+                       this.report_unexpected_token (current, "</%s>".printf (tag_name));
+                       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 Vala.Collection<Block>? parse_docbook_informalexample () {
+               if (!check_xml_open_tag ("informalexample")) {
+                       this.report_unexpected_token (current, "<informalexample>");
+                       return null;
+               }
+
+               next ();
+
+               parse_docbook_spaces ();
+
+               Vala.Collection<Block> content = new Vala.ArrayList<Block> ();
+
+               if (current.type == TokenType.XML_OPEN && current.content == "title") {
+                       append_block_content_not_null (content, parse_docbook_title ());
+                       parse_docbook_spaces ();
+               }
+
+               if (current.type == TokenType.XML_OPEN && current.content == "programlisting") {
+                       append_block_content_not_null (content, parse_docbook_programlisting ());
+               } else if (current.type == TokenType.XML_OPEN && current.content == "inlinegraphic") {
+                       Embedded? img = parse_docbook_inlinegraphic ();
+                       Paragraph p = factory.create_paragraph ();
+                       append_block_content_not_null (content, p);
+                       p.content.add (img);
+
+               }
+
+               parse_docbook_spaces ();
+
+               if (!check_xml_close_tag ("informalexample")) {
+                       this.report_unexpected_token (current, "</informalexample>");
+                       return content;
+               }
+
+               next ();
+               return content;
+       }
+*/
+
+       private inline Vala.Collection<Block>? parse_docbook_informalexample () {
+               return parse_docbook_example ("informalexample");
+       }
+
+       private Vala.Collection<Block>? parse_docbook_example (string tag_name = "example") {
+               if (!check_xml_open_tag (tag_name)) {
+                       this.report_unexpected_token (current, "<%s>".printf (tag_name));
+                       return null;
+               }
+
+               next ();
+
+               parse_docbook_spaces ();
+
+               Vala.Collection<Block> content = new Vala.ArrayList<Block> ();
+
+               content.add_all (parse_mixed_content ());
+
+               /*
+               while (current.type == TokenType.XML_OPEN) {
+                       if (current.type == TokenType.XML_OPEN && current.content == "inlinegraphic") {
+                               Paragraph p = factory.create_paragraph ();
+                               while (current.type == TokenType.XML_OPEN && current.content == 
"inlinegraphic") {
+                                       p.content.add (parse_docbook_inlinegraphic ());
+                                       parse_docbook_spaces ();
+                               }
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "programlisting") 
{
+                               append_block_content_not_null (content, parse_docbook_programlisting ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "para") {
+                               this.append_block_content_not_null_all (content, parse_docbook_para ());
+                       } else {
+                               break;
+                       }
+
+                       parse_docbook_spaces ();
+               } */
+
+               if (!check_xml_close_tag (tag_name)) {
+                       this.report_unexpected_token (current, "</%s>".printf (tag_name));
+                       return content;
+               }
+
+               next ();
+               return content;
+       }
+
+       private Vala.List<Block>? parse_docbook_refsect2 (int nr = 2) {
+               if (!check_xml_open_tag ("refsect%d".printf (nr))) {
+                       this.report_unexpected_token (current, "<refsect%d>".printf (nr));
+                       return null;
+               }
+
+               string id = current.attributes.get ("id");
+               if (id != null) {
+                       id_registrar.register_symbol (id, element);
+               }
+               next ();
+
+               parse_docbook_spaces ();
+
+               Vala.List<Block> content = new Vala.ArrayList<Block> ();
+
+               this.append_block_content_not_null_all (content, parse_mixed_content ());
+
+               if (!check_xml_close_tag ("refsect%d".printf (nr))) {
+                       this.report_unexpected_token (current, "</refsect%d>".printf (nr));
+                       return content;
+               }
+
+               next ();
+               return content;
+       }
+
+       private Vala.List<Block>? parse_docbook_figure () {
+               if (!check_xml_open_tag ("figure")) {
+                       this.report_unexpected_token (current, "<figure>");
+                       return null;
+               }
+               next ();
+
+               Vala.List<Block> content = new Vala.ArrayList<Block> ();
+               parse_docbook_spaces ();
+
+               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 = (content.size > 0)? content[0] as Paragraph : null;
+                               if (p == null) {
+                                       p = factory.create_paragraph ();
+                               }
+
+                               while (current.type == TokenType.XML_OPEN && current.content == 
"inlinegraphic") {
+                                       p.content.add (parse_docbook_inlinegraphic ());
+                                       parse_docbook_spaces ();
+                               }
+                       } else if (current.content == "graphic") {
+                               append_block_content_not_null (content, parse_docbook_graphic ());
+                       } else {
+                               break;
+                       }
+
+                       parse_docbook_spaces ();
+               }
+
+               if (!check_xml_close_tag ("figure")) {
+                       this.report_unexpected_token (current, "</figure>");
+                       return content;
+               }
+
+               next ();
+               return content;
+       }
+
+       private Run? parse_docbook_footnote () {
+               if (!check_xml_open_tag ("footnote")) {
+                       this.report_unexpected_token (current, "<footnote>");
+                       return null;
+               }
+               next ();
+
+               int counter = this.footnotes.size + 1;
+               Run? nr = factory.create_run (Run.Style.ITALIC);
+               nr.content.add (factory.create_text ("[%d] ".printf (counter)));
+               Vala.List<Block> content = new Vala.ArrayList<Block> ();
+               this.footnotes.add (content);
+
+               content.add_all (parse_mixed_content ());
+
+               Paragraph? first = (content.is_empty)? null : content.first () as Paragraph;
+               if (first == null) {
+                       first = factory.create_paragraph ();
+                       content.insert (0, first);
+               }
+
+               Run entry = factory.create_run (Run.Style.ITALIC);
+               entry.content.add (factory.create_text (counter.to_string () + ": "));
+               first.content.insert (0, entry);
+
+               if (!check_xml_close_tag ("footnote")) {
+                       this.report_unexpected_token (current, "</footnote>");
+                       return nr;
+               }
+
+               next ();
+               return nr;
+       }
+
+       private inline void append_block_content_not_null_all (Vala.Collection<Block> run, 
Vala.Collection<Block>? elements) {
+               if (elements != null) {
+                       run.add_all (elements);
+               }
+       }
+
+       private inline void append_block_content_not_null (Vala.Collection<Block> run, Block? element) {
+               if (element != null) {
+                       run.add (element);
+               }
+       }
+
+       private TableRow? parse_docbook_thead () {
+               if (!check_xml_open_tag ("thead")) {
+                       this.report_unexpected_token (current, "<thead>");
+                       return null;
+               }
+               next ();
+
+               parse_docbook_spaces ();
+               TableRow? row = parse_docbook_row (Run.Style.BOLD);
+               parse_docbook_spaces ();
+
+               if (!check_xml_close_tag ("thead")) {
+                       this.report_unexpected_token (current, "</thead>");
+                       return row;
+               }
+
+               next ();
+               return row;
+       }
+
+       private TableCell? parse_docbook_entry (Run.Style default_style = Run.Style.NONE) {
+               if (!check_xml_open_tag ("entry")) {
+                       this.report_unexpected_token (current, "<entry>");
+                       return null;
+               }
+               next ();
+
+               TableCell cell = factory.create_table_cell ();
+               Run run = factory.create_run (default_style);
+               run.content.add (parse_inline_content ());
+               cell.content.add (run);
+
+               if (!check_xml_close_tag ("entry")) {
+                       this.report_unexpected_token (current, "</entry>");
+                       return cell;
+               }
+
+               next ();
+               return cell;
+       }
+
+       private TableRow? parse_docbook_row (Run.Style default_style = Run.Style.NONE) {
+               if (!check_xml_open_tag ("row")) {
+                       this.report_unexpected_token (current, "<row>");
+                       return null;
+               }
+               next ();
+
+               TableRow row = factory.create_table_row ();
+               parse_docbook_spaces ();
+
+               while (current.type == TokenType.XML_OPEN && current.content == "entry") {
+                       TableCell? table_cell = parse_docbook_entry (default_style);
+                       if (table_cell == null) {
+                               break;
+                       }
+
+                       row.cells.add (table_cell);
+                       parse_docbook_spaces ();
+               }
+
+               if (!check_xml_close_tag ("row")) {
+                       this.report_unexpected_token (current, "</row>");
+                       return row;
+               }
+
+               next ();
+               return row;
+       }
+
+       private Vala.Collection<TableRow>? parse_docbook_tbody () {
+               if (!check_xml_open_tag ("tbody")) {
+                       this.report_unexpected_token (current, "<tbody>");
+                       return null;
+               }
+               next ();
+
+               parse_docbook_spaces ();
+
+               Vala.Collection<TableRow> rows = new Vala.ArrayList<TableRow> ();
+               while (current.type == TokenType.XML_OPEN && current.content == "row") {
+                       TableRow? row = parse_docbook_row ();
+                       if (row == null) {
+                               break;
+                       }
+
+                       parse_docbook_spaces ();
+                       rows.add (row);
+               }
+
+
+               if (!check_xml_close_tag ("tbody")) {
+                       this.report_unexpected_token (current, "</tbody>");
+                       return rows;
+               }
+
+               next ();
+               return rows;
+       }
+
+       private Table? parse_docbook_tgroup () {
+               if (!check_xml_open_tag ("tgroup")) {
+                       this.report_unexpected_token (current, "<tgroup>");
+                       return null;
+               }
+               next ();
+
+               Table table = factory.create_table ();
+               parse_docbook_spaces ();
+
+               if (current.type == TokenType.XML_OPEN && current.content == "thead") {
+                       TableRow? row = parse_docbook_thead ();
+                       if (row != null) {
+                               parse_docbook_spaces ();
+                               table.rows.add (row);
+                       }
+
+                       parse_docbook_spaces ();
+               }
+
+               if (current.type == TokenType.XML_OPEN && current.content == "tbody") {
+                       Vala.Collection<TableRow>? rows = parse_docbook_tbody ();
+                       if (rows != null) {
+                               table.rows.add_all (rows);
+                       }
+
+                       parse_docbook_spaces ();
+               }
+
+               if (!check_xml_close_tag ("tgroup")) {
+                       this.report_unexpected_token (current, "</tgroup>");
+                       return table;
+               }
+
+               next ();
+               return table;
+       }
+
+       private Table? parse_docbook_informaltable () {
+               if (!check_xml_open_tag ("informaltable")) {
+                       this.report_unexpected_token (current, "<informaltable>");
+                       return null;
+               }
+               next ();
+
+               parse_docbook_spaces ();
+               Table? table = this.parse_docbook_tgroup ();
+               parse_docbook_spaces ();
+
+               if (!check_xml_close_tag ("informaltable")) {
+                       this.report_unexpected_token (current, "</informaltable>");
+                       return table;
+               }
+
+               next ();
+               return table;
+       }
+
+       private Vala.Collection<Block>? parse_docbook_section () {
+               if (!check_xml_open_tag ("section")) {
+                       this.report_unexpected_token (current, "<section>");
+                       return null;
+               }
+
+               string id = current.attributes.get ("id");
+               if (id != null) {
+                       id_registrar.register_symbol (id, element);
+               }
+               next ();
+
+               Vala.Collection<Block> content = parse_mixed_content ();
+
+               if (!check_xml_close_tag ("section")) {
+                       this.report_unexpected_token (current, "</section>");
+                       return content;
+               }
+
+               next ();
+               return content;
+       }
+
+       private ListItem? parse_docbook_member () {
+               if (!check_xml_open_tag ("member")) {
+                       this.report_unexpected_token (current, "<member>");
+                       return null;
+               }
+               next ();
+
+               parse_docbook_spaces ();
+
+               ListItem item = factory.create_list_item ();
+               Paragraph para = factory.create_paragraph ();
+               item.content.add (para);
+
+               para.content.add (parse_inline_content ());
+
+               parse_docbook_spaces ();
+
+               if (!check_xml_close_tag ("member")) {
+                       this.report_unexpected_token (current, "</member>");
+                       return item;
+               }
+
+               next ();
+               return item;
+       }
+
+       private Content.List? parse_docbook_simplelist () {
+               if (!check_xml_open_tag ("simplelist")) {
+                       this.report_unexpected_token (current, "<simplelist>");
+                       return null;
+               }
+               next ();
+
+               parse_docbook_spaces ();
+
+               Content.List list = factory.create_list ();
+
+               while (current.type == TokenType.XML_OPEN && current.content == "member") {
+                       ListItem item = parse_docbook_member ();
+                       if (item == null) {
+                               break;
+                       }
+
+                       list.items.add (item);
+                       parse_docbook_spaces ();
+               }
+
+
+               if (!check_xml_close_tag ("simplelist")) {
+                       this.report_unexpected_token (current, "</simplelist>");
+                       return list;
+               }
+
+               next ();
+               return list;
+       }
+
+       private Paragraph? parse_docbook_term () {
+               if (!check_xml_open_tag ("term")) {
+                       this.report_unexpected_token (current, "<term>");
+                       return null;
+               }
+               next ();
+
+               parse_docbook_spaces ();
+
+               Paragraph? p = factory.create_paragraph ();
+               Run run = parse_inline_content ();
+               run.style = Run.Style.ITALIC;
+               p.content.add (run);
+
+               if (!check_xml_close_tag ("term")) {
+                       this.report_unexpected_token (current, "</term>");
+                       return p;
+               }
+
+               next ();
+               return p;
+       }
+
+       private ListItem? parse_docbook_varlistentry () {
+               if (!check_xml_open_tag ("varlistentry")) {
+                       this.report_unexpected_token (current, "<varlistentry>");
+                       return null;
+               }
+               next ();
+
+               parse_docbook_spaces ();
+
+               if (current.type != TokenType.XML_OPEN || current.content != "term") {
+                       return null;
+               }
+
+               Paragraph? term = parse_docbook_term ();
+               if (term == null) {
+                       return null;
+               }
+
+               parse_docbook_spaces ();
+               ListItem? desc = parse_docbook_listitem ();             
+               if (desc == null) {
+                       return null;
+               }
+
+               parse_docbook_spaces ();
+
+               Content.ListItem listitem = factory.create_list_item ();
+               Content.List list = factory.create_list ();
+
+               listitem.content.add (term);
+               listitem.content.add (list);
+               list.items.add (desc);
+
+               if (!check_xml_close_tag ("varlistentry")) {
+                       this.report_unexpected_token (current, "</varlistentry>");
+                       return listitem;
+               }
+
+               next ();
+               return listitem;
+       }
+
+       private Vala.Collection<Block>? parse_docbook_variablelist () {
+               if (!check_xml_open_tag ("variablelist")) {
+                       this.report_unexpected_token (current, "<variablelist>");
+                       return null;
+               }
+               next ();
+
+               parse_docbook_spaces ();
+
+               Vala.Collection<Block> content = new Vala.ArrayList<Block> ();
+
+               if (current.type == TokenType.XML_OPEN && current.content == "title") {
+                       append_block_content_not_null (content, parse_docbook_title ());
+                       parse_docbook_spaces ();
+               }
+
+               Content.List list = factory.create_list ();
+               content.add (list);
+
+               while (current.type == TokenType.XML_OPEN && current.content == "varlistentry") {
+                       ListItem item = parse_docbook_varlistentry ();
+                       if (item == null) {
+                               break;
+                       }
+
+                       list.items.add (item);
+                       parse_docbook_spaces ();
+               }
+
+               if (!check_xml_close_tag ("variablelist")) {
+                       this.report_unexpected_token (current, "</variablelist>");
+                       return content;
+               }
+
+               next ();
+               return content;
+       }
+
+       private Vala.Collection<Block> parse_block_content () {
+               Vala.Collection<Block> content = new Vala.ArrayList<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_all (content, parse_docbook_itemizedlist 
());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "orderedlist") {
+                               this.append_block_content_not_null_all (content, parse_docbook_orderedlist 
());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "variablelist") {
+                               this.append_block_content_not_null_all (content, parse_docbook_variablelist 
());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "simplelist") {
+                               this.append_block_content_not_null (content, parse_docbook_simplelist ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "informaltable") {
+                               this.append_block_content_not_null (content, parse_docbook_informaltable ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "programlisting") 
{
+                               this.append_block_content_not_null (content, parse_docbook_programlisting ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "para") {
+                               this.append_block_content_not_null_all (content, parse_docbook_para ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "simpara") {
+                               this.append_block_content_not_null_all (content, parse_docbook_simpara ());
+                       } 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 (content, parse_docbook_warning ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "note") {
+                               this.append_block_content_not_null (content, parse_docbook_note ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "important") {
+                               this.append_block_content_not_null (content, parse_docbook_important ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "refsect3") {
+                               this.append_block_content_not_null_all (content, parse_docbook_refsect2 (3));
+                       } 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.XML_OPEN && current.content == "figure") {
+                               this.append_block_content_not_null_all (content, parse_docbook_figure ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "title") {
+                               this.append_block_content_not_null (content, parse_docbook_title ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "section") {
+                               this.append_block_content_not_null_all (content, parse_docbook_section ());
+                       } 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 Run? parse_xml_tag () {
+               if (!check_xml_open_tag ("tag")) {
+                       this.report_unexpected_token (current, "<tag>");
+                       return null;
+               }
+               string? _class = current.attributes.get ("class");
+               next ();
+
+               parse_docbook_spaces (false);
+
+               if (current.type != TokenType.WORD) {
+                       this.report_unexpected_token (current, "<WORD>");
+                       return null;
+               }
+
+               Run run = factory.create_run (Run.Style.MONOSPACED);
+               if (_class == null || _class == "starttag") {
+                       run.content.add (factory.create_text ("<" + current.content + ">"));
+                       next ();
+               } else if (_class == "endtag") {
+                       run.content.add (factory.create_text ("</" + current.content + ">"));
+                       next ();
+               } else {
+                       this.report_unexpected_token (current, "<tag class=\"%s\">".printf (_class));
+                       return run;
+               }
+
+               parse_docbook_spaces (false);
+
+
+               if (!check_xml_close_tag ("tag")) {
+                       this.report_unexpected_token (current, "</tag>");
+                       return run;
+               }
+
+               next ();
+               return run;
+       }
+
+       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, bool c_accept_plural = false) {
+               if (name == "TRUE" || name == "FALSE" || name == "NULL" || is_numeric (name)) {
+                       var monospaced = factory.create_run (Run.Style.MONOSPACED);
+                       monospaced.content.add (factory.create_text (name.down ()));
+                       return monospaced;
+               } else {
+                       Taglets.Link? taglet = factory.create_taglet ("link") as Taglets.Link;
+                       assert (taglet != null);
+                       taglet.c_accept_plural = c_accept_plural;
+                       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 == "abbrev") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("abbrev", 
Run.Style.ITALIC));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "term") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("term", 
Run.Style.ITALIC));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "literal") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("literal", 
Run.Style.ITALIC));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "literallayout") {
+                               append_inline_content_not_null (run, parse_highlighted_template 
("literallayout", Run.Style.MONOSPACED));
+                       } 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 == "varname") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("varname", 
Run.Style.MONOSPACED));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "computeroutput") 
{
+                               append_inline_content_not_null (run, parse_highlighted_template 
("computeroutput", Run.Style.MONOSPACED));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "emphasis") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("emphasis", 
Run.Style.MONOSPACED));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "pre") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("pre", 
Run.Style.MONOSPACED));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "code") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("code", 
Run.Style.MONOSPACED));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "guimenuitem") {
+                               append_inline_content_not_null (run, parse_highlighted_template 
("guimenuitem", Run.Style.MONOSPACED));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "command") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("command", 
Run.Style.MONOSPACED));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "option") {
+                               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 == "parameter") {
+                               append_inline_content_not_null (run, parse_highlighted_template ("parameter", 
Run.Style.MONOSPACED));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "replaceable") {
+                               append_inline_content_not_null (run, parse_highlighted_template 
("replaceable", Run.Style.ITALIC));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "quote") {
+                               run.content.add (factory.create_text ("“"));
+                               append_inline_content_not_null (run, parse_highlighted_template ("quote", 
Run.Style.NONE));
+                               run.content.add (factory.create_text ("”"));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "footnote") {
+                               append_inline_content_not_null (run, parse_docbook_footnote ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "type") {
+                               append_inline_content_not_null (run, parse_symbol_link ("type"));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "function") {
+                               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 == "inlinegraphic") {
+                               append_inline_content_not_null (run, parse_docbook_inlinegraphic ());
+                       } 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", 
true));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "ulink") {
+                               append_inline_content_not_null (run, parse_docbook_link_tempalte ("ulink", 
false));
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "xref") {
+                               append_inline_content_not_null (run, parse_xref ());
+                       } else if (current.type == TokenType.XML_OPEN && current.content == "tag") {
+                               append_inline_content_not_null (run, parse_xml_tag ());
+                       } else if (current.type == TokenType.GTKDOC_FUNCTION) {
+                               run.content.add (this.create_type_link (current.content));
+                               next ();
+                       } else if (current.type == TokenType.GTKDOC_PARAM) {
+                               if (current.content == instance_param_name) {
+                                       Content.Run keyword_run = factory.create_run 
(Content.Run.Style.LANG_KEYWORD);
+                                       Content.Text text = factory.create_text ("this");
+                                       keyword_run.content.add (text);
+                                       run.content.add (keyword_run);
+                               } else {
+                                       string? param_array_name;
+                                       bool is_return_type_len;
+                                       string? param_name;
+
+                                       string? cname = ImporterHelper.resolve_parameter_ctype (
+                                               this.tree,
+                                               this.element,
+                                               current.content,
+                                               out param_name,
+                                               out param_array_name,
+                                               out is_return_type_len);
+
+                                       Run current_run = factory.create_run (Run.Style.MONOSPACED);
+                                       run.content.add (current_run);
+
+                                       if (is_return_type_len) {
+                                               Run keyword_run = factory.create_run (Run.Style.LANG_KEYWORD);
+                                               keyword_run.content.add (factory.create_text ("return"));
+                                               current_run.content.add (keyword_run);
+
+                                               current_run.content.add (factory.create_text (".length"));
+                                       } else if (param_array_name != null) {
+                                               current_run.content.add (factory.create_text 
(param_array_name + ".length"));
+                                       } else {
+                                               current_run.content.add (factory.create_text (param_name));
+                                       }
+
+                                       if (cname != null) {
+                                               run.content.add (factory.create_text ("."));
+
+                                               Taglets.Link link = factory.create_taglet ("link") as 
Taglets.Link;
+                                               link.symbol_name = cname;
+                                               run.content.add (link);
+                                       }
+                               }
+                               next ();
+                       } else if (current.type == TokenType.GTKDOC_SIGNAL) {
+                               run.content.add (this.create_type_link ("::" + current.content, true));
+                               next ();
+                       } else if (current.type == TokenType.GTKDOC_PROPERTY) {
+                               run.content.add (this.create_type_link (":" + current.content, true));
+                               next ();
+                       } else if (current.type == TokenType.GTKDOC_CONST) {
+                               run.content.add (this.create_type_link (current.content, true));
+                               next ();
+                       } else if (current.type == TokenType.GTKDOC_TYPE) {
+                               run.content.add (this.create_type_link (current.content, true));
+                               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/libvaladoc/documentation/gtkdoccommentscanner.vala 
b/libvaladoc/documentation/gtkdoccommentscanner.vala
new file mode 100644
index 0000000..d81bc91
--- /dev/null
+++ b/libvaladoc/documentation/gtkdoccommentscanner.vala
@@ -0,0 +1,887 @@
+/* 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;
+
+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 Vala.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, Vala.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 static string unescape (string txt) {
+               StringBuilder builder = new StringBuilder ();
+               unowned string start = txt;
+               unowned string pos;
+               unichar c;
+
+               for (pos = txt; (c = pos.get_char ()) != '\0'; pos = pos.next_char ()) {
+                       if (c == '&') {
+                               if (pos.has_prefix ("&solidus;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 9);
+                                       pos = (string) ((char*) pos + 8);
+                                       builder.append_unichar ('⁄');
+                               } else if (pos.has_prefix ("&percnt;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 8);
+                                       pos = (string) ((char*) pos + 7);
+                                       builder.append_c ('%');
+                               } else if (pos.has_prefix ("&commat;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 8);
+                                       pos = (string) ((char*) pos + 7);
+                                       builder.append_c ('@');
+                               } else if (pos.has_prefix ("&nbsp;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 6);
+                                       pos = (string) ((char*) pos + 5);
+                                       builder.append_c (' ');
+                               } else if (pos.has_prefix ("&quot;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 6);
+                                       pos = (string) ((char*) pos + 5);
+                                       builder.append_c ('"');
+                               } else if (pos.has_prefix ("&apos;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 6);
+                                       pos = (string) ((char*) pos + 5);
+                                       builder.append_c ('\'');
+                               } else if (pos.has_prefix ("&lpar;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 6);
+                                       pos = (string) ((char*) pos + 5);
+                                       builder.append_c ('(');
+                               } else if (pos.has_prefix ("&rpar;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 6);
+                                       pos = (string) ((char*) pos + 5);
+                                       builder.append_c (')');
+                               } else if (pos.has_prefix ("&num;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 5);
+                                       pos = (string) ((char*) pos + 4);
+                                       builder.append_c ('#');
+                               } else if (pos.has_prefix ("&amp;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 5);
+                                       pos = (string) ((char*) pos + 4);
+                                       builder.append_c ('&');
+                               } else if (pos.has_prefix ("&ast;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 5);
+                                       pos = (string) ((char*) pos + 4);
+                                       builder.append_c ('*');
+                               } else if (pos.has_prefix ("&pi;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 4);
+                                       pos = (string) ((char*) pos + 3);
+                                       builder.append_unichar ('π');
+                               } else if (pos.has_prefix ("&lt;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 4);
+                                       pos = (string) ((char*) pos + 3);
+                                       builder.append_c ('<');
+                               } else if (pos.has_prefix ("&gt;")) {
+                                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                                       start = (string) ((char*) pos + 4);
+                                       pos = (string) ((char*) pos + 3);
+                                       builder.append_c ('>');
+                               }
+                       }
+               } 
+
+               if (&txt == &start) {
+                       return txt;
+               } else {
+                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                       return (owned) builder.str;
+               }
+       }
+
+       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 vararg_prefix () {
+               if (this.pos.has_prefix ("...")) {
+                       next_char ();
+                       next_char ();
+                       next_char ();
+                       return 3;
+               }
+
+               return 0;
+       }
+
+       private inline int id_prefix () {
+               unichar c = get ();
+
+               if (!letter (c) && c != '_') {
+                       return 0;
+               }
+
+               int start = this.column;
+               while ((c = next_char ()) == '_' || letter_or_number (c));
+               return this.column - start;
+       }
+
+       private inline int g_id_prefix () {
+               unowned string start = this.pos;
+               unichar c = get ();
+
+               if (!letter (c)) {
+                       return 0;
+               }
+
+               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) {
+                       if (type == TokenType.GTKDOC_PARAM && (id_len = vararg_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;
+                       }
+               } else if (this.pos.has_prefix ("->") || this.pos.has_prefix (".")) {
+                       unowned string sep_start = this.pos;
+                       int sep_column_start = this.column;                     
+                       int separator_len = 1;
+
+                       if (this.pos.has_prefix ("->")) {
+                               separator_len = 2;
+                               next_char ();   
+                       }
+
+                       next_char ();
+
+                       Token? func_token = function_prefix ();
+                       if (func_token == null) {
+                               int id_len2;
+
+                               if ((id_len2 = id_prefix ()) > 0) {
+                                       id_len += separator_len + id_len2;
+                               } else {
+                                       this.column = sep_column_start;
+                                       this.pos = sep_start;
+                               }
+                       } else {
+                               id_len += separator_len + func_token.content.length;
+                       }
+               }
+
+               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,
+                                                                                 unescape (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;
+               }
+
+               Vala.HashMap<string, string> map = new Vala.HashMap<string, string> (str_hash, str_equal);
+
+               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;
+               unichar c = get ();
+               if (c == '<' || c == '@') {
+                       next_char ();
+               }
+
+               for (c = get (); c != ' ' && c != '\t' && c != '\n' && c != '\0' && c != '<' && 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,
+                                                 unescape (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/libvaladoc/documentation/gtkdocmarkdownparser.vala 
b/libvaladoc/documentation/gtkdocmarkdownparser.vala
new file mode 100644
index 0000000..66218e1
--- /dev/null
+++ b/libvaladoc/documentation/gtkdocmarkdownparser.vala
@@ -0,0 +1,837 @@
+/* gtkdocmarkdownparser.vala
+ *
+ * Copyright (C) 2014 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;
+
+public class Valadoc.Gtkdoc.MarkdownParser : Object, ResourceLocator {
+       private Valadoc.Parser parser;
+       private Content.ContentFactory _factory;
+
+       private Settings _settings;
+       private ErrorReporter _reporter;
+       private Api.Tree _tree;
+
+       private Vala.ArrayList<Object> _stack = new Vala.ArrayList<Object> ();
+
+       private Valadoc.Token preserved_token = null;
+       private Regex regex_source_lang;
+
+       private Importer.InternalIdRegistrar id_registrar;
+       private GirMetaData metadata;
+       private Api.GirSourceComment gir_comment;
+       private Api.Node element;
+
+
+       public MarkdownParser (Settings settings, ErrorReporter reporter, Api.Tree? tree, ModuleLoader 
_modules) {
+               MarkdownScanner scanner = new MarkdownScanner (settings);
+               parser = new Valadoc.Parser (settings, scanner, reporter);
+               scanner.set_parser (parser);
+
+
+               _factory = new Content.ContentFactory (settings, this, _modules);
+               _settings = settings;
+               _reporter = reporter;
+               _tree = tree;
+
+               init_rules ();
+
+               try {
+                       regex_source_lang = new Regex ("^<!--[ \t]+language=\"([A-Za-z]*)\"[ \t]+-->");
+               } catch (Error e) {
+                       assert_not_reached ();
+               }
+       }
+
+       public void init_rules () {
+               Valadoc.TokenType word = Valadoc.TokenType.any_word ().action (add_text);
+
+               StubRule content = new StubRule ();
+               content.set_name ("Content");
+
+               StubRule run = new StubRule ();
+               run.set_name ("Run");
+
+
+               Rule param = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_PARAMETER.action ((token) => {
+                               Run _run = null;
+
+                               if (token.value == gir_comment.instance_param_name) {                         
  
+                                       _run = _factory.create_run (Run.Style.LANG_KEYWORD);
+                                       _run.content.add (_factory.create_text ("this"));
+                               } else if (is_error_parameter (token.value)) {
+                                       _run = _factory.create_run (Run.Style.LANG_KEYWORD);
+                                       _run.content.add (_factory.create_text ("throws"));
+                               } else {
+                                       string? param_name;
+                                       string? param_array_name;
+                                       bool is_return_type_len;
+
+                                       ImporterHelper.resolve_parameter_ctype (
+                                               this._tree,
+                                               this.element,
+                                               token.value,
+                                               out param_name,
+                                               out param_array_name,
+                                               out is_return_type_len);
+
+                                       _run = _factory.create_run (Run.Style.MONOSPACED);
+
+                                       if (is_return_type_len) {
+                                               Run keyword_run = _factory.create_run 
(Run.Style.LANG_KEYWORD);
+                                               keyword_run.content.add (_factory.create_text ("return"));
+                                               _run.content.add (keyword_run);
+
+                                               _run.content.add (_factory.create_text (".length"));
+                                       } else if (param_array_name != null) {
+                                               _run.content.add (_factory.create_text (param_array_name + 
".length"));
+                                       } else {
+                                               _run.content.add (_factory.create_text (param_name));
+                                       }
+
+
+                               }
+
+                               push (_run);
+                       })
+               })
+               .set_name ("Parameter");
+
+
+               Rule constant = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_CONSTANT.action ((token) => {
+                               if (is_literal (token.value)) {
+                                       var _run = _factory.create_run (Run.Style.LANG_LITERAL);
+                                       _run.content.add (_factory.create_text (token.value.down ()));
+                                       push (_run);
+                               } else {
+                                       add_symbol_link ("c::" + token.value, true);
+                               }
+                       })
+               })
+               .set_name ("Constant");
+
+
+               Rule gmember = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_LOCAL_GMEMBER.action ((token) => {
+                               Api.Item gtype = element;
+                               while (gtype is Api.Class == false && gtype is Api.Interface == false && 
gtype != null) {
+                                       gtype = gtype.parent;
+                               }
+
+                               string parent_cname;
+                               if (gtype is Api.Class) {
+                                       parent_cname = ((Api.Class) gtype).get_cname ();
+                               } else if (gtype is Api.Interface) {
+                                       parent_cname = ((Api.Interface) gtype).get_cname ();
+                               } else {
+                                       parent_cname = "";
+                               }
+
+                               add_symbol_link ("c::" + parent_cname + token.value, true);
+                       })
+               })
+               .set_name ("GLocalMember");
+
+
+               Rule symbol = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_SYMBOL.action ((token) => {
+                               add_symbol_link ("c::" + token.value, true);
+                       })
+               })
+               .set_name ("Symbol");
+
+
+               Rule function = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_FUNCTION.action ((token) => {
+                               add_symbol_link ("c::" + token.value, false);
+                       })
+               })
+               .set_name ("Function");
+
+
+               Rule link_short = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_LESS_THAN,
+                       Rule.option ({
+                               Rule.one_of ({
+                                       Valadoc.TokenType.MARKDOWN_MAIL.action (preserve_token),
+                                       Valadoc.TokenType.MARKDOWN_LINK.action (preserve_token)
+                               }),
+                               Rule.option ({
+                                       Valadoc.TokenType.MARKDOWN_GREATER_THAN,
+                               })
+                               .set_reduce (() => {
+                                       Link url = _factory.create_link ();
+                                       url.url = pop_preserved_link ();
+                                       push (url);
+                               })
+                               .set_skip (() => {
+                                       add_content_string ("<");
+                                       add_value (preserved_token);
+                                       preserved_token = null;
+                               })
+                       })
+                       .set_skip (() => {
+                               add_content_string ("<");
+                       })
+               })
+               .set_name ("Link");
+
+
+               Rule link = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_OPEN_BRACKET,
+                       Rule.option ({
+                               Rule.option ({
+                                       run
+                               }),
+                               Valadoc.TokenType.MARKDOWN_CLOSE_BRACKET,
+                               Rule.option ({
+                                       Rule.one_of ({
+                                               // External link:
+                                               Rule.seq ({
+                                                       Valadoc.TokenType.MARKDOWN_OPEN_PARENS,
+                                                       Rule.option ({
+                                                               Rule.one_of ({
+                                                                       
Valadoc.TokenType.MARKDOWN_LINK.action (preserve_token),
+                                                                       
Valadoc.TokenType.MARKDOWN_MAIL.action (preserve_token)
+                                                               }),
+                                                               Rule.option ({
+                                                                       
Valadoc.TokenType.MARKDOWN_CLOSE_PARENS
+                                                               })
+                                                               .set_reduce (() => {
+                                                                       Link url = _factory.create_link ();
+                                                                       url.url = pop_preserved_link ();
+
+                                                                       Run label = (Run) peek ();
+                                                                       url.content.add_all (label.content);
+                                                                       label.content.clear ();
+                                                                       label.content.add (url);
+                                                               })
+                                                               .set_skip (() => {
+                                                                       Run _run = (Run) peek ();
+                                                                       _run.content.insert (0, 
_factory.create_text ("["));
+                                                                       _run.content.add 
(_factory.create_text ("](" + pop_preserved_link ()));
+                                                               })
+                                                       })
+                                                       .set_skip (() => {
+                                                               Run _run = (Run) peek ();
+                                                               _run.content.insert (0, _factory.create_text 
("["));
+                                                               _run.content.add (_factory.create_text 
("]("));
+                                                       })
+                                               }),
+                                               // Internal link:
+                                               Rule.seq ({
+                                                       Valadoc.TokenType.MARKDOWN_OPEN_BRACKET,
+                                                       Rule.option ({
+                                                               Valadoc.TokenType.any_word ().action 
(preserve_token),
+                                                               Rule.option ({
+                                                                       
Valadoc.TokenType.MARKDOWN_CLOSE_BRACKET
+                                                               })
+                                                               .set_reduce (() => {
+                                                                       Link url = _factory.create_link ();
+                                                                       url.url = pop_preserved_link ();
+                                                                       url.id_registrar = id_registrar;
+
+                                                                       Run label = (Run) peek ();
+                                                                       url.content.add_all (label.content);
+                                                                       label.content.clear ();
+                                                                       label.content.add (url);
+                                                               })
+                                                               .set_skip (() => {
+                                                                       Run _run = (Run) peek ();
+                                                                       _run.content.insert (0, 
_factory.create_text ("["));
+
+                                                                       _run.content.add 
(_factory.create_text ("][" + pop_preserved_link ()));
+                                                               })
+                                                       })
+                                                       .set_skip (() => {
+                                                               Run _run = (Run) peek ();
+                                                               _run.content.insert (0, _factory.create_text 
("["));
+                                                               _run.content.add (_factory.create_text 
("]["));
+                                                       })
+                                               })
+                                       })
+                               })
+                               .set_skip (() => {
+                                       Run _run = (Run) peek ();
+                                       _run.content.insert (0, _factory.create_text ("["));
+                                       _run.content.add (_factory.create_text ("]"));
+                               })
+                       })
+                       .set_skip (() => {
+                               Run _run = (Run) peek ();
+                               _run.content.insert (0, _factory.create_text ("["));
+                       })
+               })
+               .set_start (() => { push (_factory.create_run (Run.Style.NONE)); })
+               .set_name ("Link");
+
+
+               Rule image = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_EXCLAMATION_MARK,
+                       Rule.option ({
+                               Valadoc.TokenType.MARKDOWN_OPEN_BRACKET,
+                               Rule.option ({
+                                       run
+                               }),
+                               Valadoc.TokenType.MARKDOWN_CLOSE_BRACKET,
+                               Rule.option ({
+                                       Valadoc.TokenType.MARKDOWN_OPEN_BRACKET,
+                                       Rule.option ({
+                                               Rule.one_of ({
+                                                       Valadoc.TokenType.any_word ().action (preserve_token),
+                                                       Valadoc.TokenType.MARKDOWN_LINK.action 
(preserve_token),
+                                                       Valadoc.TokenType.MARKDOWN_MAIL.action 
(preserve_token)
+                                               }),
+                                               Rule.option ({
+                                                       Valadoc.TokenType.MARKDOWN_CLOSE_BRACKET,
+                                               })
+                                               .set_reduce (() => {
+                                                       Run label = (Run) peek ();
+
+                                                       string label_str;
+                                                       try {
+                                                               label_str = run_to_string (label, "<image>");
+                                                       } catch (Error e) {
+                                                               parser.warning (preserved_token, e.message);
+                                                               label_str = null;
+                                                       }
+
+                                                       Embedded embedded = _factory.create_embedded ();
+                                                       embedded.url = fix_resource_path (pop_preserved_path 
());
+                                                       embedded.caption = label_str;
+
+                                                       label.content.clear ();
+                                                       label.content.add (embedded);
+                                               })
+                                               .set_skip (() => {
+                                                       Run _run = (Run) peek ();
+                                                       _run.content.insert (0, _factory.create_text ("!["));
+                                                       _run.content.add (_factory.create_text ("][" + 
pop_preserved_link ()));
+                                               })
+                                       })
+                                       .set_skip (() => {
+                                               Run _run = (Run) peek ();
+                                               _run.content.insert (0, _factory.create_text ("!["));
+                                               _run.content.add (_factory.create_text ("]["));
+                                       })
+                               })
+                               .set_skip (() => {
+                                       Run _run = (Run) peek ();
+                                       _run.content.insert (0, _factory.create_text ("!["));
+                                       _run.content.add (_factory.create_text ("]"));
+                               })
+                       })
+                       .set_skip (() => {
+                               Run _run = (Run) peek ();
+                               _run.content.insert (0, _factory.create_text ("!"));
+                       })
+               })
+               .set_start (() => { push (_factory.create_run (Run.Style.NONE)); })
+               .set_name ("Image");
+
+
+               Rule source = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_SOURCE.action ((token) => {
+                               SourceCode code = _factory.create_source_code ();
+                               MatchInfo info;
+
+                               unowned string source = token.value;
+                               if (regex_source_lang.match (source, 0, out info)) {
+                                       string lang_name = info.fetch (1).down ();
+                                       SourceCode.Language? lang = SourceCode.Language.from_string 
(lang_name);
+                                       code.language = lang;
+
+                                       if (lang == null) {
+                                               parser.warning (token, "Unknown language `%s' in source code 
block |[<!-- language=\"\"".printf (lang_name));
+                                       }
+
+                                       source = source.offset (source.index_of_char ('>') + 1);
+                               } else {
+                                       code.language = (Highlighter.XmlScanner.is_xml (source))
+                                               ? SourceCode.Language.XML
+                                               : SourceCode.Language.C;
+                               }
+
+                               code.code = source;
+                               push (code);
+                       })
+               })
+               .set_name ("Source");
+
+
+               Rule text = Rule.many ({
+                       Rule.one_of ({
+                               word,
+                               Valadoc.TokenType.MARKDOWN_SPACE.action (add_text),
+                               Valadoc.TokenType.MARKDOWN_MAIL.action (add_value),
+                               Valadoc.TokenType.MARKDOWN_LINK.action (add_value),
+                               Valadoc.TokenType.MARKDOWN_OPEN_PARENS.action (add_text),
+                               Valadoc.TokenType.MARKDOWN_CLOSE_PARENS.action (add_text),
+                               Valadoc.TokenType.MARKDOWN_CLOSE_BRACKET.action (add_text),
+                               Valadoc.TokenType.MARKDOWN_GREATER_THAN.action (add_text)
+                       })
+               })
+               .set_start (() => { push (_factory.create_text ()); })
+               .set_name ("Text");
+
+
+               run.set_rule (
+                       Rule.many ({
+                               Rule.one_of ({
+                                       text,
+                                       link,
+                                       link_short,
+                                       image,
+                                       function,
+                                       constant,
+                                       param,
+                                       symbol,
+                                       gmember,
+                                       source
+                               })
+                               .set_reduce (() => {
+                                       var head = (Inline) pop ();
+                                       ((InlineContent) peek ()).content.add (head);
+                               })
+                       })
+               );
+
+
+               Rule unordered_list = Rule.seq ({
+                       Rule.seq ({
+                               Valadoc.TokenType.MARKDOWN_UNORDERED_LIST_ITEM_START,
+                               content,
+                               Valadoc.TokenType.MARKDOWN_UNORDERED_LIST_ITEM_END
+                       })
+                       .set_start (() => { push (_factory.create_list_item ()); })
+                       .set_reduce (() => {
+                               var head = (ListItem) pop ();
+                               ((Content.List) peek ()).items.add (head);
+                       })
+               })
+               .set_start (() => {
+                       var siblings = ((BlockContent) peek ()).content;
+                       if (siblings.size > 0 && siblings.last () is Content.List) {
+                               push (siblings.last ());                                
+                       } else {
+                               Content.List list = _factory.create_list ();
+                               list.bullet = Content.List.Bullet.UNORDERED;
+                               siblings.add (list);
+                               push (list);
+                       }
+               })
+               .set_reduce (() => {
+                       (Content.List) pop ();
+               })
+               .set_name ("UnorderedList");
+
+
+               Rule ordered_list = Rule.seq ({
+                       Rule.seq ({
+                               Valadoc.TokenType.MARKDOWN_ORDERED_LIST_ITEM_START,
+                               content,
+                               Valadoc.TokenType.MARKDOWN_ORDERED_LIST_ITEM_END
+                       })
+                       .set_start (() => { push (_factory.create_list_item ()); })
+                       .set_reduce (() => {
+                               var head = (ListItem) pop ();
+                               ((Content.List) peek ()).items.add (head);
+                       })
+               })
+               .set_start (() => {
+                       var siblings = ((BlockContent) peek ()).content;
+                       if (siblings.size > 0 && siblings.last () is Content.List) {
+                               push (siblings.last ());                                
+                       } else {
+                               Content.List list = _factory.create_list ();
+                               list.bullet = Content.List.Bullet.ORDERED_NUMBER;
+                               siblings.add (list);
+                               push (list);
+                       }
+               })
+               .set_reduce (() => {
+                       (Content.List) pop ();
+               })
+               .set_name ("OrderedList");
+
+
+               Rule paragraph = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_PARAGRAPH,
+                       Rule.option ({
+                               Valadoc.TokenType.MARKDOWN_SPACE
+                       }),
+                       Rule.option ({
+                               run
+                       })
+               })
+               .set_start (() => { push (_factory.create_paragraph ()); })
+               .set_reduce (() => {
+                       var head = (Paragraph) pop ();
+                       ((BlockContent) peek ()).content.add (head);
+               })
+               .set_name ("Paragraph");
+
+
+               Rule block = Rule.seq ({
+                       Valadoc.TokenType.MARKDOWN_BLOCK_START,
+                       content,
+                       Valadoc.TokenType.MARKDOWN_BLOCK_END
+               })
+               .set_start (() => { push (_factory.create_note ()); })
+               .set_reduce (() => {
+                       var head = (Note) pop ();
+                       ((BlockContent) peek ()).content.add (head);
+               })
+               .set_name ("Block");
+
+
+               Rule headline = Rule.seq ({
+                       Rule.one_of ({
+                               Valadoc.TokenType.MARKDOWN_HEADLINE_1.action ((token) => {
+                                       Headline h = (Headline) peek ();
+                                       h.level = 1;
+                               }),
+                               Valadoc.TokenType.MARKDOWN_HEADLINE_2.action ((token) => {
+                                       Headline h = (Headline) peek ();
+                                       h.level = 2;
+                               })
+                       }),
+                       run,
+                       Rule.option ({
+                               Valadoc.TokenType.MARKDOWN_HEADLINE_HASH.action ((token) => {
+                                       id_registrar.register_symbol (token.value, element);
+                               })
+                       }),
+                       Valadoc.TokenType.MARKDOWN_HEADLINE_END
+               })
+               .set_start (() => { push (_factory.create_headline ()); })
+               .set_reduce (() => {
+                       Headline h = (Headline) pop ();
+                       ((BlockContent) peek ()).content.add (h);                       
+               })
+               .set_name ("Headline");
+
+               content.set_rule (
+                       Rule.many ({
+                               Rule.one_of ({
+                                       paragraph,
+                                       unordered_list,
+                                       ordered_list,
+                                       headline,
+                                       block
+                               })
+                       })
+               );
+
+
+               Rule comment = Rule.seq ({
+                       content,
+                       Valadoc.TokenType.MARKDOWN_EOC
+               })
+               .set_start (() => { push (_factory.create_comment ()); })
+               .set_name ("Comment");
+
+               parser.set_root_rule (comment);
+       }
+
+       private Comment? _parse (Api.SourceComment comment) {
+               try {
+                       _stack.clear ();
+                       parser.parse (comment.content, comment.file.get_name (), comment.first_line, 
comment.first_column);
+                       return (Comment) pop ();
+               } catch (ParserError e) {
+                       return null;
+               }
+       }
+
+       private Taglet? _parse_block_taglet (Api.SourceComment comment, string taglet_name) {
+               Comment? cmnt = _parse (comment);
+               if (cmnt == null) {
+                       return null;
+               }
+
+               Taglet? taglet = _factory.create_taglet (taglet_name);
+               BlockContent block = (BlockContent) taglet;
+               assert (taglet != null && block != null);
+
+               block.content.add_all (cmnt.content);
+
+               return taglet;
+       }
+
+       private Note? _parse_note (Api.SourceComment comment) {
+               Comment? cmnt = _parse (comment);
+               if (cmnt == null) {
+                       return null;
+               }
+
+               Note note = _factory.create_note ();
+               note.content.add_all (cmnt.content);
+
+               return note;
+       }
+
+       private void add_taglet (ref Comment? comment, Taglet? taglet) {
+               if (taglet == null) {
+                       return ;
+               }
+
+               if (comment == null) {
+                       comment = _factory.create_comment ();
+               }
+
+               comment.taglets.add (taglet);
+       }
+
+       private void add_note (ref Comment? comment, Note? note) {
+               if (note == null) {
+                       return ;
+               }
+
+               if (comment == null) {
+                       comment = _factory.create_comment ();
+               }
+
+               if (comment.content.size == 0) {
+                       comment.content.add (_factory.create_paragraph ());
+               }
+
+               comment.content.insert (1, note);
+       }
+
+       public Comment? parse (Api.Node element, Api.GirSourceComment gir_comment, GirMetaData metadata, 
Importer.InternalIdRegistrar id_registrar, string? this_name = null) {
+               this.metadata = metadata;
+               this.id_registrar = id_registrar;
+               this.gir_comment = gir_comment;
+               this.element = element;
+
+               // main:
+               Comment? cmnt = _parse (gir_comment);
+               if (cmnt != null) {
+                       ImporterHelper.extract_short_desc (cmnt, _factory);
+               }
+
+
+               // deprecated:
+               if (gir_comment.deprecated_comment != null) {
+                       Note? note = _parse_note (gir_comment.deprecated_comment);
+                       add_note (ref cmnt, note);
+               }
+
+
+               // version:
+               if (gir_comment.version_comment != null) {
+                       Note? note = _parse_note (gir_comment.version_comment);
+                       add_note (ref cmnt, note);
+               }
+
+
+               // stability:
+               if (gir_comment.stability_comment != null) {
+                       Note? note = _parse_note (gir_comment.stability_comment);
+                       add_note (ref cmnt, note);
+               }
+
+
+               // return:
+               if (gir_comment.return_comment != null) {
+                       Taglet? taglet = _parse_block_taglet (gir_comment.return_comment, "return");
+                       add_taglet (ref cmnt, taglet);
+               }
+
+
+               // parameters:
+               Vala.MapIterator<string, Api.SourceComment> iter = gir_comment.parameter_iterator ();
+               for (bool has_next = iter.next (); has_next; has_next = iter.next ()) {
+                       Taglets.Param? taglet = _parse_block_taglet (iter.get_value (), "param") as 
Taglets.Param;
+                       string param_name = iter.get_key ();
+
+                       taglet.is_c_self_param = (param_name == gir_comment.instance_param_name);
+                       taglet.parameter_name = param_name;
+                       add_taglet (ref cmnt, taglet);
+               }
+
+
+               this.metadata = null;
+               this.gir_comment = null;
+               this.id_registrar = null;
+               this.element = null;
+
+               return cmnt;
+       }
+
+
+       private void add_text (Valadoc.Token token) {
+               add_content_string (token.to_string ());
+       }
+
+       private void add_value (Valadoc.Token token) {
+               assert (token.value != null);
+
+               add_content_string (token.value);
+       }
+
+       private void add_content_string (string str) {
+               var text = peek () as Text;
+               if (text == null) {
+                       push (text = _factory.create_text ());
+               }
+
+               text.content += str;
+       }
+
+       private void add_symbol_link (string symbol, bool accept_plural) {
+               var taglet = new Taglets.Link ();
+               taglet.c_accept_plural = accept_plural;
+               taglet.symbol_name = symbol;
+
+               var run = _factory.create_run (Run.Style.NONE);
+               run.content.add (taglet);
+
+               push (run);
+       }
+
+       private void preserve_token (Valadoc.Token token) {
+               assert (preserved_token == null);
+               preserved_token = token;
+       }
+
+       private string pop_preserved_link () {
+               assert (preserved_token != null);
+
+               Valadoc.Token _link_token = (owned) preserved_token;
+
+               // email:
+               if (_link_token.token_type == Valadoc.TokenType.MARKDOWN_MAIL) {
+                       return "mailto:"; + _link_token.value;
+               }
+
+               // http or https link:
+               if (_link_token.value != null) {
+                       return _link_token.value;
+               }
+
+               // GTKDOC-ID:
+               return _link_token.word;
+       }
+
+       private string pop_preserved_path () {
+               assert (preserved_token != null);
+
+               Valadoc.Token _path_token = (owned) preserved_token;
+               return _path_token.word ?? _path_token.value;
+       }
+
+       private inline string run_to_string (Run run, string rule_name) throws Error {
+               StringBuilder builder = new StringBuilder ();
+               inline_to_string (run, rule_name, builder);
+               return (owned) builder.str;
+       }
+
+       private void inline_to_string (Inline element, string rule_name, StringBuilder? builder) throws Error 
{
+               if (element is Run) {
+                       Run run = (Run) element;
+
+                       foreach (Inline item in run.content) {
+                               inline_to_string (item, rule_name, builder);
+                       }
+               } else if (element is Text) {
+                       Text text = (Text) element;
+                       builder.append (text.content);
+               } else if (element is Embedded) {
+                       throw new ContentToStringError.UNEXPECTED_ELEMENT ("Unexpected tag: <image> in `%s'", 
rule_name);
+               } else if (element is Link) {
+                       throw new ContentToStringError.UNEXPECTED_ELEMENT ("Unexpected tag: <link> in `%s'", 
rule_name);
+               } else if (element is SourceCode) {
+                       throw new ContentToStringError.UNEXPECTED_ELEMENT ("Unexpected tag: `|[' in `%s'", 
rule_name);
+               } else {
+                       throw new ContentToStringError.UNEXPECTED_ELEMENT ("Unexpected tag in `%s''", 
rule_name);
+               }
+       }
+
+       private bool is_literal (string str) {
+               if (str == "TRUE") {
+                       return true;
+               }
+
+               if (str == "FALSE") {
+                       return true;
+               }
+
+               if (str == "NULL") {
+                       return true;
+               }
+
+               if (str[0].isdigit ()) {
+                       return true;
+               }
+
+               return true;
+       }
+
+       private bool is_error_parameter (string name) {
+               if (element == null || name != "error") {
+                       return false;
+               }
+
+               if (!(element is Api.Method || element is Api.Delegate)) {
+                       return false;
+               }
+
+               return element.get_children_by_types ({
+                       Api.NodeType.ERROR_DOMAIN,
+                       Api.NodeType.CLASS}).size > 0;
+       }
+
+
+       public string resolve (string path) {
+               return path;
+       }
+
+       private void push (Object element) {
+               _stack.add (element);
+       }
+
+       private Object peek (int offset = -1) {
+               assert (_stack.size >= - offset);
+               return _stack.get (_stack.size + offset);
+       }
+
+       private Object pop () {
+               Object node = peek ();
+               _stack.remove_at (_stack.size - 1);
+               return node;
+       }
+
+       private inline string fix_resource_path (string path) {
+               return metadata.get_resource_path (path);
+       }
+}
+
+
+private errordomain Valadoc.Gtkdoc.ContentToStringError {
+       UNEXPECTED_ELEMENT
+}
+
diff --git a/libvaladoc/documentation/gtkdocmarkdownscanner.vala 
b/libvaladoc/documentation/gtkdocmarkdownscanner.vala
new file mode 100644
index 0000000..944d8ce
--- /dev/null
+++ b/libvaladoc/documentation/gtkdocmarkdownscanner.vala
@@ -0,0 +1,758 @@
+/* gtkdocmarkdownscanner.vala
+ *
+ * Copyright (C) 2014 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;
+
+public class Valadoc.Gtkdoc.MarkdownScanner : GLib.Object, Valadoc.Scanner {
+       private enum State {
+               NORMAL,
+               UNORDERED_LIST,
+               ORDERED_LIST,
+               BLOCK
+       }
+
+       private Settings _settings;
+       private Valadoc.Parser parser;
+
+       private unowned string _content;
+       private int _skip;
+
+       private StringBuilder _current_string = new StringBuilder ();
+       private unowned string _index;
+       private bool contains_at;
+
+       private int _line;
+       private int _column;
+       private int _last_line;
+       private int _last_column;
+       private bool _stop;
+
+       private string? headline_end;
+
+       private Regex regex_mail;
+
+       private Vala.List<State> states = new Vala.ArrayList<State> ();
+
+       private inline void push_state (State state) {
+               states.insert (0, state);
+       }
+
+       private inline State pop_state () {
+               return states.remove_at (0);
+       }
+
+       private inline State peek_state () {
+               return states.get (0);
+       }
+
+
+       public MarkdownScanner (Settings settings) {
+               _settings = settings;
+
+               try {
+                       regex_mail = new Regex ("^[A-Za-z0-9._-]+@[A-Za-z0-9._-]+$");
+               } catch (Error e) {
+                       assert_not_reached ();
+               }
+       }
+
+       public void set_parser (Valadoc.Parser parser) {
+               this.parser = parser;
+       }
+
+       public void reset () {
+               _stop = false;
+               _last_line = 0;
+               _last_column = 0;
+               _line = 0;
+               _column = 0;
+               _skip = 0;
+               _current_string.erase (0, -1);
+               contains_at = false;
+               
+               states.clear ();
+               push_state (State.NORMAL);
+       }
+
+       public void scan (string content) throws ParserError {
+               _content = content;
+               _index = _content;
+
+
+               // Accept block taglets:
+               if (handle_newline (_index, true)) {
+                       _index = _index.next_char ();
+               } else {
+                       // Empty string
+                       emit_token (Valadoc.TokenType.MARKDOWN_PARAGRAPH);
+               }
+
+
+               while (!_stop && _index.get_char () != 0) {
+                       unichar c = _index.get_char ();
+                       accept (c);
+                       
+                       _index = _index.next_char ();
+               }
+
+
+               // Close open blocks:
+               while (peek_state () != State.NORMAL) {
+                       if (peek_state () == State.BLOCK) {
+                               emit_token (Valadoc.TokenType.MARKDOWN_BLOCK_END);                      
+                               pop_state ();
+                       } else {
+                               close_block ();
+                       }
+               }
+
+
+               emit_token (Valadoc.TokenType.MARKDOWN_EOC);
+       }
+
+       private void accept (unichar c) throws ParserError {
+               _column++;
+               if (_skip > 0) {
+                       _skip--;
+                       return ;
+               }
+
+               // In headline:
+               string? hash = null;
+               
+               if (headline_end != null && is_headline_end (ref _index, headline_end, out hash)) {
+                       if (hash != null) {
+                               emit_token (Valadoc.TokenType.MARKDOWN_HEADLINE_HASH, hash);
+                       }
+                       emit_token (Valadoc.TokenType.MARKDOWN_HEADLINE_END);
+                       headline_end = null;
+
+                       handle_newline (_index, true);
+
+                       return ;
+               }
+
+               switch (c) {
+               case '\\':
+                       switch (get_next_char ()) {
+                       case '(':
+                               if (get_next_char (2) == ')') {
+                                       _current_string.append ("()");
+                                       _skip += 2;
+                                       break;
+                               }
+
+                               _current_string.append ("\\(");
+                               _skip++;
+                               break;
+
+                       case '<':
+                               append_char ('<');
+                               _skip++;
+                               break;
+
+                       case '>':
+                               append_char ('>');
+                               _skip++;
+                               break;
+
+                       case '@':
+                               append_char ('@');
+                               _skip++;
+                               break;
+
+                       case '%':
+                               append_char ('%');
+                               _skip++;
+                               break;
+
+                       case '#':
+                               append_char ('#');
+                               _skip++;
+                               break;
+
+                       default:
+                               append_char ('\\');
+                               break;
+                       }
+
+                       break;
+
+               case ':':
+                       unichar next_char = get_next_char ();
+                       unichar next2_char = get_next_char (2);
+
+                       // :id or ::id
+                       if ((_current_string.len == 0 || !_current_string.str[_current_string.len - 
1].isalpha ())
+                               && (next_char.isalpha () || (next_char == ':' && next2_char.isalpha ()))) {
+
+                               unowned string _iter;
+                               if (next_char == ':') {
+                                       _iter = _index.offset (2);
+                                       _skip++;
+                               } else {
+                                       _iter = _index.offset (1);
+                               }
+
+                               while (_iter[0].isalnum () || _iter[0] == '_' || (_iter[0] == '-' && 
_iter[1].isalnum ())) {
+                                       _iter = _iter.offset (1);
+                                       _skip++;
+                               }
+
+                               emit_token (Valadoc.TokenType.MARKDOWN_LOCAL_GMEMBER, _index.substring (0, 
_skip + 1));
+                               break;
+                       }
+
+                       append_char (c);
+                       break;
+
+               case '%':
+                       // " %foo", "-%foo" but not " %", "a%foo", ...
+                       if ((_current_string.len == 0 || !_current_string.str[_current_string.len - 
1].isalpha ()) && get_next_char ().isalpha ()) {
+                               unowned string _iter = _index.offset (1);
+
+                               while (_iter[0].isalnum () || _iter[0] == '_') {
+                                       _iter = _iter.offset (1);
+                                       _skip++;
+                               }
+
+                               emit_token (Valadoc.TokenType.MARKDOWN_CONSTANT, _index.substring (1, _skip));
+                               break;
+                       }
+                       // %numeric:
+                       if ((_current_string.len == 0 || !_current_string.str[_current_string.len - 
1].isalpha ()) && get_next_char ().isdigit ()) {
+                               unowned string _iter = _index.offset (1);
+
+                               while (_iter[0].isdigit ()) {
+                                       _iter = _iter.offset (1);
+                                       _skip++;
+                               }
+
+                               // Integers:
+                               if (_iter[0].tolower () == 'u' && _iter[0].tolower () == 'l') {
+                                       _iter = _iter.offset (1);
+                                       _skip += 2;
+
+                                       emit_token (Valadoc.TokenType.MARKDOWN_CONSTANT, _index.substring (1, 
_skip));
+                                       break;
+                               } else if (_iter[0].tolower () == 'u' || _iter[0].tolower () == 'l') {
+                                       _iter = _iter.offset (1);
+                                       _skip++;
+
+                                       emit_token (Valadoc.TokenType.MARKDOWN_CONSTANT, _index.substring (1, 
_skip));
+                                       break;
+                               }
+
+
+                               // Float, double:
+                               if (_iter[0] == '.' && _iter[1].isdigit ()) {
+                                       _iter = _iter.offset (2);
+                                       _skip += 2;
+                               }
+
+                               while (_iter[0].isdigit ()) {
+                                       _iter = _iter.offset (1);
+                                       _skip++;
+                               }
+       
+                               if (_iter[0].tolower () == 'f' || _iter[0].tolower () == 'l') {
+                                       _iter = _iter.offset (1);
+                                       _skip++;
+                               }
+
+                               emit_token (Valadoc.TokenType.MARKDOWN_CONSTANT, _index.substring (1, _skip));
+                               break;
+                       }
+
+                       append_char (c);
+                       break;
+
+               case '#':
+                       // " #foo", "-#foo" but not " #"", "a#""foo", ...
+                       if ((_current_string.len == 0 || !_current_string.str[_current_string.len - 
1].isalpha ()) && get_next_char ().isalpha ()) {
+                               unowned string _iter = _index.offset (1);
+
+                               while (_iter[0].isalnum () || _iter[0] == '_') {
+                                       _iter = _iter.offset (1);
+                                       _skip++;
+                               }
+
+                               // signals, fields, properties
+                               bool is_field = false;
+                               if (((_iter[0] == ':' || _iter[0] == '.') && _iter[1].isalpha ())
+                                       || (_iter.has_prefix ("::") && _iter[2].isalpha ())) {
+
+                                       is_field = (_iter[0] == '.');
+                                       _iter = _iter.offset (2);
+                                       _skip += 2;
+
+                                       while (_iter[0].isalnum () || _iter[0] == '_' || (!is_field && 
_iter[0] == '-')) {
+                                               _iter = _iter.offset (1);
+                                               _skip++;
+                                       }
+                               }
+
+                               if (is_field && _iter.has_prefix ("()")) {
+                                       _skip += 2;
+
+                                       emit_token (Valadoc.TokenType.MARKDOWN_SYMBOL, _index.substring (1, 
_skip - 2));
+                               } else {
+                                       emit_token (Valadoc.TokenType.MARKDOWN_SYMBOL, _index.substring (1, 
_skip));
+                               }
+
+                               break;
+                       }
+
+                       append_char (c);
+                       break;
+
+               case '@':
+                       // " @foo", "-@foo" but not " @", "a@foo", ...
+                       if ((_current_string.len == 0 || !_current_string.str[_current_string.len - 
1].isalpha ())) {
+                               if (get_next_char ().isalpha ()) {
+                                       unowned string _iter = _index.offset (1);
+
+                                       while (_iter[0].isalnum () || _iter[0] == '_') {
+                                               _iter = _iter.offset (1);
+                                               _skip++;
+                                       }
+
+                                       emit_token (Valadoc.TokenType.MARKDOWN_PARAMETER, _index.substring 
(1, _skip));
+                                       break;
+                               } else if (_index.has_prefix ("@...")) {
+                                       _skip += 3;
+                                       emit_token (Valadoc.TokenType.MARKDOWN_PARAMETER, "...");
+                                       break;
+                               }
+                       }
+
+                       append_char (c);
+                       contains_at = true;
+                       break;
+
+               case '(':
+                       if (get_next_char () == ')' && is_id ()) {
+                               string id = _current_string.str;
+                               _current_string.erase (0, -1);
+                               contains_at = false;
+
+                               emit_token (Valadoc.TokenType.MARKDOWN_FUNCTION, id);
+                               _skip++;
+                               break;
+                       }
+
+                       emit_token (Valadoc.TokenType.MARKDOWN_OPEN_PARENS);
+                       break;
+
+               case ')':
+                       emit_token (Valadoc.TokenType.MARKDOWN_CLOSE_PARENS);
+                       break;
+
+               case '[':
+                       unowned string iter = _index;
+                       int count = 1;
+                       while (iter[0] != '\n' && iter[0] != '\0' && count > 0) {
+                               iter = iter.offset (1);
+                               switch (iter[0]) {
+                               case '[':
+                                       count++;
+                                       break;
+
+                               case ']':
+                                       count--;
+                                       break;
+                               }
+                       }
+
+                       if (iter[0] == ']') {
+                               emit_token (Valadoc.TokenType.MARKDOWN_OPEN_BRACKET);
+                       } else {
+                               append_char ('[');
+                       }
+                       break;
+
+               case ']':
+                       emit_token (Valadoc.TokenType.MARKDOWN_CLOSE_BRACKET);
+                       break;
+
+               case '<':
+                       emit_token (Valadoc.TokenType.MARKDOWN_LESS_THAN);
+                       break;
+
+               case '>':
+                       emit_token (Valadoc.TokenType.MARKDOWN_GREATER_THAN);
+                       break;
+
+               case '!':
+                       emit_token (Valadoc.TokenType.MARKDOWN_EXCLAMATION_MARK);
+                       break;
+
+               case '|':
+                       if (get_next_char () == '[') {
+                               unowned string _iter = _index.offset (2);
+                               int end = _iter.index_of ("]|");
+                               if (end < 0) {
+                                       append_char ('|');
+                               } else {
+                                       emit_token (Valadoc.TokenType.MARKDOWN_SOURCE, _index.substring (2, 
end));
+                                       _skip = end + 3;
+                               }
+
+                               break;
+                       }
+
+                       append_char (c);
+                       break;
+
+               case '\t':
+               case ' ':
+                       unowned string _iter = _index.offset (1);
+                       _skip += skip_spaces (ref _iter);
+
+                       if (_iter[0] != '\n' && _iter[0] != '\0') {
+                               emit_token (Valadoc.TokenType.MARKDOWN_SPACE);
+                       }
+                       break;
+
+               case '\r':
+                       // Ignore
+                       break;
+
+               case '\n':
+                       unowned string _iter = _index.offset (1);
+
+                       _line++;
+                       _column = 0;
+                       _last_column = 0;
+                       handle_newline (_iter, false);
+                       break;
+
+               default:
+                       append_char (c);
+                       break;
+               }
+       }
+
+       private bool handle_newline (string _iter, bool is_paragraph) throws ParserError {
+               int leading_spaces;
+
+               leading_spaces = skip_spaces (ref _iter);
+
+               if (_iter[0] == '\0') {
+                       return false;
+               }
+
+               // Do not emit paragraphs twice:
+               if (is_paragraph) {
+                       while (_iter[0] == '\n') {
+                               _line++;
+                               _iter = _iter.offset (1);
+                               leading_spaces = skip_spaces (ref _iter);
+                       }
+               }
+
+               bool in_block = states.contains (State.BLOCK);
+               if (_iter[0] == '>') {
+                       if (!in_block) {
+                               close_block ();
+
+                               if (is_paragraph) {
+                                       _column += (int) ((char*) _iter - (char*) _index);
+                                       _index = _iter.offset (1);
+                                       emit_token (Valadoc.TokenType.MARKDOWN_BLOCK_START);
+                                       push_state (State.BLOCK);
+                               }
+                       }
+
+                       if (in_block || is_paragraph) {
+                               _column++;
+                               _index = _iter;
+
+                               _iter = _iter.offset (1);
+                               skip_spaces (ref _iter);
+                       }
+               } else if (in_block && is_paragraph) {
+                       _column += (int) ((char*) _iter - (char*) _index);
+                       _index = _iter;
+
+                       close_block ();
+
+                       emit_token (Valadoc.TokenType.MARKDOWN_BLOCK_END);
+                       pop_state ();
+               }
+
+
+               int list_token_len = 0;
+               bool is_unsorted_list = _iter[0] == '-' && _iter[1].isspace ();
+               bool is_sorted_list = is_ordered_list (_iter, out list_token_len);
+               if ((is_unsorted_list || is_sorted_list)  && (is_paragraph || states.contains 
(State.UNORDERED_LIST) || states.contains (State.ORDERED_LIST))) {
+                       Valadoc.TokenType start_token = Valadoc.TokenType.MARKDOWN_ORDERED_LIST_ITEM_START;
+                       State new_state = State.ORDERED_LIST;
+
+                       if (is_unsorted_list) {
+                               start_token = Valadoc.TokenType.MARKDOWN_UNORDERED_LIST_ITEM_START;
+                               new_state = State.UNORDERED_LIST;
+                               list_token_len = 2;
+                       }
+
+
+                       _iter = _iter.offset (list_token_len);
+                       close_block ();
+
+                       skip_spaces (ref _iter);
+
+                       _column += (int) ((char*) _iter - (char*) _index);
+                       _index = _iter.offset (-1);
+                       emit_token (start_token);
+                       push_state (new_state);
+
+                       emit_token (Valadoc.TokenType.MARKDOWN_PARAGRAPH);
+                       return true;
+               }
+
+               if ((_iter[0] == '#' && _iter[1].isspace ()) || (_iter[0] == '#' && _iter[1] == '#' && 
_iter[2].isspace ()) && is_paragraph) {
+                       close_block ();
+
+                       if (_iter[1] != '#') {
+                               _iter = _iter.offset (1);
+                               emit_token (Valadoc.TokenType.MARKDOWN_HEADLINE_1);
+                               headline_end = "#";
+                       } else {
+                               emit_token (Valadoc.TokenType.MARKDOWN_HEADLINE_2);
+                               _iter = _iter.offset (2);       
+                               headline_end = "##";
+                       }
+
+                       _column += (int) ((char*) _iter - (char*) _index);
+                       _index = _iter.offset (-1);
+
+                       return true;
+               }
+
+               if (is_paragraph) {
+                       if (leading_spaces == 0) {
+                               close_block ();
+                       }
+
+                       _column += (int) ((char*) _iter - (char*) _index);
+                       _index = _iter.offset (-1);
+                       emit_token (Valadoc.TokenType.MARKDOWN_PARAGRAPH);
+               } else if (_iter[0] == '\n') {
+                       _line++;
+                       _column = 0;
+                       _last_column = 0;
+
+                       handle_newline (_iter.offset (1), true);
+               } else {
+                       emit_token (Valadoc.TokenType.MARKDOWN_SPACE);
+               }
+
+               return true;
+       }
+
+       private bool is_headline_end (ref unowned string iter, string separator, out string? hash) {
+               unowned string _iter = iter;
+               hash = null;
+
+
+               if (_iter[0] == '\n' || _iter[0] == '\0') {
+                       _line++;
+                       return true;
+               }
+               if (!_iter.has_prefix (separator)) {
+                       return false;
+               }
+
+               _iter = _iter.offset (separator.length);
+
+
+               skip_spaces (ref _iter);
+               if (_iter[0] == '\n' || _iter[0] == '\0') {
+                       iter = _iter;
+                       _line++;
+                       return true;
+               } else if (!_iter.has_prefix ("{#")) {
+                       return false;
+               }
+               _iter = _iter.offset (2);
+
+               unowned string id_start = _iter;
+               int hash_len = 0;
+               
+               while (_iter[0] != '}' && _iter[0] != '\n' && _iter[0] != '\0') {
+                       _iter = _iter.offset (1);
+                       hash_len++;
+               }
+
+               if (_iter[0] != '}') {
+                       return false;
+               }
+
+               _iter = _iter.offset (1);
+
+               skip_spaces (ref _iter);
+
+               if (_iter[0] == '\n' || _iter[0] == '\0') {
+                       hash = id_start.substring (0, hash_len);
+                       iter = _iter;
+                       _line++;
+                       return true;
+               }
+
+               return false;
+       }
+
+       private bool is_ordered_list (string iter, out int numeric_prefix_count) {
+               numeric_prefix_count = 0;
+               while (iter[0] >= '0' && iter[0] <= '9') {
+                       numeric_prefix_count++;
+                       iter = iter.offset (1);
+               }
+
+               if (numeric_prefix_count > 0 && iter[0] == '.' && iter[1].isspace ()) {
+                       numeric_prefix_count++;
+                       return true;
+               }
+
+               return false;
+       }
+
+       private inline int skip_spaces (ref unowned string _iter) {
+               int count = 0;
+               while (_iter[0] == ' ' || _iter[0] == '\t' || _iter[0] == '\r') {
+                       _iter = _iter.offset (1);
+                       count++;
+               }
+
+               return count;
+       }
+
+       private bool close_block () throws ParserError {
+               if (states.get (0) == State.UNORDERED_LIST) {
+                       emit_token (Valadoc.TokenType.MARKDOWN_UNORDERED_LIST_ITEM_END);
+                       pop_state ();
+                       return true;
+               } else if (states.get (0) == State.ORDERED_LIST) {
+                       emit_token (Valadoc.TokenType.MARKDOWN_ORDERED_LIST_ITEM_END);
+                       pop_state ();
+                       return true;
+               }
+
+               return false;
+       }
+
+       public void end () throws ParserError {
+               emit_token (Valadoc.TokenType.EOF);
+       }
+
+       public void stop () {
+               _stop = true;
+       }
+
+       public string get_line_content () {
+               StringBuilder builder = new StringBuilder ();
+               weak string line_start = _index;
+               unichar c;
+
+               while ((char*) line_start > (char*) _content && line_start.prev_char ().get_char () != '\n') {
+                       line_start = line_start.prev_char ();
+               }
+
+               while ((c = line_start.get_char ()) != '\n' && c != '\0') {
+                       if (c == '\t') {
+                               builder.append_c (' ');
+                       } else {
+                               builder.append_unichar (c);
+                       }
+                       line_start = line_start.next_char ();
+               }
+
+               return builder.str;
+       }
+
+       private void emit_token (Valadoc.TokenType type, string? value = null) throws ParserError {
+               emit_current_word ();
+
+               parser.accept_token (new Valadoc.Token.from_type (type, get_begin (), get_end (_skip), 
value));
+       }
+
+       private void emit_current_word () throws ParserError {
+               if (_current_string.len > 0) {
+                       if (is_mail ()) {
+                               parser.accept_token (new Valadoc.Token.from_type 
(Valadoc.TokenType.MARKDOWN_MAIL, get_begin (), get_end (_skip), _current_string.str));
+                       } else if (_current_string.str.has_prefix ("http://";) || 
_current_string.str.has_prefix ("https://";)) {
+                               // TODO: (https?:[\/]{2}[^\s]+?)
+                               parser.accept_token (new Valadoc.Token.from_type 
(Valadoc.TokenType.MARKDOWN_LINK, get_begin (), get_end (_skip), _current_string.str));
+                       } else {
+                               parser.accept_token (new Valadoc.Token.from_word (_current_string.str, 
get_begin (), get_end (-1)));
+                       }
+
+                       _current_string.erase (0, -1);
+                       contains_at = false;
+               }
+       }
+
+       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);
+       }
+
+       public int get_line_start_column () {
+               return 0;
+       }
+
+       private void append_char (unichar c) {
+               _current_string.append_unichar (c);
+       }
+
+       private unichar get_next_char (int offset = 1) {
+               return _index.get_char (_index.index_of_nth_char (offset));
+       }
+
+       private inline bool is_mail () {
+               return contains_at && regex_mail.match (_current_string.str);
+       }
+
+       private bool is_id () {
+               if (_current_string.len == 0) {
+                       return false;
+               }
+
+               if (_current_string.str[0].isalpha () == false && _current_string.str[0] != '_') {
+                       return false;
+               }
+
+               for (int i = 1; i < _current_string.len ; i++) {
+                       if (_current_string.str[i].isalnum () == false && _current_string.str[i] != '_') {
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+}
+
diff --git a/libvaladoc/documentation/importerhelper.vala b/libvaladoc/documentation/importerhelper.vala
new file mode 100644
index 0000000..76888d7
--- /dev/null
+++ b/libvaladoc/documentation/importerhelper.vala
@@ -0,0 +1,264 @@
+/* importhelper.vala
+ *
+ * Copyright (C) 2014 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;
+
+namespace Valadoc.ImporterHelper {
+
+       //
+       // resolve-parameter-ctype:
+       //
+
+       internal string? resolve_parameter_ctype (Api.Tree tree, Api.Node element, string parameter_name,
+               out string? param_name, out string? param_array_name, out bool is_return_type_len)
+       {
+               string[]? parts = split_type_name (parameter_name);
+               is_return_type_len = false;
+               param_array_name = null;
+
+               Api.FormalParameter? param = null; // type parameter or formal parameter
+               foreach (Api.Node node in element.get_children_by_type (Api.NodeType.FORMAL_PARAMETER, 
false)) {
+                       if (node.name == parts[0]) {
+                               param = node as Api.FormalParameter;
+                               break;
+                       }
+
+                       if (((Api.FormalParameter) node).implicit_array_length_cparameter_name == parts[0]) {
+                               param_array_name = ((Api.FormalParameter) node).name;
+                               break;
+                       }
+               }
+
+               if (element is Api.Callable
+                       && ((Api.Callable) element).implicit_array_length_cparameter_name == parts[0])
+               {
+                       is_return_type_len = true;
+               }
+
+               if (parts.length == 1) {
+                       param_name = parameter_name;
+                       return null;
+               }
+
+
+               Api.Item? inner = null;
+
+               if (param_array_name != null || is_return_type_len) {
+                       inner = tree.search_symbol_str (null, "int");
+               } else if (param != null) {
+                       inner = param.parameter_type;
+               }
+
+               while (inner != null) {
+                       if (inner is Api.TypeReference) {
+                               inner = ((Api.TypeReference) inner).data_type;
+                       } else if (inner is Api.Pointer) {
+                               inner = ((Api.Pointer) inner).data_type;
+                       } else if (inner is Api.Array) {
+                               inner = ((Api.Array) inner).data_type;
+                       } else {
+                               break ;
+                       }
+               }
+
+
+               if (inner == null) {
+                       param_name = parameter_name;
+                       return null;
+               }
+
+               string? cname = null;
+               if (inner is Api.ErrorDomain) {
+                       cname = ((Api.ErrorDomain) inner).get_cname ();
+               } else if (inner is Api.Struct) {
+                       cname = ((Api.Struct) inner).get_cname ();
+               } else if (inner is Api.Class) {
+                       cname = ((Api.Class) inner).get_cname ();
+               } else if (inner is Api.Enum) {
+                       cname = ((Api.Enum) inner).get_cname ();
+               } else {
+                       assert_not_reached ();
+               }
+
+               param_name = (owned) parts[0];
+               return "c::" + cname + parts[1] + parts[2];
+       }
+
+
+       private string[]? split_type_name (string id) {
+               unichar c;
+
+               for (unowned string pos = id; (c = pos.get_char ()) != '\0'; pos = pos.next_char ()) {
+                       switch (c) {
+                       case '-': // ->
+                               return {id.substring (0, (long) (((char*) pos) - ((char*) id))), "->", 
(string) (((char*) pos) + 2)};
+
+                       case ':': // : or ::
+                               string sep = (pos.next_char ().get_char () == ':')? "::" : ":";
+                               return {id.substring (0, (long) (((char*) pos) - ((char*) id))), sep, 
(string) (((char*) pos) + sep.length)};
+
+                       case '.':
+                               return {id.substring (0, (long) (((char*) pos) - ((char*) id))), ".", 
(string) (((char*) pos) + 1)};
+                       }
+               }
+
+               return {id};
+       }
+
+
+
+       //
+       // extract-short-desc:
+       //
+
+       internal void extract_short_desc (Comment comment, ContentFactory factory) {
+               if (comment.content.size == 0) {
+                       return ;
+               }
+
+               Paragraph? first_paragraph = comment.content[0] as Paragraph;
+               if (first_paragraph == null) {
+                       // add empty paragraph to avoid non-text as short descriptions
+                       comment.content.insert (1, factory.create_paragraph ());
+                       return ;
+               }
+
+
+               // avoid fancy stuff in short descriptions:
+               first_paragraph.horizontal_align = null;
+               first_paragraph.vertical_align = null;
+               first_paragraph.style = null;
+
+
+               Paragraph? second_paragraph = split_paragraph (first_paragraph, factory);
+               if (second_paragraph == null) {
+                       return ;
+               }
+
+               if (second_paragraph.is_empty () == false) {
+                       comment.content.insert (1, second_paragraph);
+               }
+       }
+
+       private inline Text? split_text (Text text, ContentFactory factory) {
+               int offset = 0;
+               while ((offset = text.content.index_of_char ('.', offset)) >= 0) {
+                       if (offset >= 2) {
+                               // ignore "e.g."
+                               unowned string cmp4 = ((string) (((char*) text.content) + offset - 2));
+                               if (cmp4.has_prefix (" e.g.") || cmp4.has_prefix ("(e.g.")) {
+                                       offset = offset + 3;
+                                       continue;
+                               }
+
+                               // ignore "i.e."
+                               if (cmp4.has_prefix (" i.e.") || cmp4.has_prefix ("(i.e.")) {
+                                       offset = offset + 3;
+                                       continue;
+                               }
+                       }
+
+                       unowned string cmp0 = ((string) (((char*) text.content) + offset));
+
+                       // ignore ... (varargs)
+                       if (cmp0.has_prefix ("...")) {
+                               offset = offset + 3;
+                               continue;
+                       }
+
+                       // ignore numbers
+                       if (cmp0.get (1).isdigit ()) {
+                               offset = offset + 2;
+                               continue;
+                       }
+
+
+                       Text sec = factory.create_text (text.content.substring (offset+1, -1));
+                       text.content = text.content.substring (0, offset+1);
+                       return sec;
+               }
+
+               return null;
+       }
+
+       private inline Run? split_run (Run run, ContentFactory factory) {
+               if (run.style != Run.Style.NONE) {
+                       return null;
+               }
+
+               Run? sec = null;
+
+
+               Vala.Iterator<Inline> iter = run.content.iterator ();
+               for (bool has_next = iter.next (); has_next; has_next = iter.next ()) {
+                       Inline item = iter.get ();
+                       if (sec == null) {
+                               Inline? tmp = split_inline (item, factory);
+                               if (tmp != null) {
+                                       sec = factory.create_run (run.style);
+                                       sec.content.add (tmp);
+                               }
+                       } else {
+                               sec.content.add (item);
+                               iter.remove ();
+                       }
+               }
+
+               return sec;
+       }
+
+       private inline Inline? split_inline (Inline item, ContentFactory factory) {
+               if (item is Text) {
+                       return split_text ((Text) item, factory);
+               } else if (item is Run) {
+                       return split_run ((Run) item, factory);
+               }
+
+               return null;
+       }
+
+       private inline Paragraph? split_paragraph (Paragraph p, ContentFactory factory) {
+               Paragraph? sec = null;
+
+               Vala.Iterator<Inline> iter = p.content.iterator ();
+               for (bool has_next = iter.next (); has_next; has_next = iter.next ()) {
+                       Inline item = iter.get ();
+                       if (sec == null) {
+                               Inline? tmp = split_inline (item, factory);
+                               if (tmp != null) {
+                                       sec = factory.create_paragraph ();
+                                       sec.horizontal_align = p.horizontal_align;
+                                       sec.vertical_align = p.vertical_align;
+                                       sec.style = p.style;
+                                       sec.content.add (tmp);
+                               }
+                       } else {
+                               sec.content.add (item);
+                               iter.remove ();
+                       }
+               }
+
+               return sec;
+       }
+
+}
diff --git a/libvaladoc/documentation/wiki.vala b/libvaladoc/documentation/wiki.vala
new file mode 100644
index 0000000..2f0296f
--- /dev/null
+++ b/libvaladoc/documentation/wiki.vala
@@ -0,0 +1,157 @@
+/* wiki.vala
+ *
+ * Copyright (C) 2008-2009 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>
+ */
+
+
+public class Valadoc.WikiPage : Object, Documentation {
+       public Content.Page documentation {
+               protected set;
+               get;
+       }
+
+       public string documentation_str {
+               private set;
+               get;
+       }
+
+       public string path {
+               private set;
+               get;
+       }
+
+       public string name {
+               private set;
+               get;
+       }
+
+
+       public Api.Package? package {
+               get {
+                       return _package;
+               }
+       }
+
+       private Api.Package _package;
+
+       /**
+        * The corresponding file name
+        */
+       public string? get_filename () {
+               return Path.get_basename(this.path);
+       }
+
+       public WikiPage (string name, string path, Api.Package package) {
+               this._package = package;
+               this.name = name;
+               this.path = path;
+       }
+
+       public void read (ErrorReporter reporter) {
+               try {
+                       string content;
+                       FileUtils.get_contents (this.path, out content);
+                       this.documentation_str = content;
+               } catch (FileError err) {
+                       reporter.simple_error (null, "Unable to read file '%s': %s", this.path, err.message);
+               }
+       }
+
+       public void parse (DocumentationParser docparser, Api.Package pkg) {
+               documentation = docparser.parse_wikipage (pkg, this);
+       }
+}
+
+
+public class Valadoc.WikiPageTree : Object {
+       private Vala.ArrayList<WikiPage> wikipages;
+
+
+       public WikiPageTree () {
+       }
+
+       public Vala.Collection<WikiPage> get_pages () {
+               return this.wikipages == null ? new Vala.ArrayList<WikiPage> () : this.wikipages;
+       }
+
+       public WikiPage? search (string name) {
+               if (this.wikipages == null) {
+                       return null;
+               }
+
+               foreach (WikiPage page in this.wikipages ) {
+                       if (page.name == name) {
+                               return page;
+                       }
+               }
+               return null;
+       }
+
+       private void create_tree_from_path (DocumentationParser docparser, Api.Package package,
+                                                                               ErrorReporter reporter, 
string path, string? nameoffset = null)
+       {
+               try {
+                       Dir dir = Dir.open (path);
+
+                       for (string? curname = dir.read_name (); curname!=null ; curname = dir.read_name ()) {
+                               string filename = Path.build_filename (path, curname);
+                               if (curname.has_suffix (".valadoc") && FileUtils.test (filename, 
FileTest.IS_REGULAR)) {
+                                       WikiPage wikipage = new WikiPage ((nameoffset!=null)
+                                               ? Path.build_filename (nameoffset, curname)
+                                               : curname, filename, package);
+                                       this.wikipages.add(wikipage);
+                                       wikipage.read (reporter);
+                               } else if (FileUtils.test (filename, FileTest.IS_DIR)) {
+                                       this.create_tree_from_path (docparser, package, reporter, filename, 
(nameoffset!=null)
+                                               ? Path.build_filename (nameoffset, curname)
+                                               : curname);
+                               }
+                       }
+               } catch (FileError err) {
+                       reporter.simple_error (null, "Unable to open directory '%s': %s", path, err.message);
+               }
+       }
+
+       public void parse (Settings settings, DocumentationParser docparser, Api.Package package, 
ErrorReporter reporter) {
+               weak string path = settings.wiki_directory;
+               if (path == null) {
+                       return ;
+               }
+
+               this.wikipages = new Vala.ArrayList<WikiPage> ();
+               this.create_tree_from_path (docparser, package, reporter, path);
+
+               foreach (WikiPage page in this.wikipages) {
+                       page.parse (docparser, package);
+               }
+       }
+
+       public void check (Settings settings, DocumentationParser docparser, Api.Package pkg) {
+               if (this.wikipages == null) {
+                       return ;
+               }
+
+               foreach (WikiPage page in this.wikipages) {
+                       docparser.check_wikipage (pkg, page);
+               }
+       }
+}
+
+
diff --git a/libvaladoc/documentation/wikiscanner.vala b/libvaladoc/documentation/wikiscanner.vala
new file mode 100644
index 0000000..625a77a
--- /dev/null
+++ b/libvaladoc/documentation/wikiscanner.vala
@@ -0,0 +1,396 @@
+/* wikiscanner.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.WikiScanner : Object, Scanner {
+
+       public WikiScanner (Settings settings) {
+               _settings = settings;
+       }
+
+       private Settings _settings;
+       private Parser _parser;
+
+       private string _content;
+       private unowned string _index;
+       private bool _stop;
+       private int _last_line;
+       private int _last_column;
+       private int _line;
+       private int _column;
+       private bool _url_escape_mode;
+       private bool _code_escape_mode;
+       private unichar _last_char;
+       private int _skip;
+       private StringBuilder _current_string = new StringBuilder ();
+
+       public void set_parser (Parser parser) {
+               _parser = parser;
+       }
+
+       public virtual void reset () {
+               _stop = false;
+               _last_line = 0;
+               _last_column = 0;
+               _line = 0;
+               _column = 0;
+               _url_escape_mode = false;
+               _code_escape_mode = false;
+               _last_char = 0;
+               _skip = 0;
+               _current_string.erase (0, -1);
+       }
+
+       public void scan (string content) throws ParserError {
+               this._content = content;
+
+               for (_index = _content; !_stop && _index.get_char () != 0; _index = _index.next_char ()) {
+                       unichar c = _index.get_char ();
+                       accept (c);
+               }
+       }
+
+       public void end () throws ParserError {
+               emit_token (TokenType.EOF);
+       }
+
+       public virtual void stop () {
+               _stop = true;
+       }
+
+       public void set_url_escape_mode (bool escape_mode) {
+               _url_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 () {
+               StringBuilder builder = new StringBuilder ();
+               weak string line_start = _index;
+               unichar c;
+
+               while ((char*) line_start > (char*) _content && line_start.prev_char ().get_char () != '\n') {
+                       line_start = line_start.prev_char ();
+               }
+
+               while ((c = line_start.get_char ()) != '\n' && c != '\0') {
+                       if (c == '\t') {
+                               builder.append_c (' ');
+                       } else {
+                               builder.append_unichar (c);
+                       }
+                       line_start = line_start.next_char ();
+               }
+
+               return builder.str;
+       }
+
+       protected unichar get_next_char (int offset = 1) {
+               return _index.get_char (_index.index_of_nth_char (offset));
+       }
+
+       protected virtual void accept (unichar c) throws ParserError {
+               _column++;
+               if (_skip == 0) {
+                       if (_code_escape_mode) {
+                               if (c == '}' && get_next_char (1) == '}' && get_next_char (2) == '}') {
+                                       _code_escape_mode = false; // This is a temporary hack
+                                       emit_token (TokenType.TRIPLE_CLOSED_BRACE);
+                                       _skip = 2;
+                               } else {
+                                       append_char (c);
+                               }
+                               return;
+                       } else if (_url_escape_mode) {
+                               switch (c) {
+                               // Reserved characters
+                               case ';':
+                               case '/':
+                               case '?':
+                               case ':':
+                               case '@':
+                               case '#':
+                               case '=':
+                               case '&':
+                               // Special characters
+                               case '$':
+                               case '-':
+                               case '_':
+                               case '.':
+                               case '+':
+                               case '!':
+                               case '*':
+                               case '\'':
+                               case '(':
+                               case ')':
+                               case ',':
+                                       append_char (c);
+                                       return;
+                               default:
+                                       break;
+                               }
+                       }
+
+                       switch (c) {
+                       case '@':
+                               emit_token (TokenType.AROBASE);
+                               break;
+
+                       case '{':
+                               look_for_three (c,
+                                               TokenType.OPEN_BRACE,
+                                               TokenType.DOUBLE_OPEN_BRACE,
+                                               TokenType.TRIPLE_OPEN_BRACE);
+                               break;
+
+                       case '}':
+                               look_for_three (c,
+                                               TokenType.CLOSED_BRACE,
+                                               TokenType.DOUBLE_CLOSED_BRACE,
+                                               TokenType.TRIPLE_CLOSED_BRACE);
+                               break;
+
+                       case '[':
+                               look_for_two_or_append (c, TokenType.DOUBLE_OPEN_BRACKET);
+                               break;
+
+                       case ']':
+                               look_for_two_or_append (c, TokenType.DOUBLE_CLOSED_BRACKET);
+                               break;
+
+                       case '|':
+                               look_for_two (c,
+                                             TokenType.PIPE,
+                                             TokenType.DOUBLE_PIPE);
+                               break;
+
+                       case ')':
+                               if (get_next_char () == ')') {
+                                       emit_token (TokenType.ALIGN_RIGHT);
+                                       _skip = 1;
+                               } else if (get_next_char () == '(') {
+                                       emit_token (TokenType.ALIGN_CENTER);
+                                       _skip = 1;
+                               } else {
+                                       append_char (c);
+                               }
+                               break;
+
+                       case '-':
+                               emit_token (TokenType.MINUS);
+                               break;
+
+                       case '=':
+                               look_for_five (c,
+                                  TokenType.EQUAL_1,
+                                  TokenType.EQUAL_2,
+                                  TokenType.EQUAL_3,
+                                  TokenType.EQUAL_4,
+                                  TokenType.EQUAL_5);
+                               break;
+
+                       case '<':
+                               if (!look_for ("<<BR>>", TokenType.BREAK)) {
+                                       emit_token (TokenType.LESS_THAN);
+                               }
+                               break;
+
+                       case '>':
+                               emit_token (TokenType.GREATER_THAN);
+                               break;
+
+                       case '^':
+                               emit_token (TokenType.ALIGN_TOP);
+                               break;
+
+                       case 'v':
+                               unichar next_char = get_next_char ();
+                               if (_last_char.isalnum () || _last_char == ' '
+                                       || next_char.isalnum () || next_char == ' ') {
+                                       append_char (c);
+                               } else {
+                                       emit_token (TokenType.ALIGN_BOTTOM);
+                               }
+                               break;
+
+                       case '\'':
+                               look_for_two_or_append (c, TokenType.SINGLE_QUOTE_2);
+                               break;
+
+                       case '/':
+                               look_for_two_or_append (c, TokenType.SLASH_2);
+                               break;
+
+                       case '_':
+                               look_for_two_or_append (c, TokenType.UNDERSCORE_2);
+                               break;
+
+                       case '`':
+                               if (get_next_char () == '`') {
+                                       emit_token (TokenType.BACK_QUOTE_2);
+                                       _skip = 1;
+                               } else {
+                                       append_char (c);
+                               }
+                               break;
+
+                       case '\t':
+                               emit_token (TokenType.TAB);
+                               break;
+
+                       case ' ':
+                               emit_token (TokenType.SPACE);
+                               break;
+
+                       case '\r':
+                               break;
+
+                       case '\n':
+                               emit_token (TokenType.EOL);
+                               _line++;
+                               _column = 0;
+                               _last_column = 0;
+                               break;
+
+                       default:
+                               append_char (c);
+                               break;
+                       }
+               } else {
+                       _skip--;
+               }
+               _last_char = c;
+       }
+
+       private void append_char (unichar c) {
+               _current_string.append_unichar (c);
+       }
+
+       public virtual 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_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_line = _line;
+               _last_column = _column;
+       }
+
+       private void look_for_two_or_append (unichar c, TokenType type) throws ParserError {
+               if (get_next_char () == c) {
+                       emit_token (type);
+                       _skip = 1;
+               } else {
+                       append_char (c);
+               }
+       }
+
+       private void look_for_two (unichar c, TokenType one, TokenType two) throws ParserError {
+               if (get_next_char (1) == c) {
+                       emit_token (two);
+                       _skip = 1;
+               } else {
+                       emit_token (one);
+               }
+       }
+
+       private void look_for_three (unichar c, TokenType one, TokenType two, TokenType three)
+                                                                throws ParserError
+       {
+               if (get_next_char (1) == c) {
+                       if (get_next_char (2) == c) {
+                               emit_token (three);
+                               _skip = 2;
+                       } else {
+                               emit_token (two);
+                               _skip = 1;
+                       }
+               } else {
+                       emit_token (one);
+               }
+       }
+
+       private void look_for_five (unichar c, TokenType one, TokenType two, TokenType three,
+                                                               TokenType four, TokenType five) throws 
ParserError
+       {
+               if (get_next_char (1) == c) {
+                       if (get_next_char (2) == c) {
+                               if (get_next_char (3) == c) {
+                                       if (get_next_char (4) == c) {
+                                               emit_token (five);
+                                               _skip = 4;
+                                       } else {
+                                               emit_token (four);
+                                               _skip = 3;
+                                       }
+                               } else {
+                                       emit_token (three);
+                                       _skip = 2;
+                               }
+                       } else {
+                               emit_token (two);
+                               _skip = 1;
+                       }
+               } else {
+                       emit_token (one);
+               }
+       }
+
+       private bool look_for (string str, TokenType type) throws ParserError {
+               for (int i = 1; i < str.length; i++) {
+                       if (get_next_char (i) != str[i]) {
+                               return false;
+                       }
+               }
+
+               emit_token (type);
+               _skip = (int) (str.length - 1);
+               return true;
+       }
+}
diff --git a/libvaladoc/errorreporter.vala b/libvaladoc/errorreporter.vala
new file mode 100644
index 0000000..c8d09cb
--- /dev/null
+++ b/libvaladoc/errorreporter.vala
@@ -0,0 +1,390 @@
+/* errorreporter.vala
+ *
+ * Copyright (C) 2008-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:
+ *     Brosch Florian <flo brosch gmail com>
+ */
+
+
+public class Valadoc.ErrorReporter : Object {
+       private int _warnings = 0;
+       private int _errors = 0;
+
+       /**
+        * SGR end tag
+        */
+       private const string ANSI_COLOR_END = "\x1b[0m";
+
+       /**
+        * SGR start tag for source location
+        */
+       private string locus_color_start = "";
+
+       /**
+        * SGR end tag for source location
+        */
+       private unowned string locus_color_end = "";
+
+       /**
+        * SGR start tag for warning titles
+        */
+       private string warning_color_start = "";
+
+       /**
+        * SGR end tag for warning titles
+        */
+       private unowned string warning_color_end = "";
+
+       /**
+        * SGR start tag for error titles
+        */
+       private string error_color_start = "";
+
+       /**
+        * SGR end tag for error titles
+        */
+       private unowned string error_color_end = "";
+
+       /**
+        * SGR start tag for note titles
+        */
+       private string note_color_start = "";
+
+       /**
+        * SGR end tag for note titles
+        */
+       private unowned string note_color_end = "";
+
+       /**
+        * SGR start tag for caret line (^^^)
+        */
+       private string caret_color_start = "";
+
+       /**
+        * SGR end tag for caret line (^^^)
+        */
+       private unowned string caret_color_end = "";
+
+       /**
+        * SGR start tag for quotes line ('', ``, `')
+        */
+       private string quote_color_start = "";
+
+       /**
+        * SGR end tag for quotes line ('', ``, `')
+        */
+       private unowned string quote_color_end = "";
+
+
+       public int warnings_offset {
+               get;
+               set;
+       }
+
+       public int errors_offset {
+               get;
+               set;
+       }
+
+       public unowned GLib.FileStream stream {
+               get;
+               set;
+       }
+
+       public Settings? settings {
+               get;
+               set;
+       }
+
+       public int errors {
+               get {
+                       return this._errors + errors_offset;
+               }
+       }
+
+       public int warnings {
+               get {
+                       return this._warnings + warnings_offset;
+               }
+       }
+
+
+       public ErrorReporter (Settings? settings = null) {
+               this.stream = GLib.stderr;
+               this.settings = settings;
+       }
+
+       /**
+        * Set all colors by string
+        *
+        * {{{
+        *   "error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01"
+        * }}}
+        */
+       public bool set_colors (string str) {
+               Regex val_regex;
+               try {
+                       val_regex = new Regex ("^\\s*[0-9]+(;[0-9]*)*\\s*$");
+               } catch (RegexError e) {
+                       assert_not_reached ();
+               }
+
+               string error_color = null;
+               string warning_color = null;
+               string note_color = null;
+               string caret_color = null;
+               string locus_color = null;
+               string quote_color = null;
+
+               string[] fragments = str.split (":");
+               foreach (unowned string fragment in fragments) {
+                       string[] eq = fragment.split ("=", 2);
+                       if (eq.length != 2) {
+                               return false;
+                       }
+
+                       if (!val_regex.match (eq[1])) {
+                               return false;
+                       }
+
+
+                       unowned string checked_value = eq[1]._strip ();
+                       switch (eq[0]._strip ()) {
+                       case "error":
+                               error_color = checked_value;
+                               break;
+
+                       case "warning":
+                               warning_color = checked_value;
+                               break;
+
+                       case "note":
+                               note_color = checked_value;
+                               break;
+
+                       case "caret":
+                               caret_color = checked_value;
+                               break;
+
+                       case "locus":
+                               locus_color = checked_value;
+                               break;
+
+                       case "quote":
+                               quote_color = checked_value;
+                               break;
+
+                       default:
+                               return false;
+                       }
+               }
+
+               if (is_atty (this.stream.fileno ())) {
+                       if (error_color != null) {
+                               this.error_color_start = "\x1b[0" + error_color + "m";
+                               this.error_color_end = ANSI_COLOR_END;
+                       }
+
+                       if (warning_color != null) {
+                               this.warning_color_start = "\x1b[0" + warning_color + "m";
+                               this.warning_color_end = ANSI_COLOR_END;
+                       }
+
+                       if (note_color != null) {
+                               this.note_color_start = "\x1b[0" + note_color + "m";
+                               this.note_color_end = ANSI_COLOR_END;
+                       }
+
+                       if (caret_color != null) {
+                               this.caret_color_start = "\x1b[0" + caret_color + "m";
+                               this.caret_color_end = ANSI_COLOR_END;
+                       }
+
+                       if (locus_color != null) {
+                               this.locus_color_start = "\x1b[0" + locus_color + "m";
+                               this.locus_color_end = ANSI_COLOR_END;
+                       }
+
+                       if (quote_color != null) {
+                               this.quote_color_start = "\x1b[0" + quote_color + "m";
+                               this.quote_color_end = ANSI_COLOR_END;
+                       }
+               }
+               return true;
+       }
+
+       [CCode (has_target = false)]
+       private delegate int AttyFunc (int fd);
+
+       private bool is_atty (int fd) {
+               Module module = Module.open (null, ModuleFlags.BIND_LAZY);
+               if (module == null) {
+                       return false;
+               }
+
+               void* _func;
+               module.symbol ("isatty", out _func);
+               if (_func == null) {
+                       return false;
+               }
+
+               AttyFunc? func = (AttyFunc) _func;
+               return func (fd) == 1;
+       }
+
+       [PrintfFormat]
+       private inline void msg (string type, string type_color_start, string type_color_end, string file, 
long line, long startpos, long endpos,
+                                                        string errline, string msg_format, va_list args)
+       {
+               this.stream.printf ("%s%s:%lu.%lu-%lu.%lu:%s %s%s:%s ",
+                                                       locus_color_start, file, line, startpos, line, 
endpos, locus_color_end,
+                                                       type_color_start, type, type_color_end);
+               print_highlighted_message (msg_format.vprintf (args));
+               this.stream.putc ('\n');
+
+               if (startpos <= endpos) {
+                       this.stream.printf ("%s\n", errline);
+
+                       this.stream.puts (caret_color_start);
+                       for (int i = 0; i < errline.char_count ()+1; i++) {
+                               if (errline[i] == '\t') {
+                                       this.stream.printf ("\t");
+                               } else if (i >= startpos - 1 && i < endpos - 1) {
+                                       this.stream.printf ("^");
+                               } else {
+                                       this.stream.printf (" ");
+                               }
+                       }
+                       this.stream.puts (caret_color_end);
+                       this.stream.printf ("\n");
+               }
+       }
+
+       private void print_highlighted_message (string message) {
+               int start = 0;
+               int cur = 0;
+
+               while (message[cur] != '\0') {
+                       if (message[cur] == '\'' || message[cur] == '`') {
+                               unowned string end_chars = (message[cur] == '`')? "`'" : "'";
+                               this.stream.puts (message.substring (start, cur - start));
+                               start = cur;
+                               cur++;
+
+                               while (message[cur] != '\0' && end_chars.index_of_char (message[cur]) < 0) {
+                                       cur++;
+                               }
+                               if (message[cur] == '\0') {
+                                       this.stream.puts (message.substring (start, cur - start));
+                                       start = cur;
+                               } else {
+                                       cur++;
+                                       this.stream.printf ("%s%s%s", quote_color_start, message.substring 
(start, cur - start), quote_color_end);
+                                       start = cur;
+                               }
+                       } else {
+                               cur++;
+                       }
+               }
+
+               this.stream.puts (message.offset (start));
+       }
+
+       [PrintfFormat]
+       public void simple_warning (string? location, string msg_format, ...) {
+               var args = va_list();
+
+               if (location != null) {
+                       this.stream.puts (locus_color_start);
+                       this.stream.puts (location);
+                       this.stream.puts (": ");
+                       this.stream.puts (locus_color_end);
+               }
+
+               this.stream.puts (warning_color_start);
+               this.stream.puts ("warning: ");
+               this.stream.puts (warning_color_end);
+
+               print_highlighted_message (msg_format.vprintf (args));
+               this.stream.putc ('\n');
+               this._warnings++;
+       }
+
+       [PrintfFormat]
+       public void simple_error (string? location, string msg_format, ...) {
+               var args = va_list();
+
+               if (location != null) {
+                       this.stream.puts (locus_color_start);
+                       this.stream.puts (location);
+                       this.stream.puts (": ");
+                       this.stream.puts (locus_color_end);
+                       this.stream.putc (' ');
+               }
+
+               this.stream.puts (error_color_start);
+               this.stream.puts ("error: ");
+               this.stream.puts (error_color_end);
+
+               print_highlighted_message (msg_format.vprintf (args));
+               this.stream.putc ('\n');
+               this._errors++;
+       }
+
+       [PrintfFormat]
+       public void simple_note (string? location, string msg_format, ...) {
+               if (_settings == null || _settings.verbose) {
+                       var args = va_list();
+
+                       if (location != null) {
+                               this.stream.puts (locus_color_start);
+                               this.stream.puts (location);
+                               this.stream.puts (": ");
+                               this.stream.puts (locus_color_end);
+                               this.stream.putc (' ');
+                       }
+
+                       this.stream.puts (note_color_start);
+                       this.stream.puts ("note: ");
+                       this.stream.puts (note_color_end);
+
+                       print_highlighted_message (msg_format.vprintf (args));
+                       this.stream.putc ('\n');
+                       this._warnings++;
+               }
+       }
+
+       [PrintfFormat]
+       public void error (string file, long line, long startpos, long endpos, string errline,
+                                          string msg_format, ...)
+       {
+               var args = va_list();
+               this.msg ("error", error_color_start, error_color_end, file, line, startpos, endpos, errline, 
msg_format, args);
+               this._errors++;
+       }
+
+       [PrintfFormat]
+       public void warning (string file, long line, long startpos, long endpos, string errline,
+                                                string msg_format, ...)
+       {
+               var args = va_list();
+               this.msg ("warning", warning_color_start, warning_color_end, file, line, startpos, endpos, 
errline, msg_format, args);
+               this._warnings++;
+       }
+}
+
diff --git a/libvaladoc/filehelper.vala b/libvaladoc/filehelper.vala
new file mode 100644
index 0000000..54c7b87
--- /dev/null
+++ b/libvaladoc/filehelper.vala
@@ -0,0 +1,199 @@
+/* filehelper.vala
+ *
+ * Copyright (C) 2008-2009 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:
+ *     Brosch Florian <flo brosch gmail com>
+ */
+
+
+namespace Valadoc {
+       [CCode (cprefix = "", cname = "PACKAGE_ICONDIR")]
+       public extern const string icons_dir;
+
+       /**
+        * Makes a copy of the file src to dest. 
+        *
+        * @param src the file to copy
+        * @param dest the destination path
+        */
+       public bool copy_file (string src, string dest) {
+               GLib.FileStream fsrc = GLib.FileStream.open (src, "rb");
+               if (fsrc == null) {
+                       return false;
+               }
+
+               GLib.FileStream fdest = GLib.FileStream.open (dest, "wb");
+               if (fdest == null) {
+                       return false;
+               }
+
+               for (int c = fsrc.getc() ; !fsrc.eof() ; c = fsrc.getc()) {
+                       fdest.putc ((char)c);
+               }
+
+               return true;
+       }
+
+       /**
+        * Makes a copy of the directory src to dest. 
+        *
+        * @param src the directory to copy
+        * @param dest the destination path
+        */
+       public bool copy_directory (string src, string dest) {
+               try {
+                       GLib.Dir dir = GLib.Dir.open (src);
+                       for (string? file = dir.read_name (); file != null; file = dir.read_name ()) {
+                               string src_file_path = GLib.Path.build_filename (src, file);
+                               string dest_file_path = GLib.Path.build_filename (dest, file);
+                               if (GLib.FileUtils.test (src_file_path, GLib.FileTest.IS_DIR)) {
+                                       GLib.DirUtils.create (dest_file_path, 0755); // mkdir if necessary
+                                       if (!copy_directory (src_file_path, dest_file_path)) { // copy 
directories recursively
+                                               return false;
+                                       }
+                               } else {
+                                       if (!copy_file (src_file_path, dest_file_path)) {
+                                               return false;
+                                       }
+                               }
+                       }
+               }
+               catch (GLib.FileError err) {
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * A recursive directory delete function
+        *
+        * @param rpath the directory to remove
+        */
+       public bool remove_directory (string rpath) {
+               try {
+                       GLib.Dir dir = GLib.Dir.open ( rpath );
+                       if (dir == null)
+                               return false;
+
+                       for (weak string entry = dir.read_name(); entry != null ; entry = dir.read_name()) {
+                               string path = rpath + entry;
+
+                               bool is_dir = GLib.FileUtils.test (path, GLib.FileTest.IS_DIR);
+                               if (is_dir == true) {
+                                       bool tmp = remove_directory (path);
+                                       if (tmp == false) {
+                                               return false;
+                                       }
+                               } else {
+                                       int tmp = GLib.FileUtils.unlink (path);
+                                       if (tmp > 0) {
+                                               return false;
+                                       }
+                               }
+                       }
+               } catch (GLib.FileError err) {
+                       return false;
+               }
+
+               return true;
+       }
+
+
+       private inline bool ends_with_dir_separator (string s) {
+               // --- ported from libvala ---
+               return Path.is_dir_separator (s.get_char (s.length - 1));
+       }
+
+       /**
+        * Returns canonicalized absolute pathname
+        *
+        * @param name the path being checked
+        * @return a canonicalized absolute pathname
+        */
+       public string realpath (string name) {
+               // --- ported from libvala ---
+
+               string rpath;
+
+               // start of path component
+               weak string start;
+               // end of path component
+               weak string end;
+
+               if (!Path.is_absolute (name)) {
+                       // relative path
+                       rpath = Environment.get_current_dir ();
+
+                       start = end = name;
+               } else {
+                       // set start after root
+                       start = end = Path.skip_root (name);
+
+                       // extract root
+                       rpath = name.substring (0, (int) ((char*) start - (char*) name));
+               }
+
+               long root_len = (long) ((char*) Path.skip_root (rpath) - (char*) rpath);
+
+               for (; start.get_char () != 0; start = end) {
+                       // skip sequence of multiple path-separators
+                       while (Path.is_dir_separator (start.get_char ())) {
+                               start = start.next_char ();
+                       }
+
+                       // find end of path component
+                       long len = 0;
+                       for (end = start; end.get_char () != 0 && !Path.is_dir_separator (end.get_char ()); 
end = end.next_char ()) {
+                               len++;
+                       }
+
+                       if (len == 0) {
+                               break;
+                       } else if (len == 1 && start.get_char () == '.') {
+                               // do nothing
+                       } else if (len == 2 && start.has_prefix ("..")) {
+                               // back up to previous component, ignore if at root already
+                               if (rpath.length > root_len) {
+                                       do {
+                                               rpath = rpath.substring (0, rpath.length - 1);
+                                       } while (!ends_with_dir_separator (rpath));
+                               }
+                       } else {
+                               if (!ends_with_dir_separator (rpath)) {
+                                       rpath += Path.DIR_SEPARATOR_S;
+                               }
+
+                               rpath += start.substring (0, len);
+                       }
+               }
+
+               if (rpath.length > root_len && ends_with_dir_separator (rpath)) {
+                       rpath = rpath.substring (0, rpath.length - 1);
+               }
+
+               if (Path.DIR_SEPARATOR != '/') {
+                       // don't use backslashes internally,
+                       // to avoid problems in #include directives
+                       string[] components = rpath.split ("\\");
+                       rpath = string.joinv ("/", components);
+               }
+
+               return rpath;
+       }
+}
+
diff --git a/libvaladoc/gtkdocmarkupwriter.vala b/libvaladoc/gtkdocmarkupwriter.vala
new file mode 100644
index 0000000..1e72767
--- /dev/null
+++ b/libvaladoc/gtkdocmarkupwriter.vala
@@ -0,0 +1,73 @@
+/* gtkdocmarkupwriter.vala
+ *
+ * Copyright (C) 2012  Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+
+
+public class Valadoc.GtkDocMarkupWriter : Valadoc.MarkupWriter {
+       private unowned StringBuilder builder;
+
+       public void reset () {
+               last_was_tag = true;
+               current_column = 0;
+               builder.erase ();
+               indent = -1;
+       }
+
+       public unowned string content {
+               get { return builder.str; }
+       }
+
+       public GtkDocMarkupWriter () {
+               StringBuilder builder = new StringBuilder ();
+               base ((str) => { builder.append (str); }, false);
+               this.builder = builder;
+       }
+
+       protected override bool inline_element (string name) {
+               return name != "para"
+                       && name != "programlisting"
+                       && name != "table"
+                       && name != "example"
+                       && name != "figure"
+                       && name != "tr"
+                       && name != "td"
+                       && name != "mediaobject"
+                       && name != "imageobject"
+                       && name != "textobject"
+                       && name != "listitem"
+                       && name != "orderedlist"
+                       && name != "itemizedlist"
+                       && name != "title";
+       }
+
+       protected override bool content_inline_element (string name) {
+               return name == "para"
+                       || name == "programlisting"
+                       || name == "emphasis"
+                       || name == "blockquote"
+                       || name == "ulink"
+                       || name == "listitem"
+                       || name == "title";
+       }
+}
+
+
diff --git a/libvaladoc/gtkdocrenderer.vala b/libvaladoc/gtkdocrenderer.vala
new file mode 100644
index 0000000..19afb54
--- /dev/null
+++ b/libvaladoc/gtkdocrenderer.vala
@@ -0,0 +1,503 @@
+/* gtkdocrenderer.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 GLib;
+using Valadoc.Content;
+
+public class Valadoc.GtkdocRenderer : ContentRenderer {
+       private GtkDocMarkupWriter writer = new GtkDocMarkupWriter ();
+       protected Settings settings;
+       private bool separated;
+
+       private string? get_cname (Api.Item item) {
+               if (item is Api.Method) {
+                       return ((Api.Method)item).get_cname ();
+               } else if (item is Api.FormalParameter) {
+                       return ((Api.FormalParameter)item).name;
+               } else if (item is Api.Constant) {
+                       return ((Api.Constant)item).get_cname ();
+               } else if (item is Api.Property) {
+                       return ((Api.Property)item).get_cname ();
+               } else if (item is Api.Signal) {
+                       var name = ((Api.Signal)item).get_cname ();
+                       return name.replace ("_", "-");
+               } else if (item is Api.Class) {
+                       return ((Api.Class)item).get_cname ();
+               } else if (item is Api.Struct) {
+                       return ((Api.Struct)item).get_cname ();
+               } else if (item is Api.Interface) {
+                       return ((Api.Interface)item).get_cname ();
+               } else if (item is Api.ErrorDomain) {
+                       return ((Api.ErrorDomain)item).get_cname ();
+               } else if (item is Api.ErrorCode) {
+                       return ((Api.ErrorCode)item).get_cname ();
+               } else if (item is Api.Delegate) {
+                       return ((Api.Delegate)item).get_cname ();
+               } else if (item is Api.Enum) {
+                       return ((Api.Enum)item).get_cname ();
+               } else if (item is Api.EnumValue) {
+                       return ((Api.EnumValue)item).get_cname ();
+               }
+
+               return null;
+       }
+
+       public void write_docbook_link (Api.Item item) {
+               writer.set_wrap (false);
+
+               if (item is Api.Method) {
+                       writer.start_tag ("function")
+                               .text (((Api.Method)item).get_cname ())
+                               .end_tag ("function");
+               } else if (item is Api.FormalParameter) {
+                       writer.start_tag ("parameter").
+                               text (((Api.FormalParameter)item).name ?? "...")
+                               .end_tag ("parameter");
+               } else if (item is Api.Constant) {
+                       writer.start_tag ("constant").text (((Api.Constant)item)
+                               .get_cname ())
+                               .end_tag ("constant");
+               } else if (item is Api.Property) {
+                       // TODO: use docbook-tags instead
+                       writer.text ("#").text (get_cname(item.parent))
+                               .text (":")
+                               .text (((Api.Property)item)
+                               .get_cname ().replace ("_", "-"));
+               } else if (item is Api.Signal) {
+                       // TODO: use docbook-tags instead
+                       writer.text ("#").text (get_cname(item.parent))
+                               .text ("::")
+                               .text (((Api.Signal)item).get_cname ().replace ("_", "-"));
+               } else if (item is Api.Namespace) {
+                       writer.text (((Api.Namespace) item).get_full_name ());
+               } else {
+                       writer.start_tag ("type")
+                               .text (get_cname (item))
+                               .end_tag ("type");
+               }
+
+               writer.set_wrap (true);
+       }
+
+       public GtkdocRenderer () {
+       }
+
+       public override void render (ContentElement element) {
+               reset ();
+               element.accept (this);
+       }
+
+       public void render_symbol (Content.Comment? documentation) {
+               render (documentation);
+
+               append_exceptions (documentation.find_taglets (null, typeof(Taglets.Throws)));
+               append_see (documentation.find_taglets (null, typeof(Taglets.See)));
+               append_since (documentation.find_taglets (null, typeof(Taglets.Since)));
+       }
+
+       public override void render_children (ContentElement element) {
+               reset ();
+               element.accept_children (this);
+       }
+
+       private void reset () {
+               separated = false;
+               writer.reset ();
+       }
+
+       public unowned string content {
+               get {
+                       if (writer.content.has_prefix ("\n")) {
+                               return writer.content.next_char ();
+                       }
+
+                       return writer.content;
+               }
+       }
+
+       public override void visit_comment (Comment element) {
+               element.accept_children (this);
+       }
+
+       public override void visit_embedded (Embedded element) {
+               writer.start_tag ("figure");
+               if (element.caption != null) {
+                       writer.start_tag ("title")
+                               .text (element.caption)
+                               .end_tag ("title");
+               }
+
+               writer.start_tag ("mediaobject");
+
+               writer.start_tag ("imageobject")
+                       .simple_tag ("imagedata", {"fileref", element.url})
+                       .end_tag ("imageobject");
+
+               if (element.caption != null) {
+                       writer.start_tag ("textobject")
+                               .start_tag ("phrase")
+                               .text (element.caption)
+                               .end_tag ("phrase")
+                               .end_tag ("textobject");
+               }
+
+               writer.end_tag ("mediaobject");
+               writer.end_tag ("figure");
+       }
+
+       public override void visit_headline (Headline element) {
+               assert_not_reached ();
+       }
+
+       public override void visit_wiki_link (WikiLink element) {
+               // wiki pages are not supported by gir
+               if (element.content.size > 0) {
+                       element.accept_children (this);
+               } else {
+                       write_string (element.name);
+               }
+       }
+
+       public override void visit_link (Link element) {
+               writer.start_tag ("ulink", {"url", element.url});
+               element.accept_children (this);
+               writer.end_tag ("ulink");
+       }
+
+       public override void visit_symbol_link (SymbolLink element) {
+               if (element.content.size > 0) {
+                       writer.text ("\"");
+                       element.accept_children (this);
+                       writer.text ("\" (");
+                       visit_symbol_link (element);
+                       writer.text (")");
+               } else {
+                       visit_symbol_link (element);
+               }
+       }
+
+       public void write_symbol_link (SymbolLink element) {
+               if (element.symbol == null) {
+                       writer.text (element.given_symbol_name);
+               } else {
+                       write_docbook_link (element.symbol);
+               }
+       }
+
+       public override void visit_list (Content.List element) {
+               string tag = "orderedlist";
+               switch (element.bullet) {
+               case Content.List.Bullet.NONE:
+                       writer.start_tag ("itemizedlist", {"mark", "none"});
+                       tag = "itemizedlist";
+                       break;
+
+               case Content.List.Bullet.UNORDERED:
+                       writer.start_tag ("itemizedlist");
+                       tag = "itemizedlist";
+                       break;
+
+               case Content.List.Bullet.ORDERED:
+                       writer.start_tag ("orderedlist");
+                       break;
+
+               case Content.List.Bullet.ORDERED_NUMBER:
+                       writer.start_tag ("orderedlist", {"numeration", "arabic"});
+                       break;
+
+               case Content.List.Bullet.ORDERED_LOWER_CASE_ALPHA:
+                       writer.start_tag ("orderedlist", {"numeration", "loweralpha"});
+                       break;
+
+               case Content.List.Bullet.ORDERED_UPPER_CASE_ALPHA:
+                       writer.start_tag ("orderedlist", {"numeration", "upperalpha"});
+                       break;
+
+               case Content.List.Bullet.ORDERED_LOWER_CASE_ROMAN:
+                       writer.start_tag ("orderedlist", {"numeration", "lowerroman"});
+                       break;
+
+               case Content.List.Bullet.ORDERED_UPPER_CASE_ROMAN:
+                       writer.start_tag ("orderedlist", {"numeration", "upperroman"});
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+
+               element.accept_children (this);
+               
+               writer.end_tag (tag);
+       }
+
+       public override void visit_list_item (ListItem element) {
+               writer.start_tag ("listitem");
+               element.accept_children (this);
+               writer.end_tag ("listitem");
+       }
+
+       public override void visit_page (Page element) {
+               element.accept_children (this);
+       }
+
+       public override void visit_paragraph (Paragraph element) {
+               writer.start_tag ("para");
+               element.accept_children (this);
+               writer.end_tag ("para");
+       }
+
+       public override void visit_warning (Warning element) {
+               writer.start_tag ("warning");
+               element.accept_children (this);
+               writer.end_tag ("warning");
+       }
+
+       public override void visit_note (Note element) {
+               writer.start_tag ("note");
+               element.accept_children (this);
+               writer.end_tag ("note");
+       }
+
+       public override void visit_run (Run element) {
+               string? tag = null;
+
+               switch (element.style) {
+               case Run.Style.BOLD:
+                       writer.start_tag ("emphasis", {"role", "bold"});
+                       tag = "emphasis";
+                       break;
+
+               case Run.Style.ITALIC:
+                       writer.start_tag ("emphasis");
+                       tag = "emphasis";
+                       break;
+
+               case Run.Style.UNDERLINED:
+                       writer.start_tag ("emphasis", {"role", "underline"});
+                       tag = "emphasis";
+                       break;
+
+               case Run.Style.MONOSPACED:
+                       writer.start_tag ("blockquote");
+                       tag = "blockquote";
+                       break;
+               }
+
+               element.accept_children (this);
+
+               if (tag != null) {
+                       writer.end_tag (tag);
+               }
+       }
+
+       public override void visit_source_code (SourceCode element) {
+               writer.start_tag ("example")
+                       .start_tag ("programlisting");
+               writer.text (element.code);
+               writer.end_tag ("programlisting")
+                       .end_tag ("example");
+       }
+
+       public override void visit_table (Table element) {
+               writer.start_tag ("table", {"align", "center"});
+               element.accept_children (this);
+               writer.end_tag ("table");
+       }
+
+       public override void visit_table_cell (TableCell element) {
+               writer.start_tag ("td", {"colspan", element.colspan.to_string (), "rowspan", 
element.rowspan.to_string ()});
+               element.accept_children (this);
+               writer.end_tag ("td");
+       }
+
+       public override void visit_table_row (TableRow element) {
+               writer.start_tag ("tr");
+               element.accept_children (this);
+               writer.end_tag ("tr");
+       }
+
+       public override void visit_text (Text element) {
+               write_string (element.content);
+       }
+
+       private void write_string (string content) {
+               unichar chr = content[0];
+               long lpos = 0;
+               int i = 0;
+
+               for (i = 0; chr != '\0' ; i++, chr = content[i]) {
+                       switch (chr) {
+                       case '<':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&lt;");
+                               lpos = i+1;
+                               break;
+
+                       case '>':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&gt;");
+                               lpos = i+1;
+                               break;
+
+                       case '"':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&quot;");
+                               lpos = i+1;
+                               break;
+
+                       case '\'':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&apos;");
+                               lpos = i+1;
+                               break;
+
+                       case '&':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&amp;");
+                               lpos = i+1;
+                               break;
+
+                       case '#':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&num;");
+                               lpos = i+1;
+                               break;
+
+                       case '%':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&percnt;");
+                               lpos = i+1;
+                               break;
+
+                       case '@':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&commat;");
+                               lpos = i+1;
+                               break;
+
+                       case '(':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&lpar;");
+                               lpos = i+1;
+                               break;
+
+                       case ')':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.raw_text ("&rpar;");
+                               lpos = i+1;
+                               break;
+
+                       case '\n':
+                               writer.raw_text (content.substring (lpos, i-lpos));
+                               writer.simple_tag ("br");
+                               lpos = i+1;
+                               break;
+                       }
+               }
+
+               writer.raw_text (content.substring (lpos, i-lpos));
+       }
+
+       public void append_since (Vala.List<Content.Taglet> taglets) {
+               foreach (Content.Taglet _taglet in taglets) {
+                       Taglets.Since taglet = _taglet as Taglets.Since;
+                       if (taglet == null || taglet.version == null) {
+                               // ignore unexpected taglets
+                               continue ;
+                       }
+
+                       if (separated == false) {
+                               writer.text ("\n");
+                       }
+
+                       writer.set_wrap (false);
+                       writer.text ("\nSince: ")
+                               .text (taglet.version);
+                       writer.set_wrap (true);
+                       separated = true;
+
+                       // ignore multiple occurrences
+                       return ;
+               }
+       }
+
+       public void append_see (Vala.List<Content.Taglet> taglets) {
+               bool first = true;
+               foreach (Content.Taglet _taglet in taglets) {
+                       Taglets.See taglet = _taglet as Taglets.See;
+                       if (taglet == null || taglet.symbol == null) {
+                               // ignore unexpected taglets
+                               continue ;
+                       }
+
+                       if (first) {
+                               writer.start_tag ("para").text ("See also: ");
+                       } else {
+                               writer.text (", ");
+                       }
+
+                       write_docbook_link (taglet.symbol);
+                       first = false;
+               }
+
+               if (first == false) {
+                       writer.end_tag ("para");
+               }
+       }
+
+       public void append_exceptions (Vala.List<Content.Taglet> taglets) {
+               bool first = true;
+               foreach (Content.Taglet _taglet in taglets) {
+                       Taglets.Throws taglet = _taglet as Taglets.Throws;
+                       if (taglet == null || taglet.error_domain == null) {
+                               // ignore unexpected taglets
+                               continue ;
+                       }
+
+                       if (first) {
+                               writer.start_tag ("para")
+                                       .text ("This function may throw:")
+                                       .end_tag ("para");
+                               writer.start_tag ("table");
+                       }
+
+                       writer.start_tag ("tr");
+
+                       writer.start_tag ("td");
+                       write_docbook_link (taglet.error_domain);
+                       writer.end_tag ("td");
+
+                       writer.start_tag ("td");
+                       taglet.accept_children (this);
+                       writer.end_tag ("td");
+
+                       writer.end_tag ("tr");
+
+                       first = false;
+               }
+
+               if (first == false) {
+                       writer.end_tag ("table");
+               }
+       }
+}
+
diff --git a/libvaladoc/highlighter/codescanner.vala b/libvaladoc/highlighter/codescanner.vala
new file mode 100644
index 0000000..6d65c2e
--- /dev/null
+++ b/libvaladoc/highlighter/codescanner.vala
@@ -0,0 +1,572 @@
+/* codescanner.vala
+ *
+ * Copyright (C) 2015       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 GLib;
+
+
+/**
+ * A cheap scanner used to highlight C and Vala source code.
+ */
+public class Valadoc.Highlighter.CodeScanner : Object, Scanner {
+       private Vala.HashMap<string, CodeTokenType?> keywords;
+       private bool enable_string_templates;
+       private bool enabel_verbatim_string;
+       private bool enable_preprocessor_define;
+       private bool enable_preprocessor_include;
+       private bool enable_keyword_escape;
+
+
+       private Queue<CodeToken> token_queue = new Queue<CodeToken> ();
+       private unowned string content;
+       private unowned string pos;
+
+
+       public CodeScanner (string content, bool enable_string_templates, bool enabel_verbatim_string,
+               bool enable_preprocessor_define, bool enable_preprocessor_include, bool enable_keyword_escape,
+               Vala.HashMap<string, CodeTokenType?> keywords)
+       {
+               this.content = content;
+               this.pos = content;
+
+               this.enable_string_templates = enable_string_templates;
+               this.enabel_verbatim_string = enabel_verbatim_string;
+               this.enable_preprocessor_define = enable_preprocessor_define;
+               this.enable_preprocessor_include = enable_preprocessor_include;
+               this.enable_keyword_escape = enable_keyword_escape;
+
+               this.keywords = keywords;
+       }
+
+       public CodeToken next () {
+               if (!token_queue.is_empty ()) {
+                       return token_queue.pop_head ();
+               }
+
+
+               unowned string start;
+
+               for (start = pos; pos[0] != '\0'; pos = pos.next_char ()) {
+                       if (((char*) pos) == ((char*) content) || pos[0] == '\n') {
+                               unowned string line_start = pos;
+
+                               while (pos[0] == ' ' || pos[0] == '\t' || pos[0] == '\n') {
+                                       pos = pos.offset (1);
+                               }
+
+                               if (pos[0] == '\0') {
+                                       break;
+                               } else if (enable_preprocessor_include && pos.has_prefix ("#include")) {
+                                       unowned string end = pos;
+                                       if (queue_c_include ()) {
+                                               return dispatch (start, end);
+                                       } else {
+                                               pos = line_start;
+                                               continue;
+                                       }
+                               } else if (pos.has_prefix ("#if") || pos.has_prefix ("#else") || 
pos.has_prefix ("#elif") || pos.has_prefix ("#endif")
+                                       || (enable_preprocessor_define && (pos.has_prefix ("#defined") || 
pos.has_prefix ("#ifdef")))) {
+
+                                       unowned string end = pos;
+                                       queue_until ('\n', CodeTokenType.PREPROCESSOR);
+                                       return dispatch (start, end);
+                               }
+                       }
+
+                       if (pos[0] == '\'') {
+                               unowned string end = pos;
+                               queue_string_literal ("\'");
+                               return dispatch (start, end);
+                       }
+
+                       if (pos[0] == '"' || (enable_string_templates && pos[0] == '@' && pos[1] == '"')) {
+                               unowned string end = pos;
+                               if (enabel_verbatim_string && (pos.has_prefix ("\"\"\"") || 
(enable_string_templates && pos.has_prefix ("@\"\"\"")))) {
+                                       queue_string_literal ("\"\"\"");
+                               } else {
+                                       queue_string_literal ("\"");
+                               }
+                               return dispatch (start, end);
+                       }
+
+                       if (pos[0] >= '0' && pos[0] <= '9') {
+                               unowned string end = pos;
+                               queue_numeric_literal ();
+                               return dispatch (start, end);
+                       }
+
+                       if (pos.has_prefix ("/*")) {
+                               unowned string end = pos;
+                               queue_multiline_comment ();
+                               return dispatch (start, end);
+                       }
+
+                       if (pos.has_prefix ("//")) {
+                               unowned string end = pos;
+                               queue_until ('\n', CodeTokenType.COMMENT);
+                               return dispatch (start, end);
+                       }
+
+                       if ((((char*) pos) == ((char*) content) || !isidstartchar (pos[-1])) && isidstartchar 
(pos[0])) {
+                               unowned string end = pos;
+                               if (queue_keyword ()) {
+                                       return dispatch (start, end);
+                               } else {
+                                       continue;
+                               }
+                       }
+               }
+
+               token_queue.push_tail (new CodeToken (CodeTokenType.EOF, ""));
+               return dispatch (start, pos);
+       }
+
+       private bool queue_c_include () {
+               unowned string include_start = pos;
+               unowned string start = pos;
+               pos = pos.offset (8);
+
+               while (pos[0] == ' ' || pos[0] == '\t') {
+                       pos = pos.offset (1);
+               }
+
+               char? end_char = null;
+               if (pos[0] == '"') {
+                       end_char = '"';
+               } else if (pos[0] == '<') {
+                       end_char = '>';
+               }
+
+               if (end_char != null) {
+                       queue_token (start, pos, CodeTokenType.PREPROCESSOR);
+
+                       unowned string literal_start = pos;
+                       pos = pos.offset (1);
+
+                       while (pos[0] != end_char && pos[0] != '\n' && pos[0] != '\0') {
+                               pos = pos.offset (1);
+                       }
+
+                       if (pos[0] == end_char) {
+                               pos = pos.offset (1);
+
+                               queue_token (literal_start, pos, CodeTokenType.LITERAL);
+                               start = pos;
+                       } else {
+                               pos = include_start;
+                               token_queue.clear ();
+                               return false;
+                       }
+               }
+
+               while (pos[0] == ' ' || pos[0] == '\t') {
+                       pos = pos.offset (1);
+               }
+
+               if (pos[0] == '\n' || pos[0] == '\0') {
+                       queue_token (start, pos, CodeTokenType.PREPROCESSOR);
+                       return true;
+               } else {
+                       pos = include_start;
+                       token_queue.clear ();
+                       return false;
+               }
+       }
+
+       private bool queue_keyword () {
+               unowned string start = pos;
+               if (pos[0] == '@') {
+                       pos = pos.offset (1);
+               }
+               while (isidchar (pos[0])) {
+                       pos = pos.offset (1);
+               }
+
+               long length = start.pointer_to_offset (pos);
+               string word = start.substring (0, length);
+               CodeTokenType? token_type = keywords.get (word);
+               if (token_type == null) {
+                       pos = start;
+                       return false;
+               }
+
+               token_queue.push_tail (new CodeToken (token_type, word));
+               return true;
+       }
+
+       private void queue_multiline_comment () {
+               unowned string start = pos;
+               pos = pos.offset (2);
+
+               while (!(pos[0] == '*' && pos[1] == '/') && pos[0] != '\0') {
+                       pos = pos.offset (1);
+               }
+
+               if (pos[0] != '\0') {
+                       pos = pos.offset (2);
+               }
+
+               queue_token (start, pos, CodeTokenType.COMMENT);
+       }
+
+       private void queue_until (char end_char, CodeTokenType token_type) {
+               unowned string start = pos;
+               pos = pos.offset (1);
+
+               while (pos[0] != end_char && pos[0] != '\0') {
+                       pos = pos.offset (1);
+               }
+
+               if (pos[0] != '\0' && pos[0] != '\n') {
+                       pos = pos.offset (1);
+               }
+
+               queue_token (start, pos, token_type);
+       }
+
+       private void queue_string_literal (string end_chars) {
+               unowned string start = pos;
+               bool is_template = false;
+
+               if (pos[0] == '@') {
+                       pos = pos.offset (end_chars.length + 1);
+                       is_template = true;
+               } else {
+                       pos = pos.offset (end_chars.length);
+               }
+
+               while (!pos.has_prefix (end_chars) && pos[0] != '\0') {
+                       long skip = 0;
+
+                       if ((pos[0] == '%' && has_printf_format_prefix (out skip))
+                               || (pos[0] == '\\' && has_escape_prefix (out skip))
+                               || (is_template && pos[0] == '$' && has_template_literal_prefix (out skip)))
+                       {
+                               queue_token (start, pos, CodeTokenType.LITERAL);
+
+                               unowned string sub_start = pos;
+                               pos = pos.offset (skip);
+                               queue_token (sub_start, pos, CodeTokenType.ESCAPE);
+                               start = pos;
+                       } else {
+                               pos = pos.offset (1);
+                       }
+               }
+
+               if (pos[0] != '\0') {
+                       pos = pos.offset (end_chars.length);
+               }
+
+               queue_token (start, pos, CodeTokenType.LITERAL);
+       }
+
+       private bool has_template_literal_prefix (out long skip) {
+               if (isidchar (pos[1])) {
+                       skip = 1;
+                       while (isidchar (pos[skip])) {
+                               skip++;
+                       }
+                       return true;
+               }
+
+               if (pos[1] == '(') {
+                       int level = 1;
+                       skip = 2;
+
+                       while (level > 0) {
+                               switch (pos[skip]) {
+                               case '(':
+                                       level++;
+                                       break;
+                               case ')':
+                                       level--;
+                                       break;
+                               case '\0':
+                                       skip = 0;
+                                       return false;
+                               }
+                               skip++;
+                       }
+                       return true;
+               }
+
+               skip = 0;
+               return false;
+       }
+
+       private bool has_escape_prefix (out long skip) {
+               switch (pos[1]) {
+               case 'a':
+               case 'b':
+               case 'f':
+               case 'n':
+               case 'r':
+               case 't':
+               case 'v':
+               case '\\':
+               case '\'':
+               case '\"':
+               case '?':
+                       skip = 2;
+                       return true;
+
+               case 'x':
+                       if (pos[2].isxdigit ()) {
+                               for (skip = 2; pos[skip].isxdigit (); skip++) {
+                                       skip++;
+                               }
+
+                               skip++;
+                               return true;
+                       }
+
+                       skip = 0;
+                       return false;
+
+               default:
+                       if (pos[1].isdigit ()) {
+                               skip = 2;
+
+                               if (pos[2].isdigit ()) {
+                                       skip++;
+
+                                       if (pos[3].isdigit ()) {
+                                               skip++;
+                                       }
+                               }
+
+                               return true;
+                       }
+
+                       skip = 0;
+                       return false;
+               }
+       }
+
+       private bool has_printf_format_prefix (out long skip) {
+               // %[flag][min width][precision][length modifier][conversion specifier]
+               unowned string pos = this.pos;
+               unowned string start = pos;
+
+               // '%'
+               pos = pos.offset (1);
+
+               if (pos[0] == '%') {
+                       pos = pos.offset (1);
+                       skip = 2;
+                       return true;
+               }
+
+
+               // flags:
+               while ("#0+- ".index_of_char (pos[0]) > 0) {
+                       pos = pos.offset (1);
+               }
+
+               // min width:
+               while (pos[0].isdigit ()) {
+                       pos = pos.offset (1);
+               }
+
+               // precision
+               if (pos[0] == '.' && pos[1].isdigit ()) {
+                       pos = pos.offset (2);
+                       while (pos[0].isdigit ()) {
+                               pos = pos.offset (1);
+                       }
+               }
+
+               // length:
+               switch (pos[0]) {
+               case 'h':
+                       pos = pos.offset (1);
+                       if (pos[0] == 'h') {
+                               pos = pos.offset (1);
+                       }
+                       break;
+
+               case 'l':
+                       pos = pos.offset (1);
+                       if (pos[0] == 'l') {
+                               pos = pos.offset (1);
+                       }
+                       break;
+
+               case 'j':
+               case 'z':
+               case 't':
+               case 'L':
+                       pos = pos.offset (1);
+                       break;
+               }
+
+               // conversion specifier:
+               switch (pos[0]) {
+               case 'd':
+               case 'i':
+               case 'u':
+               case 'o':
+               case 'x':
+               case 'X':
+               case 'f':
+               case 'F':
+               case 'e':
+               case 'E':
+               case 'g':
+               case 'G':
+               case 'a':
+               case 'A':
+               case 'c':
+               case 's':
+               case 'p':
+               case 'n':
+                       pos = pos.offset (1);
+                       break;
+
+               default:
+                       skip = 0;
+                       return false;
+               }
+
+               skip = start.pointer_to_offset (pos);
+               return true;
+       }
+
+       private enum NumericType {
+               INTEGER,
+               REAL,
+               NONE
+       }
+
+       // based on libvala
+       private void queue_numeric_literal () {
+               NumericType numeric_type = NumericType.INTEGER;
+               unowned string start = pos;
+
+
+               // integer part
+               if (pos[0] == '0' && pos[1] == 'x' && pos[2].isxdigit ()) {
+                       // hexadecimal integer literal
+                       pos = pos.offset (2);
+                       while (pos[0].isxdigit ()) {
+                               pos = pos.offset (1);
+                       }
+               } else {
+                       // decimal number
+                       while (pos[0].isdigit ()) {
+                               pos = pos.offset (1);
+                       }
+               }
+
+
+               // fractional part
+               if (pos[0] == '.' && pos[1].isdigit ()) {
+                       numeric_type = NumericType.REAL;
+                       pos = pos.offset (1);
+                       while (pos[0].isdigit ()) {
+                               pos = pos.offset (1);
+                       }
+               }
+
+
+               // exponent part
+               if (pos[0] == 'e' || pos[0] == 'E') {
+                       numeric_type = NumericType.REAL;
+                       pos = pos.offset (1);
+                       if (pos[0] == '+' || pos[0] == '-') {
+                               pos = pos.offset (1);
+                       }
+                       while (pos[0].isdigit ()) {
+                               pos = pos.offset (1);
+                       }
+               }
+
+
+               // type suffix
+               switch (pos[0]) {
+               case 'l':
+               case 'L':
+                       if (numeric_type == NumericType.INTEGER) {
+                               pos = pos.offset (1);
+                               if (pos[0] == 'l' || pos[0] == 'L') {
+                                       pos = pos.offset (1);
+                               }
+                       }
+                       break;
+
+               case 'u':
+               case 'U':
+                       if (numeric_type == NumericType.INTEGER) {
+                               pos = pos.offset (1);
+                               if (pos[0] == 'l' || pos[0] == 'L') {
+                                       pos = pos.offset (1);
+                                       if (pos[0] == 'l' || pos[0] == 'L') {
+                                               pos = pos.offset (1);
+                                       }
+                               }
+                       }
+                       break;
+
+               case 'f':
+               case 'F':
+               case 'd':
+               case 'D':
+                       numeric_type = NumericType.REAL;
+                       pos = pos.offset (1);
+                       break;
+               }
+
+               if (pos[0].isalnum ()) {
+                       numeric_type = NumericType.NONE;
+               }
+
+               queue_token (start, pos, (numeric_type != NumericType.NONE)
+                       ? CodeTokenType.LITERAL
+                       : CodeTokenType.PLAIN);
+       }
+
+       private CodeToken dispatch (string start, string end) {
+               assert (token_queue.is_empty () == false);
+
+               if (((char*) start) == ((char*) end)) {
+                       return token_queue.pop_head ();
+               }
+
+               long length = start.pointer_to_offset (end);
+               string content = start.substring (0, length);
+               return new CodeToken (CodeTokenType.PLAIN, content);
+       }
+
+       private void queue_token (string start, string end, CodeTokenType token_type) {
+               long length = start.pointer_to_offset (end);
+               string content = start.substring (0, length);
+               token_queue.push_tail (new CodeToken (token_type, content));
+       }
+
+       private inline bool isidchar (char c) {
+               return c.isalnum () || c == '_';
+       }
+
+       private inline bool isidstartchar (char c) {
+               return c.isalnum () || c == '_' || (c == '@' && enable_keyword_escape);
+       }
+}
+
diff --git a/libvaladoc/highlighter/codetoken.vala b/libvaladoc/highlighter/codetoken.vala
new file mode 100644
index 0000000..1a02195
--- /dev/null
+++ b/libvaladoc/highlighter/codetoken.vala
@@ -0,0 +1,58 @@
+/* codetoken.vala
+ *
+ * Copyright (C) 2015       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>
+ */
+
+
+public class Valadoc.Highlighter.CodeToken {
+       public CodeTokenType token_type { get; private set; }
+       public string content { get; private set;}
+
+       public CodeToken (CodeTokenType type, string content) {
+               this.token_type = type;
+               this.content = content;
+       }
+}
+
+
+public enum Valadoc.Highlighter.CodeTokenType {
+       XML_ESCAPE,
+       XML_ELEMENT,
+       XML_ATTRIBUTE,
+       XML_ATTRIBUTE_VALUE,
+       XML_COMMENT,
+       XML_CDATA,
+
+       PREPROCESSOR,
+       COMMENT,
+       KEYWORD,
+       LITERAL,
+       ESCAPE,
+       PLAIN,
+       TYPE,
+       EOF;
+
+       public unowned string to_string () {
+        EnumClass enumc = (EnumClass) typeof (CodeTokenType).class_ref ();
+        unowned EnumValue? eval = enumc.get_value (this);
+        return_val_if_fail (eval != null, null);
+        return eval.value_nick;
+       }
+}
diff --git a/libvaladoc/highlighter/highlighter.vala b/libvaladoc/highlighter/highlighter.vala
new file mode 100644
index 0000000..5eace1c
--- /dev/null
+++ b/libvaladoc/highlighter/highlighter.vala
@@ -0,0 +1,366 @@
+/* codehighlighter.vala
+ *
+ * Copyright (C) 2015       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 GLib;
+using Valadoc.Content;
+
+
+public class Valadoc.Highlighter.Highlighter : Object {
+       private Vala.HashMap<string, CodeTokenType?> vala_keywords;
+       private Vala.HashMap<string, CodeTokenType?> c_keywords;
+
+
+       /**
+        * Used to highlight vala source code.
+        */
+       public Run highlight_vala (string source_code) {
+               if (vala_keywords == null) {
+                       vala_keywords = new Vala.HashMap<string, CodeTokenType?> (str_hash, str_equal);
+
+                       // ** Types: **
+                       vala_keywords.set ("string", CodeTokenType.TYPE);
+                       vala_keywords.set ("bool", CodeTokenType.TYPE);
+                       vala_keywords.set ("void", CodeTokenType.TYPE);
+
+                       vala_keywords.set ("double", CodeTokenType.TYPE);
+                       vala_keywords.set ("float", CodeTokenType.TYPE);
+
+                       vala_keywords.set ("char", CodeTokenType.TYPE);
+                       vala_keywords.set ("uchar", CodeTokenType.TYPE);
+                       vala_keywords.set ("unichar", CodeTokenType.TYPE);
+
+                       vala_keywords.set ("short", CodeTokenType.TYPE);
+                       vala_keywords.set ("ushort", CodeTokenType.TYPE);
+
+                       vala_keywords.set ("long", CodeTokenType.TYPE);
+                       vala_keywords.set ("ulong", CodeTokenType.TYPE);
+
+                       vala_keywords.set ("size_t", CodeTokenType.TYPE);
+                       vala_keywords.set ("ssize_t", CodeTokenType.TYPE);
+
+                       vala_keywords.set ("int", CodeTokenType.TYPE);
+                       vala_keywords.set ("int8", CodeTokenType.TYPE);
+                       vala_keywords.set ("int16", CodeTokenType.TYPE);
+                       vala_keywords.set ("int32", CodeTokenType.TYPE);
+                       vala_keywords.set ("int64", CodeTokenType.TYPE);
+
+                       vala_keywords.set ("uint", CodeTokenType.TYPE);
+                       vala_keywords.set ("uint8", CodeTokenType.TYPE);
+                       vala_keywords.set ("uint16", CodeTokenType.TYPE);
+                       vala_keywords.set ("uint32", CodeTokenType.TYPE);
+                       vala_keywords.set ("uint64", CodeTokenType.TYPE);
+
+
+                       // ** Literals: **
+                       vala_keywords.set ("null", CodeTokenType.LITERAL);
+                       vala_keywords.set ("true", CodeTokenType.LITERAL);
+                       vala_keywords.set ("false", CodeTokenType.LITERAL);
+
+
+                       // ** Keywords: **
+                       vala_keywords.set ("return", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("lock", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("var", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("yield", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("global", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("construct", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("value", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("get", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("set", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("owned", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("unowned", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("const", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("weak", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("dynamic", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("out", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("ref", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("break", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("continue", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("return", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("if", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("else", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("switch", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("case", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("default", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("do", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("while", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("for", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("foreach", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("in", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("try", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("catch", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("finally", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("throw", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("class", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("interface", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("struct", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("enum", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("delegate", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("errordomain", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("abstract", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("virtual", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("override", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("signal", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("extern", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("static", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("async", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("inline", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("new", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("public", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("private", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("protected", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("internal", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("throws", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("requires", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("ensures", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("assert", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("namespace", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("using", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("as", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("is", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("in", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("new", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("delete", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("sizeof", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("typeof", CodeTokenType.KEYWORD);
+
+                       vala_keywords.set ("this", CodeTokenType.KEYWORD);
+                       vala_keywords.set ("base", CodeTokenType.KEYWORD);
+               }
+
+               bool enable_string_templates = true;
+               bool enable_preprocessor_define = false;
+               bool enable_preprocessor_include = false;
+               bool enable_keyword_escape = true;
+               bool enabel_verbatim_string = true;
+
+               CodeScanner scanner = new CodeScanner (source_code, enable_string_templates, 
enabel_verbatim_string,
+                       enable_preprocessor_define, enable_preprocessor_include, enable_keyword_escape,
+                       vala_keywords);
+
+               return highlight_code (scanner);
+       }
+
+       /**
+        * Used to highlight C source code.
+        */
+       public Run highlight_c (string source_code) {
+               if (c_keywords == null) {
+                       c_keywords = new Vala.HashMap<string, CodeTokenType?> (str_hash, str_equal);
+
+                       // ** Types: **
+                       c_keywords.set ("auto", CodeTokenType.TYPE);
+                       c_keywords.set ("char", CodeTokenType.TYPE);
+                       c_keywords.set ("const", CodeTokenType.TYPE);
+                       c_keywords.set ("double", CodeTokenType.TYPE);
+                       c_keywords.set ("extern", CodeTokenType.TYPE);
+                       c_keywords.set ("int", CodeTokenType.TYPE);
+                       c_keywords.set ("float", CodeTokenType.TYPE);
+                       c_keywords.set ("long", CodeTokenType.TYPE);
+                       c_keywords.set ("register", CodeTokenType.TYPE);
+                       c_keywords.set ("short", CodeTokenType.TYPE);
+                       c_keywords.set ("signed", CodeTokenType.TYPE);
+                       c_keywords.set ("static", CodeTokenType.TYPE);
+                       c_keywords.set ("unsigned", CodeTokenType.TYPE);
+                       c_keywords.set ("void", CodeTokenType.TYPE);
+                       c_keywords.set ("volatile", CodeTokenType.TYPE);
+
+                       c_keywords.set ("gboolean", CodeTokenType.TYPE);
+                       c_keywords.set ("gpointer", CodeTokenType.TYPE);
+                       c_keywords.set ("gconstpointer", CodeTokenType.TYPE);
+                       c_keywords.set ("gchar", CodeTokenType.TYPE);
+                       c_keywords.set ("guchar", CodeTokenType.TYPE);
+                       c_keywords.set ("gint", CodeTokenType.TYPE);
+                       c_keywords.set ("guint", CodeTokenType.TYPE);
+                       c_keywords.set ("gshort", CodeTokenType.TYPE);
+                       c_keywords.set ("gushort", CodeTokenType.TYPE);
+                       c_keywords.set ("glong", CodeTokenType.TYPE);
+                       c_keywords.set ("gulong", CodeTokenType.TYPE);
+                       c_keywords.set ("gint8", CodeTokenType.TYPE);
+                       c_keywords.set ("guint8", CodeTokenType.TYPE);
+                       c_keywords.set ("gint16", CodeTokenType.TYPE);
+                       c_keywords.set ("guint16", CodeTokenType.TYPE);
+                       c_keywords.set ("gint32", CodeTokenType.TYPE);
+                       c_keywords.set ("guint32", CodeTokenType.TYPE);
+                       c_keywords.set ("gint64", CodeTokenType.TYPE);
+                       c_keywords.set ("guint64", CodeTokenType.TYPE);
+                       c_keywords.set ("gfloat", CodeTokenType.TYPE);
+                       c_keywords.set ("gdouble", CodeTokenType.TYPE);
+                       c_keywords.set ("gsize", CodeTokenType.TYPE);
+                       c_keywords.set ("gssize", CodeTokenType.TYPE);
+                       c_keywords.set ("goffset", CodeTokenType.TYPE);
+                       c_keywords.set ("gintptr", CodeTokenType.TYPE);
+                       c_keywords.set ("guintptr", CodeTokenType.TYPE);
+
+
+                       // ** Literals: **
+                       c_keywords.set ("NULL", CodeTokenType.LITERAL);
+                       c_keywords.set ("TRUE", CodeTokenType.LITERAL);
+                       c_keywords.set ("FALSE", CodeTokenType.LITERAL);
+
+
+                       // ** Keywords: **
+                       c_keywords.set ("break", CodeTokenType.KEYWORD);
+                       c_keywords.set ("case", CodeTokenType.KEYWORD);
+                       c_keywords.set ("continue", CodeTokenType.KEYWORD);
+                       c_keywords.set ("default", CodeTokenType.KEYWORD);
+                       c_keywords.set ("do", CodeTokenType.KEYWORD);
+                       c_keywords.set ("else", CodeTokenType.KEYWORD);
+                       c_keywords.set ("enum", CodeTokenType.KEYWORD);
+                       c_keywords.set ("for", CodeTokenType.KEYWORD);
+                       c_keywords.set ("goto", CodeTokenType.KEYWORD);
+                       c_keywords.set ("if", CodeTokenType.KEYWORD);
+                       c_keywords.set ("return", CodeTokenType.KEYWORD);
+                       c_keywords.set ("sizeof", CodeTokenType.KEYWORD);
+                       c_keywords.set ("struct", CodeTokenType.KEYWORD);
+                       c_keywords.set ("switch", CodeTokenType.KEYWORD);
+                       c_keywords.set ("typedef", CodeTokenType.KEYWORD);
+                       c_keywords.set ("union", CodeTokenType.KEYWORD);
+                       c_keywords.set ("while", CodeTokenType.KEYWORD);
+                       c_keywords.set ("assert", CodeTokenType.KEYWORD);
+               }
+
+               bool enable_string_templates = false;
+               bool enable_preprocessor_define = true;
+               bool enable_preprocessor_include = true;
+               bool enable_keyword_escape = false;
+               bool enabel_verbatim_string = false;
+
+               CodeScanner scanner = new CodeScanner (source_code, enable_string_templates, 
enabel_verbatim_string,
+                       enable_preprocessor_define, enable_preprocessor_include, enable_keyword_escape,
+                       c_keywords);
+
+               return highlight_code (scanner);
+       }
+
+       /**
+        * Used to highlight C source code.
+        */
+       public Run highlight_xml (string source_code) {
+               XmlScanner scanner = new XmlScanner (source_code);
+               return highlight_code (scanner);
+       }
+
+       /**
+        * Used to highlight source code.
+        */
+       private Run highlight_code (Scanner scanner) {
+               Run code = new Run (Run.Style.MONOSPACED);
+
+               for (CodeToken token = scanner.next (); token.token_type != CodeTokenType.EOF; token = 
scanner.next ()) {
+                       switch (token.token_type) {
+                       case CodeTokenType.PREPROCESSOR:
+                               Run run = new Run (Run.Style.LANG_PREPROCESSOR);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.COMMENT:
+                               Run run = new Run (Run.Style.LANG_COMMENT);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.KEYWORD:
+                               Run run = new Run (Run.Style.LANG_KEYWORD);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.LITERAL:
+                               Run run = new Run (Run.Style.LANG_LITERAL);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.TYPE:
+                               Run run = new Run (Run.Style.LANG_BASIC_TYPE);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.ESCAPE:
+                               Run run = new Run (Run.Style.LANG_ESCAPE);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.XML_ESCAPE:
+                               Run run = new Run (Run.Style.XML_ESCAPE);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.XML_ELEMENT:
+                               Run run = new Run (Run.Style.XML_ELEMENT);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.XML_ATTRIBUTE:
+                               Run run = new Run (Run.Style.XML_ATTRIBUTE);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.XML_ATTRIBUTE_VALUE:
+                               Run run = new Run (Run.Style.XML_ATTRIBUTE_VALUE);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.XML_COMMENT:
+                               Run run = new Run (Run.Style.XML_COMMENT);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       case CodeTokenType.XML_CDATA:
+                               Run run = new Run (Run.Style.XML_CDATA);
+                               run.content.add (new Text (token.content));
+                               code.content.add (run);
+                               break;
+
+                       default:
+                               code.content.add (new Text (token.content));
+                               break;
+                       }
+               }
+
+               return code;
+       }
+}
+
+
diff --git a/libvaladoc/highlighter/scanner.vala b/libvaladoc/highlighter/scanner.vala
new file mode 100644
index 0000000..20eedcf
--- /dev/null
+++ b/libvaladoc/highlighter/scanner.vala
@@ -0,0 +1,32 @@
+/* scanner.vala
+ *
+ * Copyright (C) 2015       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 GLib;
+
+
+/**
+ * Scanner interface used to highlight source code.
+ */
+public interface Valadoc.Highlighter.Scanner : Object {
+
+       public abstract CodeToken next ();
+}
diff --git a/libvaladoc/highlighter/xmlscanner.vala b/libvaladoc/highlighter/xmlscanner.vala
new file mode 100644
index 0000000..38b87c5
--- /dev/null
+++ b/libvaladoc/highlighter/xmlscanner.vala
@@ -0,0 +1,374 @@
+/* xmlscanner.vala
+ *
+ * Copyright (C) 2015       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 GLib;
+
+
+/**
+ * A cheap scanner used to highlight XML.
+ */
+public class Valadoc.Highlighter.XmlScanner : Object, Scanner {
+       private Queue<CodeToken> token_queue = new Queue<CodeToken> ();
+       private unowned string content;
+       private unowned string pos;
+
+
+       public XmlScanner (string content) {
+               this.content = content;
+               this.pos = content;
+       }
+
+       public CodeToken next () {
+               if (!token_queue.is_empty ()) {
+                       return token_queue.pop_head ();
+               }
+
+               unowned string start;
+
+               for (start = pos; pos[0] != '\0'; pos = pos.next_char ()) {
+                       if (pos[0] == '&') {
+                               unowned string begin = pos;
+                               if (queue_escape ()) {
+                                       return dispatch (start, begin);
+                               }
+                       } else if (pos[0] == '<') {
+                               if (pos[1] == '/') {
+                                       unowned string end = pos;
+                                       if (queue_end_element ()) {
+                                               return dispatch (start, end);
+                                       }
+                               } else if (pos[1] == '!' && pos[2] == '-' && pos[3] == '-') {
+                                       unowned string end = pos;
+                                       if (queue_comment ()) {
+                                               return dispatch (start, end);
+                                       }
+                               } else if (pos[1] == '!' && pos[2] == '[' && pos[3] == 'C' && pos[4] == 'D' 
&& pos[5] == 'A' && pos[6] == 'T' && pos[7] == 'A' && pos[8] == '[') {
+                                       unowned string end = pos;
+                                       pos = pos.offset (9);
+                                       token_queue.push_tail (new CodeToken (CodeTokenType.XML_CDATA, 
"<![CDATA["));
+                                       return dispatch (start, end);
+                               } else {
+                                       unowned string end = pos;
+                                       if (queue_start_element (start, pos[1] == '?')) {
+                                               return dispatch (start, end);
+                                       } else {
+                                               continue;
+                                       }
+                               }
+                       } else if (pos[0] == ']' && pos[1] == ']' && pos[2] == '>') {
+                               unowned string end = pos;
+                               pos = pos.offset (3);
+                               token_queue.push_tail (new CodeToken (CodeTokenType.XML_CDATA, "]]>"));
+                               return dispatch (start, end);
+                       }
+               }
+
+               token_queue.push_tail (new CodeToken (CodeTokenType.EOF, ""));
+               return dispatch (start, pos);
+       }
+
+       private bool queue_start_element (string dispatch_start, bool xml_decl) {
+               assert (token_queue.is_empty ());
+
+               unowned string element_start = pos;
+               if (xml_decl) {
+                       pos = pos.offset (2);
+               } else {
+                       pos = pos.offset (1);
+               }
+
+               skip_optional_spaces (ref pos);
+
+               if (skip_id (ref pos) == false) {
+                       token_queue.clear ();
+                       pos = element_start;
+                       return false;
+               }
+
+               skip_optional_spaces (ref pos);
+
+               queue_token (element_start, pos, CodeTokenType.XML_ELEMENT);
+
+               if (queue_attributes () == false) {
+                       token_queue.clear ();
+                       pos = element_start;
+                       return false;
+               }
+
+               unowned string element_end_start = pos;
+
+               if (!xml_decl && pos[0] == '>') {
+                       pos = pos.offset (1);
+               } else if (!xml_decl && pos[0] == '/' && pos[1] == '>') {
+                       pos = pos.offset (2);
+               } else if (xml_decl && pos[0] == '?' && pos[1] == '>') {
+                       pos = pos.offset (2);
+               } else {
+                       token_queue.clear ();
+                       pos = element_start;
+                       return false;
+               }
+
+               queue_token (element_end_start, pos, CodeTokenType.XML_ELEMENT);
+               return true;
+       }
+
+       private bool queue_attributes () {
+               while (is_id_char (pos[0])) {
+                       unowned string begin = pos;
+
+                       if (skip_id (ref pos) == false) {
+                               return false;
+                       }
+
+                       skip_optional_spaces (ref pos);
+
+                       if (pos[0] == '=') {
+                               pos = pos.offset (1);
+                       } else {
+                               return false;
+                       }
+
+                       skip_optional_spaces (ref pos);
+
+                       queue_token (begin, pos, CodeTokenType.XML_ATTRIBUTE);
+                       begin = pos;
+
+                       if (pos[0] == '"') {
+                               pos = pos.offset (1);
+                       } else {
+                               return false;
+                       }
+
+                       while (pos[0] != '"' && pos[0] != '\0') {
+                               pos = pos.offset (1);
+                       }
+
+                       if (pos[0] == '"') {
+                               pos = pos.offset (1);
+                       } else {
+                               return false;
+                       }
+
+                       skip_optional_spaces (ref pos);
+
+                       queue_token (begin, pos, CodeTokenType.XML_ATTRIBUTE_VALUE);
+               }
+
+               return true;
+       }
+
+       private bool queue_end_element () {
+               unowned string start = pos;
+               pos = pos.offset (2);
+
+               skip_optional_spaces (ref pos);
+
+               if (skip_id (ref pos) == false) {
+                       pos = start;
+                       return false;
+               }
+
+               skip_optional_spaces (ref pos);
+
+               if (pos[0] == '>') {
+                       pos = pos.offset (1);
+               } else {
+                       pos = start;
+                       return false;
+               }
+
+               queue_token (start, pos, CodeTokenType.XML_ELEMENT);
+               return true;
+       }
+
+       private bool queue_escape () {
+               unowned string start = pos;
+               pos = pos.offset (1);
+
+               if (skip_id (ref pos) == false) {
+                       pos = start;
+                       return false;
+               }
+
+               if (pos[0] == ';') {
+                       pos = pos.offset (1);
+               } else {
+                       pos = start;
+                       return false;
+               }
+
+               queue_token (start, pos, CodeTokenType.XML_ESCAPE);
+               return true;
+       }
+
+       private bool queue_comment () {
+               unowned string start = pos;
+               pos = pos.offset (4);
+
+               while (pos[0] != '>' && pos[0] != '\0') {
+                       pos = pos.offset (1);
+               }
+
+               if (pos[0] == '>') {
+                       pos = pos.offset (1);
+               } else {
+                       pos = start;
+                       return false;
+               }
+
+               queue_token (start, pos, CodeTokenType.XML_COMMENT);
+               return true;
+       }
+
+       private static bool skip_id (ref unowned string pos) {
+               bool has_next_segment = true;
+               bool has_id = false;
+
+               while (has_next_segment) {
+                       has_id = false;
+
+                       while (is_id_char (pos[0])) {
+                               pos = pos.offset (1);
+                               has_id = true;
+                       }
+
+                       if (pos[0] == ':' && has_id) {
+                               has_next_segment = true;
+                               pos = pos.offset (1);
+                       } else {
+                               has_next_segment = false;
+                       }
+               }
+
+               return has_id;
+       }
+
+       private static bool skip_optional_spaces (ref unowned string pos) {
+               bool skipped = false;
+
+               while (pos[0].isspace ()) {
+                       pos = pos.offset (1);
+                       skipped = true;
+               }
+               
+               return skipped;
+       }
+
+       private CodeToken dispatch (string start, string end) {
+               assert (token_queue.is_empty () == false);
+
+               if (((char*) start) == ((char*) end)) {
+                       return token_queue.pop_head ();
+               }
+
+               long length = start.pointer_to_offset (end);
+               string content = start.substring (0, length);
+               return new CodeToken (CodeTokenType.PLAIN, content);
+       }
+
+       private void queue_token (string start, string end, CodeTokenType token_type) {
+               long length = start.pointer_to_offset (end);
+               string content = start.substring (0, length);
+               token_queue.push_tail (new CodeToken (token_type, content));
+       }
+
+       private static inline bool is_id_char (char c) {
+               return c.isalnum () || c == '_' || c == '-';
+       }
+
+       internal static bool is_xml (string source) {
+               unowned string pos = source;
+
+               skip_optional_spaces (ref pos);
+
+               if (pos[0] == '<') {
+                       // Comment:
+                       if (pos.has_prefix ("<!--")) {
+                               return true;
+                       }
+       
+                       // CDATA:
+                       if (pos.has_prefix ("<![CDATA[")) {
+                               return true;
+                       }
+
+
+                       // Start Tag:
+                       bool proc_instr = false;
+                       pos = pos.offset (1);
+
+                       if (pos[0] == '?') {
+                               pos = pos.offset (1);
+                               proc_instr = true;
+                       }
+
+                       // ID:
+                       if (skip_id (ref pos) == false) {
+                               return false;
+                       }
+
+                       skip_optional_spaces (ref pos);
+
+                       while (skip_id (ref pos)) {
+                               if (pos[0] == '=') {
+                                       pos = pos.offset (1);
+                               } else {
+                                       return false;
+                               }
+
+                               skip_optional_spaces (ref pos);
+
+                               if (pos[0] == '"') {
+                                       pos = pos.offset (1);
+                               } else {
+                                       return false;
+                               }
+
+                               while (pos[0] != '\0' && pos[0] != '\n' && pos[0] != '"') {
+                                       pos = pos.offset (1);
+                               }
+
+                               if (pos[0] == '"') {
+                                       pos = pos.offset (1);
+                               } else {
+                                       return false;
+                               }
+
+                               skip_optional_spaces (ref pos);
+                       }
+
+                       if (proc_instr && pos[0] == '?' && pos[1] == '>') {
+                               return true;
+                       }
+
+                       if (!proc_instr && (pos[0] == '>' || (pos[0] == '/' && pos[1] == '>'))) {
+                               return true;
+                       }
+
+                       return false;
+               } else {
+                       return false;
+               }
+       }
+}
+
diff --git a/libvaladoc/html/basicdoclet.vala b/libvaladoc/html/basicdoclet.vala
new file mode 100644
index 0000000..cc9ea4e
--- /dev/null
+++ b/libvaladoc/html/basicdoclet.vala
@@ -0,0 +1,1159 @@
+/* basicdoclet.vala
+ *
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+using Valadoc.Content;
+using Valadoc.Api;
+
+
+
+public abstract class Valadoc.Html.BasicDoclet : Api.Visitor, Doclet {
+       public Html.LinkHelper linker {
+               protected set;
+               get;
+       }
+
+       public Settings settings {
+               protected set;
+               get;
+       }
+
+       public string wiki_index_name {
+               default = "index.valadoc";
+               protected set;
+               get;
+       }
+
+       protected Api.Tree tree;
+       protected HtmlRenderer _renderer;
+       protected Html.MarkupWriter writer;
+       protected Html.CssClassResolver cssresolver;
+       protected Charts.Factory image_factory;
+       protected ErrorReporter reporter;
+       protected string package_list_link = "../index.html";
+
+       // CSS:
+       private const string css_inline_navigation = "navi_inline";
+       private const string css_package_index = "package_index";
+       private const string css_brief_description = "brief_description";
+       private const string css_description = "description";
+       private const string css_known_list = "known_nodes";
+       private const string css_leaf_brief_description = "leaf_brief_description";
+       private const string css_leaf_code_definition = "leaf_code_definition";
+
+       private const string css_box_headline_text = "text";
+       private const string css_box_headline_toggle = "toggle";
+       private const string css_box_headline = "headline";
+       private const string css_box_content = "content";
+       private const string css_box_column = "column";
+       private const string css_box = "box";
+
+       private const string css_namespace_note = "namespace_note";
+       private const string css_package_note = "package_note";
+
+       private const string css_site_header = "site_header";
+       private const string css_navi = "navi_main";
+       private const string css_navi_hr = "navi_hr";
+       private const string css_errordomain_table_name = "main_errordomain_table_name";
+       private const string css_errordomain_table_text = "main_errordomain_table_text";
+       private const string css_errordomain_table = "main_errordomain_table";
+       private const string css_enum_table_name = "main_enum_table_name";
+       private const string css_enum_table_text = "main_enum_table_text";
+       private const string css_enum_table = "main_enum_table";
+       private const string css_diagram = "main_diagram";
+       private const string css_see_list = "main_see_list";
+       private const string css_wiki_table = "main_table";
+       private const string css_notification_area = "main_notification";
+       private const string css_source_sample = "main_sourcesample";
+       private const string css_exception_table = "main_parameter_table";
+       private const string css_parameter_table_text = "main_parameter_table_text";
+       private const string css_parameter_table_name = "main_parameter_table_name";
+       private const string css_parameter_table = "main_parameter_table";
+       private const string css_title = "main_title";
+       private const string css_other_type = "main_other_type";
+       private const string css_basic_type  = "main_basic_type";
+       private const string css_keyword  = "main_keyword";
+       private const string css_optional_parameter  = "main_optional_parameter";
+       private const string css_code_definition = "main_code_definition";
+       private const string css_headline_hr = "main_hr";
+       private const string css_hr = "main_hr";
+       private const string css_list_errdom = "main_list_errdom";
+       private const string css_list_en = "main_list_en";
+       private const string css_list_ns = "main_list_ns";
+       private const string css_list_cl = "main_list_cl";
+       private const string css_list_iface = "main_list_iface";
+       private const string css_list_stru = "main_list_stru";
+       private const string css_list_field = "main_list_field";
+       private const string css_list_prop = "main_list_prop";
+       private const string css_list_del = "main_list_del";
+       private const string css_list_sig = "main_list_sig";
+       private const string css_list_m = "main_list_m";
+       private const string css_style_navigation = "site_navigation";
+       private const string css_style_content = "site_content";
+       private const string css_style_body = "site_body";
+       private const string css_deprecated = "deprecated";
+
+       public virtual void process (Settings settings, Api.Tree tree, ErrorReporter reporter) {
+               this.reporter = reporter;
+               this.settings = settings;
+               this.tree = tree;
+
+               this.cssresolver = new CssClassResolver ();
+               this.linker = new LinkHelper ();
+
+               _renderer = new HtmlRenderer (settings, this.linker, this.cssresolver);
+               this.image_factory = new SimpleChartFactory (settings, linker);
+       }
+
+
+       // paths:
+       protected string? get_link (Api.Node to, Api.Node from) {
+               return linker.get_relative_link (from, to, settings);
+       }
+
+       protected virtual string get_img_path_html (Api.Node element, string type) {
+               return Path.build_filename ("img", element.get_full_name () + "." + type);
+       }
+
+       protected virtual string get_img_path (Api.Node element, string type) {
+               return Path.build_filename (settings.path, element.package.name, "img",
+                                                                       element.get_full_name () + "." + 
type);
+       }
+
+       protected virtual string get_icon_directory () {
+               return "..";
+       }
+
+
+       private TypeSymbol? unpack_type_reference (TypeReference? type_reference) {
+               Api.Item pos = type_reference;
+
+               while (pos != null) {
+                       if (pos is TypeReference) {
+                               pos = ((TypeReference) pos).data_type;
+                       } else if (pos is Api.Array) {
+                               pos = ((Api.Array) pos).data_type;
+                       } else if (pos is Pointer) {
+                               pos = ((Pointer) pos).data_type;
+                       } else {
+                               assert (pos is TypeSymbol);
+                               return (TypeSymbol) pos;
+                       }
+               }
+
+               return null;
+       }
+
+
+       protected void write_navi_entry_html_template (string style, string content, bool is_deprecated) {
+               writer.start_tag ("li", {"class", style});
+
+               if (is_deprecated) {
+                       writer.start_tag ("span", {"class", css_deprecated});
+                       writer.text (content);
+                       writer.end_tag ("span");
+               } else {
+                       writer.text (content);
+               }
+
+               writer.end_tag ("li");
+       }
+
+       protected void write_navi_entry_html_template_with_link (string style, string link,
+                                                                                                             
           string content, bool is_deprecated)
+       {
+               writer.start_tag ("li", {"class", style});
+
+               if (is_deprecated) {
+                       writer.start_tag ("span", {"class", css_deprecated});
+                       writer.link (link, content);
+                       writer.end_tag ("span");
+               } else {
+                       writer.link (link, content);
+               }
+
+               writer.end_tag ("li");
+       }
+
+       protected void write_navi_entry (Api.Node element, Api.Node? pos, string style,
+                                                                        bool link, bool full_name = false)
+       {
+               string name;
+
+               if (full_name == true && element is Namespace) {
+                       string tmp = element.get_full_name();
+                       name = (tmp == null)? "Global Namespace" : tmp;
+               } else {
+                       string tmp = element.name;
+                       name = (tmp == null)? "Global Namespace" : tmp;
+               }
+
+               bool is_deprecated = element is Symbol && ((Symbol) element).is_deprecated;
+
+               if (link == true) {
+                       this.write_navi_entry_html_template_with_link (style,
+                                                                                                             
     this.get_link (element, pos),
+                                                                                                             
     name,
+                                                                                                             
     is_deprecated);
+               } else {
+                       this.write_navi_entry_html_template (style, name, is_deprecated);
+               }
+       }
+
+       protected void write_wiki_pages (Api.Tree tree, string css_path_wiki, string js_path_wiki,
+                                                                        string contentp)
+       {
+               if (tree.wikitree == null) {
+                       return ;
+               }
+
+               if (tree.wikitree == null) {
+                       return ;
+               }
+
+               Vala.Collection<WikiPage> pages = tree.wikitree.get_pages();
+               if (pages.size == 0) {
+                       return ;
+               }
+
+               DirUtils.create (contentp, 0777);
+
+               DirUtils.create (Path.build_filename (contentp, "img"), 0777);
+
+               foreach (WikiPage page in pages) {
+                       if (page.name != wiki_index_name) {
+                               write_wiki_page (page, contentp, css_path_wiki, js_path_wiki, 
this.settings.pkg_name);
+                       }
+               }
+       }
+
+       protected virtual void write_wiki_page (WikiPage page, string contentp, string css_path,
+                                                                                       string js_path, 
string pkg_name)
+       {
+               GLib.FileStream file = GLib.FileStream.open (
+                       Path.build_filename (contentp, page.name.substring (0, page.name.length-7).replace 
("/", ".")+"htm"),
+                       "w");
+
+               writer = new MarkupWriter (file);
+               _renderer.set_writer (writer);
+               this.write_file_header (css_path, js_path, pkg_name);
+               _renderer.set_container (page);
+               _renderer.render (page.documentation);
+               this.write_file_footer ();
+       }
+
+       protected void write_navi_top_entry (Api.Node element, Api.Node? parent) {
+               string style = cssresolver.resolve (element);
+
+               writer.start_tag ("ul", {"class", css_navi});
+
+               if (element == parent || parent == null) {
+                       this.write_navi_entry (element, parent, style, false);
+               } else {
+                       this.write_navi_entry (element, parent, style, true);
+               }
+
+               writer.end_tag ("ul");
+               writer.simple_tag ("hr", {"class", css_navi_hr});
+       }
+
+       protected void write_top_element_template (string link) {
+               writer.start_tag ("ul", {"class", css_navi});
+               writer.start_tag ("li", {"class", css_package_index});
+               writer.link (link, "Packages");
+               writer.end_tag ("li");
+               writer.end_tag ("ul");
+               writer.simple_tag ("hr", {"class", css_navi_hr});
+       }
+
+       protected void write_top_elements (Api.Node element, Api.Node? parent) {
+               Vala.ArrayList<Api.Node> lst = new Vala.ArrayList<Api.Node> ();
+               Api.Node pos = element;
+
+               this.write_top_element_template (package_list_link);
+
+               while (pos != null) {
+                       lst.add (pos);
+                       pos = (Api.Node)pos.parent;
+               }
+
+               for (int i = lst.size-1; i >= 0  ; i--) {
+                       Api.Node el = lst.get (i);
+
+                       if (el.name != null) {
+                               this.write_navi_top_entry (el, parent);
+                       }
+               }
+       }
+
+       protected void fetch_subnamespace_names (Api.Node node, Vala.ArrayList<Namespace> namespaces) {
+               Vala.ArrayList<Api.Node> sorted_list = new Vala.ArrayList<Api.Node> ();
+               sorted_list.add_all (node.get_children_by_type (Api.NodeType.NAMESPACE));
+               sorted_list.sort ((CompareDataFunc) Api.Node.compare_to);
+
+               foreach (Api.Node child in sorted_list) {
+                       namespaces.add ((Namespace) child);
+                       this.fetch_subnamespace_names (child, namespaces);
+               }
+       }
+
+       protected void write_navi_package (Package package) {
+               Vala.ArrayList<Namespace> ns_list = new Vala.ArrayList<Namespace> ();
+               this.fetch_subnamespace_names (package, ns_list);
+
+               writer.start_tag ("div", {"class", css_style_navigation});
+               write_top_elements (package, package);
+               writer.start_tag ("ul", {"class", css_navi});
+
+               Namespace globals = null;
+
+               foreach (Namespace ns in ns_list) {
+                       if (ns.name == null) {
+                               globals = ns;
+                       } else {
+                               this.write_navi_entry (ns, package, cssresolver.resolve (ns), true, true);
+                       }
+               }
+
+               if (globals != null) {
+                       write_navi_children (globals, Api.NodeType.ERROR_CODE, package);
+                       write_navi_children (globals, Api.NodeType.ENUM_VALUE, package);
+                       write_navi_children (globals, Api.NodeType.ENUM, package);
+                       write_navi_children (globals, Api.NodeType.INTERFACE, package);
+                       write_navi_children (globals, Api.NodeType.CLASS, package);
+                       write_navi_children (globals, Api.NodeType.STRUCT, package);
+                       write_navi_children (globals, Api.NodeType.CONSTANT, package);
+                       write_navi_children (globals, Api.NodeType.PROPERTY, package);
+                       write_navi_children (globals, Api.NodeType.DELEGATE, package);
+                       write_navi_children (globals, Api.NodeType.STATIC_METHOD, package);
+                       write_navi_children (globals, Api.NodeType.CREATION_METHOD, package);
+                       write_navi_children (globals, Api.NodeType.METHOD, package);
+                       write_navi_children (globals, Api.NodeType.SIGNAL, package);
+                       write_navi_children (globals, Api.NodeType.FIELD, package);
+               }
+
+               writer.end_tag ("ul");
+               writer.end_tag ("div");
+       }
+
+       protected void write_navi_symbol (Api.Node node) {
+               writer.start_tag ("div", {"class", css_style_navigation});
+               write_top_elements (node, node);
+               write_navi_symbol_inline (node, node);
+               writer.end_tag ("div");
+       }
+
+       protected void write_navi_leaf_symbol (Api.Node node) {
+               writer.start_tag ("div", {"class", css_style_navigation});
+               write_top_elements ((Api.Node) node.parent, node);
+               write_navi_symbol_inline ((Api.Node) node.parent, node);
+               writer.end_tag ("div");
+       }
+
+       protected void write_navi_symbol_inline (Api.Node node, Api.Node? parent) {
+               writer.start_tag ("ul", {"class", css_navi});
+               write_navi_children (node, Api.NodeType.NAMESPACE, parent);
+               write_navi_children (node, Api.NodeType.ERROR_CODE, parent);
+               write_navi_children (node, Api.NodeType.ENUM_VALUE, parent);
+               write_navi_children (node, Api.NodeType.ENUM, parent);
+               write_navi_children (node, Api.NodeType.INTERFACE, parent);
+               write_navi_children (node, Api.NodeType.CLASS, parent);
+               write_navi_children (node, Api.NodeType.STRUCT, parent);
+               write_navi_children (node, Api.NodeType.CONSTANT, parent);
+               write_navi_children (node, Api.NodeType.PROPERTY, parent);
+               write_navi_children (node, Api.NodeType.DELEGATE, parent);
+               write_navi_children (node, Api.NodeType.STATIC_METHOD, parent);
+               write_navi_children (node, Api.NodeType.CREATION_METHOD, parent);
+               write_navi_children (node, Api.NodeType.METHOD, parent);
+               write_navi_children (node, Api.NodeType.SIGNAL, parent);
+               write_navi_children (node, Api.NodeType.FIELD, parent);
+               writer.end_tag ("ul");
+       }
+
+       protected void write_navi_children (Api.Node node, Api.NodeType type, Api.Node? parent) {
+               var children = node.get_children_by_type (type);
+               children.sort ((CompareDataFunc) Api.Node.compare_to);
+               foreach (Api.Node child in children) {
+                       write_navi_entry (child, parent, cssresolver.resolve (child), child != parent);
+               }
+       }
+
+       protected void write_package_note (Api.Node element) {
+               string package = element.package.name;
+               if (package == null) {
+                       return;
+               }
+
+               writer.start_tag ("div", {"class", css_package_note});
+               writer.start_tag ("b")
+                       .text ("Package:")
+                       .end_tag ("b");
+               writer.text (" ")
+                       .start_tag ("a", {"href", get_link (element.package, element)})
+                       .text (package)
+                       .end_tag ("a");
+               writer.end_tag ("div");
+       }
+
+       protected void write_namespace_note (Api.Node element) {
+               Namespace? ns = element.nspace;
+               if (ns == null) {
+                       return;
+               }
+
+               if (ns.name == null) {
+                       return;
+               }
+
+               writer.start_tag ("div", {"class", css_namespace_note});
+               writer.start_tag ("b")
+                       .text ("Namespace:")
+                       .end_tag ("b");
+               writer.text (" ")
+                       .start_tag ("a", {"href", get_link (ns, element)})
+                       .text (ns.get_full_name())
+                       .end_tag ("a");
+               writer.end_tag ("div");
+       }
+
+       private bool has_brief_description (Api.Node element) {
+               return element.documentation != null;
+       }
+
+       private void write_brief_description (Api.Node element , Api.Node? pos) {
+               Content.Comment? doctree = element.documentation;
+               if (doctree == null) {
+                       return;
+               }
+
+               Vala.List<Block> description = doctree.content;
+               if (description.size > 0) {
+                       writer.start_tag ("span", {"class", css_brief_description});
+
+                       _renderer.set_container (pos);
+                       _renderer.set_owner (element);
+                       _renderer.render_children (description.get (0));
+                       _renderer.set_owner (null);
+
+                       writer.end_tag ("span");
+               }
+       }
+
+       private void write_documentation (Api.Node element , Api.Node? pos) {
+               Content.Comment? doctree = element.documentation;
+               bool is_deprecated = (element is Symbol && ((Symbol) element).is_deprecated);
+
+               // avoid empty divs
+               if (doctree == null && !is_deprecated) {
+                       return;
+               }
+
+
+               writer.start_tag ("div", {"class", css_description});
+               _renderer.set_owner (element);
+
+               // deprecation warning:
+               if (is_deprecated) {
+                       Symbol symbol = (Symbol) element;
+                       Attribute? version;
+                       Attribute? deprecated;
+                       AttributeArgument? replacement;
+                       AttributeArgument? since;
+                       if ((version = symbol.get_attribute ("Version")) != null) {
+                               replacement = version.get_argument ("replacement");
+                               since = version.get_argument ("deprecated_since");
+                       } else if ((deprecated = symbol.get_attribute ("Deprecated")) != null) {
+                               replacement = deprecated.get_argument ("replacement");
+                               since = deprecated.get_argument ("version");
+                       } else {
+                               assert_not_reached ();
+                       }
+
+                       writer.start_tag ("p");
+                       writer.start_tag ("b");
+                       writer.text ("Warning:");
+                       writer.end_tag ("b");
+                       writer.text (" %s is deprecated".printf (element.name));
+
+                       if (since != null) {
+                               writer.text (" since %s".printf (since.get_value_as_string ()));
+                       }
+
+                       writer.text (".");
+
+                       if (replacement != null) {
+                               string replacement_name = replacement.get_value_as_string ();
+                               Api.Node? replacement_node = tree.search_symbol_str (pos,
+                                       replacement_name.substring (1, replacement_name.length - 2));
+
+                               writer.text (" Use ");
+                               if (replacement_node == null) {
+                                       writer.text (replacement_name);
+                               } else {
+                                       string? link = get_link (replacement_node, pos);
+                                       if (link != null) {
+                                               string css = cssresolver.resolve (replacement_node);
+                                               writer.link (link, replacement_node.get_full_name (), css);
+                                       } else {
+                                               writer.start_tag ("code")
+                                                       .text (replacement_node.get_full_name ())
+                                                       .end_tag ("code");
+                                       }
+                               }
+                               writer.text (".");
+                       }
+
+                       writer.end_tag ("p");
+               }
+
+               if (doctree != null) {
+                       _renderer.set_container (pos);
+                       _renderer.render (doctree);
+               }
+
+
+               _renderer.set_owner (null);
+               writer.end_tag ("div");
+       }
+
+       private void write_attributes (Api.Symbol element, Api.Node? pos) {
+               writer.set_wrap (false);
+               _renderer.set_container (pos);
+               foreach (Attribute att in element.get_attributes ()) {
+                       _renderer.render (att.signature);
+                       writer.simple_tag ("br");
+               }
+               writer.set_wrap (true);
+       }
+
+       private void write_signature (Api.Node element , Api.Node? pos) {
+               writer.set_wrap (false);
+               _renderer.set_container (pos);
+               _renderer.render (element.signature);
+               writer.set_wrap (true);
+       }
+
+       protected bool is_internal_node (Api.Node node) {
+               return node is Package
+                      || node is Api.Namespace
+                      || node is Api.Interface
+                      || node is Api.Class
+                      || node is Api.Struct
+                      || node is Api.Enum
+                      || node is Api.EnumValue
+                      || node is Api.ErrorDomain
+                      || node is Api.ErrorCode;
+       }
+
+       public void write_navi_packages_inline (Api.Tree tree) {
+               writer.start_tag ("ul", {"class", css_navi});
+               foreach (Package pkg in tree.get_package_list()) {
+                       if (pkg.is_browsable (settings)) {
+                               writer.start_tag ("li", {"class", cssresolver.resolve (pkg)});
+                               writer.link (linker.get_package_link (pkg, settings), pkg.name);
+                               // brief description
+                               writer.end_tag ("li");
+                       } else {
+                               writer.start_tag ("li", {"class", cssresolver.resolve (pkg)});
+                               writer.text (pkg.name);
+                               writer.end_tag ("li");
+                       }
+               }
+               writer.end_tag ("ul");
+       }
+
+       public void write_navi_packages (Api.Tree tree) {
+               writer.start_tag ("div", {"class", css_style_navigation});
+               this.write_navi_packages_inline (tree);
+               writer.end_tag ("div");
+       }
+
+       public void write_package_index_content (Api.Tree tree) {
+               writer.start_tag ("div", {"class", css_style_content});
+               writer.start_tag ("h1", {"class", css_title})
+                       .text ("Packages:")
+                       .end_tag ("h1");
+               writer.simple_tag ("hr", {"class", css_headline_hr});
+
+               WikiPage? wikiindex = (tree.wikitree == null)
+                       ? null
+                       : tree.wikitree.search (wiki_index_name);
+               if (wikiindex != null) {
+                       _renderer.set_container (wikiindex);
+                       _renderer.render (wikiindex.documentation);
+               }
+
+               writer.start_tag ("h2", {"class", css_title})
+                       .text ("Content:")
+                       .end_tag ("h2");
+               writer.start_tag ("h3", {"class", css_title})
+                       .text ("Packages:")
+                       .end_tag ("h3");
+               this.write_navi_packages_inline (tree);
+               writer.end_tag ("div");
+       }
+
+       private uint html_id_counter = 0;
+
+       private inline Vala.Collection<Api.Node> get_accessible_nodes_from_list (Vala.Collection<Api.Node> 
nodes) {
+               var list = new Vala.ArrayList<Api.Node> ();
+
+               foreach (var node in nodes) {
+                       if (node.is_browsable(_settings)) {
+                               list.add (node);
+                       }
+               }
+
+               return list;
+       }
+
+       private void write_known_symbols_note (Vala.Collection<Api.Node> nodes2, Api.Node container, string 
headline) {
+               var nodes = get_accessible_nodes_from_list (nodes2);
+               if (nodes.size == 0) {
+                       return ;
+               }
+
+               // Box:
+               var html_id = "box-content-" + html_id_counter.to_string ();
+               html_id_counter++;
+
+
+               writer.start_tag ("div", {"class", css_box});
+
+               // headline:
+               writer.start_tag ("div", {"class", css_box_headline, "onclick", "toggle_box (this, 
'%s')".printf (html_id)})
+                       .text (headline)
+                       .end_tag ("div");
+               //writer.start_tag ("div", {"class", css_box_headline_text, "onclick", "toggle_box (this, 
'%s')".printf (html_id)})
+               //      .text (headline)
+               //      .end_tag ("div");
+               //writer.start_tag ("div", {"class", css_box_headline_toggle});
+               //writer.start_tag ("img", {"onclick",
+               //                                                "toggle_box  (this, '" + html_id + "')",
+               //                                                "src",
+               //                                                Path.build_filename (get_icon_directory (),
+               //                                                "coll_open.png")});
+               //writer.raw_text ("&nbsp;");
+               //writer.end_tag ("div");
+               //writer.end_tag ("div");
+
+
+               // content:
+               int[] list_sizes = {0, 0, 0};
+               list_sizes[0] = nodes.size;
+               list_sizes[2] = list_sizes[0]/3;
+               list_sizes[0] -= list_sizes[2];
+               list_sizes[1] = list_sizes[0]/2;
+               list_sizes[0] -= list_sizes[1];
+
+               writer.start_tag ("div", {"class", css_box_content, "id", html_id});
+
+               var iter = nodes.iterator ();
+
+               for (int i = 0; i < list_sizes.length; i++) {
+                       writer.start_tag ("div", {"class", css_box_column});
+                       writer.start_tag ("ul", {"class", css_inline_navigation});
+
+                       for (int p = 0; p < list_sizes[i] && iter.next (); p++) {
+                               var node = iter.get ();
+                               writer.start_tag ("li", {"class", cssresolver.resolve (node)});
+                               string link = get_link (node, container);
+                               if (link == null) {
+                                       writer.text (node.name);
+                               } else {
+                                       writer.link (link, node.name);
+                               }
+                               writer.end_tag ("li");
+                       }
+
+                       writer.end_tag ("ul");
+                       writer.end_tag ("div");
+               }
+
+               writer.end_tag ("div"); // end content
+
+               writer.end_tag ("div"); // end box
+       }
+
+       public void write_symbol_content (Api.Node node) {
+               writer.start_tag ("div", {"class", css_style_content});
+               writer.start_tag ("h1", {"class", css_title})
+                       .text (node.name)
+                       .end_tag ("h1");
+               writer.simple_tag ("hr", {"class", css_headline_hr});
+               this.write_image_block (node);
+               writer.start_tag ("h2", {"class", css_title})
+                       .text ("Description:")
+                       .end_tag ("h2");
+               writer.start_tag ("div", {"class", css_code_definition});
+               if (node is Symbol) {
+                       this.write_attributes ((Symbol) node, node);
+               }
+               this.write_signature (node, node);
+               writer.end_tag ("div");
+               this.write_documentation (node, node);
+
+               if (node is Class) {
+                       var cl = node as Class;
+                       write_known_symbols_note (cl.get_known_child_classes (),
+                                                                         cl,
+                                                                         "All known sub-classes:");
+                       write_known_symbols_note (cl.get_known_derived_interfaces (),
+                                                                         cl,
+                                                                         "Required by:");
+               } else if (node is Interface) {
+                       var iface = node as Interface;
+                       write_known_symbols_note (iface.get_known_implementations (),
+                                                                         iface,
+                                                                         "All known implementing classes:");
+                       write_known_symbols_note (iface.get_known_related_interfaces (),
+                                                                         iface,
+                                                                         "All known sub-interfaces:");
+               } else if (node is Struct) {
+                       var stru = node as Struct;
+                       write_known_symbols_note (stru.get_known_child_structs (),
+                                                                         stru,
+                                                                         "All known sub-structs:");
+               }
+
+               if (node.parent is Namespace) {
+                       writer.simple_tag ("br");
+                       write_namespace_note (node);
+                       write_package_note (node);
+               }
+
+               if (!(node is Method || node is Delegate || node is Api.Signal)) {
+                       // avoids exception listings & implementations
+
+                       if (node.has_children ({
+                                       Api.NodeType.ERROR_CODE,
+                                       Api.NodeType.ENUM_VALUE,
+                                       Api.NodeType.CREATION_METHOD,
+                                       Api.NodeType.STATIC_METHOD,
+                                       Api.NodeType.CLASS,
+                                       Api.NodeType.STRUCT,
+                                       Api.NodeType.ENUM,
+                                       Api.NodeType.DELEGATE,
+                                       Api.NodeType.METHOD,
+                                       Api.NodeType.SIGNAL,
+                                       Api.NodeType.PROPERTY,
+                                       Api.NodeType.FIELD,
+                                       Api.NodeType.CONSTANT
+                               }))
+                       {
+                               writer.start_tag ("h2", {"class", css_title}).text ("Content:").end_tag 
("h2");
+                               write_children (node, Api.NodeType.ERROR_CODE, "Error codes", node);
+                               write_children (node, Api.NodeType.ENUM_VALUE, "Enum values", node);
+                               write_children (node, Api.NodeType.CLASS, "Classes", node);
+                               write_children (node, Api.NodeType.STRUCT, "Structs", node);
+                               write_children (node, Api.NodeType.ENUM, "Enums", node);
+                               write_children (node, Api.NodeType.CONSTANT, "Constants", node);
+                               write_children (node, Api.NodeType.PROPERTY, "Properties", node);
+                               write_children (node, Api.NodeType.DELEGATE, "Delegates", node);
+                               write_children (node, Api.NodeType.STATIC_METHOD, "Static methods", node);
+                               write_children (node, Api.NodeType.CREATION_METHOD, "Creation methods", node);
+                               write_children (node, Api.NodeType.METHOD, "Methods", node);
+                               write_children (node, Api.NodeType.SIGNAL, "Signals", node);
+                               write_children (node, Api.NodeType.FIELD, "Fields", node);
+                       }
+               }
+
+               if (node is Class) {
+                       write_inherited_symbols_note_for_class ((Class) node, node);
+               } else if (node is Interface) {
+                       write_inherited_symbols_note_for_interface ((Interface) node, node);
+               } else if (node is Struct) {
+                       write_inherited_symbols_note_for_struct ((Struct) node, node);
+               }
+
+               writer.end_tag ("div");
+       }
+
+       private static NodeType[] inheritable_members = {
+                       NodeType.CONSTANT,
+                       NodeType.PROPERTY,
+                       NodeType.DELEGATE,
+                       NodeType.STATIC_METHOD,
+                       NodeType.METHOD,
+                       NodeType.SIGNAL,
+                       NodeType.FIELD
+               };
+
+       private inline bool has_visible_inheritable_children (TypeSymbol symbol) {
+               return symbol.has_visible_children_by_types (inheritable_members, _settings);
+       }
+
+       private void write_inherited_members_headline () {
+               writer.start_tag ("h3", {"class", css_title})
+                       .text ("Inherited Members:")
+                       .end_tag ("h3");
+       }
+
+       private void write_inherited_symbols_note_for_class (Class cl, Api.Node container) {
+               bool headline_printed = false;
+
+               // class hierarchy:
+               Class base_class = unpack_type_reference (cl.base_type) as Class;
+               while (base_class != null) {
+                       if (!headline_printed && has_visible_inheritable_children (base_class)) {
+                               write_inherited_members_headline ();
+                               headline_printed = true;
+                       }
+
+                       write_inherited_symbols_note (base_class, "class", container);
+                       base_class = unpack_type_reference (base_class.base_type) as Class;
+               }
+
+
+               // implemented interfaces
+               Vala.Collection<Interface> printed_interfaces = new Vala.ArrayList<Interface> ();
+               foreach (TypeReference iface_ref in cl.get_full_implemented_interface_list ()) {
+                       Interface iface = (Interface) unpack_type_reference (iface_ref);
+
+                       if (!headline_printed && has_visible_inheritable_children (iface)) {
+                               write_inherited_members_headline ();
+                               headline_printed = true;
+                       } else if (printed_interfaces.contains (iface)) {
+                               continue ;
+                       }
+
+                       write_inherited_symbols_note (iface, "interface", container);
+                       printed_interfaces.add (iface);
+               }
+       }
+
+       private void write_inherited_symbols_note_for_interface (Interface iface, Api.Node container) {
+               bool headline_printed = false;
+
+               // class hierarchy:
+               Class base_class = unpack_type_reference (iface.base_type) as Class;
+               while (base_class != null) {
+                       if (!headline_printed && has_visible_inheritable_children (base_class)) {
+                               write_inherited_members_headline ();
+                               headline_printed = true;
+                       }
+
+                       write_inherited_symbols_note (base_class, "class", container);
+                       base_class = unpack_type_reference (base_class.base_type) as Class;
+               }
+
+
+               // interfaces:
+               Vala.Collection<Interface> printed_interfaces = new Vala.ArrayList<Interface> ();
+               foreach (TypeReference pre_ref in iface.get_full_implemented_interface_list ()) {
+                       Interface pre = (Interface) unpack_type_reference (pre_ref);
+
+                       if (!headline_printed && has_visible_inheritable_children (pre)) {
+                               write_inherited_members_headline ();
+                               headline_printed = true;
+                       } else if (printed_interfaces.contains (pre)) {
+                               continue ;
+                       }
+
+                       write_inherited_symbols_note (pre, "interface", container);
+                       printed_interfaces.add (pre);
+               }
+       }
+
+       private void write_inherited_symbols_note_for_struct (Struct str, Api.Node container) {
+               Struct base_struct = unpack_type_reference (str.base_type) as Struct;
+               if (base_struct != null && has_visible_inheritable_children (base_struct)) {
+                       write_inherited_members_headline ();
+                       write_inherited_symbols_note (base_struct, "struct", container);
+               }
+       }
+
+       private void write_inherited_symbols_note (TypeSymbol symbol, string type, Api.Node container) {
+               write_known_symbols_note (symbol.get_children_by_types (inheritable_members, false),
+                                                                 container,
+                                                                 "All known members inherited from %s 
%s".printf (type, symbol.get_full_name ()));
+
+               /*
+               write_known_symbols_note (symbol.get_children_by_type (NodeType.CONSTANT, false),
+                       container,
+                       "All known constants inherited from %s %s".printf (type, symbol.get_full_name ()));
+               write_known_symbols_note (symbol.get_children_by_type (NodeType.PROPERTY, false),
+                       container,
+                       "All known properties inherited from %s %s".printf (type, symbol.get_full_name ()));
+               write_known_symbols_note (symbol.get_children_by_type (NodeType.DELEGATE, false),
+                       container,
+                       "All known delegates inherited from %s %s".printf (type, symbol.get_full_name ()));
+               write_known_symbols_note (symbol.get_children_by_type (NodeType.STATIC_METHOD, false),
+                       container,
+                       "All known static methods inherited from %s %s".printf (type, symbol.get_full_name 
()));
+               write_known_symbols_note (symbol.get_children_by_type (NodeType.METHOD, false),
+                       container,
+                       "All known methods inherited from %s %s".printf (type, symbol.get_full_name ()));
+               write_known_symbols_note (symbol.get_children_by_type (NodeType.SIGNAL, false),
+                       container,
+                       "All known signals inherited from %s %s".printf (type, symbol.get_full_name ()));
+               write_known_symbols_note (symbol.get_children_by_type (NodeType.FIELD, false),
+                       container,
+                       "All known fields inherited from  %s %s".printf (type, symbol.get_full_name ()));
+               */
+       }
+
+       protected void write_child_namespaces (Api.Node node, Api.Node? parent) {
+               Vala.ArrayList<Namespace> namespaces = new Vala.ArrayList<Namespace> ();
+               this.fetch_subnamespace_names (node, namespaces);
+
+               if (namespaces.size == 0) {
+                       return;
+               }
+
+               if (namespaces.size == 1) {
+                       if (namespaces.get(0).name == null) {
+                               return;
+                       }
+               }
+
+               bool with_childs = parent != null && parent is Package;
+
+               writer.start_tag ("h3", {"class", css_title})
+                       .text ("Namespaces:")
+                       .end_tag ("h3");
+               writer.start_tag ("ul", {"class", css_inline_navigation});
+               foreach (Namespace child in namespaces) {
+                       if (child.name != null) {
+                               writer.start_tag ("li", {"class", cssresolver.resolve (child)});
+                               writer.link (get_link (child, parent), child.name);
+                               if (has_brief_description (child)) {
+                                       writer.text (" - ");
+                                       this.write_brief_description (child, parent);
+                               }
+                               writer.end_tag ("li");
+                               if (with_childs == true) {
+                                       write_children (child, Api.NodeType.INTERFACE, "Interfaces", parent);
+                                       write_children (child, Api.NodeType.CLASS, "Classes", parent);
+                                       write_children (child, Api.NodeType.STRUCT, "Structs", parent);
+                                       write_children (child, Api.NodeType.ENUM, "Enums", parent);
+                                       write_children (child, Api.NodeType.ERROR_DOMAIN, "Error domains", 
parent);
+                                       write_children (child, Api.NodeType.CONSTANT, "Constants", parent);
+                                       write_children (child, Api.NodeType.DELEGATE, "Delegates", parent);
+                                       write_children (child, Api.NodeType.METHOD, "Methods", parent);
+                                       write_children (child, Api.NodeType.FIELD, "Fields", parent);
+                               }
+                       }
+               }
+               writer.end_tag ("ul");
+       }
+
+       protected void write_child_dependencies (Package package, Api.Node? parent) {
+               Vala.Collection<Package>? deps = package.get_full_dependency_list ();
+               if (deps.size == 0) {
+                       return;
+               }
+
+               writer.start_tag ("h2", {"class", css_title})
+                       .text ("Dependencies:")
+                       .end_tag ("h2");
+               writer.start_tag ("ul", {"class", css_inline_navigation});
+               foreach (Package p in deps) {
+                       string? link = this.get_link (p, parent);
+                       if (link == null) {
+                               writer.start_tag ("li", {"class", cssresolver.resolve (p), "id", p.name})
+                                       .text (p.name)
+                                       .end_tag ("li");
+                       } else {
+                               writer.start_tag ("li", {"class", cssresolver.resolve (p)});
+                               writer.link (get_link (p, parent), p.name);
+                               writer.end_tag ("li");
+                       }
+               }
+               writer.end_tag ("ul");
+       }
+
+       protected void write_children (Api.Node node, Api.NodeType type, string type_string, Api.Node? 
container) {
+               var children = node.get_children_by_type (type);
+               if (children.size > 0) {
+                       writer.start_tag ("h3", {"class", css_title})
+                               .text (type_string)
+                               .text (":")
+                               .end_tag ("h3");
+                       writer.start_tag ("ul", {"class", css_inline_navigation});
+                       foreach (Api.Node child in children) {
+                               writer.start_tag ("li", {"class", cssresolver.resolve (child)});
+                               if (is_internal_node (child)) {
+                                       if (child is Symbol && ((Symbol) child).is_deprecated) {
+                                               writer.start_tag ("span", {"class", css_deprecated});
+                                               writer.link (get_link (child, container), child.name);
+                                               writer.end_tag ("span");
+                                       } else {
+                                               writer.link (get_link (child, container), child.name);
+                                       }
+                                       if (has_brief_description (child)) {
+                                               writer.text (" - ");
+                                               write_brief_description (child, container);
+                                       }
+                               } else {
+                                       writer.start_tag ("span", {"class", css_leaf_code_definition});
+                                       if (child is Symbol && ((Symbol) child).is_deprecated) {
+                                               writer.start_tag ("span", {"class", css_deprecated});
+                                               write_signature (child, container);
+                                               writer.end_tag ("span");
+                                       } else {
+                                               write_signature (child, container);
+                                       }
+                                       writer.end_tag ("span");
+
+                                       writer.start_tag ("div", {"class", css_leaf_brief_description});
+                                       write_brief_description (child, container);
+                                       writer.end_tag ("div");
+                               }
+                               writer.end_tag ("li");
+                       }
+                       writer.end_tag ("ul");
+               }
+       }
+
+       protected void write_image_block (Api.Node element) {
+               if (element is Class || element is Interface || element is Struct) {
+                       unowned string format = (settings.use_svg_images ? "svg" : "png");
+                       var chart = new Charts.Hierarchy (image_factory, element);
+                       chart.save (this.get_img_path (element, format), format);
+
+                       writer.start_tag ("h2", {"class", css_title})
+                               .text ("Object Hierarchy:")
+                               .end_tag ("h2");
+
+                       writer.simple_tag ("img", {"class",
+                                                                          css_diagram,
+                                                                          "usemap",
+                                                                          "#"+element.get_full_name (),
+                                                                          "alt",
+                                                                          "Object hierarchy for %s".printf 
(element.name),
+                                                                          "src",
+                                                                          this.get_img_path_html (element, 
format)});
+                       writer.add_usemap (chart);
+               }
+       }
+
+       public void write_namespace_content (Namespace node, Api.Node? parent) {
+               writer.start_tag ("div", {"class", css_style_content});
+               writer.start_tag ("h1", {"class", css_title})
+                       .text (node.name == null ? "Global Namespace" : node.get_full_name ())
+                       .end_tag ("h1");
+               writer.simple_tag ("hr", {"class", css_hr});
+               writer.start_tag ("h2", {"class", css_title})
+                       .text ("Description:")
+                       .end_tag ("h2");
+
+               this.write_documentation (node, parent);
+
+               writer.start_tag ("h2", {"class", css_title})
+                       .text ("Content:")
+                       .end_tag ("h2");
+
+               if (node.name == null) {
+                       this.write_child_namespaces ((Package) node.parent, parent);
+               } else {
+                       this.write_child_namespaces (node, parent);
+               }
+
+               write_children (node, Api.NodeType.INTERFACE, "Interfaces", parent);
+               write_children (node, Api.NodeType.CLASS, "Classes", parent);
+               write_children (node, Api.NodeType.STRUCT, "Structs", parent);
+               write_children (node, Api.NodeType.ENUM, "Enums", parent);
+               write_children (node, Api.NodeType.ERROR_DOMAIN, "Error domains", parent);
+               write_children (node, Api.NodeType.CONSTANT, "Constants", parent);
+               write_children (node, Api.NodeType.DELEGATE, "Delegates", parent);
+               write_children (node, Api.NodeType.METHOD, "Functions", parent);
+               write_children (node, Api.NodeType.FIELD, "Fields", parent);
+               writer.end_tag ("div");
+       }
+
+       protected void write_package_content (Package node, Api.Node? parent) {
+               writer.start_tag ("div", {"class", css_style_content});
+               writer.start_tag ("h1", {"class", css_title, "id", node.name})
+                       .text (node.name)
+                       .end_tag ("h1");
+               writer.simple_tag ("hr", {"class", css_headline_hr});
+               writer.start_tag ("h2", {"class", css_title})
+                       .text ("Description:")
+                       .end_tag ("h2");
+
+
+               WikiPage? wikipage = (tree.wikitree == null)? null : tree.wikitree.search (wiki_index_name);
+               if (wikipage != null) {
+                       _renderer.set_container (parent);
+                       _renderer.render (wikipage.documentation);
+               }
+
+               writer.start_tag ("h2", {"class", css_title})
+                       .text ("Content:")
+                       .end_tag ("h2");
+
+               this.write_child_namespaces (node, parent);
+
+               foreach (Api.Node child in node.get_children_by_type (Api.NodeType.NAMESPACE)) {
+                       if (child.name == null) {
+                               write_children (child, Api.NodeType.INTERFACE, "Interfaces", parent);
+                               write_children (child, Api.NodeType.CLASS, "Classes", parent);
+                               write_children (child, Api.NodeType.STRUCT, "Structs", parent);
+                               write_children (child, Api.NodeType.ENUM, "Enums", parent);
+                               write_children (child, Api.NodeType.ERROR_DOMAIN, "Error domains", parent);
+                               write_children (child, Api.NodeType.CONSTANT, "Constants", parent);
+                               write_children (child, Api.NodeType.DELEGATE, "Delegates", parent);
+                               write_children (child, Api.NodeType.METHOD, "Functions", parent);
+                               write_children (child, Api.NodeType.FIELD, "Fields", parent);
+                       }
+               }
+
+               this.write_child_dependencies (node, parent);
+               writer.end_tag ("div");
+       }
+
+       protected void write_file_header (string css, string js, string? title) {
+               writer.start_tag ("html");
+               writer.start_tag ("head");
+               writer.simple_tag ("meta", {"charset", "UTF-8"});
+               if (title == null) {
+                       writer.start_tag ("title")
+                               .text ("Vala Binding Reference")
+                               .end_tag ("title");
+               } else {
+                       writer.start_tag ("title")
+                               .text (title)
+                               .text (" &ndash; Vala Binding Reference")
+                               .end_tag ("title");
+               }
+               writer.stylesheet_link (css);
+               writer.javascript_link (js);
+               writer.end_tag ("head");
+               writer.start_tag ("body");
+               writer.start_tag ("div", {"class", css_site_header});
+               writer.text ("%s Reference Manual".printf (title == null ? "" : title));
+               writer.end_tag ("div");
+               writer.start_tag ("div", {"class", css_style_body});
+       }
+
+       protected void write_file_footer () {
+               writer.end_tag ("div");
+               writer.simple_tag ("br");
+               writer.start_tag ("div", {"class", "site_footer"});
+               writer.text ("Generated by ");
+               writer.link ("http://www.valadoc.org/";, "Valadoc");
+               writer.end_tag ("div");
+               writer.end_tag ("body");
+               writer.end_tag ("html");
+       }
+}
+
diff --git a/libvaladoc/html/cssclassresolver.vala b/libvaladoc/html/cssclassresolver.vala
new file mode 100644
index 0000000..e8961ae
--- /dev/null
+++ b/libvaladoc/html/cssclassresolver.vala
@@ -0,0 +1,117 @@
+/* globals.vala
+ *
+ * Copyright (C) 2008-2009 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.Api;
+
+
+namespace Valadoc.Html {
+       public class CssClassResolver : Api.Visitor {
+               private string? css_class = null;
+
+               public string resolve (Api.Node node) {
+                       node.accept (this);
+                       return (owned) css_class;
+               }
+
+               public override void visit_package (Api.Package item) {
+                       css_class = "package";
+               }
+
+               public override void visit_namespace (Api.Namespace item) {
+                       css_class = "namespace";
+               }
+
+               public override void visit_interface (Api.Interface item) {
+                       css_class = "interface";
+               }
+
+               public override void visit_class (Api.Class item) {
+                       if (item.is_abstract) {
+                               css_class = "abstract_class";
+                       } else {
+                               css_class = "class";
+                       }
+               }
+
+               public override void visit_struct (Api.Struct item) {
+                       css_class = "struct";
+               }
+
+               public override void visit_property (Api.Property item) {
+                       if (item.is_virtual || item.is_override) {
+                               css_class = "virtual_property";
+                       } else if (item.is_abstract) {
+                               css_class = "abstract_property";
+                       } else {
+                               css_class = "property";
+                       }
+               }
+
+               public override void visit_field (Api.Field item) {
+                       css_class = "field";
+               }
+
+               public override void visit_constant (Api.Constant item) {
+                       css_class = "constant";
+               }
+
+               public override void visit_delegate (Api.Delegate item) {
+                       css_class = "delegate";
+               }
+
+               public override void visit_signal (Api.Signal item) {
+                       css_class = "signal";
+               }
+
+               public override void visit_method (Api.Method item) {
+                       if (item.is_static) {
+                               css_class = "static_method";
+                       } else if (item.is_abstract) {
+                               css_class = "abstract_method";
+                       } else if (item.is_virtual || item.is_override) {
+                               css_class = "virtual_method";
+                       } else if (item.is_constructor) {
+                               css_class = "creation_method";
+                       } else {
+                               css_class = "method";
+                       }
+               }
+
+               public override void visit_error_domain (Api.ErrorDomain item) {
+                       css_class = "errordomain";
+               }
+
+               public override void visit_error_code (Api.ErrorCode item) {
+                       css_class = "errorcode";
+               }
+
+               public override void visit_enum (Api.Enum item) {
+                       css_class = "enum";
+               }
+
+               public override void visit_enum_value (Api.EnumValue item) {
+                       css_class = "enumvalue";
+               }
+       }
+}
+
+
diff --git a/libvaladoc/html/htmlchartfactory.vala b/libvaladoc/html/htmlchartfactory.vala
new file mode 100644
index 0000000..1b63b4e
--- /dev/null
+++ b/libvaladoc/html/htmlchartfactory.vala
@@ -0,0 +1,54 @@
+/* simplechartfactory.vala
+ *
+ * Copyright (C) 2008  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>
+ */
+
+
+
+public class Valadoc.Html.SimpleChartFactory : Charts.SimpleFactory {
+       private Settings _settings;
+       private Api.Node _container;
+       private LinkHelper _linker;
+
+       public SimpleChartFactory (Settings settings, LinkHelper linker) {
+               _settings = settings;
+               _linker = linker;
+       }
+
+       public override Gvc.Graph create_graph (Api.Node item) {
+               var graph = base.create_graph (item);
+               _container = item;
+               return graph;
+       }
+
+       protected override Gvc.Node configure_type (Gvc.Node node, Api.Node item) {
+               base.configure_type (node, item);
+
+               if (_container != null) {
+                       var link = _linker.get_relative_link (_container, item, _settings);
+                       if (link != null) {
+                               node.safe_set ("URL", link, "");
+                       }
+               }
+
+               return node;
+       }
+}
+
diff --git a/libvaladoc/html/htmlmarkupwriter.vala b/libvaladoc/html/htmlmarkupwriter.vala
new file mode 100644
index 0000000..15ed9ef
--- /dev/null
+++ b/libvaladoc/html/htmlmarkupwriter.vala
@@ -0,0 +1,132 @@
+/* markupwriter.vala
+ *
+ * Copyright (C) 2008-2014 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+using GLib;
+using Valadoc.Content;
+
+public class Valadoc.Html.MarkupWriter : Valadoc.MarkupWriter {
+
+       public MarkupWriter (FileStream stream, bool xml_declaration = true) {
+               // avoid broken implicit copy
+               unowned FileStream _stream = stream;
+
+               base ((str) => {
+                       _stream.printf (str);
+               }, xml_declaration);
+       }
+
+       public MarkupWriter.builder (StringBuilder builder, bool xml_declaration = true) {
+               // avoid broken implicit copy
+               unowned StringBuilder _builder = builder;
+
+               base ((str) => {
+                       _builder.append (str);
+               }, xml_declaration);
+       }
+
+       public MarkupWriter add_usemap (Charts.Chart chart) {
+               string? buf = (string?) chart.write_buffer ("cmapx");
+               if (buf != null) {
+                       raw_text ("\n");
+                       raw_text ((!) buf);
+               }
+
+               return this;
+       }
+
+       // edit
+       public MarkupWriter link (string url, string label, string? css_class = null) {
+               if (css_class == null) {
+                       start_tag ("a", {"href", url});
+               } else {
+                       start_tag ("a", {"href", url, "class", css_class});
+               }
+
+               text (label);
+               end_tag ("a");
+               return this;
+       }
+
+       public MarkupWriter image (string src, string? caption = null, string? css_class = null) {
+               if (css_class == null) {
+                       simple_tag ("img", {"src", src, "alt", caption});
+               } else {
+                       simple_tag ("img", {"src", src, "alt", caption, "class", css_class});
+               }
+               return this;
+       }
+
+       public MarkupWriter stylesheet_link (string url) {
+               simple_tag ("link", {"href", url, "rel", "stylesheet", "type", "text/css"});
+               return this;
+       }
+
+       public MarkupWriter javascript_link (string url) {
+               start_tag ("script", {"src", url, "type", "text/javascript"});
+               end_tag ("script");
+               return this;
+       }
+
+       protected override bool inline_element (string name) {
+               return name != "html"
+                       && name != "head"
+                       && name != "title"
+                       && name != "meta"
+                       && name != "link"
+                       && name != "body"
+                       && name != "div"
+                       && name != "p"
+                       && name != "table"
+                       && name != "tr"
+                       && name != "td"
+                       && name != "ul"
+                       && name != "ol"
+                       && name != "li"
+                       && name != "h1"
+                       && name != "h2"
+                       && name != "h3"
+                       && name != "h4"
+                       && name != "h5"
+                       && name != "hr"
+                       && name != "img";
+       }
+
+       protected override bool content_inline_element (string name) {
+               return name == "title"
+                       || name == "meta"
+                       || name == "p"
+                       || name == "a"
+                       || name == "h1"
+                       || name == "h2"
+                       || name == "h3"
+                       || name == "h4"
+                       || name == "h5"
+                       || name == "li"
+                       || name == "span"
+                       || name == "code"
+                       || name == "b"
+                       || name == "i"
+                       || name == "u"
+                       || name == "stoke";
+       }
+}
+
diff --git a/libvaladoc/html/htmlrenderer.vala b/libvaladoc/html/htmlrenderer.vala
new file mode 100644
index 0000000..d26d606
--- /dev/null
+++ b/libvaladoc/html/htmlrenderer.vala
@@ -0,0 +1,632 @@
+/* htmlrenderer.vala
+ *
+ * Copyright (C) 2008-20014 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+using GLib;
+using Valadoc.Content;
+
+public class Valadoc.Html.HtmlRenderer : ContentRenderer {
+
+       protected Documentation? _container;
+       protected Documentation? _owner;
+       protected unowned MarkupWriter writer;
+       protected Html.CssClassResolver cssresolver;
+       protected LinkHelper linker;
+       protected Settings settings;
+
+       public HtmlRenderer (Settings settings, LinkHelper linker, CssClassResolver cssresolver) {
+               this.cssresolver = cssresolver;
+               this.settings = settings;
+               this.linker = linker;
+       }
+
+       public void set_container (Documentation? container) {
+               _container = container;
+       }
+
+       public void set_owner (Documentation? owner) {
+               _owner = owner;
+       }
+
+       public void set_writer (MarkupWriter writer) {
+               this.writer = writer;
+       }
+
+       public override void render (ContentElement element) {
+               element.accept (this);
+       }
+
+       public override void render_children (ContentElement element) {
+               element.accept_children (this);
+       }
+
+       private string get_url (Documentation symbol) {
+               return linker.get_relative_link (_container, symbol, settings);
+       }
+
+       private void write_unresolved_symbol_link (string given_symbol_name, InlineContent? label_owner = 
null) {
+               if (label_owner == null || label_owner.content.size == 0) {
+                       writer.start_tag ("code");
+                       writer.text (given_symbol_name);
+                       writer.end_tag ("code");
+               } else {
+                       writer.start_tag ("i");
+                       label_owner.accept_children (this);
+                       writer.end_tag ("i");
+               }
+       }
+
+       private void write_resolved_symbol_link (Api.Node symbol, string? given_symbol_name, InlineContent? 
label_owner = null) {
+               var symbol_name = (given_symbol_name == null || given_symbol_name == "") ? 
symbol.get_full_name () : given_symbol_name;
+               string href = (symbol == _container || symbol == _owner)? null : get_url (symbol);
+               string css_class = cssresolver.resolve (symbol);
+               string end_tag_name;
+
+
+               // Start Tag:
+               if (href != null) {
+                       writer.start_tag ("a", {"href", href, "class", css_class});
+                       end_tag_name = "a";
+               } else {
+                       writer.start_tag ("span", {"class", css_class});
+                       end_tag_name = "span";
+               }
+
+
+               // Content:
+               if (label_owner != null && label_owner.content.size > 0) {
+                       label_owner.accept_children (this);
+               } else {
+                       writer.text (symbol_name);
+               }
+
+
+               // End Tag:
+               writer.end_tag (end_tag_name);
+       }
+
+       private delegate void Write ();
+       private delegate void TagletWrite (Taglet taglet);
+
+       private void write_taglets (Write header, Write footer, Write separator,
+                                   Vala.List<Taglet> taglets, TagletWrite write) {
+               if (taglets.size > 0) {
+                       header ();
+                       bool first = true;
+                       foreach (var taglet in taglets) {
+                               if (!first) {
+                                       separator ();
+                               }
+                               write (taglet);
+                               first = false;
+                       }
+                       footer ();
+               }
+       }
+
+       public override void visit_comment (Comment element) {
+               Vala.List<Taglet> taglets;
+
+               taglets = element.find_taglets ((Api.Node) _container, typeof (Taglets.Deprecated));
+               write_taglets (
+                       () => {
+                               writer.start_tag ("p", {"class", "main_title"});
+                               writer.start_tag ("b")
+                                       .text ("Deprecated: ")
+                                       .end_tag ("b");
+                       },
+                       () => {
+                               writer.end_tag ("p");
+                       },
+                       () => {},
+                       taglets,
+                       (taglet) => {
+                               var deprecated = taglet as Taglets.Deprecated;
+                               deprecated.accept_children (this);
+                       });
+
+               // Write description
+               element.accept_children (this);
+
+               taglets = element.find_taglets ((Api.Node) _container, typeof (Taglets.Param));
+               taglets.sort ((_a, _b) => {
+                       Taglets.Param a = _a as Taglets.Param;
+                       Taglets.Param b = _b as Taglets.Param;
+
+                       if (a.position < 0 && b.position < 0) {
+                               int cmp = a.parameter_name.ascii_casecmp (b.parameter_name);
+                               if (cmp == 0) {
+                                       return 0;
+                               }
+
+                               if (a.parameter_name == "...") {
+                                       return 1;
+                               }
+
+                               if (b.parameter_name == "...") {
+                                       return -1;
+                               }
+
+                               return cmp;
+                       }
+
+                       if (a.position < 0) {
+                               return 1;
+                       }
+
+                       if (b.position < 0) {
+                               return -1;
+                       }
+
+                       return a.position - b.position;
+               });
+
+               write_taglets (
+                       () => {
+                               writer.start_tag ("h2", {"class", "main_title"})
+                                       .text ("Parameters:")
+                                       .end_tag ("h2");
+                               writer.start_tag ("table", {"class", "main_parameter_table"});
+                       },
+                       () => {
+                               writer.end_tag ("table");
+                       },
+                       () => {},
+                       taglets,
+                       (taglet) => {
+                               var param = taglet as Taglets.Param;
+                               string[]? unknown_parameter_css = null;
+                               if (param.parameter == null && !param.is_this) {
+                                       unknown_parameter_css = {"class", 
"main_parameter_table_unknown_parameter"};
+                               }
+
+                               writer.start_tag ("tr", unknown_parameter_css);
+                               writer.start_tag ("td", {"class", "main_parameter_table_name"})
+                                       .text (param.parameter_name)
+                                       .end_tag ("td");
+                               writer.start_tag ("td");
+                               param.accept_children (this);
+                               writer.end_tag ("td");
+                               writer.end_tag ("tr");
+                       });
+
+               taglets = element.find_taglets ((Api.Node) _container, typeof (Taglets.Return));
+               write_taglets (
+                       () => {
+                               writer.start_tag ("h2", {"class", "main_title"})
+                                       .text ("Returns:")
+                                       .end_tag ("h2");
+                               writer.start_tag ("table", {"class", "main_parameter_table"});
+                       },
+                       () => {
+                               writer.end_tag ("table");
+                       },
+                       () => {},
+                       taglets,
+                       (taglet) => {
+                               var param = taglet as Taglets.Return;
+                               writer.start_tag ("tr");
+                               writer.start_tag ("td");
+                               param.accept_children (this);
+                               writer.end_tag ("td");
+                               writer.end_tag ("tr");
+                       });
+
+               taglets = element.find_taglets ((Api.Node) _container, typeof (Taglets.Throws));
+               write_taglets (
+                       () => {
+                               writer.start_tag ("h2", {"class", "main_title"})
+                                       .text ("Exceptions:")
+                                       .end_tag ("h2");
+                               writer.start_tag ("table", {"class", "main_parameter_table"});
+                       },
+                       () => {
+                               writer.end_tag ("table");
+                       },
+                       () => {},
+                       taglets,
+                       (taglet) => {
+                               var exception = taglet as Taglets.Throws;
+                               writer.start_tag ("tr");
+                               writer.start_tag ("td", {"class", "main_parameter_table_name"})
+                                       .text (exception.error_domain_name)
+                                       .end_tag ("td");
+                               writer.start_tag ("td");
+                               exception.accept_children (this);
+                               writer.end_tag ("td");
+                               writer.end_tag ("tr");
+                       });
+
+               taglets = element.find_taglets ((Api.Node) _container, typeof (Taglets.Since));
+               write_taglets (
+                       () => {
+                               writer.start_tag ("h2", {"class", "main_title"})
+                                       .text ("Since:")
+                                       .end_tag ("h2");
+                               writer.start_tag ("p");
+                       },
+                       () => {
+                               writer.end_tag ("p");
+                       },
+                       () => {},
+                       taglets,
+                       (taglet) => {
+                               var since = taglet as Taglets.Since;
+                               writer.text (since.version);
+                       });
+
+               taglets = element.find_taglets ((Api.Node) _container, typeof (Taglets.See));
+               write_taglets (
+                       () => {
+                               writer.start_tag ("h2", {"class", "main_title"})
+                                       .text ("See also:")
+                                       .end_tag ("h2");
+                               writer.start_tag ("p");
+                       },
+                       () => {
+                               writer.end_tag ("p");
+                       },
+                       () => {
+                               writer.text (", ");
+                       },
+                       taglets,
+                       (taglet) => {
+                               var see = taglet as Taglets.See;
+                               if (see.symbol == null) {
+                                       write_unresolved_symbol_link (see.symbol_name);
+                               } else {
+                                       write_resolved_symbol_link (see.symbol, see.symbol_name);
+                               }
+                       });
+       }
+
+       public override void visit_embedded (Embedded element) {
+               var caption = element.caption;
+
+               var absolute_path = Path.build_filename (settings.path, element.package.name, "img",
+                                                                                                
Path.get_basename (element.url));
+               var relative_path = Path.build_filename ("img", Path.get_basename (element.url));
+
+               copy_file (element.url, absolute_path);
+
+               writer.image (relative_path, (caption == null || caption == "") ? "" : caption);
+       }
+
+       public override void visit_headline (Headline element) {
+               writer.start_tag ("h%d".printf (element.level));
+               element.accept_children (this);
+               writer.end_tag ("h%d".printf (element.level));
+       }
+
+       public override void visit_wiki_link (WikiLink element) {
+               if (element.page != null) {
+                       writer.start_tag ("a", {"href", get_url (element.page)});
+               }
+
+               if (element.content.size > 0) {
+                       element.accept_children (this);
+               } else {
+                       writer.text (element.name.substring (0, element.name.last_index_of_char ('.')));
+               }
+
+               if (element.page != null) {
+                       writer.end_tag ("a");
+               }
+       }
+
+       public override void visit_link (Link element) {
+               if (Uri.parse_scheme (element.url) != null) {
+                       writer.start_tag ("a", {"href", element.url, "target", "_blank"});
+               } else {
+                       writer.start_tag ("a", {"href", element.url});
+               }
+
+               if (element.content.size > 0) {
+                       element.accept_children (this);
+               } else {
+                       writer.text (element.url);
+               }
+
+               writer.end_tag ("a");
+       }
+
+       public override void visit_symbol_link (SymbolLink element) {
+               if (element.symbol == null) {
+                       write_unresolved_symbol_link (element.given_symbol_name, element);
+               } else {
+                       write_resolved_symbol_link (element.symbol, element.given_symbol_name, element);
+               }
+       }
+
+       public override void visit_list (Content.List element) {
+               string list_type = null;
+               string bullet_type = null;
+               string css_class = null;
+               switch (element.bullet) {
+               case Content.List.Bullet.NONE:
+                       list_type = "ul";
+                       css_class = "no_bullet";
+                       break;
+               case Content.List.Bullet.UNORDERED:
+                       list_type = "ul";
+                       break;
+               case Content.List.Bullet.ORDERED:
+                       list_type = "ol";
+                       break;
+               case Content.List.Bullet.ORDERED_NUMBER:
+                       list_type = "ol";
+                       bullet_type = "1";
+                       break;
+               case Content.List.Bullet.ORDERED_LOWER_CASE_ALPHA:
+                       list_type = "ol";
+                       bullet_type = "a";
+                       break;
+               case Content.List.Bullet.ORDERED_UPPER_CASE_ALPHA:
+                       list_type = "ol";
+                       bullet_type = "A";
+                       break;
+               case Content.List.Bullet.ORDERED_LOWER_CASE_ROMAN:
+                       list_type = "ol";
+                       bullet_type = "i";
+                       break;
+               case Content.List.Bullet.ORDERED_UPPER_CASE_ROMAN:
+                       list_type = "ol";
+                       bullet_type = "I";
+                       break;
+               }
+               writer.start_tag (list_type, {"class", css_class, "type", bullet_type});
+               element.accept_children (this);
+               writer.end_tag (list_type);
+       }
+
+       public override void visit_list_item (ListItem element) {
+               writer.start_tag ("li");
+               Paragraph? first_para = (element.content.size > 0)? element.content[0] as Paragraph : null;
+               if (first_para != null) {
+                       // We do not pick up alignments in gir-files.
+                       first_para.accept_children (this);
+                       bool first_entry = true;
+                       foreach (var item in element.content) {
+                               if (!first_entry) {
+                                       item.accept (this);
+                               }
+                               first_entry = false;
+                       }
+               } else {
+                       element.accept_children (this);
+               }
+               writer.end_tag ("li");
+       }
+
+       public override void visit_page (Page element) {
+               element.accept_children (this);
+       }
+
+       public override void visit_paragraph (Paragraph element) {
+               //FIXME: the extra-field is just a workarround for the current codegen ...
+               if (element.horizontal_align == null) {
+                       writer.start_tag ("p");
+               } else {
+                       HorizontalAlign tmp = element.horizontal_align;
+                       switch (tmp) {
+                       case HorizontalAlign.CENTER:
+                               writer.start_tag ("p", {"style", "text-align: center;"});
+                               break;
+
+                       case HorizontalAlign.RIGHT:
+                               writer.start_tag ("p", {"style", "text-align: right;"});
+                               break;
+
+                       default:
+                               writer.start_tag ("p");
+                               break;
+                       }
+               }
+               element.accept_children (this);
+               writer.end_tag ("p");
+       }
+
+       private void visit_notification_block (BlockContent element, string headline) {
+               writer.start_tag ("div", {"class", "main_notification_block"});
+               writer.start_tag ("span", {"class", "main_block_headline"})
+                       .text (headline)
+                       .end_tag ("span")
+                       .text (" ");
+               writer.start_tag ("div", {"class", "main_block_content"});
+               element.accept_children (this);
+               writer.end_tag ("div");
+               writer.end_tag ("div");
+       }
+
+       public override void visit_warning (Warning element) {
+               visit_notification_block (element, "Warning:");
+       }
+
+       public override void visit_note (Note element) {
+               visit_notification_block (element, "Note:");
+       }
+
+       public override void visit_run (Run element) {
+               string tag = null;
+               string css_type = null;
+               switch (element.style) {
+               case Run.Style.BOLD:
+                       tag = "b";
+                       break;
+               case Run.Style.ITALIC:
+                       tag = "i";
+                       break;
+               case Run.Style.UNDERLINED:
+                       tag = "u";
+                       break;
+               case Run.Style.MONOSPACED:
+                       tag = "code";
+                       break;
+               case Run.Style.STROKE:
+                       tag = "stroke";
+                       break;
+               case Run.Style.LANG_KEYWORD:
+                       tag = "span";
+                       css_type = "main_keyword";
+                       break;
+               case Run.Style.LANG_ESCAPE:
+                       tag = "span";
+                       css_type = "main_escape";
+                       break;
+               case Run.Style.LANG_LITERAL:
+                       tag = "span";
+                       css_type = "main_literal";
+                       break;
+               case Run.Style.LANG_BASIC_TYPE:
+                       tag = "span";
+                       css_type = "main_basic_type";
+                       break;
+               case Run.Style.LANG_TYPE:
+                       tag = "span";
+                       css_type = "main_type";
+                       break;
+               case Run.Style.LANG_COMMENT:
+                       tag = "span";
+                       css_type = "main_comment";
+                       break;
+               case Run.Style.LANG_PREPROCESSOR:
+                       tag = "span";
+                       css_type = "main_preprocessor";
+                       break;
+
+               case Run.Style.XML_ESCAPE:
+                       tag = "span";
+                       css_type = "xml_escape";
+                       break;
+
+               case Run.Style.XML_ELEMENT:
+                       tag = "span";
+                       css_type = "xml_element";
+                       break;
+
+               case Run.Style.XML_ATTRIBUTE:
+                       tag = "span";
+                       css_type = "xml_attribute";
+                       break;
+
+               case Run.Style.XML_ATTRIBUTE_VALUE:
+                       tag = "span";
+                       css_type = "xml_attribute_value";
+                       break;
+
+               case Run.Style.XML_COMMENT:
+                       tag = "span";
+                       css_type = "xml_comment";
+                       break;
+
+               case Run.Style.XML_CDATA:
+                       tag = "span";
+                       css_type = "xml_cdata";
+                       break;
+               }
+               if (tag != null) {
+                       writer.start_tag (tag, {"class", css_type});
+               }
+               element.accept_children (this);
+               if (tag != null) {
+                       writer.end_tag (tag);
+               }
+       }
+
+       public override void visit_source_code (SourceCode element) {
+               writer.set_wrap (false);
+               writer.start_tag ("pre", {"class", "main_source"});
+               element.accept_children (this);
+               writer.end_tag ("pre");
+               writer.set_wrap (true);
+       }
+
+       public override void visit_table (Table element) {
+               writer.start_tag ("table", {"class", "main_table"});
+               element.accept_children (this);
+               writer.end_tag ("table");
+       }
+
+       public override void visit_table_cell (TableCell element) {
+               string style = "";
+
+               if (element.horizontal_align != null) {
+                       style += "text-align: "+element.horizontal_align.to_string ()+"; ";
+               }
+
+               if (element.vertical_align != null) {
+                       style += "vertical-align: "+element.vertical_align.to_string ()+"; ";
+               }
+
+               writer.start_tag ("td", {"class", "main_table",
+                                                 "colspan", element.colspan.to_string (),
+                                                 "rowspan", element.rowspan.to_string (),
+                                                 "style", style});
+               element.accept_children (this);
+               writer.end_tag ("td");
+       }
+
+       public override void visit_table_row (TableRow element) {
+               writer.start_tag ("tr");
+               element.accept_children (this);
+               writer.end_tag ("tr");
+       }
+
+       public override void visit_taglet (Taglet element) {
+       }
+
+       public override void visit_text (Text element) {
+               write_string (element.content);
+       }
+
+       private void write_string (string content) {
+               unichar chr = content[0];
+               long lpos = 0;
+               int i = 0;
+
+               for (i = 0; chr != '\0' ; i++, chr = content[i]) {
+                       switch (chr) {
+                       case '\n':
+                               writer.text (content.substring (lpos, i-lpos));
+                               writer.simple_tag ("br");
+                               lpos = i+1;
+                               break;
+                       case '<':
+                               writer.text (content.substring (lpos, i-lpos));
+                               writer.text ("&lt;");
+                               lpos = i+1;
+                               break;
+                       case '>':
+                               writer.text (content.substring (lpos, i-lpos));
+                               writer.text ("&gt;");
+                               lpos = i+1;
+                               break;
+                       case '&':
+                               writer.text (content.substring (lpos, i-lpos));
+                               writer.text ("&amp;");
+                               lpos = i+1;
+                               break;
+                       }
+               }
+               writer.text (content.substring (lpos, i-lpos));
+       }
+}
+
diff --git a/libvaladoc/html/linkhelper.vala b/libvaladoc/html/linkhelper.vala
new file mode 100644
index 0000000..7e3c9bd
--- /dev/null
+++ b/libvaladoc/html/linkhelper.vala
@@ -0,0 +1,186 @@
+/* linkhelper.vala
+ *
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+
+public class Valadoc.Html.LinkHelper : Object {
+       protected Settings _settings = null;
+
+       public bool enable_browsable_check {
+               default = true;
+               get;
+               set;
+       }
+
+       public virtual string? get_package_link (Api.Package package, Settings settings) {
+               if (enable_browsable_check && !package.is_browsable (settings)) {
+                       return null;
+               }
+
+               return Path.build_filename (package.name, "index.htm");
+       }
+
+       public string? get_relative_link (Documentation from, Documentation to, Settings settings) {
+               _settings = settings;
+
+               //TODO: find a better solution which does not require too much code ...
+               if (from is Api.Package) {
+                       if (to is Api.Package) {
+                               return from_package_to_package ((Api.Package) from, (Api.Package) to);
+                       } else if (to is Api.Node) {
+                               return from_package_to_node ((Api.Package) from, (Api.Node) to);
+                       } else if (to is WikiPage) {
+                               return from_package_to_wiki ((Api.Package) from, (WikiPage) to);
+                       } else {
+                               assert (true);
+                       }
+               } else if (from is Api.Node) {
+                       if (to is Api.Package) {
+                               return from_node_to_package ((Api.Node) from, (Api.Package) to);
+                       } else if (to is Api.Node) {
+                               return from_node_to_node ((Api.Node) from, (Api.Node) to);
+                       } else if (to is WikiPage) {
+                               return from_node_to_wiki ((Api.Node) from, (WikiPage) to);
+                       } else {
+                               assert (true);
+                       }
+               } else if (from is WikiPage) {
+                       if (to is Api.Package) {
+                               return from_wiki_to_package ((WikiPage) from, (Api.Package) to);
+                       } else if (to is Api.Node) {
+                               return from_wiki_to_node ((WikiPage) from, (Api.Node) to);
+                       } else if (to is WikiPage) {
+                               return from_wiki_to_wiki ((WikiPage) from, (WikiPage) to);
+                       } else {
+                               assert (true);
+                       }
+               } else {
+                       assert (true);
+               }
+
+               return null;
+       }
+
+       protected string translate_wiki_name (WikiPage page) {
+               var name = page.name;
+               return name.substring (0, name.last_index_of_char ('.')).replace ("/", ".") + ".htm";
+       }
+
+
+
+
+       protected virtual string? from_package_to_package (Api.Package from, Api.Package to) {
+               if (enable_browsable_check && !to.is_browsable(_settings)) {
+                       return null;
+               }
+
+               if (from == to) {
+                       return "#";
+               } else {
+                       return Path.build_filename ("..", to.name, "index.htm");
+               }
+       }
+
+       protected virtual string? from_package_to_wiki (Api.Package from, WikiPage to) {
+               if (from.is_package) {
+                       return Path.build_filename ("..", _settings.pkg_name, translate_wiki_name (to));
+               } else {
+                       return translate_wiki_name (to);
+               }
+       }
+
+       protected virtual string? from_package_to_node (Api.Package from, Api.Node to) {
+               if (enable_browsable_check && (!to.is_browsable(_settings) || !to.package.is_browsable 
(_settings))) {
+                       return null;
+               }
+
+               if (from == to.package) {
+                       return Path.build_filename (to.get_full_name () + ".html");
+               } else {
+                       return Path.build_filename ("..", to.package.name, to.get_full_name () + ".html");
+               }
+       }
+
+
+
+       protected virtual string? from_wiki_to_package (WikiPage from, Api.Package to) {
+               if (enable_browsable_check && !to.is_browsable(_settings)) {
+                       return null;
+               }
+
+               if (to.is_package) {
+                       return Path.build_filename ("..", to.name, "index.htm");
+               } else {
+                       return "index.htm";
+               }
+       }
+
+       protected virtual string? from_wiki_to_wiki (WikiPage from, WikiPage to) {
+               return translate_wiki_name (to);
+       }
+
+       protected virtual string? from_wiki_to_node (WikiPage from, Api.Node to) {
+               if (enable_browsable_check && (!to.is_browsable(_settings) || !to.package.is_browsable 
(_settings))) {
+                       return null;
+               }
+
+               if (to.package.is_package) {
+                       return Path.build_filename ("..", to.package.name, to.get_full_name () + ".html");
+               } else {
+                       return to.get_full_name () + ".html";
+               }
+       }
+
+
+
+       protected virtual string? from_node_to_package (Api.Node from, Api.Package to) {
+               if (enable_browsable_check && !to.is_browsable (_settings)) {
+                       return null;
+               }
+
+               if (from.package == to) {
+                       return "index.htm";
+               } else {
+                       return Path.build_filename ("..", to.name, "index.htm");
+               }
+       }
+
+       protected virtual string? from_node_to_wiki (Api.Node from, WikiPage to) {
+               if (from.package.is_package) {
+                       return Path.build_filename ("..", _settings.pkg_name, translate_wiki_name (to));
+               } else {
+                       return translate_wiki_name (to);
+               }
+       }
+
+       protected virtual string? from_node_to_node (Api.Node from, Api.Node to) {
+               if (enable_browsable_check && (!to.is_browsable(_settings) || !to.package.is_browsable 
(_settings))) {
+                       return null;
+               }
+
+               if (from.package == to.package) {
+                       return Path.build_filename (to.get_full_name() + ".html");
+               } else {
+                       return Path.build_filename ("..", to.package.name, to.get_full_name() + ".html");
+               }
+       }
+ }
+
diff --git a/libvaladoc/importer/documentationimporter.vala b/libvaladoc/importer/documentationimporter.vala
new file mode 100644
index 0000000..2701571
--- /dev/null
+++ b/libvaladoc/importer/documentationimporter.vala
@@ -0,0 +1,44 @@
+/* resourcelocator.vala
+ *
+ * Copyright (C) 2008-2009 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>
+ */
+
+
+public abstract class Valadoc.Importer.DocumentationImporter : Object, ResourceLocator {
+       protected ModuleLoader modules;
+       protected Settings settings;
+       protected Api.Tree tree;
+
+       public abstract string file_extension { get; }
+
+       public DocumentationImporter (Api.Tree tree, ModuleLoader modules, Settings settings) {
+               this.settings = settings;
+               this.modules = null;
+               this.tree = tree;
+       }
+
+       public virtual string resolve (string path) {
+               return path;
+       }
+
+       public abstract void process (string filename);
+}
+
+
diff --git a/libvaladoc/importer/girdocumentationimporter.vala 
b/libvaladoc/importer/girdocumentationimporter.vala
new file mode 100644
index 0000000..e64dfc6
--- /dev/null
+++ b/libvaladoc/importer/girdocumentationimporter.vala
@@ -0,0 +1,859 @@
+/* girdocumentationimporter.vala
+ *
+ * Copyright (C) 2008-2010  Jürg Billeter
+ * Copyright (C) 2011       Luca Bruno
+ * Copyright (C) 2011-2014  Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Jürg Billeter <j bitron ch>
+ *     Luca Bruno <lucabru src gnome org>
+ *  Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Valadoc;
+
+public class Valadoc.Importer.GirDocumentationImporter : DocumentationImporter {
+       public override string file_extension {
+               get {
+                       return "gir";
+               }
+       }
+
+       private MarkupTokenType current_token;
+       private MarkupSourceLocation begin;
+       private MarkupSourceLocation end;
+       private MarkupReader reader;
+
+       private DocumentationParser parser;
+       private ErrorReporter reporter;
+       private Api.SourceFile file;
+
+       private string parent_c_identifier;
+
+       private struct ImplicitParameterPos {
+               public int parameter;
+               public int position;
+
+               public ImplicitParameterPos (int parameter, int position) {
+                       this.parameter = parameter;
+                       this.position = position;
+               }
+       }
+
+       public GirDocumentationImporter (Api.Tree tree, DocumentationParser parser,
+                                                                        ModuleLoader modules, Settings 
settings,
+                                                                        ErrorReporter reporter)
+       {
+               base (tree, modules, settings);
+               this.reporter = reporter;
+               this.parser = parser;
+       }
+
+       public override void process (string source_file) {
+               this.file = new Api.SourceFile (new Api.Package (Path.get_basename (source_file), true, null),
+                                                                               source_file, null, null);
+               this.reader = new MarkupReader (source_file, reporter);
+
+               // xml prolog
+               next ();
+               next ();
+
+               next ();
+               parse_repository ();
+
+               reader = null;
+               file = null;
+       }
+
+       private Api.FormalParameter? find_parameter (Api.Node node, string name) {
+               Vala.List<Api.Node> parameters = node.get_children_by_type (Api.NodeType.FORMAL_PARAMETER, 
false);
+               foreach (Api.Node param in parameters) {
+                       if (((Api.FormalParameter) param).name == name) {
+                               return (Api.FormalParameter) param;
+                       }
+               }
+
+               return null;
+       }
+
+       private inline string? get_cparameter_name (string[] param_names, int length_pos) {
+               if (length_pos < 0 || param_names.length < length_pos) {
+                       return null;
+               }
+
+               return param_names[length_pos];
+       }
+
+       private void attach_comment (string cname,
+                                                                Api.GirSourceComment? comment,
+                                                                string[]? param_names = null,
+                                                                ImplicitParameterPos[]? destroy_notifies = 
null,
+                                                                ImplicitParameterPos[]? closures = null,
+                                                                ImplicitParameterPos[]? array_lengths = null,
+                                                                int array_length_ret = -1)
+       {
+               if (comment == null) {
+                       return ;
+               }
+
+               Api.Node? node = this.tree.search_symbol_cstr (null, cname);
+               if (node == null) {
+                       return;
+               }
+
+               if (param_names != null) {
+                       foreach (ImplicitParameterPos pos in destroy_notifies) {
+                               Api.FormalParameter? param = find_parameter (node, 
param_names[pos.parameter]);
+                               if (param == null) {
+                                       continue ;
+                               }
+
+                               param.implicit_destroy_cparameter_name
+                                       = get_cparameter_name (param_names, pos.position);
+                       }
+
+                       foreach (ImplicitParameterPos pos in closures) {
+                               Api.FormalParameter? param = find_parameter (node, 
param_names[pos.parameter]);
+                               if (param == null) {
+                                       continue ;
+                               }
+
+                               param.implicit_closure_cparameter_name
+                                       = get_cparameter_name (param_names, pos.position);
+                       }
+
+                       foreach (ImplicitParameterPos pos in array_lengths) {
+                               Api.FormalParameter? param = find_parameter (node, 
param_names[pos.parameter]);
+                               if (param == null) {
+                                       continue ;
+                               }
+
+                               param.implicit_array_length_cparameter_name
+                                       = get_cparameter_name (param_names, pos.position);
+                       }
+
+                       if (node is Api.Callable) {
+                               ((Api.Callable) node).implicit_array_length_cparameter_name
+                                       = get_cparameter_name (param_names, array_length_ret);
+                       }
+               }
+
+               Content.Comment? content = this.parser.parse (node, comment);
+               if (content == null) {
+                       return;
+               }
+
+               node.documentation = content;
+       }
+
+       private void warning (string message) {
+               reporter.warning (this.file.relative_path, this.begin.line, this.begin.column, 
this.end.column,
+                                                 this.reader.get_line_content (this.begin.line), message);
+       }
+
+       private void error (string message) {
+               reporter.error (this.file.relative_path, this.begin.line, this.begin.column, this.end.column,
+                                               this.reader.get_line_content (this.begin.line), message);
+       }
+
+       private void next () {
+               current_token = reader.read_token (out begin, out end);
+
+               // Skip <annotation /> (only generated by valac)
+               if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "annotation") {
+                       next (); // MarkupTokenType.END_ELEMENT, annotation
+                       next ();
+               }
+       }
+
+       private void start_element (string name) {
+               if (current_token != MarkupTokenType.START_ELEMENT || reader.name != name) {
+                       // error
+                       error ("expected start element of `%s'".printf (name));
+               }
+       }
+
+       private void end_element (string name) {
+               if (current_token != MarkupTokenType.END_ELEMENT || reader.name != name) {
+                       // error
+                       error ("expected end element of `%s'".printf (name));
+               }
+               next ();
+       }
+
+       private const string GIR_VERSION = "1.2";
+
+       private void parse_repository () {
+               start_element ("repository");
+               if (reader.get_attribute ("version") != GIR_VERSION) {
+                       error ("unsupported GIR version %s (supported: %s)"
+                               .printf (reader.get_attribute ("version"), GIR_VERSION));
+                       return;
+               }
+               next ();
+
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+                       if (reader.name == "namespace") {
+                               parse_namespace ();
+                       } else if (reader.name == "include") {
+                               parse_include ();
+                       } else if (reader.name == "package") {
+                               parse_package ();
+                       } else if (reader.name == "c:include") {
+                               parse_c_include ();
+                       } else {
+                               // error
+                               error ("unknown child element `%s' in `repository'".printf (reader.name));
+                               skip_element ();
+                       }
+               }
+               end_element ("repository");
+       }
+
+       private void parse_include () {
+               start_element ("include");
+               next ();
+
+               end_element ("include");
+       }
+
+       private void parse_package () {
+               start_element ("package");
+               next ();
+
+               end_element ("package");
+       }
+
+       private void parse_c_include () {
+               start_element ("c:include");
+               next ();
+
+               end_element ("c:include");
+       }
+
+       private void skip_element () {
+               next ();
+
+               int level = 1;
+               while (level > 0) {
+                       if (current_token == MarkupTokenType.START_ELEMENT) {
+                               level++;
+                       } else if (current_token == MarkupTokenType.END_ELEMENT) {
+                               level--;
+                       } else if (current_token == MarkupTokenType.EOF) {
+                               error ("unexpected end of file");
+                               break;
+                       }
+                       next ();
+               }
+       }
+
+       private void parse_namespace () {
+               start_element ("namespace");
+
+               next ();
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+                       if (reader.name == "alias") {
+                               parse_alias ();
+                       } else if (reader.name == "enumeration") {
+                               parse_enumeration ();
+                       } else if (reader.name == "bitfield") {
+                               parse_bitfield ();
+                       } else if (reader.name == "function") {
+                               parse_method ("function");
+                       } else if (reader.name == "callback") {
+                               parse_callback ();
+                       } else if (reader.name == "record") {
+                               parse_record ();
+                       } else if (reader.name == "class") {
+                               parse_class ();
+                       } else if (reader.name == "interface") {
+                               parse_interface ();
+                       } else if (reader.name == "glib:boxed") {
+                               parse_boxed ("glib:boxed");
+                       } else if (reader.name == "union") {
+                               parse_union ();
+                       } else if (reader.name == "constant") {
+                               parse_constant ();
+                       } else {
+                               // error
+                               error ("unknown child element `%s' in `namespace'".printf (reader.name));
+                               skip_element ();
+                       }
+               }
+
+               end_element ("namespace");
+       }
+
+       private void parse_alias () {
+               start_element ("alias");
+               string c_identifier = reader.get_attribute ("c:type");
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               attach_comment (c_identifier, comment);
+
+               parse_type ();
+
+               end_element ("alias");
+       }
+
+       private Api.GirSourceComment? parse_symbol_doc () {
+               Api.GirSourceComment? comment = null;
+
+               if (reader.name == "doc") {
+                       start_element ("doc");
+                       next ();
+
+
+                       if (current_token == MarkupTokenType.TEXT) {
+                               comment = new Api.GirSourceComment (reader.content, file, begin.line,
+                                                                                                       
begin.column, end.line, end.column);
+                               next ();
+                       }
+
+                       end_element ("doc");
+               }
+
+               while (true) {
+                       if (reader.name == "doc-deprecated") {
+                               Api.SourceComment? doc_deprecated = parse_doc ("doc-deprecated");
+                               if (doc_deprecated != null) {
+                                       if (comment == null) {
+                                               comment = new Api.GirSourceComment ("", file, begin.line, 
end.line,
+                                                                                                             
          begin.line, end.line);
+                                       }
+
+                                       comment.deprecated_comment = doc_deprecated;
+                               }
+                       } else if (reader.name == "doc-version") {
+                               Api.SourceComment? doc_version = parse_doc ("doc-version");
+                               if (doc_version != null) {
+                                       if (comment == null) {
+                                               comment = new Api.GirSourceComment ("", file, begin.line, 
end.line,
+                                                                                                             
          begin.line, end.line);
+                                       }
+
+                                       comment.version_comment = doc_version;
+                               }
+                       } else if (reader.name == "doc-stability") {
+                               Api.SourceComment? doc_stability = parse_doc ("doc-stability");
+                               if (doc_stability != null) {
+                                       if (comment == null) {
+                                               comment = new Api.GirSourceComment ("", file, begin.line, 
end.line,
+                                                                                                             
          begin.line, end.line);
+                                       }
+
+                                       comment.stability_comment = doc_stability;
+                               }
+                       } else {
+                               break;
+                       }
+               }
+
+               return comment;
+       }
+
+       private Api.SourceComment? parse_doc (string element_name = "doc") {
+               if (reader.name != element_name) {
+                       return null;
+               }
+
+               start_element (element_name);
+               next ();
+
+               Api.SourceComment? comment = null;
+
+               if (current_token == MarkupTokenType.TEXT) {
+                       comment = new Api.SourceComment (reader.content, file, begin.line,
+                                                                                        begin.column, 
end.line, end.column);
+                       next ();
+               }
+
+               end_element (element_name);
+               return comment;
+       }
+
+       private void parse_enumeration (string element_name = "enumeration") {
+               start_element (element_name);
+               this.parent_c_identifier = reader.get_attribute ("c:type");
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               attach_comment (this.parent_c_identifier, comment);
+
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+                       if (reader.name == "member") {
+                               parse_enumeration_member ();
+                       } else if (reader.name == "function") {
+                               skip_element ();
+                       } else {
+                               // error
+                               error ("unknown child element `%s' in `%s'".printf (reader.name, 
element_name));
+                               skip_element ();
+                       }
+               }
+
+               this.parent_c_identifier = null;
+               end_element (element_name);
+       }
+
+       private void parse_bitfield () {
+               parse_enumeration ("bitfield");
+       }
+
+       private void parse_enumeration_member () {
+               start_element ("member");
+               string c_identifier = reader.get_attribute ("c:identifier");
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               attach_comment (c_identifier, comment);
+
+               end_element ("member");
+       }
+
+       private void parse_return_value (out Api.SourceComment? comment, out int array_length_ret) {
+               start_element ("return-value");
+               next ();
+
+               comment = parse_doc ();
+
+               parse_type (out array_length_ret);
+
+               end_element ("return-value");
+       }
+
+       private void parse_parameter (out Api.SourceComment? comment, out string param_name,
+                                                                 out int destroy_pos,
+                                                                 out int closure_pos, out int 
array_length_pos) {
+               start_element ("parameter");
+               param_name = reader.get_attribute ("name");
+               array_length_pos = -1;
+               destroy_pos = -1;
+               closure_pos = -1;
+
+               string? closure = reader.get_attribute ("closure");
+               if (closure != null) {
+                       closure_pos = int.parse (closure);
+                       if (closure_pos < 0) {
+                               warning ("invalid closure position");
+                       }
+               }
+
+               string? destroy = reader.get_attribute ("destroy");
+               if (destroy != null) {
+                       destroy_pos = int.parse (destroy);
+                       if (destroy_pos < 0) {
+                               warning ("invalid destroy position");
+                       }
+               }
+               next ();
+
+               comment = parse_doc ();
+
+               if (reader.name == "varargs") {
+                       start_element ("varargs");
+                       param_name = "...";
+                       next ();
+
+                       end_element ("varargs");
+               } else {
+                       parse_type (out array_length_pos);
+               }
+
+               end_element ("parameter");
+       }
+
+       private void parse_type (out int array_length_pos = null) {
+               array_length_pos = -1;
+
+               if (reader.name == "array") {
+                       string? length = reader.get_attribute ("length");
+                       if (length != null) {
+                               array_length_pos = int.parse (length);
+                               if (array_length_pos < 0) {
+                                       warning ("invalid array lenght position");
+                               }
+                       }
+
+                       skip_element ();
+               } else {
+                       skip_element ();
+               }
+       }
+
+       private void parse_record () {
+               start_element ("record");
+               this.parent_c_identifier = reader.get_attribute ("c:type");
+               if (this.parent_c_identifier.has_suffix ("Private")) {
+                       this.parent_c_identifier = null;
+                       skip_element ();
+                       return ;
+               }
+
+               bool is_type_struct = (reader.get_attribute ("glib:is-gtype-struct-for") != null);
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               if (is_type_struct == false) {
+                       attach_comment (this.parent_c_identifier, comment);
+               }
+
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+                       if (reader.name == "field") {
+                               parse_field ();
+                       } else if (reader.name == "constructor") {
+                               parse_constructor ();
+                       } else if (reader.name == "method") {
+                               parse_method ("method");
+                       } else if (reader.name == "function") {
+                               skip_element ();
+                       } else if (reader.name == "union") {
+                               parse_union ();
+                       } else {
+                               // error
+                               error ("unknown child element `%s' in `record'".printf (reader.name));
+                               skip_element ();
+                       }
+               }
+
+               this.parent_c_identifier = null;
+               end_element ("record");
+       }
+
+       private void parse_class () {
+               start_element ("class");
+               this.parent_c_identifier = reader.get_attribute ("c:type");
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               attach_comment (this.parent_c_identifier, comment);
+
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+                       if (reader.name == "implements") {
+                               skip_element ();
+                       } else if (reader.name == "constant") {
+                               parse_constant ();
+                       } else if (reader.name == "field") {
+                               parse_field ();
+                       } else if (reader.name == "property") {
+                               parse_property ();
+                       } else if (reader.name == "constructor") {
+                               parse_constructor ();
+                       } else if (reader.name == "function") {
+                               parse_method ("function");
+                       } else if (reader.name == "method") {
+                               parse_method ("method");
+                       } else if (reader.name == "virtual-method") {
+                               parse_method ("virtual-method");
+                       } else if (reader.name == "union") {
+                               parse_union ();
+                       } else if (reader.name == "glib:signal") {
+                               parse_signal ();
+                       } else {
+                               // error
+                               error ("unknown child element `%s' in `class'".printf (reader.name));
+                               skip_element ();
+                       }
+               }
+
+               this.parent_c_identifier = null;
+               end_element ("class");
+       }
+
+       private void parse_interface () {
+               start_element ("interface");
+               this.parent_c_identifier = reader.get_attribute ("c:type");
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               attach_comment (this.parent_c_identifier, comment);
+
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+                       if (reader.name == "prerequisite") {
+                               skip_element ();
+                       } else if (reader.name == "field") {
+                               parse_field ();
+                       } else if (reader.name == "property") {
+                               parse_property ();
+                       } else if (reader.name == "virtual-method") {
+                               parse_method ("virtual-method");
+                       } else if (reader.name == "function") {
+                               parse_method ("function");
+                       } else if (reader.name == "method") {
+                               parse_method ("method");
+                       } else if (reader.name == "glib:signal") {
+                               parse_signal ();
+                       } else {
+                               // error
+                               error ("unknown child element `%s' in `interface'".printf (reader.name));
+                               skip_element ();
+                       }
+               }
+
+               this.parent_c_identifier = null;
+               end_element ("interface");
+       }
+
+       private void parse_field () {
+               start_element ("field");
+               string c_identifier = reader.get_attribute ("name");
+               if (this.parent_c_identifier != null) {
+                       c_identifier = this.parent_c_identifier + "." + c_identifier;
+               }
+               next ();
+
+               parse_symbol_doc ();
+
+               parse_type ();
+
+               end_element ("field");
+       }
+
+       private void parse_property () {
+               start_element ("property");
+               string c_identifier = "%s:%s".printf (parent_c_identifier, reader.get_attribute ("name")
+                       .replace ("-", "_"));
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               attach_comment (c_identifier, comment);
+
+               parse_type ();
+
+               end_element ("property");
+       }
+
+       private void parse_callback () {
+               parse_function ("callback");
+       }
+
+       private void parse_constructor () {
+               parse_function ("constructor");
+       }
+
+       private void parse_function (string element_name) {
+               start_element (element_name);
+
+               string? c_identifier = null;
+               switch (element_name) {
+               case "constructor":
+               case "function":
+               case "method":
+                       c_identifier = reader.get_attribute ("c:identifier");
+                       break;
+
+               case "callback":
+                       c_identifier = reader.get_attribute ("c:type");
+                       break;
+
+               case "virtual-method":
+                       c_identifier = "%s->%s".printf (this.parent_c_identifier, reader.get_attribute 
("name")
+                               .replace ("-", "_"));
+                       break;
+
+               case "glib:signal":
+                       c_identifier = "%s::%s".printf (this.parent_c_identifier, reader.get_attribute 
("name")
+                               .replace ("-", "_"));
+                       break;
+
+               default:
+                       skip_element ();
+                       return ;
+               }
+
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+
+               ImplicitParameterPos[] destroy_notifies = new ImplicitParameterPos[0];
+               ImplicitParameterPos[] array_lengths = new ImplicitParameterPos[0];
+               ImplicitParameterPos[] closures = new ImplicitParameterPos[0];
+               string[] param_names = new string[0];
+               int array_length_ret = -1;
+
+               if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "return-value") {
+                       Api.SourceComment? return_comment;
+                       parse_return_value (out return_comment, out array_length_ret);
+                       if (return_comment != null) {
+                               if (comment == null) {
+                                       comment = new Api.GirSourceComment ("", file, begin.line, 
begin.column,
+                                                                                                             
  end.line, end.column);
+                               }
+                               comment.return_comment = return_comment;
+                       }
+               }
+
+
+               if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "parameters") {
+                       start_element ("parameters");
+                       next ();
+
+                       if (current_token == MarkupTokenType.START_ELEMENT && reader.name == 
"instance-parameter") {
+                               string instance_param_name = reader.get_attribute ("name");
+                               next ();
+
+                               Api.SourceComment? param_comment = parse_doc ();
+                               parse_type (null);
+                               end_element ("instance-parameter");
+
+                               if (param_comment != null) {
+                                       if (comment == null) {
+                                               comment = new Api.GirSourceComment ("", file, begin.line, 
begin.column,
+                                                                                                             
          end.line, end.column);
+                                       }
+
+                                       comment.add_parameter_content (instance_param_name, param_comment);
+                                       comment.instance_param_name = instance_param_name;
+                               }
+                       }
+
+                       for (int pcount = 0; current_token == MarkupTokenType.START_ELEMENT; pcount++) {
+                               Api.SourceComment? param_comment;
+                               int array_length_pos;
+                               int destroy_pos;
+                               int closure_pos;
+                               string? param_name;
+
+                               parse_parameter (out param_comment, out param_name, out destroy_pos,
+                                                                out closure_pos, out array_length_pos);
+                               param_names += param_name;
+
+                               if (destroy_pos >= 0 && pcount != destroy_pos) {
+                                       destroy_notifies += ImplicitParameterPos (pcount, destroy_pos);
+                               }
+
+                               if (closure_pos >= 0 && pcount != closure_pos) {
+                                       closures += ImplicitParameterPos (pcount, closure_pos);
+                               }
+
+                               if (array_length_pos >= 0 && pcount != destroy_pos) {
+                                       array_lengths += ImplicitParameterPos (pcount, array_length_pos);
+                               }
+
+                               if (param_comment != null) {
+                                       if (comment == null) {
+                                               comment = new Api.GirSourceComment ("", file, begin.line, 
begin.column,
+                                                                                                             
          end.line, end.column);
+                                       }
+
+                                       comment.add_parameter_content (param_name, param_comment);
+                               }
+                       }
+                       end_element ("parameters");
+               }
+
+               attach_comment (c_identifier, comment, param_names, destroy_notifies, closures,
+                                               array_lengths, array_length_ret);
+
+               end_element (element_name);
+       }
+
+       private void parse_method (string element_name) {
+               parse_function (element_name);
+       }
+
+       private void parse_signal () {
+               parse_function ("glib:signal");
+       }
+
+       private void parse_boxed (string element_name) {
+               start_element (element_name);
+
+               this.parent_c_identifier = reader.get_attribute ("name");
+               if (this.parent_c_identifier == null) {
+                       this.parent_c_identifier = reader.get_attribute ("glib:name");
+               }
+
+               next ();
+
+               parse_symbol_doc ();
+
+               // TODO: process comments
+
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+                       if (reader.name == "field") {
+                               parse_field ();
+                       } else if (reader.name == "constructor") {
+                               parse_constructor ();
+                       } else if (reader.name == "method") {
+                               parse_method ("method");
+                       } else if (reader.name == "function") {
+                               skip_element ();
+                       } else if (reader.name == "union") {
+                               parse_union ();
+                       } else {
+                               // error
+                               error ("unknown child element `%s' in `class'".printf (reader.name));
+                               skip_element ();
+                       }
+               }
+
+               this.parent_c_identifier = null;
+               end_element (element_name);
+       }
+
+       private void parse_union () {
+               start_element ("union");
+               this.parent_c_identifier = reader.get_attribute ("c:type");
+               if (this.parent_c_identifier == null) {
+                       skip_element ();
+                       return ;
+               }
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               attach_comment (this.parent_c_identifier, comment);
+
+               while (current_token == MarkupTokenType.START_ELEMENT) {
+                       if (reader.name == "field") {
+                               parse_field ();
+                       } else if (reader.name == "constructor") {
+                               parse_constructor ();
+                       } else if (reader.name == "method") {
+                               parse_method ("method");
+                       } else if (reader.name == "function") {
+                               skip_element ();
+                       } else if (reader.name == "record") {
+                               parse_record ();
+                       } else {
+                               // error
+                               error ("unknown child element `%s' in `union'".printf (reader.name));
+                               skip_element ();
+                       }
+               }
+
+               this.parent_c_identifier = null;
+               end_element ("union");
+       }
+
+       private void parse_constant () {
+               start_element ("constant");
+               string c_identifier = reader.get_attribute ("c:type");
+               next ();
+
+               Api.GirSourceComment? comment = parse_symbol_doc ();
+               attach_comment (c_identifier, comment);
+
+               parse_type ();
+
+               end_element ("constant");
+       }
+}
+
diff --git a/libvaladoc/importer/internalidregistrar.vala b/libvaladoc/importer/internalidregistrar.vala
new file mode 100644
index 0000000..c92cf3f
--- /dev/null
+++ b/libvaladoc/importer/internalidregistrar.vala
@@ -0,0 +1,87 @@
+/* gtkdocindexsgmlreader.vala
+ *
+ * Copyright (C) 2014  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.InternalIdRegistrar {
+       private Vala.HashMap<string, Api.Node> symbol_map;
+       private Vala.HashMap<string, string> map;
+
+
+       public InternalIdRegistrar () {
+               map = new Vala.HashMap<string, string> (str_hash, str_equal);
+               symbol_map = new Vala.HashMap<string, Api.Node> (str_hash, str_equal);
+       }
+
+       
+       public void register_symbol (string id, Api.Node symbol) {
+               this.symbol_map.set (id, symbol);
+       }
+
+       public string? map_url_id (string id) {
+               return map.get (id);
+       }
+
+       public Api.Node? map_symbol_id (string id) {
+               return symbol_map.get (id);
+       }
+
+
+       public void read_index_sgml_file (string filename, string? index_sgml_online, ErrorReporter reporter) 
{
+               MarkupSourceLocation begin;
+               MarkupSourceLocation end;
+               MarkupTokenType token;
+
+               string base_path = index_sgml_online ?? realpath (filename);
+               var reader = new MarkupReader (filename, reporter);
+
+               while ((token = reader.read_token (out begin, out end)) != MarkupTokenType.EOF) {
+                       if (token == MarkupTokenType.START_ELEMENT && reader.name == "ONLINE") {
+                               if (index_sgml_online == null) {
+                                       base_path = reader.get_attribute ("href");
+                                       if (base_path == null) {
+                                               reporter.error (filename, begin.line, begin.column, 
end.column, reader.get_line_content (begin.line), "missing attribute `href' in <ONLINE>");
+                                       }
+                               }
+                       } else if (token == MarkupTokenType.START_ELEMENT && reader.name == "ANCHOR") {
+                               string id = reader.get_attribute ("id");
+                               if (id == null) {
+                                       reporter.error (filename, begin.line, begin.column, end.column, 
reader.get_line_content (begin.line), "missing attribute `id' in <ANCHOR>");
+                               }
+
+                               string href = reader.get_attribute ("href");
+                               if (href == null) {
+                                       reporter.error (filename, begin.line, begin.column, end.column, 
reader.get_line_content (begin.line), "missing attribute `href' in <ANCHOR>");
+                               } else if (index_sgml_online != null) {
+                                       href = Path.get_basename (href);
+                               }
+
+                               map.set (id, Path.build_path ("/", base_path, href));
+                       } else {
+                               reporter.error (filename, begin.line, begin.column, end.column, 
reader.get_line_content (begin.line), "expected element of <ONLINE> or <ANCHOR>");
+                       }
+               }
+       }
+}
+
+
diff --git a/libvaladoc/importer/valadocdocumentationimporter.vala 
b/libvaladoc/importer/valadocdocumentationimporter.vala
new file mode 100644
index 0000000..62ef1d0
--- /dev/null
+++ b/libvaladoc/importer/valadocdocumentationimporter.vala
@@ -0,0 +1,198 @@
+/* resourcelocator.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 Valadoc.Content;
+
+public class Valadoc.Importer.ValadocDocumentationImporter : DocumentationImporter, ResourceLocator {
+       public override string file_extension { get { return "valadoc"; } }
+
+       private ValadocDocumentationScanner _scanner;
+       private DocumentationParser _doc_parser;
+       private Parser _parser;
+
+       private MappedFile _mapped_file;
+       private string _filename;
+       private string _cname;
+       private StringBuilder _comment;
+       private SourceLocation _comment_location;
+       protected Content.ContentFactory factory;
+
+
+       private ErrorReporter reporter;
+
+       public ValadocDocumentationImporter (Api.Tree tree, DocumentationParser parser, ModuleLoader modules,
+                                                                                Settings settings, 
ErrorReporter reporter)
+       {
+               base (tree, modules, settings);
+               this.factory = new Content.ContentFactory (settings, this, modules);
+               this.reporter = reporter;
+
+               _scanner = new ValadocDocumentationScanner (settings);
+               _doc_parser = parser;
+
+               _scanner = new ValadocDocumentationScanner (settings);
+               _parser = new Parser (settings, _scanner, reporter);
+               _scanner.set_parser (_parser);
+
+               _comment = new StringBuilder ();
+               
+               // init parser rules:
+               Rule unprinted_spaces = Rule.many ({
+                       Rule.one_of ({
+                               TokenType.VALADOC_SPACE,
+                               TokenType.VALADOC_TAB
+                       })
+               });
+
+               Rule empty_lines = Rule.many ({
+                       Rule.one_of ({
+                               unprinted_spaces,
+                               TokenType.VALADOC_EOL
+                       })
+               })
+               .set_name ("EmptyLines");
+
+               Rule optional_empty_lines = Rule.option ({
+                       empty_lines
+               });
+
+               Rule documentation = Rule.one_of ({
+                       Rule.seq ({
+                               TokenType.VALADOC_COMMENT_START.action ((token) => { _comment_location = 
token.end; }),
+                               Rule.many ({
+                                       Rule.one_of ({
+                                               TokenType.ANY_WORD.action ((token) => { _comment.append 
(token.to_string ()); }),
+                                               TokenType.VALADOC_COMMENT_START.action ((token) => { 
_comment.append (token.to_string ()); }),
+                                               TokenType.VALADOC_SPACE.action ((token) => { _comment.append 
(token.to_string ()); }),
+                                               TokenType.VALADOC_TAB.action ((token) => { _comment.append 
(token.to_string ()); }),
+                                               TokenType.VALADOC_EOL.action ((token) => { _comment.append 
(token.to_string ()); })
+                                       })
+                               }),
+                               TokenType.VALADOC_COMMENT_END,
+                               optional_empty_lines,
+                               TokenType.ANY_WORD.action ((token) => { _cname = token.to_string (); })
+                       })
+                       .set_reduce (() => {
+                               add_documentation (_cname, _comment, _filename, _comment_location);
+                               _comment.erase ();
+                               _cname = null;
+                       }),
+
+                       TokenType.ANY_WORD.action ((token) => {
+                               add_documentation (token.to_string (), null, _filename, _comment_location);
+                       })
+               })
+               .set_name ("Documentation");
+
+               Rule file = Rule.many ({
+                       Rule.one_of ({
+                               documentation,
+                               optional_empty_lines
+                       })
+               })
+               .set_name ("ValadocFile");
+
+               _parser.set_root_rule (file);
+       }
+
+       private enum InsertionMode {
+               APPEND,
+               PREPEND,
+               REPLACE
+       }
+
+       private void add_documentation (string _symbol_name, StringBuilder? comment, string filename,
+                                                                       SourceLocation src_ref)
+       {
+               Api.Node? symbol = null;
+
+               InsertionMode insertion_mode;
+               string symbol_name;
+               if (_symbol_name.has_suffix ("::append")) {
+                       symbol_name = _symbol_name.substring (0, _symbol_name.length - 8);
+                       insertion_mode = InsertionMode.APPEND;
+               } else if (_symbol_name.has_suffix ("::prepend")) {
+                       symbol_name = _symbol_name.substring (0, _symbol_name.length - 9);
+                       insertion_mode = InsertionMode.PREPEND;
+               } else {
+                       symbol_name = _symbol_name;
+                       insertion_mode = InsertionMode.REPLACE;
+               }
+
+               if (symbol_name.has_prefix ("c::")) {
+                       symbol = tree.search_symbol_cstr (null, symbol_name.substring (3));
+               } else {
+                       symbol = tree.search_symbol_str (null, symbol_name);
+               }
+
+               if (symbol == null) {
+                       if (settings.verbose) {
+                               reporter.simple_warning (filename, "Node `%s' does not exist", symbol_name);
+                       }
+
+                       return ;
+               }
+
+               if (comment != null) {
+                       var docu = _doc_parser.parse_comment_str (symbol, comment.str, filename, 
src_ref.line, src_ref.column);
+                       if (docu != null) {
+                               docu.check (tree, symbol, filename, reporter, settings);
+
+                               if (symbol.documentation == null || insertion_mode == InsertionMode.REPLACE) {
+                                       if (insertion_mode == InsertionMode.APPEND) {
+                                               docu.content.insert (0, factory.create_paragraph ());
+                                       }
+                                       symbol.documentation = docu;
+                               } else if (insertion_mode == InsertionMode.APPEND) {
+                                       symbol.documentation.content.add_all (docu.content);
+                                       merge_taglets (symbol.documentation, docu);
+                               } else if (insertion_mode == InsertionMode.PREPEND) {
+                                       symbol.documentation.content.insert_all (0, docu.content);
+                                       merge_taglets (symbol.documentation, docu);
+                               }
+                       }
+               }
+       }
+
+       private void merge_taglets (Comment comment, Comment imported) {
+               foreach (Taglet taglet in imported.taglets) {
+                       imported.taglets.add (taglet);
+               }
+       }
+
+       public override void process (string filename) {
+               try {
+                       _filename = filename;
+                       _mapped_file = new MappedFile (filename, false);
+                       var content = _mapped_file.get_contents ();
+                       if (content != null) {
+                               _parser.parse ((string) content, filename, 0, 0);
+                       }
+               } catch (FileError err) {
+                       reporter.simple_error (null, "Unable to map file `%s': %s", filename, err.message);
+               } catch (ParserError err) {
+               }
+       }
+}
+
diff --git a/libvaladoc/importer/valadocdocumentationimporterscanner.vala 
b/libvaladoc/importer/valadocdocumentationimporterscanner.vala
new file mode 100644
index 0000000..ec52fdd
--- /dev/null
+++ b/libvaladoc/importer/valadocdocumentationimporterscanner.vala
@@ -0,0 +1,188 @@
+/* valadodocumentationscanner.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>
+ */
+
+
+public class Valadoc.Importer.ValadocDocumentationScanner : Object, Scanner {
+
+       public ValadocDocumentationScanner (Settings settings) {
+               _settings = settings;
+       }
+
+       private Settings _settings;
+       private Parser _parser;
+
+       private string _content;
+       private unowned string _index;
+       private bool _stop;
+       private int _last_line;
+       private int _last_column;
+       private int _line;
+       private int _column;
+       private unichar _last_char;
+       private int _skip;
+       private StringBuilder _current_string = new StringBuilder ();
+
+       public void set_parser (Parser parser) {
+               _parser = parser;
+       }
+
+       public virtual void reset () {
+               _stop = false;
+               _last_line = 0;
+               _last_column = 0;
+               _line = 0;
+               _column = 0;
+               _last_char = 0;
+               _skip = 0;
+               _current_string.erase (0, -1);
+       }
+
+       public void scan (string content) throws ParserError {
+               this._content = content;
+
+               for (_index = _content; !_stop && _index.get_char () != 0; _index = _index.next_char ()) {
+                       unichar c = _index.get_char ();
+                       accept (c);
+               }
+       }
+
+       public void end () throws ParserError {
+               emit_token (TokenType.EOF);
+       }
+
+       public virtual void stop () {
+               _stop = true;
+       }
+
+       public int get_line () {
+               return _line;
+       }
+
+       public virtual string get_line_content () {
+               StringBuilder builder = new StringBuilder ();
+               weak string line_start = _index;
+               unichar c;
+
+               while ((char*) line_start > (char*) _content && line_start.prev_char ().get_char () != '\n') {
+                       line_start = line_start.prev_char ();
+               }
+
+               while ((c = line_start.get_char ()) != '\n' && c != '\0') {
+                       if (c == '\t') {
+                               builder.append_c (' ');
+                       } else {
+                               builder.append_unichar (c);
+                       }
+                       line_start = line_start.next_char ();
+               }
+
+               return builder.str;
+       }
+
+       protected unichar get_next_char (int offset = 1) {
+               return _index.get_char (_index.index_of_nth_char (offset));
+       }
+
+
+       protected void accept (unichar c) throws ParserError {
+               _column++;
+               if (_skip == 0) {
+                       switch (c) {
+                       case '/':
+                               if (get_next_char (1) == '*') {
+                                       emit_token (TokenType.VALADOC_COMMENT_START);
+                                       _skip = 1;
+                               } else {
+                                       append_char (c);
+                               }
+                               break;
+
+                       case '*':
+                               if (get_next_char (1) == '/') {
+                                       emit_token (TokenType.VALADOC_COMMENT_END);
+                                       _skip = 1;
+                               } else {
+                                       append_char (c);
+                               }
+                               break;
+
+                       case '\t':
+                               emit_token (TokenType.VALADOC_TAB);
+                               break;
+
+                       case ' ':
+                               emit_token (TokenType.VALADOC_SPACE);
+                               break;
+
+                       case '\n':
+                               emit_token (TokenType.VALADOC_EOL);
+                               _line++;
+                               _column = 0;
+                               _last_column = 0;
+                               break;
+
+                       default:
+                               append_char (c);
+                               break;
+                       }
+               } else {
+                       _skip--;
+               }
+               _last_char = c;
+       }
+
+       private void append_char (unichar c) {
+               _current_string.append_unichar (c);
+       }
+
+       public virtual 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_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_line = _line;
+               _last_column = _column;
+       }
+
+}
diff --git a/libvaladoc/markupreader.vala b/libvaladoc/markupreader.vala
new file mode 100644
index 0000000..595095d
--- /dev/null
+++ b/libvaladoc/markupreader.vala
@@ -0,0 +1,334 @@
+/* markupreader.vala
+ *
+ * Copyright (C) 2008-2009  Jürg Billeter
+ * Copyright (C) 2011       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Jürg Billeter <j bitron ch>
+ */
+
+
+/**
+ * Simple reader for a subset of XML.
+ */
+public class Valadoc.MarkupReader : Object {
+       public string filename {
+               private set;
+               get;
+       }
+
+       public string name {
+               private set;
+               get;
+       }
+
+       public string content {
+               private set;
+               get;
+       }
+
+       private MappedFile mapped_file;
+
+       private string[] lines;
+       private char* begin;
+       private char* current;
+       private char* end;
+
+       private int line;
+       private int column;
+
+       private Vala.Map<string, string> attributes = new Vala.HashMap<string, string> (str_hash, str_equal);
+       private bool empty_element;
+
+       private ErrorReporter reporter;
+
+       public MarkupReader.from_string (string filename, string content, ErrorReporter reporter) {
+               this.filename = filename;
+               this.reporter = reporter;
+
+               lines = content.split ("\n");
+               begin = content;
+               end = begin + content.length;
+               current = begin;
+
+               column = 1;
+               line = 1;
+       }
+
+       public MarkupReader (string filename, ErrorReporter reporter) {
+               this.filename = filename;
+               this.reporter = reporter;
+
+               try {
+                       mapped_file = new MappedFile (filename, false);
+                       begin = mapped_file.get_contents ();
+                       lines = ((string) begin).split ("\n");
+                       end = begin + mapped_file.get_length ();
+
+                       current = begin;
+
+                       line = 1;
+                       column = 1;
+               } catch (FileError e) {
+                       reporter.simple_error (null, "Unable to map file '%s': %s", filename, e.message);
+               }
+       }
+
+       public string? get_line_content (int line_nr) {
+               if (this.lines.length > line_nr) {
+                       return this.lines[line_nr];
+               }
+
+               return null;
+       }
+
+       public string? get_attribute (string attr) {
+               return attributes[attr];
+       }
+
+       /*
+        * Returns a copy of the current attributes.
+        *
+        * @return map of current attributes
+        */
+       public Vala.Map<string,string> get_attributes () {
+               var result = new Vala.HashMap<string, string> (str_hash, str_equal);
+               foreach (var key in attributes.get_keys ()) {
+                       result.set (key, attributes.get (key));
+               }
+               return result;
+       }
+
+       private string read_name () {
+               char* begin = current;
+               while (current < end) {
+                       if (current[0] == ' ' || current[0] == '\t' || current[0] == '>'
+                           || current[0] == '/' || current[0] == '=' || current[0] == '\n') {
+                               break;
+                       }
+                       unichar u = ((string) current).get_char_validated ((long) (end - current));
+                       if (u != (unichar) (-1)) {
+                               current += u.to_utf8 (null);
+                       } else {
+                               reporter.simple_error ("%s:%d".printf (filename, line),
+                                                                          "invalid UTF-8 character");
+                       }
+               }
+               if (current == begin) {
+                       // syntax error: invalid name
+               }
+               return ((string) begin).substring (0, (int) (current - begin));
+       }
+
+       public MarkupTokenType read_token (out MarkupSourceLocation token_begin, out MarkupSourceLocation 
token_end) {
+               attributes.clear ();
+
+               if (empty_element) {
+                       empty_element = false;
+                       token_begin = MarkupSourceLocation (begin, line, column);
+                       token_end = MarkupSourceLocation (begin, line, column);
+                       return MarkupTokenType.END_ELEMENT;
+               }
+
+               content = null;
+               name = null;
+
+               space ();
+
+               MarkupTokenType type = MarkupTokenType.NONE;
+               char* begin = current;
+               token_begin = MarkupSourceLocation (begin, line, column);
+
+               if (current >= end) {
+                       type = MarkupTokenType.EOF;
+               } else if (current[0] == '<') {
+                       current++;
+                       if (current >= end) {
+                               // error
+                       } else if (current[0] == '?') {
+                               // processing instruction
+                       } else if (current[0] == '!') {
+                               // comment or doctype
+                               current++;
+                               if (current < end - 1 && current[0] == '-' && current[1] == '-') {
+                                       // comment
+                                       current += 2;
+                                       while (current < end - 2) {
+                                               if (current[0] == '-' && current[1] == '-' && current[2] == 
'>') {
+                                                       // end of comment
+                                                       current += 3;
+                                                       break;
+                                               } else if (current[0] == '\n') {
+                                                       line++;
+                                                       column = 0;
+                                               }
+                                               current++;
+                                       }
+
+                                       // ignore comment, read next token
+                                       return read_token (out token_begin, out token_end);
+                               }
+                       } else if (current[0] == '/') {
+                               type = MarkupTokenType.END_ELEMENT;
+                               current++;
+                               name = read_name ();
+                               if (current >= end || current[0] != '>') {
+                                       // error
+                               }
+                               current++;
+                       } else {
+                               type = MarkupTokenType.START_ELEMENT;
+                               name = read_name ();
+                               space ();
+                               while (current < end && current[0] != '>' && current[0] != '/') {
+                                       string attr_name = read_name ();
+                                       if (current >= end || current[0] != '=') {
+                                               // error
+                                       }
+                                       current++;
+                                       // FIXME allow single quotes
+                                       if (current >= end || current[0] != '"') {
+                                               // error
+                                       }
+                                       current++;
+
+                                       string attr_value = text ('"', false);
+
+                                       if (current >= end || current[0] != '"') {
+                                               // error
+                                       }
+                                       current++;
+                                       attributes.set (attr_name, attr_value);
+                                       space ();
+                               }
+                               if (current[0] == '/') {
+                                       empty_element = true;
+                                       current++;
+                                       space ();
+                               } else {
+                                       empty_element = false;
+                               }
+                               if (current >= end || current[0] != '>') {
+                                       // error
+                               }
+                               current++;
+                       }
+               } else {
+                       space ();
+
+                       if (current[0] != '<') {
+                               content = text ('<', true);
+                       } else {
+                               // no text
+                               // read next token
+                               return read_token (out token_begin, out token_end);
+                       }
+
+                       type = MarkupTokenType.TEXT;
+               }
+
+               token_end = MarkupSourceLocation (current, line, column - 1);
+
+               return type;
+       }
+
+       private string text (char end_char, bool rm_trailing_whitespace) {
+               StringBuilder content = new StringBuilder ();
+               char* text_begin = current;
+               char* last_linebreak = current;
+
+               while (current < end && current[0] != end_char) {
+                       unichar u = ((string) current).get_char_validated ((long) (end - current));
+                       if (u == (unichar) (-1)) {
+                               reporter.simple_error ("%s:%d".printf (filename, line),
+                                                                          "invalid UTF-8 character");
+                       } else if (u == '&') {
+                               char* next_pos = current + u.to_utf8 (null);
+                               if (((string) next_pos).has_prefix ("amp;")) {
+                                       content.append (((string) text_begin).substring (0, (int) (current - 
text_begin)));
+                                       content.append_c ('&');
+                                       current += 5;
+                                       text_begin = current;
+                               } else if (((string) next_pos).has_prefix ("quot;")) {
+                                       content.append (((string) text_begin).substring (0, (int) (current - 
text_begin)));
+                                       content.append_c ('"');
+                                       current += 6;
+                                       text_begin = current;
+                               } else if (((string) next_pos).has_prefix ("apos;")) {
+                                       content.append (((string) text_begin).substring (0, (int) (current - 
text_begin)));
+                                       content.append_c ('\'');
+                                       current += 6;
+                                       text_begin = current;
+                               } else if (((string) next_pos).has_prefix ("lt;")) {
+                                       content.append (((string) text_begin).substring (0, (int) (current - 
text_begin)));
+                                       content.append_c ('<');
+                                       current += 4;
+                                       text_begin = current;
+                               } else if (((string) next_pos).has_prefix ("gt;")) {
+                                       content.append (((string) text_begin).substring (0, (int) (current - 
text_begin)));
+                                       content.append_c ('>');
+                                       current += 4;
+                                       text_begin = current;
+                               } else if (((string) next_pos).has_prefix ("percnt;")) {
+                                       content.append (((string) text_begin).substring (0, (int) (current - 
text_begin)));
+                                       content.append_c ('>');
+                                       current += 8;
+                                       text_begin = current;
+                               } else {
+                                       current += u.to_utf8 (null);
+                               }
+                       } else {
+                               if (u == '\n') {
+                                       line++;
+                                       column = 0;
+                                       last_linebreak = current;
+                               }
+
+                               current += u.to_utf8 (null);
+                               column++;
+                       }
+               }
+
+               if (text_begin != current) {
+                       content.append (((string) text_begin).substring (0, (int) (current - text_begin)));
+               }
+
+               column += (int) (current - last_linebreak);
+
+               // Removes trailing whitespace
+               if (rm_trailing_whitespace) {
+                       char* str_pos = ((char*)content.str) + content.len;
+                       for (str_pos--; str_pos > ((char*)content.str) && str_pos[0].isspace(); str_pos--);
+                       content.erase ((ssize_t) (str_pos-((char*) content.str) + 1), -1);
+               }
+
+               return content.str;
+       }
+
+       private void space () {
+               while (current < end && current[0].isspace ()) {
+                       if (current[0] == '\n') {
+                               line++;
+                               column = 0;
+                       }
+                       current++;
+                       column++;
+               }
+       }
+}
+
+
diff --git a/libvaladoc/markupsourcelocation.vala b/libvaladoc/markupsourcelocation.vala
new file mode 100644
index 0000000..af7dff1
--- /dev/null
+++ b/libvaladoc/markupsourcelocation.vala
@@ -0,0 +1,39 @@
+/* valasourcelocation.vala
+ *
+ * Copyright (C) 2008  Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Jürg Billeter <j bitron ch>
+ */
+
+using GLib;
+
+/**
+ * Represents a position in a source file.
+ */
+public struct Valadoc.MarkupSourceLocation {
+       public char* pos;
+       public int line;
+       public int column;
+
+       public MarkupSourceLocation (char* _pos, int _line, int _column) {
+               pos = _pos;
+               line = _line;
+               column = _column;
+       }
+}
+
diff --git a/libvaladoc/markuptokentype.vala b/libvaladoc/markuptokentype.vala
new file mode 100644
index 0000000..d2dcad7
--- /dev/null
+++ b/libvaladoc/markuptokentype.vala
@@ -0,0 +1,51 @@
+/* markuptokentype.vala
+ *
+ * Copyright (C) 2008-2009  Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Jürg Billeter <j bitron ch>
+ */
+
+
+public enum Valadoc.MarkupTokenType {
+       NONE,
+       COMMENT,
+       START_ELEMENT,
+       END_ELEMENT,
+       TEXT,
+       EOF;
+
+       public string to_string () {
+               switch (this) {
+               case START_ELEMENT:
+                       return "start element";
+
+               case END_ELEMENT:
+                       return "end element";
+
+               case TEXT:
+                       return "text";
+
+               case EOF:
+                       return "end of file";
+
+               default:
+                       return "unknown token type";
+               }
+       }
+}
+
diff --git a/libvaladoc/markupwriter.vala b/libvaladoc/markupwriter.vala
new file mode 100644
index 0000000..28a61ff
--- /dev/null
+++ b/libvaladoc/markupwriter.vala
@@ -0,0 +1,272 @@
+/* markupwriter.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+/**
+ * Writes markups and text to a file.
+ */
+public class Valadoc.MarkupWriter {
+       protected WriteFunc write;
+       protected int indent;
+
+       protected long current_column = 0;
+       protected bool last_was_tag;
+       private bool wrap = true;
+
+       public static string escape (string txt) {
+               StringBuilder builder = new StringBuilder ();
+               unowned string start = txt;
+               unowned string pos;
+               unichar c;
+
+               for (pos = txt; (c = pos.get_char ()) != '\0'; pos = pos.next_char ()) {
+                       switch (c) {
+                       case '"':
+                               builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                               builder.append ("&quot;");
+                               start = pos.next_char ();
+                               break;
+
+                       case '<':
+                               builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                               builder.append ("&lt;");
+                               start = pos.next_char ();
+                               break;
+
+                       case '>':
+                               builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                               builder.append ("&gt;");
+                               start = pos.next_char ();
+                               break;
+
+                       case '&':
+                               builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                               builder.append ("&amp;");
+                               start = pos.next_char ();
+                               break;
+
+                       case '\'':
+                               builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                               builder.append ("&apos;");
+                               start = pos.next_char ();
+                               break;
+                       }
+               }
+
+               if (&txt == &start) {
+                       return txt;
+               } else {
+                       builder.append_len (start, (ssize_t) ((char*) pos - (char*) start));
+                       return (owned) builder.str;
+               }
+       }
+
+       /**
+        * Writes text to a desination like a {@link GLib.StringBuilder} or a {@link GLib.FileStream}
+        */
+       public delegate void WriteFunc (string text);
+
+       private const int MAX_COLUMN = 150;
+
+       /**
+        * Initializes a new instance of the MarkupWriter
+        * 
+        * @param write stream a WriteFunc
+        * @param xml_declaration specifies whether this file starts with an xml-declaration
+        */
+       public MarkupWriter (owned WriteFunc write, bool xml_declaration = true) {
+               this.write = (owned) write;
+               if (xml_declaration) {
+                       do_write ("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+               }
+               indent = -1;
+               last_was_tag = true;
+       }
+
+       /**
+        * Writes an start tag of a markup element to the file
+        *
+        * @param name the name of the markup
+        * @param attributes a list of name/value pairs
+        * @return this
+        */
+       public MarkupWriter start_tag (string name, string[]? attributes=null) {
+               indent++;
+               check_column (name);
+
+               if (attributes.length % 2 != 0) {
+                       attributes.resize (attributes.length+1);
+                       attributes[attributes.length-1] = "";
+               }
+
+               var content = new StringBuilder ("<");
+               content.append (name);
+               for (int i = 0; i < attributes.length; i=i+2) {
+                       if (attributes[i+1] != null) {
+                               content.append_printf (" %s=\"%s\"", attributes[i], attributes[i+1]);
+                       }
+               }
+               content.append (">");
+
+               do_write (content.str);
+               last_was_tag = true;
+               return this;
+       }
+
+       /**
+        * Writes a simple tag (<name />) to the file
+        *
+        * @param name the name of the markup
+        * @param attributes a list of name/value pairs
+        * @return this
+        */
+       public MarkupWriter simple_tag (string name, string[]? attributes=null) {
+               indent++;
+               check_column (name);
+
+               if (attributes.length % 2 != 0) {
+                       attributes.resize (attributes.length+1);
+                       attributes[attributes.length-1] = "";
+               }
+
+               var content = new StringBuilder ("<");
+               content.append (name);
+               for (int i = 0; i < attributes.length; i=i+2) {
+                       if (attributes[i+1] != null) {
+                               content.append_printf (" %s=\"%s\"", attributes[i], attributes[i+1]);
+                       }
+               }
+               content.append ("/>");
+
+               do_write (content.str);
+               indent--;
+               last_was_tag = true;
+               return this;
+       }
+
+       /**
+        * Writes an end tag of a markup element to the file
+        *
+        * @param name the name of the markup
+        * @return this
+        */
+       public MarkupWriter end_tag (string name) {
+               check_column (name, true);
+               do_write ("</%s>".printf (name));
+               indent--;
+               last_was_tag = true;
+               return this;
+       }
+
+       /**
+        * Writes the specified string to the output stream
+        *
+        * @see raw_text
+        * @return this
+        */
+       public MarkupWriter text (string text) {
+               if (wrap && text.length + current_column > MAX_COLUMN) {
+                       long wrote = 0;
+                       while (wrote < text.length) {
+                               long space_pos = -1;
+                               for (long i = wrote + 1; i < text.length; i++) {
+                                       if (text[i] == ' ') {
+                                               if (i - wrote + current_column > MAX_COLUMN) {
+                                                       break;
+                                               }
+                                               space_pos = i;
+                                       }
+                               }
+                               if (text.length - wrote + current_column <= MAX_COLUMN) {
+                                       do_write (text.substring (wrote));
+                                       wrote = text.length + 1;
+                               } else if (space_pos == -1) {
+                                       // Force line break
+                               } else {
+                                       do_write (text.substring (wrote, space_pos - wrote));
+                                       wrote = space_pos + 1;
+                               }
+                               if (wrote < text.length) {
+                                       break_line ();
+                                       do_write ("  ");
+                               }
+                       }
+               } else {
+                       do_write (text);
+               }
+               last_was_tag = false;
+               return this;
+       }
+
+       /**
+        * Writes the specified string to the output stream
+        *
+        * @see text
+        * @return this
+        */
+       public MarkupWriter raw_text (string text) {
+               do_write (text);
+               last_was_tag = false;
+               return this;
+       }
+
+       public void set_wrap (bool wrap) {
+               this.wrap = wrap;
+       }
+
+       private void break_line () {
+               write ("\n");
+               write (string.nfill (indent * 2, ' '));
+               current_column = indent * 2;
+       }
+
+       protected void do_write (string text) {
+               if (wrap && current_column + text.length > MAX_COLUMN) {
+                       break_line ();
+               }
+               write (text);
+               current_column += text.length;
+       }
+
+       private void check_column (string name, bool end_tag = false) {
+               if (!wrap) {
+                       return;
+               } else if (!end_tag && inline_element (name) /*&& !last_was_tag*/) {
+                       return;
+               } else if (end_tag && content_inline_element (name)) {
+                       return;
+               } else if (end_tag && !last_was_tag) {
+                       return;
+               }
+               break_line ();
+       }
+
+       protected virtual bool inline_element (string name) {
+               return false;
+       }
+
+       protected virtual bool content_inline_element (string name) {
+               return true;
+       }
+}
+
+
diff --git a/libvaladoc/moduleloader.vala b/libvaladoc/moduleloader.vala
new file mode 100644
index 0000000..7f729a0
--- /dev/null
+++ b/libvaladoc/moduleloader.vala
@@ -0,0 +1,122 @@
+/* moduleloader.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch
+ * 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:
+ *     Brosch Florian <flo brosch gmail com>
+ */
+
+[CCode (has_target = false)]
+public delegate void Valadoc.TagletRegisterFunction (ModuleLoader loader);
+
+public class Valadoc.ModuleLoader : Object {
+       private Vala.HashMap<string, ModuleData> doclets = new Vala.HashMap<string, ModuleData> (str_hash, 
str_equal);
+       private Vala.HashMap<string, GLib.Type> taglets = new Vala.HashMap<string, GLib.Type> (str_hash, 
str_equal);
+
+       private static ModuleLoader instance;
+
+       public static ModuleLoader get_instance () {
+               if (instance == null) {
+                       instance = new ModuleLoader ();
+                       Taglets.init (instance);
+               }
+               return instance;
+       }
+
+       private ModuleLoader () {
+       }
+
+       private class ModuleData : Object {
+               public Module module;
+               public Type type;
+       }
+
+
+       //
+       // path helpers:
+       //
+
+       public static bool is_doclet (string path) {
+               string library_path = Path.build_filename (path, "libdoclet." + Module.SUFFIX);
+               return FileUtils.test (path, FileTest.EXISTS) && FileUtils.test (library_path, 
FileTest.EXISTS);
+       }
+
+       private static string get_plugin_path (string pluginpath, string pluginsubdir) {
+               if (Path.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 = Path.build_filename (Environment.get_current_dir(), pluginpath);
+                       if (is_doclet(local_path)) {
+                               return local_path;
+                       } else {
+                               return Path.build_filename (Config.PACKAGE_DATADIR, pluginsubdir, pluginpath);
+                       }
+               }
+
+               return pluginpath;
+       }
+
+       public static string get_doclet_path (string? docletpath, ErrorReporter reporter) {
+               if (docletpath == null) {
+                       return Path.build_filename (Config.PACKAGE_DATADIR, "doclets", "html");
+               }
+
+               return get_plugin_path (docletpath, "doclets");
+       }
+
+       //
+       // Creation methods:
+       //
+
+       public Content.Taglet? create_taglet (string keyword) {
+               return (taglets.contains (keyword))? (Content.Taglet) GLib.Object.new (taglets.get (keyword)) 
: null;
+       }
+
+       public void register_taglet (string keyword, Type type) {
+               taglets.set (keyword, type);
+       }
+
+       public Doclet? create_doclet (string _path) {
+               string path = realpath (_path);
+
+               ModuleData? data = doclets.get (path);
+               if (data == null) {
+                       void* function;
+
+                       Module? module = Module.open (Module.build_path (path, "libdoclet"), 
ModuleFlags.BIND_LAZY | ModuleFlags.BIND_LOCAL);
+                       if (module == null) {
+                               return null;
+                       }
+
+                       module.symbol("register_plugin", out function);
+                       if (function == null) {
+                               return null;
+                       }
+
+                       Valadoc.DocletRegisterFunction register_func = (Valadoc.DocletRegisterFunction) 
function;
+                       data = new ModuleData ();
+                       doclets.set (path, data);
+
+                       data.type = register_func (this);
+                       data.module = (owned) module;
+               }
+
+               return (Doclet) GLib.Object.new (data.type);
+       }
+}
+
diff --git a/libvaladoc/parser/manyrule.vala b/libvaladoc/parser/manyrule.vala
new file mode 100644
index 0000000..00d928a
--- /dev/null
+++ b/libvaladoc/parser/manyrule.vala
@@ -0,0 +1,111 @@
+/* manyrule.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+internal class Valadoc.ManyRule : Rule {
+
+       public ManyRule (Object scheme) {
+               _scheme = scheme;
+       }
+
+       private Object _scheme;
+
+       private class State : Object {
+               public bool started = false;
+               public bool done_one = false;
+       }
+
+       public override bool is_optional () {
+               return is_optional_rule (_scheme);
+       }
+
+       public override bool starts_with_token (Token token) {
+               if (has_start_token (_scheme, token)) {
+                       return true;
+               }
+               return false;
+       }
+
+       public override bool accept_token (Token token, ParserCallback parser, Rule.Forward forward)
+                                                                          throws ParserError
+       {
+               var state = parser.get_rule_state () as State;
+               if (state == null) {
+                       state = new State ();
+                       parser.set_rule_state (state);
+               }
+
+               if (!state.started) {
+                       do_start (parser);
+                       state.started = true;
+               }
+
+               if (state.done_one && parser.would_parent_accept_token (token)) {
+                       do_reduce (parser);
+                       return false;
+               }
+               if (parser.would_parent_reduce_to_rule (token, this)) {
+                       do_reduce (parser);
+                       return false;
+               }
+
+               bool handled;
+               if (try_to_apply (_scheme, token, parser, out handled)) {
+                       state.done_one = true;
+                       return handled;
+               }
+               if (parser.would_parent_accept_token (token)) {
+                       do_reduce (parser);
+                       return false;
+               }
+
+               if (_scheme is TokenType) {
+                       parser.error (null, "expected %s".printf (((TokenType) _scheme).to_pretty_string ()));
+               } else {
+                       parser.error (token, "unexpected token");
+               }
+               assert_not_reached ();
+       }
+
+       public override bool would_accept_token (Token token, Object? state) {
+               if (has_start_token (_scheme, token)) {
+                       return true;
+               }
+               return false;
+       }
+
+       public override bool would_reduce (Token token, Object? rule_state) {
+               var state = rule_state as State;
+               return state.done_one || is_optional_rule (_scheme);
+       }
+
+       public override string to_string (Object? rule_state) {
+               var state = rule_state as State;
+               if (state == null) {
+                       state = new State ();
+               }
+               return "%-15s%-15s(started=%s;done_one=%s)".printf (name != null ? name : " ",
+                                                                                                             
          "[many]",
+                                                                                                             
          state.started.to_string (),
+                                                                                                             
          state.done_one.to_string ());
+       }
+}
diff --git a/libvaladoc/parser/oneofrule.vala b/libvaladoc/parser/oneofrule.vala
new file mode 100644
index 0000000..4e0144d
--- /dev/null
+++ b/libvaladoc/parser/oneofrule.vala
@@ -0,0 +1,97 @@
+/* oneofrule.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+internal class Valadoc.OneOfRule : Rule {
+
+       public OneOfRule (Object[] scheme) {
+               _scheme = scheme;
+       }
+
+       private Object[] _scheme;
+
+       private class State : Object {
+               public int selected = -1;
+       }
+
+       public override bool is_optional () {
+               return false;
+       }
+
+       public override bool starts_with_token (Token token) {
+               foreach (Object? scheme_element in _scheme) {
+                       if (has_start_token (scheme_element, token)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       public override bool accept_token (Token token, ParserCallback parser, Rule.Forward forward)
+                                                                          throws ParserError
+       {
+               var state = parser.get_rule_state () as State;
+               if (state == null) {
+                       state = new State ();
+                       parser.set_rule_state (state);
+               }
+
+               if (state.selected == -1) {
+                       do_start (parser);
+
+                       bool handled;
+                       for (int i = 0; i < _scheme.length; i++) {
+                               Object? scheme_element = _scheme[i];
+                               if (try_to_apply (scheme_element, token, parser, out handled)) {
+                                       state.selected = i;
+                                       return handled;
+                               }
+                       }
+               } else {
+                       do_reduce (parser);
+                       return false;
+               }
+
+               parser.error (token, "unexpected token");
+               assert_not_reached ();
+       }
+
+       public override bool would_accept_token (Token token, Object? state) {
+               return false;
+       }
+
+       public override bool would_reduce (Token token, Object? rule_state) {
+               var state = rule_state as State;
+               return state.selected != -1;
+       }
+
+       public override string to_string (Object? rule_state) {
+               var state = rule_state as State;
+               if (state == null) {
+                       state = new State ();
+               }
+               return "%-15s%-15s(selected=%d/%d)".printf (name != null ? name : " ",
+                                                                                                       
"[one-of]",
+                                                                                                       
state.selected,
+                                                                                                       
_scheme.length);
+       }
+}
diff --git a/libvaladoc/parser/optionalrule.vala b/libvaladoc/parser/optionalrule.vala
new file mode 100644
index 0000000..aeef1da
--- /dev/null
+++ b/libvaladoc/parser/optionalrule.vala
@@ -0,0 +1,87 @@
+/* optionalrule.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+internal class Valadoc.OptionalRule : Rule {
+
+       public OptionalRule (Object scheme) {
+               _scheme = scheme;
+       }
+
+       private Object _scheme;
+
+       private class State : Object {
+               public bool started = false;
+       }
+
+       public override bool is_optional () {
+               return true;
+       }
+
+       public override bool starts_with_token (Token token) {
+               return has_start_token (_scheme, token);
+       }
+
+       public override bool accept_token (Token token, ParserCallback parser, Rule.Forward forward)
+                                                                          throws ParserError
+       {
+               var state = parser.get_rule_state () as State;
+               if (state == null) {
+                       state = new State ();
+                       parser.set_rule_state (state);
+               }
+
+               if (!state.started) {
+                       do_start (parser);
+                       state.started = true;
+
+                       bool handled;
+                       if (try_to_apply (_scheme, token, parser, out handled)) {
+                               return handled;
+                       } else {
+                               do_skip (parser);
+                               return false;
+                       }
+               } else {
+                       do_reduce (parser);
+                       return false;
+               }
+       }
+
+       public override bool would_accept_token (Token token, Object? state) {
+               return false;
+       }
+
+       public override bool would_reduce (Token token, Object? state) {
+               return true;
+       }
+
+       public override string to_string (Object? rule_state) {
+               var state = rule_state as State;
+               if (state == null) {
+                       state = new State ();
+               }
+               return "%-15s%-15s(started=%s)".printf (name != null ? name : " ",
+                                                                                               "[option]",
+                                                                                               
state.started.to_string ());
+       }
+}
diff --git a/libvaladoc/parser/parser.vala b/libvaladoc/parser/parser.vala
new file mode 100644
index 0000000..acf1d82
--- /dev/null
+++ b/libvaladoc/parser/parser.vala
@@ -0,0 +1,305 @@
+/* parser.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public errordomain Valadoc.ParserError {
+       INTERNAL_ERROR,
+       UNEXPECTED_TOKEN
+}
+
+public class Valadoc.Parser : ParserCallback {
+
+       public Parser (Settings settings, Scanner scanner, ErrorReporter reporter) {
+               _settings = settings;
+               _scanner = scanner;
+               _reporter = reporter;
+
+               TokenType.init_token_types ();
+       }
+
+       private Settings _settings;
+       private Scanner _scanner;
+       private ErrorReporter _reporter;
+       private Rule _root_rule;
+
+       private string _filename;
+       private int _first_line;
+       private int _first_column;
+       private Token _current_token;
+
+       private Vala.ArrayList<Rule> rule_stack = new Vala.ArrayList<Rule> ();
+       private Vala.ArrayList<Object?> rule_state_stack = new Vala.ArrayList<Object?> ();
+
+       public void set_root_rule (Rule root_rule) {
+               _root_rule = root_rule;
+       }
+
+       public void parse (string content, string filename, int first_line, int first_column)
+                                          throws ParserError
+       {
+               _filename = filename;
+               _first_line = first_line;
+               _first_column = first_column;
+
+               rule_stack.clear ();
+               rule_state_stack.clear ();
+
+               try {
+                       push_rule (_root_rule);
+                       _scanner.reset ();
+                       _scanner.scan (content);
+                       _scanner.end ();
+
+                       if (rule_stack.size != 0) {
+                               error (null, "Rule stack is not empty!");
+                       }
+               } catch (ParserError e) {
+                       #if DEBUG
+                               log_error (e.message);
+                       #endif
+                       // Set an in_error boolean, try to recover
+                       // And only throw the error at the end of parse ?
+                       throw e;
+               }
+       }
+
+       public void accept_token (Token token) throws ParserError {
+               #if HARD_DEBUG
+                       debug ("Incomming token: %s", token.to_pretty_string ());
+               #endif
+
+               _current_token = token;
+               int rule_depth = rule_stack.size;
+               Rule.Forward forward = Rule.Forward.NONE;
+               Rule? rule = peek_rule ();
+               if (rule == null) {
+                       throw new ParserError.INTERNAL_ERROR ("Rule stack is empty!");
+               }
+               while (rule != null) {
+                       if (rule.accept_token (token, this, forward)) {
+                               break;
+                       }
+
+                       // Check for invalid recursion
+                       if (rule_depth != rule_stack.size && peek_rule () == rule) {
+                               error (null, "Parser state error");
+                               break;
+                       }
+                       rule = peek_rule ();
+
+                       // Rule stack size have changed
+                       // Check for propagation
+                       forward = rule_depth > rule_stack.size ? Rule.Forward.CHILD
+                                                              : Rule.Forward.PARENT;
+                       rule_depth = rule_stack.size;
+               }
+       }
+
+       private Rule? peek_rule (int offset = -1) {
+               assert (offset < 0);
+               if (rule_stack.size + offset < 0) {
+                       return null;
+               }
+               return rule_stack.get (rule_stack.size + offset);
+       }
+
+       private Rule pop_rule () {
+               int last_index = rule_stack.size - 1;
+               Rule rule = rule_stack.get (last_index);
+               rule_stack.remove_at (last_index);
+               rule_state_stack.remove_at (last_index);
+               return rule;
+       }
+
+       public void push_rule (Rule rule) {
+               rule_stack.add (rule);
+               rule_state_stack.add (null);
+
+               #if HARD_DEBUG
+                       debug ("Pushed at  %2d: %s", rule_stack.size - 1, rule.to_string (null));
+               #endif
+       }
+
+       private Object? peek_state (int offset = -1) {
+               assert (offset < 0);
+               if (rule_state_stack.size + offset < 0) {
+                       return null;
+               }
+               return rule_state_stack.get (rule_state_stack.size + offset);
+       }
+
+       public Object? get_rule_state () {
+               return peek_state ();
+       }
+
+       public void set_rule_state (Object state) {
+               int last_index = rule_stack.size - 1;
+               rule_state_stack.set (last_index, state);
+       }
+
+       public void reduce () {
+               pop_rule ();
+
+               #if HARD_DEBUG
+                       Rule? parent_rule = peek_rule ();
+                       if (parent_rule != null) {
+                               debug ("Reduced to %2d: %s", rule_stack.size - 1,
+                                          parent_rule.to_string (peek_state ()));
+                       }
+               #endif
+       }
+
+       public bool would_parent_accept_token (Token token) {
+               int offset = -2;
+               Rule? parent_rule = peek_rule (offset);
+               Object? state = peek_state (offset);
+               while (parent_rule != null) {
+                       #if VERY_HARD_DEBUG
+                               debug ("WouldAccept - Offset %d; Index %d: %s", offset,
+                                       rule_stack.size + offset, parent_rule.to_string (state));
+                       #endif
+                       if (parent_rule.would_accept_token (token, state)) {
+                               #if VERY_HARD_DEBUG
+                                       debug ("WouldAccept - Yes");
+                               #endif
+                               return true;
+                       }
+                       if (!parent_rule.would_reduce (token, state)) {
+                               #if VERY_HARD_DEBUG
+                                       debug ("WouldAccept - No");
+                               #endif
+                               return false;
+                       }
+                       offset--;
+                       parent_rule = peek_rule (offset);
+                       state = peek_state (offset);
+               }
+               #if VERY_HARD_DEBUG
+                       debug ("WouldAccept - No");
+               #endif
+               return false;
+       }
+
+       public bool would_parent_reduce_to_rule (Token token, Rule rule) {
+               int offset = -2;
+               Rule? parent_rule = peek_rule (offset);
+               Object? state = peek_state (offset);
+               while (parent_rule != null) {
+                       #if VERY_HARD_DEBUG
+                               debug ("WouldReduce - Offset %d; Index %d: %s", offset,
+                                       rule_stack.size + offset, parent_rule.to_string (state));
+                       #endif
+                       if (!parent_rule.would_reduce (token, state)) {
+                               break;
+                       }
+                       offset--;
+                       parent_rule = peek_rule (offset);
+                       state = peek_state (offset);
+               }
+               if ((parent_rule != null && parent_rule.would_accept_token (token, state))
+                       || (parent_rule == null && TokenType.EOF.matches (token))) {
+                       #if VERY_HARD_DEBUG
+                               debug ("WouldReduce - Yes");
+                       #endif
+                       return true;
+               }
+               #if VERY_HARD_DEBUG
+                       debug ("WouldReduce - No");
+               #endif
+               return false;
+       }
+
+       public void warning (Token? token, string message) {
+               string error_message;
+
+               if (token != null) {
+                       error_message = message + ": " + token.to_pretty_string ();
+               } else {
+                       error_message = message;
+               }
+
+               _reporter.warning (_filename,
+                                  get_line (token),
+                                  get_start_column (token),
+                                  get_end_column (token),
+                                  _scanner.get_line_content (),
+                                  error_message);
+       }
+
+       public void error (Token? token, string message) throws ParserError {
+               string error_message;
+
+               if (token != null) {
+                       error_message = message + ": " + token.to_pretty_string ();
+               } else {
+                       error_message = message;
+               }
+
+               _reporter.error (_filename,
+                                                get_line (token),
+                                get_start_column (token),
+                                get_end_column (token),
+                                _scanner.get_line_content (),
+                                error_message);
+
+               throw new ParserError.UNEXPECTED_TOKEN (error_message);
+       }
+
+       private int get_line (Token? token) {
+               if (token == null) {
+                       token = _current_token;
+               }
+               return token.begin.line + _first_line;
+       }
+
+       private int get_start_column (Token? token) {
+               if (token == null) {
+                       token = _current_token;
+               }
+               if (token.begin.line == 0) {
+                       return token.begin.column + _first_column + 1;
+               } else {
+                       return token.begin.column + 1;
+               }
+       }
+
+       private int get_end_column (Token? token) {
+               if (token == null) {
+                       token = _current_token;
+               }
+               if (token.end.line == 0) {
+                       return token.end.column + _first_column + 1;
+               } else {
+                       return token.end.column + 1;
+               }
+       }
+
+#if DEBUG
+       private void log_error (string message) {
+               stderr.printf ("An error occured while parsing: %s\n", message);
+               stderr.printf ("\nDumping rule stack:\n");
+               for (int i = 0; i < rule_stack.size; i++) {
+                       stderr.printf ("\t%2d: %s\n", i, rule_stack[i].to_string (rule_state_stack[i]));
+               }
+       }
+#endif
+}
diff --git a/libvaladoc/parser/parsercallback.vala b/libvaladoc/parser/parsercallback.vala
new file mode 100644
index 0000000..8014ee9
--- /dev/null
+++ b/libvaladoc/parser/parsercallback.vala
@@ -0,0 +1,36 @@
+/* parsercallback.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public interface Valadoc.ParserCallback {
+       public abstract Object? get_rule_state ();
+       public abstract void set_rule_state (Object state);
+
+       public abstract void push_rule (Rule rule);
+       public abstract void reduce ();
+
+       public abstract bool would_parent_accept_token (Token token);
+       public abstract bool would_parent_reduce_to_rule (Token token, Rule rule);
+
+       public abstract void warning (Token? token, string message);
+       public abstract void error (Token? token, string message) throws ParserError;
+}
diff --git a/libvaladoc/parser/rule.vala b/libvaladoc/parser/rule.vala
new file mode 100644
index 0000000..88be423
--- /dev/null
+++ b/libvaladoc/parser/rule.vala
@@ -0,0 +1,172 @@
+/* rule.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public abstract class Valadoc.Rule : Object {
+
+       public static Rule seq (Object[] scheme) {
+               return new SequenceRule (scheme);
+       }
+
+       public static Rule one_of (Object[] scheme) {
+               return new OneOfRule (scheme);
+       }
+
+       public static Rule many (Object[] scheme) {
+               if (scheme.length == 1) {
+                       return new ManyRule (scheme[0]);
+               } else {
+                       return new ManyRule (new SequenceRule (scheme));
+               }
+       }
+
+       public static Rule option (Object[] scheme) {
+               if (scheme.length == 1) {
+                       return new OptionalRule (scheme[0]);
+               } else {
+                       return new OptionalRule (new SequenceRule (scheme));
+               }
+       }
+
+       protected Rule () {
+       }
+
+       private string? _name = null;
+       private Action _start_action;
+       private Action _reduce_action;
+       private Action _skip_action;
+
+       public string name { get { return _name; } }
+
+       public Rule set_name (string name) {
+               _name = name;
+               return this;
+       }
+
+       public delegate void Action () throws ParserError;
+
+       public Rule set_start (Action action) {
+               //TODO: Ownership Transfer
+               _start_action = () => { action (); };
+               return this;
+       }
+
+       public Rule set_reduce (Action action) {
+               //TODO: Ownership Transfer
+               _reduce_action = () => { action (); };
+               return this;
+       }
+
+       public Rule set_skip (Action action) {
+               //TODO: Ownership Transfer
+               _skip_action = () => { action (); };
+               return this;
+       }
+
+       public enum Forward {
+               NONE,
+               PARENT,
+               CHILD
+       }
+
+       public abstract bool is_optional ();
+       public abstract bool starts_with_token (Token token);
+       public abstract bool accept_token (Token token, ParserCallback parser, Rule.Forward forward) throws 
ParserError;
+       public abstract bool would_accept_token (Token token, Object? state);
+       public abstract bool would_reduce (Token token, Object? state);
+
+       public abstract string to_string (Object? state);
+
+       protected bool is_optional_rule (Object? scheme_element) {
+               Rule? scheme_rule = scheme_element as Rule;
+               if (scheme_rule != null) {
+                       return scheme_rule.is_optional ();
+               }
+               return false;
+       }
+
+       protected bool has_start_token (Object? scheme_element, Token token) {
+               TokenType? scheme_token_type = scheme_element as TokenType;
+               if (scheme_token_type != null) {
+                       return scheme_token_type.matches (token);
+               }
+               Rule? scheme_rule = scheme_element as Rule;
+               if (scheme_rule != null) {
+                       return scheme_rule.starts_with_token (token);
+               }
+               return false;
+       }
+
+       protected bool try_to_apply (Object? scheme_element, Token token, ParserCallback parser,
+                                                                out bool handled) throws ParserError
+       {
+               #if VERY_HARD_DEBUG
+                       {
+                               TokenType? scheme_token = scheme_element as TokenType;
+                               Rule? scheme_rule = scheme_element as Rule;
+                               if (scheme_token != null) {
+                                       message ("TryToApply: token='%s'; scheme_token='%s'", token.to_string 
(),
+                                               scheme_token.to_string ());
+                               } else if (scheme_rule != null) {
+                                       message ("TryToApply: token='%s'; scheme_rule='%s'", token.to_string 
(),
+                                               scheme_rule.to_string (parser.get_rule_state ()));
+                               } else {
+                                       assert (scheme_element != null);
+                               }
+                       }
+               #endif
+               TokenType? scheme_token_type = scheme_element as TokenType;
+               if (scheme_token_type != null && scheme_token_type.matches (token)) {
+                       scheme_token_type.do_action (token);
+                       handled = true;
+                       return true;
+               }
+               Rule? scheme_rule = scheme_element as Rule;
+               if (scheme_rule != null && scheme_rule.starts_with_token (token)) {
+                       parser.push_rule (scheme_rule);
+                       handled = false;
+                       return true;
+               }
+
+               handled = false;
+               return false;
+       }
+
+       protected void do_start (ParserCallback parser) throws ParserError {
+               if (_start_action != null) {
+                       _start_action ();
+               }
+       }
+
+       protected void do_reduce (ParserCallback parser) throws ParserError {
+               if (_reduce_action != null) {
+                       _reduce_action ();
+               }
+               parser.reduce ();
+       }
+
+       protected void do_skip (ParserCallback parser) throws ParserError {
+               if (_skip_action != null) {
+                       _skip_action ();
+               }
+       }
+}
diff --git a/libvaladoc/parser/scanner.vala b/libvaladoc/parser/scanner.vala
new file mode 100644
index 0000000..fd148ef
--- /dev/null
+++ b/libvaladoc/parser/scanner.vala
@@ -0,0 +1,37 @@
+/* scanner.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public interface Valadoc.Scanner : Object {
+
+       public abstract void set_parser (Parser parser);
+
+       public abstract void reset ();
+
+       public abstract void scan (string content) throws ParserError;
+
+       public abstract void end () throws ParserError;
+
+       public abstract void stop ();
+
+       public abstract string get_line_content ();
+}
diff --git a/libvaladoc/parser/sequencerule.vala b/libvaladoc/parser/sequencerule.vala
new file mode 100644
index 0000000..e1e6797
--- /dev/null
+++ b/libvaladoc/parser/sequencerule.vala
@@ -0,0 +1,131 @@
+/* sequencerule.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+internal class Valadoc.SequenceRule : Rule {
+
+       public SequenceRule (Object[] scheme) {
+               _scheme = scheme;
+       }
+
+       private Object[] _scheme;
+
+       private class State : Object {
+               public int index = 0;
+       }
+
+       public override bool is_optional () {
+               return false;
+       }
+
+       public override bool starts_with_token (Token token) {
+               return test_token (0, token);
+       }
+
+       private bool test_token (int from_index, Token token) {
+               int i = from_index;
+               while (i < _scheme.length) {
+                       if (has_start_token (_scheme[i], token)) {
+                               return true;
+                       }
+                       if (!is_optional_rule (_scheme[i])) {
+                               break;
+                       }
+                       i++;
+               }
+               return false;
+       }
+
+       private bool test_reduce (int from_index, Token token) {
+               int i = from_index;
+               while (i < _scheme.length) {
+                       if (!is_optional_rule (_scheme[i])) {
+                               return false;
+                       }
+                       i++;
+               }
+               return true;
+       }
+
+       public override bool accept_token (Token token, ParserCallback parser,
+                                                                          Rule.Forward forward) throws 
ParserError
+       {
+               var state = parser.get_rule_state () as State;
+               if (state == null) {
+                       state = new State ();
+                       parser.set_rule_state (state);
+               }
+
+               if (state.index == 0) {
+                       do_start (parser);
+               } else if (state.index == _scheme.length) {
+                       do_reduce (parser);
+                       return false;
+               }
+
+               Object? scheme_element = null;
+               bool handled;
+               do {
+                       scheme_element = _scheme[state.index];
+                       if (try_to_apply (scheme_element, token, parser, out handled)) {
+                               state.index++;
+                               return handled;
+                       }
+                       if (!is_optional_rule (scheme_element)) {
+                               break;
+                       } else {
+                               ((Rule) scheme_element).do_skip (parser);
+                       }
+                       state.index++;
+               } while (state.index < _scheme.length);
+
+               if (state.index == _scheme.length) {
+                       do_reduce (parser);
+                       return false;
+               }
+
+               if (scheme_element is TokenType) {
+                       parser.error (token, "expected %s".printf (((TokenType) 
scheme_element).to_pretty_string ()));
+               } else {
+                       parser.error (token, "unexpected token");
+               }
+               assert_not_reached ();
+       }
+
+       public override bool would_accept_token (Token token, Object? rule_state) {
+               var state = rule_state as State;
+               return test_token (state.index, token);
+       }
+
+       public override bool would_reduce (Token token, Object? rule_state) {
+               var state = rule_state as State;
+               return state.index == _scheme.length || test_reduce (state.index, token);
+       }
+
+       public override string to_string (Object? rule_state) {
+               var state = rule_state as State;
+               if (state == null) {
+                       state = new State ();
+               }
+               return "%-15s%-15s(index=%d/%d)".printf (name != null ? name : " ", "[seq]", state.index, 
_scheme.length);
+       }
+}
diff --git a/libvaladoc/parser/sourcelocation.vala b/libvaladoc/parser/sourcelocation.vala
new file mode 100644
index 0000000..51b5bc1
--- /dev/null
+++ b/libvaladoc/parser/sourcelocation.vala
@@ -0,0 +1,35 @@
+/* sourcelocation.vala
+ *
+ * Copyright (C) 2008  Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Jürg Billeter <j bitron ch>
+ */
+
+
+/**
+ * Represents a position in a source file.
+ */
+public struct Valadoc.SourceLocation {
+       public int line;
+       public int column;
+
+       public SourceLocation (int _line, int _column) {
+               line = _line;
+               column = _column;
+       }
+}
diff --git a/libvaladoc/parser/stubrule.vala b/libvaladoc/parser/stubrule.vala
new file mode 100644
index 0000000..73f0665
--- /dev/null
+++ b/libvaladoc/parser/stubrule.vala
@@ -0,0 +1,61 @@
+/* stubrule.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.StubRule : Rule {
+
+       public StubRule () {
+       }
+
+       private Rule _rule;
+
+       public Rule set_rule (Rule rule) {
+               _rule = rule;
+               return this;
+       }
+
+       public override bool is_optional () {
+               return _rule.is_optional ();
+       }
+
+       public override bool starts_with_token (Token token) {
+               return _rule.starts_with_token (token);
+       }
+
+       public override bool accept_token (Token token, ParserCallback parser, Rule.Forward forward)
+                                                                          throws ParserError
+       {
+               return _rule.accept_token (token, parser, forward);
+       }
+
+       public override bool would_accept_token (Token token, Object? state) {
+               return _rule.would_accept_token (token, state);
+       }
+
+       public override bool would_reduce (Token token, Object? state) {
+               return _rule.would_reduce (token, state);
+       }
+
+       public override string to_string (Object? state) {
+               return _rule.to_string (state);
+       }
+}
diff --git a/libvaladoc/parser/token.vala b/libvaladoc/parser/token.vala
new file mode 100644
index 0000000..52833b2
--- /dev/null
+++ b/libvaladoc/parser/token.vala
@@ -0,0 +1,109 @@
+/* token.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.Token : Object {
+
+       public Token.from_type (TokenType type, SourceLocation begin, SourceLocation end, string? val = null) 
{
+               _type = type;
+               _begin = begin;
+               _end = end;
+               _value = val;
+       }
+
+       public Token.from_word (string word, SourceLocation begin, SourceLocation end) {
+               _word = word;
+               _begin = begin;
+               _end = end;
+       }
+
+       private TokenType? _type = null;
+       private string? _word = null;
+       private SourceLocation _begin;
+       private SourceLocation _end;
+       private string? _value;
+
+       public bool is_word {
+               get {
+                       return _word != null;
+               }
+       }
+
+       public bool is_number {
+               get {
+                       if (_word == null || _word.length == 0) {
+                               return false;
+                       } else if (_word[0] == '0' && _word.length > 1) {
+                               return false;
+                       }
+                       for (int i = 0; i < _word.length; i++) {
+                               if (_word[i] < '0' || _word[i] > '9') {
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+       }
+
+       public string? word {
+               get {
+                       return _word;
+               }
+       }
+
+       public string? value {
+               get {
+                       return _value;
+               }
+       }
+
+       public TokenType? token_type {
+               get {
+                       return _type;
+               }
+       }
+
+       public SourceLocation begin {
+               get {
+                       return _begin;
+               }
+       }
+
+       public SourceLocation end {
+               get {
+                       return _end;
+               }
+       }
+
+       public string to_string () {
+               return _word == null ? _type.to_string () : _word;
+       }
+
+       public string to_pretty_string () {
+               return _word == null ? _type.to_pretty_string () : _word;
+       }
+
+       public int to_int () {
+               assert (is_number);
+               return int.parse (_word);
+       }
+}
diff --git a/libvaladoc/parser/tokentype.vala b/libvaladoc/parser/tokentype.vala
new file mode 100644
index 0000000..4a51d02
--- /dev/null
+++ b/libvaladoc/parser/tokentype.vala
@@ -0,0 +1,270 @@
+/* tokentype.vala
+ *
+ * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
+ *
+ * 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+public class Valadoc.TokenType : Object {
+       // valadoc-comments:
+       public static TokenType ANY;
+       public static TokenType ANY_WORD;
+       public static TokenType ANY_NUMBER;
+       public static TokenType EOF;
+       public static TokenType EOL;
+       public static TokenType BREAK;
+       public static TokenType AROBASE;
+       public static TokenType SPACE;
+       public static TokenType TAB;
+       public static TokenType EQUAL_1;
+       public static TokenType EQUAL_2;
+       public static TokenType EQUAL_3;
+       public static TokenType EQUAL_4;
+       public static TokenType EQUAL_5;
+       public static TokenType MINUS;
+       public static TokenType LESS_THAN;
+       public static TokenType GREATER_THAN;
+       public static TokenType ALIGN_TOP;
+       public static TokenType ALIGN_BOTTOM;
+       public static TokenType SINGLE_QUOTE_2;
+       public static TokenType SLASH_2;
+       public static TokenType UNDERSCORE_2;
+       public static TokenType BACK_QUOTE_2;
+       public static TokenType OPEN_BRACE;
+       public static TokenType CLOSED_BRACE;
+       public static TokenType DOUBLE_OPEN_BRACE;
+       public static TokenType DOUBLE_CLOSED_BRACE;
+       public static TokenType TRIPLE_OPEN_BRACE;
+       public static TokenType TRIPLE_CLOSED_BRACE;
+       public static TokenType DOUBLE_OPEN_BRACKET;
+       public static TokenType DOUBLE_CLOSED_BRACKET;
+       public static TokenType PIPE;
+       public static TokenType DOUBLE_PIPE;
+       public static TokenType ALIGN_RIGHT;
+       public static TokenType ALIGN_CENTER;
+
+
+       // .valadoc (importer)
+       public static TokenType VALADOC_COMMENT_START;
+       public static TokenType VALADOC_COMMENT_END;
+       public static TokenType VALADOC_ANY_WORD;
+       public static TokenType VALADOC_SPACE;
+       public static TokenType VALADOC_TAB;
+       public static TokenType VALADOC_EOL;
+
+
+       // markdown:
+       public static TokenType MARKDOWN_PARAGRAPH;
+       public static TokenType MARKDOWN_ANY_WORD;
+       public static TokenType MARKDOWN_SPACE;
+       public static TokenType MARKDOWN_SOURCE;
+       public static TokenType MARKDOWN_PARAMETER;
+       public static TokenType MARKDOWN_CONSTANT;
+       public static TokenType MARKDOWN_SYMBOL;
+       public static TokenType MARKDOWN_LOCAL_GMEMBER;
+       public static TokenType MARKDOWN_FUNCTION;
+       public static TokenType MARKDOWN_MAIL;
+       public static TokenType MARKDOWN_LINK;
+       public static TokenType MARKDOWN_GREATER_THAN;
+       public static TokenType MARKDOWN_LESS_THAN;
+       public static TokenType MARKDOWN_OPEN_BRACKET;
+       public static TokenType MARKDOWN_CLOSE_BRACKET;
+       public static TokenType MARKDOWN_OPEN_PARENS;
+       public static TokenType MARKDOWN_CLOSE_PARENS;
+       public static TokenType MARKDOWN_EXCLAMATION_MARK;
+       public static TokenType MARKDOWN_HEADLINE_1;
+       public static TokenType MARKDOWN_HEADLINE_2;
+       public static TokenType MARKDOWN_HEADLINE_HASH;
+       public static TokenType MARKDOWN_HEADLINE_END;
+       public static TokenType MARKDOWN_UNORDERED_LIST_ITEM_START;
+       public static TokenType MARKDOWN_UNORDERED_LIST_ITEM_END;
+       public static TokenType MARKDOWN_ORDERED_LIST_ITEM_START;
+       public static TokenType MARKDOWN_ORDERED_LIST_ITEM_END;
+       public static TokenType MARKDOWN_BLOCK_START;
+       public static TokenType MARKDOWN_BLOCK_END;
+       public static TokenType MARKDOWN_EOC;
+
+
+       private static bool initialized = false;
+
+       internal static void init_token_types () {
+               if (!initialized) {
+                       // valadoc-comments:
+                       ANY = new TokenType.basic ("<any>");
+                       ANY_WORD = new TokenType.basic ("<any-word>");
+                       ANY_NUMBER = new TokenType.basic ("<any-number>");
+                       EOF = new TokenType.basic ("\0", "<end-of-file>");
+                       EOL = new TokenType.basic ("\n", "<end-of-line>");
+                       BREAK = new TokenType.basic ("<<BR>>");
+                       AROBASE = new TokenType.basic ("@");
+                       SPACE = new TokenType.basic (" ", "<space>");
+                       TAB = new TokenType.basic ("\t", "<tab>");
+                       EQUAL_1 = new TokenType.basic ("=");
+                       EQUAL_2 = new TokenType.basic ("==");
+                       EQUAL_3 = new TokenType.basic ("====");
+                       EQUAL_4 = new TokenType.basic ("=====");
+                       EQUAL_5 = new TokenType.basic ("======");
+                       MINUS = new TokenType.basic ("-");
+                       LESS_THAN = new TokenType.basic ("<");
+                       GREATER_THAN = new TokenType.basic (">");
+                       ALIGN_TOP = new TokenType.basic ("^");
+                       ALIGN_BOTTOM = new TokenType.basic ("v");
+                       SINGLE_QUOTE_2 = new TokenType.basic ("''");
+                       SLASH_2 = new TokenType.basic ("//");
+                       UNDERSCORE_2 = new TokenType.basic ("__");
+                       BACK_QUOTE_2 = new TokenType.basic ("``");
+                       OPEN_BRACE = new TokenType.basic ("{");
+                       CLOSED_BRACE = new TokenType.basic ("}");
+                       DOUBLE_OPEN_BRACE = new TokenType.basic ("{{");
+                       DOUBLE_CLOSED_BRACE = new TokenType.basic ("}}");
+                       TRIPLE_OPEN_BRACE = new TokenType.basic ("{{{");
+                       TRIPLE_CLOSED_BRACE = new TokenType.basic ("}}}");
+                       DOUBLE_OPEN_BRACKET = new TokenType.basic ("[[");
+                       DOUBLE_CLOSED_BRACKET = new TokenType.basic ("]]");
+                       PIPE = new TokenType.basic ("|");
+                       DOUBLE_PIPE = new TokenType.basic ("||");
+                       ALIGN_RIGHT = new TokenType.basic ("))");
+                       ALIGN_CENTER = new TokenType.basic (")(");
+
+                       // .valadoc (importer)
+                       VALADOC_COMMENT_START = new TokenType.basic ("/*");
+                       VALADOC_COMMENT_END = new TokenType.basic ("*/");
+                       VALADOC_ANY_WORD = ANY_WORD;
+                       VALADOC_SPACE = SPACE;
+                       VALADOC_TAB = TAB;
+                       VALADOC_EOL = EOL;
+
+                       initialized = true;
+
+
+                       // Markdown: (importer)
+                       MARKDOWN_PARAGRAPH = new TokenType.basic ("<paragraph>");
+                       MARKDOWN_BLOCK_START = new TokenType.basic ("<block>");
+                       MARKDOWN_BLOCK_END = new TokenType.basic ("</block>");
+                       MARKDOWN_UNORDERED_LIST_ITEM_START = new TokenType.basic ("<unordered-list>");
+                       MARKDOWN_UNORDERED_LIST_ITEM_END = new TokenType.basic ("</unordered-list>");
+                       MARKDOWN_ORDERED_LIST_ITEM_START = new TokenType.basic ("<ordered-list>");
+                       MARKDOWN_ORDERED_LIST_ITEM_END  = new TokenType.basic ("</ordered-list>");
+
+                       MARKDOWN_HEADLINE_1 = new TokenType.basic ("<headline-1>");
+                       MARKDOWN_HEADLINE_2 = new TokenType.basic ("<headline-2>");
+                       MARKDOWN_HEADLINE_HASH = new TokenType.basic ("<hash>");
+                       MARKDOWN_HEADLINE_END = new TokenType.basic ("</headline>");
+                       MARKDOWN_SOURCE = new TokenType.basic ("<source>");
+                       MARKDOWN_PARAMETER = new TokenType.basic ("<parameter>");
+                       MARKDOWN_CONSTANT = new TokenType.basic ("<constant>");
+                       MARKDOWN_FUNCTION = new TokenType.basic ("<function>");
+                       MARKDOWN_SYMBOL = new TokenType.basic ("<symbol>");
+                       MARKDOWN_LOCAL_GMEMBER = new TokenType.basic ("<local-gmember>");
+                       MARKDOWN_MAIL = new TokenType.basic ("<mail>");
+                       MARKDOWN_LINK = new TokenType.basic ("<link>");
+
+                       MARKDOWN_OPEN_BRACKET = new TokenType.basic ("[");
+                       MARKDOWN_CLOSE_BRACKET = new TokenType.basic ("]");
+                       MARKDOWN_OPEN_PARENS = new TokenType.basic ("(");
+                       MARKDOWN_CLOSE_PARENS = new TokenType.basic (")");
+                       MARKDOWN_EXCLAMATION_MARK = new TokenType.basic ("!");
+                       MARKDOWN_GREATER_THAN = GREATER_THAN;
+                       MARKDOWN_LESS_THAN = LESS_THAN;
+
+                       MARKDOWN_ANY_WORD = ANY_WORD;
+                       MARKDOWN_SPACE = SPACE;
+                       MARKDOWN_EOC = EOL;
+               }
+       }
+
+       private static int EXACT_WORD = -1;
+
+       public static TokenType str (string str) {
+               return new TokenType (str, EXACT_WORD, null);
+       }
+
+       public static TokenType any () {
+               return ANY;
+       }
+
+       public static TokenType any_word () {
+               return ANY_WORD;
+       }
+
+       public static TokenType any_number () {
+               return ANY_NUMBER;
+       }
+
+       private TokenType (string string_value, int basic_value, Action? __action) {
+               _string_value = string_value;
+               _basic_value = basic_value;
+               if (__action != null) {
+                       _action = (token) => { __action (token); };
+               } else {
+                       _action = null;
+               }
+       }
+
+       private TokenType.basic (string string_value, string? pretty_string = null) {
+               _string_value = string_value;
+               _pretty_string = pretty_string;
+               _basic_value = ++_last_basic_value;
+       }
+
+       private static int _last_basic_value = -1;
+
+       private string _string_value;
+       private string? _pretty_string;
+       private int _basic_value = -1;
+       private Action? _action = null;
+
+       public delegate void Action (Token token) throws ParserError;
+
+       public TokenType action (Action action) {
+               return new TokenType (_string_value, _basic_value, action);
+       }
+
+       public void do_action (Token matched_token) throws ParserError {
+               if (_action != null) {
+                       _action (matched_token);
+               }
+       }
+
+       public bool matches (Token token) {
+               if (_basic_value == ANY._basic_value) {
+                       return true;
+               } else if (_basic_value == ANY_WORD._basic_value && token.is_word) {
+                       return true;
+               } else if (_basic_value == ANY_NUMBER._basic_value && token.is_number) {
+                       return true;
+               } else if (_basic_value == EXACT_WORD && token.is_word && token.word == _string_value) {
+                       return true;
+               } else if (token.token_type != null && token.token_type._basic_value == _basic_value) {
+                       return true;
+               }
+               return false;
+       }
+
+       public string to_string () {
+               return _string_value;
+       }
+
+       public string to_pretty_string () {
+               if (_pretty_string != null) {
+                       return _pretty_string;
+               }
+               return _string_value;
+       }
+}
diff --git a/libvaladoc/settings.vala b/libvaladoc/settings.vala
new file mode 100644
index 0000000..823dd5b
--- /dev/null
+++ b/libvaladoc/settings.vala
@@ -0,0 +1,169 @@
+/* settings.vala
+ *
+ * Copyright (C) 2008-2009 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:
+ *     Brosch Florian <flo brosch gmail com>
+ */
+
+
+/**
+ * Contains information about output settings configuration
+ */
+public class Valadoc.Settings : Object {
+       /**
+        * Output directory/file name.
+        */
+       public string path = "documentation/";
+
+       /**
+        * Package name
+        */
+       public string pkg_name = null;
+
+       /**
+        * Package version
+        */
+       public string pkg_version;
+
+       /**
+        * Wiki directory
+        */
+       public string wiki_directory;
+
+       /**
+        * Plugin-specific command line arguments
+        */
+       public string[] pluginargs;
+
+
+       /**
+        * Add private elements to documentation
+        */
+       public bool _private = false;
+
+       /**
+        * Add protected elements to documentation
+        */
+       public bool _protected = false;
+
+       /**
+        * Add internal elements to documentation
+        */
+       public bool _internal = false;
+
+       /**
+        * Add dependencies to the documentation
+        */
+       public bool with_deps = false;
+
+       public bool add_inherited = false;
+
+       /**
+        * Show all warnings
+        */
+       public bool verbose = false;
+
+
+
+       /**
+        * Do not warn when using experimental features.
+        */
+       public bool experimental;
+
+       /**
+        * Enable experimental enhancements for non-null types.
+        */
+       public bool experimental_non_null;
+
+       /**
+        * Use the given profile (dova, gobject, posix, ...) instead of the defaul
+        */
+       public string? profile;
+
+       /**
+        * Base source directory.
+        */
+       public string? basedir;
+
+       /**
+        * Output directory/file name.
+        */
+       public string? directory;
+
+
+       /**
+        * A list of defined symbols.
+        */
+       public string[] defines;
+
+       /**
+        * List of directories where to find .vapi files.
+        */
+       public string[] vapi_directories;
+
+       /**
+        * A list of all packages
+        */
+       public string[] packages;
+
+       /**
+        * A list of all source files.
+        */
+       public string[] source_files;
+
+       /**
+        * GObject-Introspection directory
+        */
+       public string? gir_directory;
+
+       /**
+        * GObject-Introspection repository file name
+        */
+       public string? gir_name;
+
+       /**
+        * A list of all metadata directories
+        */
+       public string[] metadata_directories;
+
+       /**
+        * Alternative paths for resources
+        */
+       public string[] alternative_resource_dirs;
+
+       /**
+        * A list of all gir directories.
+        */
+       public string[] gir_directories;
+
+       /**
+        * GLib version to target.
+        */
+       public string target_glib;
+
+       public string gir_namespace;
+
+       public string gir_version;
+
+       /**
+        * Use SVG as chart images
+        */
+       public bool use_svg_images = false;
+}
+
+
diff --git a/libvaladoc/taglets/tagletdeprecated.vala b/libvaladoc/taglets/tagletdeprecated.vala
new file mode 100644
index 0000000..5911ef8
--- /dev/null
+++ b/libvaladoc/taglets/tagletdeprecated.vala
@@ -0,0 +1,60 @@
+/* tagletdeprecated.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+public class Valadoc.Taglets.Deprecated : BlockContent, Taglet, Block {
+       public Rule? get_parser_rule (Rule run_rule) {
+               return run_rule;
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               base.check (api_root, container, file_path, reporter, settings);
+               reporter.simple_warning ("%s: %s: @deprecated".printf (file_path, container.get_full_name ()),
+                                                                "@deprecated is deprecated. Use [Version 
(deprecated = true)]");
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_taglet (this);
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Deprecated deprecated = new Deprecated ();
+               deprecated.parent = new_parent;
+
+               foreach (Block element in content) {
+                       Block copy = element.copy (deprecated) as Block;
+                       deprecated.content.add (copy);
+               }
+
+               return deprecated;
+       }
+}
+
diff --git a/libvaladoc/taglets/tagletinheritdoc.vala b/libvaladoc/taglets/tagletinheritdoc.vala
new file mode 100644
index 0000000..5ce4a8c
--- /dev/null
+++ b/libvaladoc/taglets/tagletinheritdoc.vala
@@ -0,0 +1,232 @@
+/* tagletinheritdoc.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+public class Valadoc.Taglets.InheritDoc : InlineTaglet {
+       private Taglet? parent_taglet = null;
+
+       public Api.Node? inherited {
+               private set;
+               get;
+       }
+
+
+       public override Rule? get_parser_rule (Rule run_rule) {
+               return null;
+       }
+
+       private Taglet? find_parent_taglet () {
+               if (_inherited == null || _inherited.documentation == null) {
+                       return null;
+               }
+
+               ContentElement pos;
+               for (pos = this.parent; pos != null && pos is Taglet == false; pos = pos.parent);
+               if (pos is Taglet) {
+                       return (Taglet) pos;
+               }
+
+               return null;
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // TODO Check that the container is an override of an abstract symbol
+               // Also retrieve that abstract symbol _inherited
+
+               if (container is Api.Method) {
+                       _inherited = ((Api.Method) container).base_method;
+               } else if (container is Api.Property) {
+                       _inherited = ((Api.Property) container).base_property;
+               } else if (container is Api.Class && ((Api.Class) container).base_type != null) {
+                       _inherited = (Api.Node) ((Api.Class) container).base_type.data_type;
+               } else if (container is Api.Struct && ((Api.Struct) container).base_type != null) {
+                       _inherited = (Api.Node) ((Api.Struct) container).base_type.data_type;
+               }
+
+               parent_taglet = find_parent_taglet ();
+               if (parent_taglet == null && _inherited != null) {
+                       api_root.register_inheritdoc (container, this);
+               }
+
+
+               // TODO report error if inherited is null
+
+               // TODO postpone check after complete parse of the api tree comments
+               // And reenable that check
+               //base.check (api_root, container, reporter);
+       }
+
+       private Run[]? split_run (Inline? separator) {
+               if (separator == null) {
+                       return null;
+               }
+
+               ContentElement parent = separator.parent;
+               Vala.List<Inline> parent_content = null;
+
+               if (parent is Run && ((Run) parent).style == Run.Style.NONE) {
+                       parent_content = ((Run) parent).content;
+               } else if (parent is Paragraph) {
+                       parent_content = ((Paragraph) parent).content;
+               }
+
+               if (parent_content != null) {
+                       Run right_run = new Run (Run.Style.NONE);
+                       Run left_run = new Run (Run.Style.NONE);
+                       bool separated = false;
+
+                       foreach (var current in parent_content) {
+                               if (current == separator) {
+                                       separated = true;
+                               } else if (separated) {
+                                       right_run.content.add (current);
+                                       current.parent = right_run;
+                               } else {
+                                       left_run.content.add (current);
+                                       current.parent = left_run;
+                               }
+                       }
+
+                       return { left_run, right_run };
+               }
+
+               return null;
+       }
+
+       internal void transform (Api.Tree api_root, Api.Node container, string file_path,
+                                                        ErrorReporter reporter, Settings settings)
+       {
+               ContentElement separator = this;
+               Run right_run = null;
+               Run left_run = null;
+               Run[]? parts;
+
+               while ((parts = split_run (separator as Inline)) != null) {
+                       if (left_run != null) {
+                               parts[0].content.add (left_run);
+                               left_run.parent = parts[0];
+                       }
+
+                       if (right_run != null) {
+                               parts[1].content.insert (0, right_run);
+                               right_run.parent = parts[1];
+                       }
+
+                       separator = separator.parent;
+                       right_run = parts[1];
+                       left_run = parts[0];
+               }
+
+               if (separator is Paragraph == false || separator.parent is Comment == false) {
+                       reporter.simple_error ("%s: %s: @inheritDoc".printf (file_path, 
container.get_full_name ()),
+                                                                  "Parent documentation can't be copied to 
this location.");
+                       return ;
+               }
+
+               Comment comment = separator.parent as Comment;
+               assert (comment != null);
+
+               int insert_pos = comment.content.index_of ((Paragraph) separator);
+               int start_pos = insert_pos;
+               assert (insert_pos >= 0);
+
+               foreach (Block block in _inherited.documentation.content) {
+                       comment.content.insert (insert_pos, (Block) block.copy (comment));
+                       insert_pos++;
+               }
+
+               if (right_run != null) {
+                       if (comment.content[insert_pos - 1] is Paragraph) {
+                               ((Paragraph) comment.content[insert_pos - 1]).content.add (right_run);
+                               right_run.parent = comment.content[insert_pos - 1];
+                       } else {
+                               Paragraph p = new Paragraph ();
+                               p.content.add (right_run);
+                               right_run.parent = p;
+                               p.parent = comment;
+                               comment.content.insert (insert_pos, p);
+                       }
+               }
+
+               if (left_run != null) {
+                       if (comment.content[start_pos] is Paragraph) {
+                               ((Paragraph) comment.content[start_pos]).content.insert (0, left_run);
+                               left_run.parent = comment.content[start_pos];
+                       } else {
+                               Paragraph p = new Paragraph ();
+                               p.content.add (left_run);
+                               left_run.parent = p;
+                               p.parent = comment;
+                               comment.content.insert (start_pos, p);
+                       }
+               }
+
+               comment.content.remove ((Paragraph) separator);
+       }
+
+       private Run content_copy (Vala.List<ContentElement>? content) {
+               Run run = new Run (Run.Style.NONE);
+               run.parent = this;
+
+               if (content != null) {
+                       foreach (ContentElement item in content) {
+                               run.content.add (item.copy (this) as Inline);
+                       }
+               }
+
+               return run;
+       }
+
+       public override ContentElement produce_content () {
+               if (_inherited != null && _inherited.documentation != null && parent_taglet != null) {
+                       Vala.List<Taglet> parent_taglets = _inherited.documentation.find_taglets (null, 
parent_taglet.get_type ());
+                       foreach (Taglet parent in parent_taglets) {
+                               // we only care about the first match:
+                               if (parent.inheritable (parent_taglet)) {
+                                       return content_copy (parent.get_inheritable_documentation ());
+                               }
+                       }
+               }
+               return new Text ("");
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               InheritDoc doc = new InheritDoc ();
+               doc.parent = new_parent;
+
+               doc.settings = settings;
+               doc.locator = locator;
+
+               doc._inherited = _inherited;
+
+               return doc;
+       }
+}
diff --git a/libvaladoc/taglets/tagletinit.vala b/libvaladoc/taglets/tagletinit.vala
new file mode 100644
index 0000000..7e88126
--- /dev/null
+++ b/libvaladoc/taglets/tagletinit.vala
@@ -0,0 +1,35 @@
+/* tagletinit.vala
+ *
+ * Copyright (C) 2008-2009 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>
+ */
+
+
+namespace Valadoc.Taglets {
+       public void init (ModuleLoader loader) {
+               loader.register_taglet ("see", typeof (Valadoc.Taglets.See));
+               loader.register_taglet ("since", typeof (Valadoc.Taglets.Since));
+               loader.register_taglet ("link", typeof (Valadoc.Taglets.Link));
+               loader.register_taglet ("throws", typeof (Valadoc.Taglets.Throws));
+               loader.register_taglet ("return", typeof (Valadoc.Taglets.Return));
+               loader.register_taglet ("param", typeof (Valadoc.Taglets.Param));
+               loader.register_taglet ("deprecated", typeof (Valadoc.Taglets.Deprecated));
+               loader.register_taglet ("inheritDoc", typeof (Valadoc.Taglets.InheritDoc));
+       }
+}
diff --git a/libvaladoc/taglets/tagletlink.vala b/libvaladoc/taglets/tagletlink.vala
new file mode 100644
index 0000000..799bec6
--- /dev/null
+++ b/libvaladoc/taglets/tagletlink.vala
@@ -0,0 +1,185 @@
+/* taglet.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2014 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:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+public class Valadoc.Taglets.Link : InlineTaglet {
+       public string symbol_name { internal set; get; }
+
+       /**
+        * Accept leading 's', e.g. #Widgets
+        */
+       public bool c_accept_plural { internal set; get; }
+
+       /**
+        * True if symbol_name could only be resolved after removing 's'
+        *
+        * E.g. true or #Widgets, false for #Widget
+        */
+       public bool c_is_plural { private set; get; }
+
+
+       private enum SymbolContext {
+               NORMAL,
+               FINISH,
+               TYPE
+       }
+
+       private SymbolContext _context = SymbolContext.NORMAL;
+       private Api.Node _symbol;
+
+       public override Rule? get_parser_rule (Rule run_rule) {
+               return Rule.seq ({
+                       Rule.option ({ Rule.many ({ TokenType.SPACE }) }),
+                       TokenType.any_word ().action ((token) => { symbol_name = token.to_string (); }),
+                       Rule.option ({
+                               Rule.many ({
+                                       Rule.one_of ({
+                                               TokenType.any_word ().action ((token) => { symbol_name += 
token.to_string (); }),
+                                               TokenType.MINUS.action ((token => { symbol_name += 
token.to_string (); }))
+                                       })
+                               })
+                       })
+               });
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings) {
+
+               if (symbol_name.has_prefix ("c::")) {
+                       _symbol_name = _symbol_name.substring (3);
+                       string? singular_symbol_name = (c_accept_plural && _symbol_name.has_suffix ("s"))
+                               ? symbol_name.substring (0, _symbol_name.length - 1)
+                               : null;
+
+                       _symbol = api_root.search_symbol_cstr (container, symbol_name);
+                       if (_symbol == null && singular_symbol_name != null) {
+                               _symbol = api_root.search_symbol_cstr (container, singular_symbol_name);
+                               c_is_plural = true;
+                       }
+                       _context = SymbolContext.NORMAL;
+
+                       if (_symbol == null && _symbol_name.has_suffix ("_finish")) {
+                               string tmp = _symbol_name.substring (0, _symbol_name.length - 7);
+
+                               _symbol = api_root.search_symbol_cstr (container, tmp + "_async") as 
Api.Method;
+                               if (_symbol != null && ((Api.Method) _symbol).is_yields) {
+                                       _context = SymbolContext.FINISH;
+                               } else {
+                                       _symbol = api_root.search_symbol_cstr (container, tmp) as Api.Method;
+                                       if (_symbol != null && ((Api.Method) _symbol).is_yields) {
+                                               _context = SymbolContext.FINISH;
+                                       } else {
+                                               _symbol = null;
+                                       }
+                               }
+                       }
+
+                       if (_symbol == null) {
+                               _symbol = api_root.search_symbol_type_cstr (symbol_name);
+                               if (_symbol == null && singular_symbol_name != null) {
+                                       _symbol = api_root.search_symbol_type_cstr (singular_symbol_name);
+                                       c_is_plural = true;
+                               }
+                               if (_symbol != null) {
+                                       _context = SymbolContext.TYPE;
+                               }
+                       }
+
+                       if (_symbol != null) {
+                               symbol_name = _symbol.name;
+                       }
+               } else {
+                       _symbol = api_root.search_symbol_str (container, symbol_name);
+               }
+
+               if (_symbol == null && symbol_name != "main") {
+                       string node_segment = (container is Api.Package)? "" : container.get_full_name () + 
": ";
+                       reporter.simple_warning ("%s: %s@link".printf (file_path, node_segment),
+                                                                        "`%s' does not exist", symbol_name);
+               }
+
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override ContentElement produce_content () {
+               var link = new Content.SymbolLink ();
+               link.symbol = _symbol;
+               link.given_symbol_name = symbol_name;
+
+               Content.Inline content;
+               switch (_context) {
+               case SymbolContext.FINISH:
+                       link.given_symbol_name += ".end";
+                       content = link;
+                       break;
+
+               case SymbolContext.TYPE:
+                       Run run = new Content.Run (Run.Style.MONOSPACED);
+                       content = run;
+
+                       Content.Run keyword = new Content.Run (Run.Style.LANG_KEYWORD);
+                       keyword.content.add (new Content.Text ("typeof"));
+                       run.content.add (keyword);
+
+                       run.content.add (new Content.Text (" ("));
+                       run.content.add (link);
+                       run.content.add (new Content.Text (")"));
+                       break;
+
+               default:
+                       content = link;
+                       break;
+               }
+
+               if (c_is_plural == true) {
+                       Run run = new Content.Run (Run.Style.NONE);
+                       run.content.add (content);
+                       run.content.add (new Content.Text ("s"));
+                       return run;
+               }
+
+               return content;
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Link link = new Link ();
+               link.parent = new_parent;
+
+               link.settings = settings;
+               link.locator = locator;
+
+               link.symbol_name = symbol_name;
+               link.c_accept_plural = c_accept_plural;
+               link.c_is_plural = c_is_plural;
+               link._context = _context;
+               link._symbol = _symbol;
+
+               return link;
+       }
+}
diff --git a/libvaladoc/taglets/tagletparam.vala b/libvaladoc/taglets/tagletparam.vala
new file mode 100644
index 0000000..2746691
--- /dev/null
+++ b/libvaladoc/taglets/tagletparam.vala
@@ -0,0 +1,165 @@
+/* taglet.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+public class Valadoc.Taglets.Param : BlockContent, Taglet, Block {
+       public string parameter_name { internal set; get; }
+
+       public weak Api.Symbol? parameter { private set; get; }
+
+       public int position { private set; get; default = -1; }
+
+       public bool is_c_self_param { internal set; get; }
+
+       public bool is_this { private set; get; }
+
+
+       public Rule? get_parser_rule (Rule run_rule) {
+               return Rule.seq ({
+                       Rule.option ({ Rule.many ({ TokenType.SPACE }) }),
+                       TokenType.any_word ().action ((token) => { parameter_name = token.to_string (); }),
+                       run_rule
+               });
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // Check for the existence of such a parameter
+               unowned string? implicit_return_array_length = null;
+               bool has_instance = has_instance (container);
+               bool is_implicit = false;
+               this.parameter = null;
+
+               if (container is Api.Callable) {
+                       implicit_return_array_length = ((Api.Callable) 
container).implicit_array_length_cparameter_name;
+               } else {
+                       reporter.simple_warning ("%s: %s: @param".printf (file_path, container.get_full_name 
()),
+                                                                        "@param used outside 
method/delegate/signal context");
+                       base.check (api_root, container, file_path, reporter, settings);
+                       return ;
+               }
+
+               if (is_c_self_param == true && has_instance) {
+                       this.parameter_name = "this";
+                       this.is_this = true;
+                       this.position = 0;
+               } else if (parameter_name == "...") {
+                       Vala.List<Api.Node> params = container.get_children_by_type 
(Api.NodeType.FORMAL_PARAMETER, false);
+                       foreach (Api.Node param in params) {
+                               if (((Api.FormalParameter) param).ellipsis) {
+                                       this.parameter = (Api.Symbol) param;
+                                       this.position = (has_instance)? params.size : params.size - 1;
+                                       break;
+                               }
+                       }
+               } else {
+                       Vala.List<Api.Node> params = container.get_children_by_types 
({Api.NodeType.FORMAL_PARAMETER,
+                                                                                                             
                                    Api.NodeType.TYPE_PARAMETER},
+                                                                                                             
                                   false);
+                       int pos = (has_instance)? 1 : 0;
+
+                       foreach (Api.Node param in params) {
+                               if (param.name == parameter_name) {
+                                       this.parameter = (Api.Symbol) param;
+                                       this.position = pos;
+                                       break;
+                               }
+
+                               Api.FormalParameter formalparam = param as Api.FormalParameter;
+                               if (formalparam != null && (formalparam.implicit_array_length_cparameter_name 
== parameter_name
+                                       || formalparam.implicit_closure_cparameter_name == parameter_name
+                                       || formalparam.implicit_destroy_cparameter_name == parameter_name))
+                               {
+                                       is_implicit = true;
+                                       break;
+                               }
+
+                               pos++;
+                       }
+
+                       if (this.parameter == null
+                               && (parameter_name == "error"
+                               && container.has_children ({Api.NodeType.ERROR_DOMAIN, Api.NodeType.CLASS})
+                          || parameter_name == implicit_return_array_length))
+                       {
+                               is_implicit = true;
+                       }
+               }
+
+               if (this.parameter == null) {
+                       if (is_implicit) {
+                               reporter.simple_note ("%s: %s: @param".printf (file_path, 
container.get_full_name ()),
+                                                                         "Implicit parameter `%s' exposed in 
documentation", parameter_name);
+                       } else if (!is_c_self_param) {
+                               reporter.simple_warning ("%s: %s: @param".printf (file_path, 
container.get_full_name ()),
+                                                                                "Unknown parameter `%s'", 
parameter_name);
+                       }
+               }
+
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       private bool has_instance (Api.Item element) {
+               if (element is Api.Method) {
+                       return !((Api.Method) element).is_static;
+               }
+
+               return false;
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_taglet (this);
+       }
+
+       public Vala.List<ContentElement>? get_inheritable_documentation () {
+               return content;
+       }
+
+       public bool inheritable (Taglet taglet) {
+               if (taglet is Taglets.Param == false) {
+                       return false;
+               }
+
+               Taglets.Param t = (Taglets.Param) taglet;
+               return (parameter == t.parameter || parameter_name == t.parameter_name);
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Param param = new Param ();
+               param.parent = new_parent;
+
+               param.parameter_name = parameter_name;
+               param.parameter = parameter;
+               param.position = position;
+
+               foreach (Block element in content) {
+                       Block copy = element.copy (param) as Block;
+                       param.content.add (copy);
+               }
+
+               return param;
+       }
+}
diff --git a/libvaladoc/taglets/tagletreturn.vala b/libvaladoc/taglets/tagletreturn.vala
new file mode 100644
index 0000000..691a4a3
--- /dev/null
+++ b/libvaladoc/taglets/tagletreturn.vala
@@ -0,0 +1,78 @@
+/* taglet.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+public class Valadoc.Taglets.Return : BlockContent, Taglet, Block {
+       public Rule? get_parser_rule (Rule run_rule) {
+               return run_rule;
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings) {
+               Api.TypeReference? type_ref = null;
+               bool creation_method = false;
+
+               if (container is Api.Method) {
+                       creation_method = ((Api.Method) container).is_constructor;
+                       type_ref = ((Api.Method) container).return_type;
+               } else if (container is Api.Callable) {
+                       type_ref = ((Api.Callable) container).return_type;
+               } else {
+                       reporter.simple_warning ("%s: %s: @return".printf (file_path, container.get_full_name 
()),
+                                                                        "@return used outside 
method/delegate/signal context");
+               }
+
+               if (type_ref != null && type_ref.data_type == null && !creation_method) {
+                       reporter.simple_warning ("%s: %s: @return".printf (file_path, container.get_full_name 
()),
+                                                                        "Return description declared for 
void function");
+               }
+
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_taglet (this);
+       }
+
+       public Vala.List<ContentElement>? get_inheritable_documentation () {
+               return content;
+       }
+
+       public bool inheritable (Taglet taglet) {
+               return taglet is Taglets.Return;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Return ret = new Return ();
+               ret.parent = new_parent;
+
+               foreach (Block element in content) {
+                       Block copy = element.copy (ret) as Block;
+                       ret.content.add (copy);
+               }
+
+               return ret;
+       }
+}
diff --git a/libvaladoc/taglets/tagletsee.vala b/libvaladoc/taglets/tagletsee.vala
new file mode 100644
index 0000000..f509443
--- /dev/null
+++ b/libvaladoc/taglets/tagletsee.vala
@@ -0,0 +1,76 @@
+/* tagletsee.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+public class Valadoc.Taglets.See : ContentElement, Taglet, Block {
+       public string symbol_name { private set; get; }
+       public Api.Node symbol { private set; get; }
+
+       public Rule? get_parser_rule (Rule run_rule) {
+               Rule optional_spaces = Rule.option ({ Rule.many ({ TokenType.SPACE }) });
+
+               return Rule.seq ({
+                       optional_spaces,
+                       TokenType.any_word ().action ((token) => { symbol_name = token.to_string (); }),
+                       optional_spaces
+               });
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings) {
+               if (symbol_name.has_prefix ("c::")) {
+                       symbol_name = symbol_name.substring (3);
+                       symbol = api_root.search_symbol_cstr (container, 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_warning ("%s: %s: @see".printf (file_path, container.get_full_name 
()),
+                                                                        "`%s' does not exist", symbol_name);
+               }
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_taglet (this);
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               See see = new See ();
+               see.parent = new_parent;
+
+               see.symbol_name = symbol_name;
+               see.symbol = symbol;
+
+               return see;
+       }}
diff --git a/libvaladoc/taglets/tagletsince.vala b/libvaladoc/taglets/tagletsince.vala
new file mode 100644
index 0000000..1244742
--- /dev/null
+++ b/libvaladoc/taglets/tagletsince.vala
@@ -0,0 +1,62 @@
+/* tagletsince.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+public class Valadoc.Taglets.Since : ContentElement, Taglet, Block {
+       public string version { get; internal set; }
+
+       public Rule? get_parser_rule (Rule run_rule) {
+               Rule optional_spaces = Rule.option ({ Rule.many ({ TokenType.SPACE }) });
+
+               return Rule.seq ({
+                       optional_spaces,
+                       TokenType.any_word ().action ((token) => { version = token.to_string (); }),
+                       optional_spaces
+               });
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_taglet (this);
+       }
+
+       public override bool is_empty () {
+               return false;
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Since since = new Since ();
+               since.parent = new_parent;
+
+               since.version = version;
+
+               return since;
+       }
+}
+
diff --git a/libvaladoc/taglets/tagletthrows.vala b/libvaladoc/taglets/tagletthrows.vala
new file mode 100644
index 0000000..6a94551
--- /dev/null
+++ b/libvaladoc/taglets/tagletthrows.vala
@@ -0,0 +1,124 @@
+/* tagletthrows.vala
+ *
+ * Copyright (C) 2008-2009 Didier Villevalois
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Didier 'Ptitjes Villevalois <ptitjes free fr>
+ */
+
+
+using Valadoc.Content;
+
+public class Valadoc.Taglets.Throws : BlockContent, Taglet, Block {
+       // TODO: rename
+       public string error_domain_name { private set; get; }
+
+       /**
+        * Thrown  Error domain or Error code
+        */
+       // TODO: rename
+       public Api.Node error_domain { private set; get; }
+
+       public Rule? get_parser_rule (Rule run_rule) {
+               return Rule.seq ({
+                       Rule.option ({ Rule.many ({ TokenType.SPACE }) }),
+                       TokenType.any_word ().action ((token) => { error_domain_name = token.to_string (); }),
+                       run_rule
+               });
+       }
+
+       public override void check (Api.Tree api_root, Api.Node container, string file_path,
+                                                               ErrorReporter reporter, Settings settings)
+       {
+               // context check:
+               if (container is Api.Method == false && container is Api.Delegate == false) {
+                       reporter.simple_warning ("%s: %s: @throws".printf (file_path, container.get_full_name 
()),
+                                                                        "@throws used outside 
method/delegate context");
+                       base.check (api_root, container, file_path, reporter, settings);
+                       return ;
+               }
+
+
+               // type check:
+               error_domain = api_root.search_symbol_str (container, error_domain_name);
+               if (error_domain == null) {
+                       // TODO use ContentElement's source reference
+                       reporter.simple_error ("%s: %s: @throws".printf (file_path, container.get_full_name 
()),
+                                                                  "`%s' does not exist", error_domain_name);
+                       base.check (api_root, container, file_path, reporter, settings);
+                       return ;
+               }
+
+
+               // Check if the method is allowed to throw the given type or error code:
+               Vala.List<Api.Node> exceptions = container.get_children_by_types ({Api.NodeType.ERROR_DOMAIN,
+                                                                                                             
                                    Api.NodeType.CLASS},
+                                                                                                             
                                   false);
+               Api.Item expected_error_domain = (error_domain is Api.ErrorCode)
+                       ? error_domain.parent
+                       : error_domain;
+               bool report_warning = true;
+               foreach (Api.Node exception in exceptions) {
+                       if (exception == expected_error_domain
+                               || (exception is Api.Class && expected_error_domain is Api.ErrorDomain))
+                       {
+                               report_warning = false;
+                               break;
+                       }
+               }
+               if (report_warning) {
+                       reporter.simple_warning ("%s: %s: @throws".printf (file_path, container.get_full_name 
()),
+                                                                        "`%s' does not exist in exception 
list", error_domain_name);
+               }
+
+               base.check (api_root, container, file_path, reporter, settings);
+       }
+
+       public override void accept (ContentVisitor visitor) {
+               visitor.visit_taglet (this);
+       }
+
+       public Vala.List<ContentElement>? get_inheritable_documentation () {
+               return content;
+       }
+
+       public bool inheritable (Taglet taglet) {
+               if (taglet is Taglets.Throws == false) {
+                       return false;
+               }
+
+               Taglets.Throws t = (Taglets.Throws) taglet;
+               return (error_domain == t.error_domain || error_domain_name == t.error_domain_name);
+       }
+
+       public override ContentElement copy (ContentElement? new_parent = null) {
+               Throws tr = new Throws ();
+               tr.parent = new_parent;
+
+               tr.error_domain_name = error_domain_name;
+               tr.error_domain = error_domain;
+
+               foreach (Block element in content) {
+                       Block copy = element.copy (tr) as Block;
+                       tr.content.add (copy);
+               }
+
+               return tr;
+       }
+}
+
diff --git a/libvaladoc/valadoc.deps.in b/libvaladoc/valadoc.deps.in
new file mode 100644
index 0000000..024e034
--- /dev/null
+++ b/libvaladoc/valadoc.deps.in
@@ -0,0 +1,3 @@
+gmodule-2.0
+libgvc
+libvala@PACKAGE_SUFFIX@
diff --git a/libvaladoc/valadoc.pc.in b/libvaladoc/valadoc.pc.in
new file mode 100644
index 0000000..b621d46
--- /dev/null
+++ b/libvaladoc/valadoc.pc.in
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+vapidir=@datadir@/vala/vapi
+
+Name: Valadoc
+Description: The Vala documentation compiler library
+Version: @VERSION@
+Requires: gmodule-2.0 libgvc libvala@PACKAGE_SUFFIX@
+Libs: -L${libdir} -lvaladoc@PACKAGE_SUFFIX@
+Cflags: -I${includedir}/valadoc@PACKAGE_SUFFIX@
diff --git a/valadoc/.gitignore b/valadoc/.gitignore
new file mode 100644
index 0000000..ed661db
--- /dev/null
+++ b/valadoc/.gitignore
@@ -0,0 +1 @@
+valadoc
diff --git a/valadoc/Makefile.am b/valadoc/Makefile.am
new file mode 100644
index 0000000..c6c9cda
--- /dev/null
+++ b/valadoc/Makefile.am
@@ -0,0 +1,79 @@
+include $(top_srcdir)/Makefile.common
+
+NULL =
+
+SUBDIRS = \
+       doclets \
+       icons \
+       tests \
+       $(NULL)
+
+AM_CFLAGS = \
+       -DPACKAGE_DATADIR=\"$(libdir)/valadoc\" \
+       -DPACKAGE_VERSION=\"$(VERSION)\" \
+       -I$(top_srcdir)/libvaladoc/ \
+       -I$(top_srcdir)/gee \
+       -I$(top_srcdir)/ccode \
+       -I$(top_srcdir)/vala \
+       -I$(top_srcdir)/codegen \
+       $(GLIB_CFLAGS) \
+       $(GMODULE_CFLAGS) \
+       $(LIBGVC_CFLAGS) \
+       $(NULL)
+
+BUILT_SOURCES = valadoc.vala.stamp
+
+bin_PROGRAMS = valadoc
+
+valadoc_VALASOURCES = \
+       driver.vala \
+       girwriter.vala \
+       initializerbuilder.vala \
+       symbolresolver.vala \
+       treebuilder.vala \
+       valadoc.vala \
+    $(NULL)
+
+valadoc_SOURCES = \
+       valadoc.vala.stamp \
+       $(valadoc_VALASOURCES:.vala=.c) \
+       $(NULL)
+
+valadoc_LDADD = \
+       $(top_builddir)/libvaladoc/libvaladoc@PACKAGE_SUFFIX@.la \
+       $(top_builddir)/vala/libvala@PACKAGE_SUFFIX@.la \
+       $(top_builddir)/ccode/libvalaccode.la \
+       $(top_builddir)/codegen/libvalaccodegen.la \
+       $(GLIB_LIBS) \
+       $(GMODULE_LIBS) \
+       $(LIBGVC_LIBS) \
+       $(NULL)
+
+valadoc.vala.stamp: $(valadoc_VALASOURCES) $(top_srcdir)/vala/libvala@PACKAGE_SUFFIX@.vapi 
$(top_srcdir)/libvaladoc/valadoc@PACKAGE_SUFFIX@.vapi
+       $(VALAC) \
+               $(VALAFLAGS) \
+               -C \
+               --vapidir $(top_srcdir)/vala \
+               --vapidir $(top_srcdir)/vapi \
+               --pkg gmodule-2.0 \
+               --pkg gobject-2.0 \
+               --vapidir $(top_srcdir)/ccode --pkg ccode \
+               --vapidir $(top_srcdir)/codegen --pkg codegen \
+               --vapidir $(top_srcdir)/libvaladoc --pkg valadoc@PACKAGE_SUFFIX@ \
+               --pkg config \
+               $(filter %.vala %.c,$^)
+       touch $@
+
+EXTRA_DIST = \
+       $(valadoc_VALASOURCES) \
+       valadoc.vala.stamp \
+       $(NULL)
+
+if ENABLE_UNVERSIONED
+install-exec-hook:
+       cd $(DESTDIR)$(bindir) && $(LN_S) -f valadoc@PACKAGE_SUFFIX@$(EXEEXT) valadoc$(EXEEXT)
+endif
+
+MAINTAINERCLEANFILES = \
+       $(valadoc_VALASOURCES:.vala=.c) \
+       $(NULL)
diff --git a/valadoc/doclets/Makefile.am b/valadoc/doclets/Makefile.am
new file mode 100644
index 0000000..90cf4b3
--- /dev/null
+++ b/valadoc/doclets/Makefile.am
@@ -0,0 +1,9 @@
+NULL =
+
+SUBDIRS = \
+       html \
+       devhelp \
+       gtkdoc \
+       $(NULL)
+
+
diff --git a/valadoc/doclets/devhelp/Makefile.am b/valadoc/doclets/devhelp/Makefile.am
new file mode 100644
index 0000000..b1ad704
--- /dev/null
+++ b/valadoc/doclets/devhelp/Makefile.am
@@ -0,0 +1,53 @@
+include $(top_srcdir)/Makefile.common
+
+NULL =
+
+AM_CFLAGS = \
+       -DPACKAGE_ICONDIR=\"$(datadir)/valadoc/icons/\" \
+       -I$(top_srcdir)/gee/ \
+       -I$(top_srcdir)/libvaladoc/ \
+       $(GLIB_CFLAGS) \
+       $(LIBGVC_CFLAGS) \
+       $(NULL)
+
+BUILT_SOURCES = libdoclet.vala.stamp
+
+doclet_LTLIBRARIES = libdoclet.la
+
+docletdir = $(libdir)/valadoc/doclets/devhelp
+
+libdoclet_la_LDFLAGS = -module -avoid-version -no-undefined
+
+libdoclet_la_VALASOURCES = \
+       doclet.vala \
+       $(NULL)
+
+libdoclet_la_SOURCES = \
+       libdoclet.vala.stamp \
+       $(libdoclet_la_VALASOURCES:.vala=.c) \
+       $(NULL)
+
+libdoclet.vala.stamp: $(libdoclet_la_VALASOURCES)
+       $(VALAC) \
+               $(VALAFLAGS) \
+               -C \
+               --vapidir $(top_srcdir)/vala \
+               --vapidir $(top_srcdir)/vapi \
+               --vapidir $(top_srcdir)/libvaladoc --pkg valadoc@PACKAGE_SUFFIX@ \
+               $(filter %.vala %.c,$^)
+       touch $@
+
+libdoclet_la_LIBADD = \
+       $(top_builddir)/libvaladoc/libvaladoc@PACKAGE_SUFFIX@.la \
+       $(GLIB_LIBS) \
+       $(NULL)
+
+EXTRA_DIST = \
+       $(libdoclet_la_VALASOURCES) \
+       libdoclet.vala.stamp \
+       $(NULL)
+
+MAINTAINERCLEANFILES = \
+       $(libdoclet_la_VALASOURCES:.vala=.c) \
+       $(NULL)
+
diff --git a/valadoc/doclets/devhelp/doclet.vala b/valadoc/doclets/devhelp/doclet.vala
new file mode 100644
index 0000000..a166cc1
--- /dev/null
+++ b/valadoc/doclets/devhelp/doclet.vala
@@ -0,0 +1,247 @@
+/* doclet.vala
+ *
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Valadoc;
+using Valadoc.Api;
+using Valadoc.Html;
+
+public class Valadoc.Devhelp.Doclet : Valadoc.Html.BasicDoclet {
+       private const string css_path_wiki = "devhelpstyle.css";
+       private const string css_path = "devhelpstyle.css";
+
+       private const string js_path_wiki = "scripts.js";
+       private const string js_path = "scripts.js";
+
+
+       private Vala.ArrayList<Api.Node> nodes = new Vala.ArrayList<Api.Node> ();
+       private string package_dir_name = ""; // remove
+
+       private Devhelp.MarkupWriter _devhelpwriter;
+
+       private string get_path (Api.Node element) {
+               return element.get_full_name () + ".html";
+       }
+
+       private string get_real_path (Api.Node element) {
+               return GLib.Path.build_filename (this.settings.path,
+                               this.package_dir_name, element.get_full_name () + ".html");
+       }
+
+       protected override string get_icon_directory () {
+               return "";
+       }
+
+
+       public override void process (Settings settings, Api.Tree tree, ErrorReporter reporter) {
+               base.process (settings, tree, reporter);
+               DirUtils.create_with_parents (this.settings.path, 0777);
+               write_wiki_pages (tree,
+                                                 css_path_wiki,
+                                                 js_path_wiki,
+                                                 Path.build_filename (this.settings.path, 
this.settings.pkg_name));
+               tree.accept (this);
+       }
+
+       public override void visit_tree (Api.Tree tree) {
+               tree.accept_children (this);
+       }
+
+       public override void visit_package (Package package) {
+               if (!package.is_browsable (settings)) {
+                       return ;
+               }
+
+               string pkg_name = package.name;
+
+               string path = GLib.Path.build_filename (this.settings.path, pkg_name);
+               string filepath = GLib.Path.build_filename (path, "index.htm");
+               string imgpath = GLib.Path.build_filename (path, "img");
+               string devpath = GLib.Path.build_filename (path, pkg_name + ".devhelp2");
+
+               this.package_dir_name = pkg_name;
+
+               var rt = DirUtils.create (path, 0777);
+               rt = DirUtils.create (imgpath, 0777);
+               copy_directory (icons_dir, path);
+
+               var devfile = FileStream.open (devpath, "w");
+               _devhelpwriter = new Devhelp.MarkupWriter (devfile);
+
+               _devhelpwriter.start_book (pkg_name+" Reference Manual",
+                                                                  "vala",
+                                                                  "index.htm",
+                                                                  pkg_name,
+                                                                  "",
+                                                                  "");
+
+               GLib.FileStream file = GLib.FileStream.open (filepath, "w");
+               writer = new Html.MarkupWriter (file);
+               _renderer.set_writer (writer);
+               write_file_header (Valadoc.Devhelp.Doclet.css_path, Valadoc.Devhelp.Doclet.js_path, pkg_name);
+               write_package_content (package, package);
+               write_file_footer ();
+               file = null;
+
+
+               _devhelpwriter.start_chapters ();
+               package.accept_all_children (this);
+               _devhelpwriter.end_chapters ();
+
+               _devhelpwriter.start_functions ();
+               foreach (Api.Node node in this.nodes) {
+                       string typekeyword = "";
+                       if (node is Api.Enum) {
+                               typekeyword = "enum";
+                       } else if (node is Api.Constant) {
+                               typekeyword = "constant";
+                       } else if (node is Api.Method) {
+                               typekeyword = "function";
+                       } else if (node is Api.Field) {
+                               typekeyword = "variable";
+                       } else if (node is Api.Property) {
+                               typekeyword = "property";
+                       } else if (node is Api.Signal) {
+                               typekeyword = "signal";
+                       } else if (node is Api.Struct) {
+                               typekeyword = "struct";
+                       }
+
+                       _devhelpwriter.simple_tag ("keyword", {"type", typekeyword,
+                                                                                                  "name", 
node.get_full_name (),
+                                                                                                  "link", 
get_link (node, node.package)});
+               }
+               _devhelpwriter.end_functions ();
+
+               _devhelpwriter.end_book ();
+       }
+
+       private void process_compound_node (Api.Node node) {
+               string rpath = this.get_real_path (node);
+               string path = this.get_path (node);
+
+               if (node.name != null) {
+                       GLib.FileStream file = GLib.FileStream.open (rpath, "w");
+                       writer = new Html.MarkupWriter (file);
+                       _renderer.set_writer (writer);
+                       write_file_header (css_path,
+                                                          js_path,
+                                                          node.get_full_name () + " &ndash; " + 
node.package.name);
+                       write_symbol_content (node);
+                       write_file_footer ();
+                       file = null;
+               }
+
+               if (node.name != null) {
+                       _devhelpwriter.start_sub (node.name, path);
+                       node.accept_all_children (this);
+                       _devhelpwriter.end_sub ();
+                       this.nodes.add (node);
+               } else {
+                       node.accept_all_children (this);
+               }
+       }
+
+       private void process_node (Api.Node node, bool accept_all_children) {
+               string rpath = this.get_real_path (node);
+               string path = this.get_path (node);
+
+               GLib.FileStream file = GLib.FileStream.open (rpath, "w");
+               writer = new Html.MarkupWriter (file);
+               _renderer.set_writer (writer);
+               write_file_header (css_path,
+                                                  js_path,
+                                                  node.get_full_name() + " &ndash; " + node.package.name);
+               write_symbol_content (node);
+               write_file_footer ();
+               file = null;
+
+               if (accept_all_children) {
+                       _devhelpwriter.start_sub (node.name, path);
+                       node.accept_all_children (this);
+                       _devhelpwriter.end_sub ();
+               }
+               this.nodes.add (node);
+       }
+
+       public override void visit_namespace (Namespace item) {
+               process_compound_node (item);
+       }
+
+       public override void visit_interface (Interface item) {
+               process_compound_node (item);
+       }
+
+       public override void visit_class (Class item) {
+               process_compound_node (item);
+       }
+
+       public override void visit_struct (Struct item) {
+               process_compound_node (item);
+       }
+
+       public override void visit_error_domain (ErrorDomain item) {
+               process_node (item, true);
+       }
+
+       public override void visit_enum (Api.Enum item) {
+               process_node (item, true);
+       }
+
+       public override void visit_property (Property item) {
+               process_node (item, false);
+       }
+
+       public override void visit_constant (Constant item) {
+               process_node (item, false);
+       }
+
+       public override void visit_field (Field item) {
+               process_node (item, false);
+       }
+
+       public override void visit_error_code (ErrorCode item) {
+               process_node (item, false);
+       }
+
+       public override void visit_enum_value (Api.EnumValue item) {
+               process_node (item, false);
+       }
+
+       public override void visit_delegate (Delegate item) {
+               process_node (item, false);
+       }
+
+       public override void visit_signal (Api.Signal item) {
+               process_node (item, false);
+       }
+
+       public override void visit_method (Method item) {
+               process_node (item, false);
+       }
+}
+
+
+public Type register_plugin (Valadoc.ModuleLoader module_loader) {
+       return typeof (Valadoc.Devhelp.Doclet);
+}
+
diff --git a/valadoc/doclets/gtkdoc/Makefile.am b/valadoc/doclets/gtkdoc/Makefile.am
new file mode 100644
index 0000000..c0d35ab
--- /dev/null
+++ b/valadoc/doclets/gtkdoc/Makefile.am
@@ -0,0 +1,58 @@
+include $(top_srcdir)/Makefile.common
+
+NULL =
+
+AM_CFLAGS = \
+       -DPACKAGE_ICONDIR=\"$(datadir)/valadoc/icons/\" \
+       -I$(top_srcdir)/gee/ \
+       -I$(top_srcdir)/libvaladoc/ \
+       $(GLIB_CFLAGS) \
+       $(LIBGVC_CFLAGS) \
+       $(NULL)
+
+BUILT_SOURCES = libdoclet.vala.stamp
+
+doclet_LTLIBRARIES = libdoclet.la
+
+docletdir = $(libdir)/valadoc/doclets/gtkdoc
+
+libdoclet_la_LDFLAGS = -module -avoid-version -no-undefined
+
+libdoclet_la_VALASOURCES = \
+       commentconverter.vala \
+       dbus.vala \
+       doclet.vala \
+       gcomment.vala \
+       generator.vala \
+       utils.vala \
+       $(NULL)
+
+libdoclet_la_SOURCES = \
+       libdoclet.vala.stamp \
+       $(libdoclet_la_VALASOURCES:.vala=.c) \
+       $(NULL)
+
+libdoclet.vala.stamp: $(libdoclet_la_VALASOURCES)
+       $(VALAC) \
+               $(VALAFLAGS) \
+               -C \
+               --vapidir $(top_srcdir)/vala \
+               --vapidir $(top_srcdir)/vapi \
+               --vapidir $(top_srcdir)/libvaladoc --pkg valadoc@PACKAGE_SUFFIX@ \
+               $(filter %.vala %.c,$^)
+       touch $@
+
+libdoclet_la_LIBADD = \
+       $(top_builddir)/libvaladoc/libvaladoc@PACKAGE_SUFFIX@.la \
+       $(GLIB_LIBS) \
+       $(NULL)
+
+EXTRA_DIST = \
+       $(libdoclet_la_VALASOURCES) \
+       libdoclet.vala.stamp \
+       $(NULL)
+
+MAINTAINERCLEANFILES = \
+       $(libdoclet_la_VALASOURCES:.vala=.c) \
+       $(NULL)
+
diff --git a/valadoc/doclets/gtkdoc/commentconverter.vala b/valadoc/doclets/gtkdoc/commentconverter.vala
new file mode 100644
index 0000000..25e7a09
--- /dev/null
+++ b/valadoc/doclets/gtkdoc/commentconverter.vala
@@ -0,0 +1,305 @@
+/* commentconverter.vala
+ *
+ * Copyright (C) 2010 Luca Bruno
+ *
+ * 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:
+ *     Luca Bruno <lethalman88 gmail com>
+ */
+
+using Valadoc;
+using Valadoc.Api;
+using Valadoc.Content;
+
+public class Gtkdoc.CommentConverter : ContentVisitor {
+       public Api.Node node_reference;
+
+       public bool is_dbus;
+       public string brief_comment;
+       public string long_comment;
+       public string returns;
+       public Vala.List<Header> parameters = new Vala.ArrayList<Header> ();
+       public Vala.List<Header> versioning = new Vala.ArrayList<Header> ();
+       public string[] see_also = new string[]{};
+
+       private StringBuilder current_builder = new StringBuilder ();
+       private bool in_brief_comment = true;
+       private ErrorReporter reporter;
+
+       public CommentConverter (ErrorReporter reporter, Api.Node? node_reference = null) {
+               this.node_reference = node_reference;
+               this.reporter = reporter;
+       }
+
+       public void convert (Content.Comment comment, bool is_dbus = false) {
+               this.is_dbus = is_dbus;
+               comment.accept (this);
+
+               long_comment = current_builder.str.strip ();
+               if (long_comment == "") {
+                       long_comment = null;
+               }
+       }
+
+       public override void visit_comment (Content.Comment c) {
+               c.accept_children (this);
+       }
+  
+       public override void visit_embedded (Embedded em) {
+               current_builder.append ("<figure>");
+               if (em.caption != null) {
+                       current_builder.append_printf ("<title>%s</title>", em.caption);
+               }
+
+               current_builder.append_printf ("<mediaobject><imageobject><imagedata 
fileref=\"%s\"/></imageobject>",
+                                                                          em.url);
+
+               if (em.caption != null) {
+                       current_builder.append_printf ("<textobject><phrase>%s</phrase></textobject>", 
em.caption);
+               }
+
+               em.accept_children (this);
+               current_builder.append ("</mediaobject>");
+               current_builder.append ("</figure>");
+       }
+
+       public override void visit_headline (Headline hl) {
+               // what to do here?
+               reporter.simple_warning ("GtkDoc", "Headline elements not supported");
+               current_builder.append ("\n");
+               hl.accept_children (this);
+               current_builder.append ("\n");
+       }
+  
+       public override void visit_wiki_link (WikiLink link) {
+               // wiki pages are not supported right now
+               if (link.content.size > 0) {
+                       link.accept_children (this);
+               } else {
+                       current_builder.append (link.name);
+               }
+       }
+
+       public override void visit_link (Link link) {
+               current_builder.append_printf ("<ulink url=\"%s\">", link.url);
+               link.accept_children (this);
+               current_builder.append ("</ulink>");
+       }
+
+       public override void visit_symbol_link (SymbolLink sl) {
+               if (sl.symbol != null) {
+                       // If the symbol is a method and it doesn't have a constructor, fall back to linking 
to the class
+                       if (sl.symbol is Method && ((Method) sl.symbol).is_constructor &&
+                           ((Method) sl.symbol).parent is Class && ((Class) ((Method) 
sl.symbol).parent).is_abstract) {
+                               current_builder.append (get_docbook_link (((Method) sl.symbol).parent, 
is_dbus) ?? sl.given_symbol_name);
+                       } else {
+                               current_builder.append (get_docbook_link (sl.symbol, is_dbus) ?? 
sl.given_symbol_name);
+                       }
+               } else {
+                       current_builder.append (sl.given_symbol_name);
+               }
+       }
+
+       public override void visit_list (Content.List list) {
+               string tag = "orderedlist";
+               switch (list.bullet) {
+               case Content.List.Bullet.NONE:
+                       current_builder.append ("<itemizedlist mark=\"none\">");
+                       tag = "itemizedlist";
+                       break;
+
+               case Content.List.Bullet.UNORDERED:
+                       current_builder.append ("<itemizedlist>");
+                       tag = "itemizedlist";
+                       break;
+
+               case Content.List.Bullet.ORDERED:
+                       current_builder.append ("<orderedlist>");
+                       break;
+
+               case Content.List.Bullet.ORDERED_NUMBER:
+                       current_builder.append ("<orderedlist numeration=\"arabic\">");
+                       break;
+
+               case Content.List.Bullet.ORDERED_LOWER_CASE_ALPHA:
+                       current_builder.append ("<orderedlist numeration=\"loweralpha\">");
+                       break;
+
+               case Content.List.Bullet.ORDERED_UPPER_CASE_ALPHA:
+                       current_builder.append ("<orderedlist numeration=\"upperalpha\">");
+                       break;
+
+               case Content.List.Bullet.ORDERED_LOWER_CASE_ROMAN:
+                       current_builder.append ("<orderedlist numeration=\"lowerroman\">");
+                       break;
+
+               case Content.List.Bullet.ORDERED_UPPER_CASE_ROMAN:
+                       current_builder.append ("<orderedlist numeration=\"upperroman\">");
+                       break;
+
+               default:
+                       reporter.simple_warning ("GtkDoc",
+                                                                        "unsupported list type: '%s'", 
list.bullet.to_string ());
+                       break;
+               }
+
+               list.accept_children (this);
+               current_builder.append_printf ("</%s>", tag);
+       }
+  
+       public override void visit_list_item (ListItem item) {
+               current_builder.append ("<listitem>");
+               item.accept_children (this);
+               current_builder.append ("</listitem>");
+       }
+  
+       public override void visit_paragraph (Paragraph para) {
+               if (!in_brief_comment) {
+                       current_builder.append ("<para>");
+               }
+               para.accept_children (this);
+
+               if (in_brief_comment) {
+                       brief_comment = current_builder.str;
+                       current_builder = new StringBuilder ();
+                       in_brief_comment = false;
+               } else {
+                       current_builder.append ("</para>");
+               }
+       }
+
+       public override void visit_warning (Warning element) {
+               current_builder.append ("<warning>");
+               element.accept_children (this);
+               current_builder.append ("</warning>");
+       }
+
+       public override void visit_note (Note element) {
+               current_builder.append ("<note>");
+               element.accept_children (this);
+               current_builder.append ("</note>");
+       }
+
+       public override void visit_page (Page page) {
+               page.accept_children (this);
+       }
+  
+       public override void visit_run (Run run) {
+               string? tag = null;
+               switch (run.style) {
+               case Run.Style.BOLD:
+                       current_builder.append ("<emphasis role=\"bold\">");
+                       tag = "emphasis";
+                       break;
+
+               case Run.Style.ITALIC:
+                       current_builder.append ("<emphasis>");
+                       tag = "emphasis";
+                       break;
+
+               case Run.Style.UNDERLINED:
+                       current_builder.append ("<emphasis role=\"underline\">");
+                       tag = "emphasis";
+                       break;
+
+               case Run.Style.MONOSPACED:
+                       current_builder.append ("<code>");
+                       tag = "code";
+                       break;
+               }
+               run.accept_children (this);
+
+               if (tag != null) {
+                       current_builder.append_printf ("</%s>", tag);
+               }
+       }
+  
+       public override void visit_source_code (SourceCode code) {
+               current_builder.append ("\n|[\n");
+               current_builder.append (Markup.escape_text (code.code));
+               current_builder.append ("\n]|\n");
+       }
+  
+       public override void visit_table (Table t) {
+               current_builder.append ("<table>");
+               t.accept_children (this);
+               current_builder.append ("</table>");
+       }
+  
+       public override void visit_table_row (TableRow row) {
+               current_builder.append ("<tr>");
+               row.accept_children (this);
+               current_builder.append ("</tr>");
+       }
+
+       public override void visit_table_cell (TableCell cell) {
+               current_builder.append ("<td>");
+               cell.accept_children (this);
+               current_builder.append ("</td>");
+       }
+  
+       public override void visit_taglet (Taglet t) {
+               var old_builder = (owned)current_builder;
+               current_builder = new StringBuilder ();
+
+               t.accept_children (this);
+               if (t is Taglets.Param) {
+                       double pos = double.MAX;
+                       var param_name = ((Taglets.Param)t).parameter_name;
+                       if (node_reference != null) {
+                               pos = get_parameter_pos (node_reference, param_name);
+                       }
+                       var header = new Header (param_name, current_builder.str, pos);
+                       parameters.add (header);
+               } else if (t is Taglets.InheritDoc) {
+                       ((Taglets.InheritDoc)t).produce_content().accept (this);
+               } else if (t is Taglets.Return) {
+                       returns = current_builder.str;
+               } else if (t is Taglets.Since) {
+                       var header = new Header ("Since", ((Taglets.Since)t).version);
+                       versioning.add (header);
+               } else if (t is Taglets.Deprecated) {
+                       var header = new Header ("Deprecated", current_builder.str);
+                       versioning.add (header);
+               } else if (t is Taglets.See) {
+                       var see = (Taglets.See)t;
+                       var see_also = this.see_also; // vala bug
+                       if (see.symbol != null) {
+                               see_also += get_docbook_link (see.symbol, is_dbus) ?? see.symbol_name;
+                       } else {
+                               see_also += see.symbol_name;
+                       }
+                       this.see_also = see_also;
+               } else if (t is Taglets.Link) {
+                       ((Taglets.Link)t).produce_content().accept (this);
+               } else if (t is Taglets.Throws) {
+                       var taglet = (Taglets.Throws) t;
+                       var link = get_docbook_link (taglet.error_domain) ?? taglet.error_domain_name;
+                       old_builder.append_printf ("\n<para>%s will be returned in @error %s</para>",
+                                                                          link,
+                                                                          current_builder.str);
+               } else {
+                       reporter.simple_warning ("GtkDoc", "Taglet not supported"); // TODO
+               }
+               current_builder = (owned)old_builder;
+       }
+  
+       public override void visit_text (Text t) {
+               current_builder.append (Markup.escape_text (t.content));
+               t.accept_children (this);
+       }
+}
+
diff --git a/valadoc/doclets/gtkdoc/dbus.vala b/valadoc/doclets/gtkdoc/dbus.vala
new file mode 100644
index 0000000..fbdab78
--- /dev/null
+++ b/valadoc/doclets/gtkdoc/dbus.vala
@@ -0,0 +1,300 @@
+/* doclet.vala
+ *
+ * Copyright (C) 2010 Luca Bruno
+ *
+ * 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:
+ *     Luca Bruno <lethalman88 gmail com>
+ */
+
+using Valadoc;
+using Valadoc.Api;
+using Valadoc.Content;
+
+namespace Gtkdoc.DBus {
+       public class Parameter {
+               public enum Direction {
+                       NONE,
+                       IN,
+                       OUT;
+
+                       public string to_string () {
+                               switch (this) {
+                               case NONE:
+                                       return "";
+                               case IN:
+                                       return "in";
+                               case OUT:
+                                       return "out";
+                               default:
+                                       assert_not_reached ();
+                               }
+                       }
+               }
+
+               public string name;
+               public string signature;
+               public Direction direction;
+
+               public Parameter (string name, string signature, Direction direction = Direction.NONE) {
+                       this.name = name;
+                       this.signature = signature;
+                       this.direction = direction;
+               }
+
+               public string to_string () {
+                       if (direction == Direction.NONE) {
+                               return """<parameter><type>'%s'</type> %s</parameter>""".printf (signature, 
name);
+                       } else {
+                               return """<parameter>%s <type>'%s'</type> %s</parameter>""".printf 
(direction.to_string(),
+                                                                                                             
                                                          signature,
+                                                                                                             
                                                          name);
+                       }
+               }
+       }
+
+       public class Member {
+               public string name;
+               public Vala.List<Parameter> parameters = new Vala.ArrayList<Parameter>();
+               public GComment comment;
+
+               internal DBus.Interface iface;
+
+               public Member (string name) {
+                       this.name = name;
+               }
+
+               public void add_parameter (Parameter parameter) {
+                       parameters.add (parameter);
+               }
+
+               public string get_docbook_id () {
+                       return to_docbook_id (name);
+               }
+
+               public string to_string (int indent, bool link) {
+                       var builder = new StringBuilder ();
+
+                       if (link) {
+                               builder.append_printf ("""
+<link linkend="%s-%s">%s</link>%s(""",
+                                                                          iface.get_docbook_id (),
+                                                                          get_docbook_id (),
+                                                                          name,
+                                                                          string.nfill (indent-name.length, 
' '));
+                       } else {
+                               builder.append_printf ("\n%s%s(",
+                                                                          name,
+                                                                          string.nfill (indent-name.length, 
' '));
+                       }
+
+                       if (parameters.size > 0) {
+                               builder.append (parameters[0].to_string ());
+                       }
+                       for (int i=1; i < parameters.size; i++) {
+                               builder.append (",\n");
+                               builder.append (string.nfill (indent+1, ' '));
+                               builder.append (parameters[i].to_string ());
+                       }
+                       builder.append_c (')');
+                       return builder.str;
+               }
+       }
+
+       public class Interface {
+               public string package_name;
+               public string name;
+               public string purpose;
+               public string description;
+               public Vala.List<Member> methods = new Vala.ArrayList<Member>();
+               public Vala.List<Member> signals = new Vala.ArrayList<Member>();
+
+               public Interface (string package_name,
+                                                 string name,
+                                                 string purpose = "",
+                                                 string description = "")
+               {
+                       this.package_name = package_name;
+                       this.name = name;
+                       this.purpose = purpose;
+                       this.description = description;
+               }
+
+               public void add_method (Member member) {
+                       member.iface = this;
+                       methods.add (member);
+               }
+
+               public void add_signal (Member member) {
+                       member.iface = this;
+                       signals.add (member);
+               }
+
+               public string get_docbook_id () {
+                       return to_docbook_id (name);
+               }
+
+               public bool write (Settings settings, ErrorReporter reporter) {
+                       var xml_dir = Path.build_filename (settings.path, "xml");
+                       DirUtils.create_with_parents (xml_dir, 0777);
+
+                       var xml_file = Path.build_filename (xml_dir,
+                                                                                               
"%s.xml".printf (to_docbook_id (name)));
+                       var writer = new TextWriter (xml_file, "w");
+                       if (!writer.open ()) {
+                               reporter.simple_error ("GtkDoc",
+                                                                          "unable to open '%s' for writing", 
writer.filename);
+                               return false;
+                       }
+                       writer.write_line (to_string (reporter));
+                       writer.close ();
+                       return true;
+               }
+
+               public string to_string (ErrorReporter reporter) {
+                       /* compute minimum indent for methods */
+                       var method_indent = 0;
+                       foreach (var method in methods) {
+                               method_indent = int.max (method_indent, (int)method.name.length);
+                       }
+                       method_indent += 5;
+
+                       /* compute minimum indent for signals */
+                       var signal_indent = 0;
+                       foreach (var sig in signals) {
+                               signal_indent = int.max (signal_indent, (int)sig.name.length);
+                       }
+                       signal_indent += 5;
+
+                       var builder = new StringBuilder ();
+                       var docbook_id = get_docbook_id ();
+
+                       builder.append ("<?xml version=\"1.0\"?><!DOCTYPE refentry PUBLIC \"-//OASIS//DTD 
DocBook XML V4.3//EN\" \"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd\"";);
+                       builder.append_printf ("""
+[<!ENTITY %% local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">]>
+<refentry id="docs-%s">
+<refmeta>
+<refentrytitle role="top_of_page" id="docs-%s.top_of_page">%s</refentrytitle>
+<manvolnum>3</manvolnum>
+<refmiscinfo>
+%s D-Bus API
+</refmiscinfo>
+</refmeta>
+<refnamediv>
+<refname>%s</refname>
+<refpurpose>%s</refpurpose>
+</refnamediv>""",
+                                                               docbook_id,
+                                                               docbook_id,
+                                                               name,
+                                                               package_name.up (),
+                                                               name,
+                                                               purpose ?? "");
+
+                       /*
+                        * Methods
+                        */
+                       if (methods.size > 0) {
+                               builder.append_printf ("""
+<refsynopsisdiv id="docs-%s.synopsis" role="synopsis">
+<title role="synopsis.title">Methods</title>
+<synopsis>""", docbook_id);
+                               foreach (var method in methods) {
+                                       builder.append (method.to_string (method_indent, true));
+                               }
+                               builder.append ("</synopsis></refsynopsisdiv>");
+                       }
+
+                       /*
+                        * Signals
+                        */
+                       if (signals.size > 0) {
+                               builder.append_printf ("""
+<refsynopsisdiv id="docs-%s.signals" role="signal_proto">
+<title role="signal_proto.title">Signals</title>
+<synopsis>""", docbook_id);
+                               foreach (var sig in signals) {
+                                       builder.append (sig.to_string (signal_indent, true));
+                               }
+                               builder.append ("</synopsis></refsynopsisdiv>");
+                       }
+
+                       /*
+                        * Description
+                        */
+                       builder.append_printf ("""
+<refsect1 id="docs-%s.description" role="desc">
+<title role="desc.title">Description</title>
+%s
+</refsect1>""", docbook_id, description);
+
+                       /*
+                        * Methods details
+                        */
+                       if (methods.size > 0) {
+                               builder.append_printf ("""
+<refsect1 id="docs-%s.details" role="details">
+<title role="details.title">Details</title>""", docbook_id);
+
+                               foreach (var method in methods) {
+                                       builder.append_printf ("""
+<refsect2 id="%s-%s" role="function">
+<title>%s ()</title>
+<programlisting>%s
+</programlisting>
+%s
+</refsect2>""",
+                                                       docbook_id,
+                                                       method.get_docbook_id (),
+                                                       method.name,
+                                                       method.to_string (method_indent, false),
+                                                       method.comment != null ? method.comment.to_docbook 
(reporter) : "");
+                               }
+
+                               builder.append ("</refsect1>");
+                       }
+
+                       /*
+                        * Signals details
+                        */
+                       if (signals.size > 0) {
+                               builder.append_printf ("""
+<refsect1 id="docs-%s.signal-details" role="signals">
+<title role="signals.title">Signal Details</title>""", docbook_id);
+
+                               foreach (var sig in signals) {
+                                       builder.append_printf ("""
+<refsect2 id="%s-%s" role="signal">
+<title>The <literal>%s</literal> signal</title>
+<programlisting>%s
+</programlisting>
+%s
+</refsect2>""",
+                                               docbook_id,
+                                               sig.get_docbook_id (),
+                                               sig.name,
+                                               sig.to_string (signal_indent, false),
+                                               sig.comment != null ? sig.comment.to_docbook (reporter) : "");
+                               }
+
+                               builder.append ("</refsect1>");
+                       }
+
+                       builder.append ("</refentry>");
+                       return builder.str;
+               }
+       }
+}
diff --git a/valadoc/doclets/gtkdoc/doclet.vala b/valadoc/doclets/gtkdoc/doclet.vala
new file mode 100644
index 0000000..2d000f6
--- /dev/null
+++ b/valadoc/doclets/gtkdoc/doclet.vala
@@ -0,0 +1,443 @@
+/* doclet.vala
+ *
+ * Copyright (C) 2010 Luca Bruno
+ *
+ * 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:
+ *     Luca Bruno <lethalman88 gmail com>
+ */
+
+using Valadoc;
+using Valadoc.Api;
+using Valadoc.Content;
+
+namespace Gtkdoc.Config {
+       public static bool nohtml;
+       [CCode (array_length = false, array_null_terminated = true)]
+       public static string[] library_filenames;
+       [CCode (array_length = false, array_null_terminated = true)]
+       public static string[] ignore_headers;
+       [CCode (array_length = false, array_null_terminated = true)]
+       public static string[] source_files;
+       public static string deprecated_guards;
+       public static string ignore_decorators;
+
+       private const GLib.OptionEntry[] options = {
+                       { "library", 'l', 0, OptionArg.FILENAME_ARRAY, ref library_filenames, "Shared library 
path", "FILENAME" },
+                       { "ignore-headers", 'x', 0, OptionArg.FILENAME_ARRAY, ref ignore_headers, "A list of 
header files to not scan", "FILES" },
+                       { "deprecated-guards", 'd', 0, OptionArg.STRING, ref deprecated_guards, "A 
|-separated list of symbols used as deprecation guards", "GUARDS" },
+                       { "ignore-decorators", 0, 0, OptionArg.STRING, ref ignore_decorators, "A |-separated 
list of addition decorators in declarations that should be ignored", "DECS" },
+                       { "no-html", 0, 0, OptionArg.NONE, ref nohtml, "Disable HTML generation", null },
+                       { "", 0, 0, OptionArg.FILENAME_ARRAY, ref source_files, null, "FILE..." },
+                       { null }
+               };
+
+       public static bool parse (string[] rargs, ErrorReporter reporter) {
+               string[] args = { "gtkdoc" };
+               foreach (var arg in rargs) {
+                       args += arg;
+               }
+
+               try {
+                       var opt_context = new OptionContext ("- Vala GTK-Doc");
+                       opt_context.set_help_enabled (true);
+                       opt_context.add_main_entries (options, null);
+                       unowned string[] gtkdoc_args = args;
+                       opt_context.parse (ref gtkdoc_args);
+               } catch (OptionError e) {
+                       reporter.simple_error ("GtkDoc", "%s\nRun '-X --help' to see a full list of available 
command line options.", e.message);
+                       return false;
+               }
+
+               // real path to ignored headers
+               for (int i=0; i < ignore_headers.length; i++) {
+                       var realheader = realpath (ignore_headers[i]);
+                       if (realheader != null) {
+                               ignore_headers[i] = realheader;
+                       }
+               }
+
+               return true;
+       }
+}
+
+
+
+public class Gtkdoc.Director : Valadoc.Doclet, Object {
+       private ErrorReporter reporter;
+       private Settings settings;
+       private Api.Tree tree;
+       private Gtkdoc.Generator generator;
+       private string[] vala_headers;
+       private string[] c_headers;
+
+       private static string[] combine_string_arrays (string[] a, string[] b) {
+               string[] result = a;
+               foreach (string e in b) {
+                       result += e;
+               }
+               return result;
+       }
+
+       /*
+        * 1) Scan normal code, this generates -decl.txt for both C and Vala.
+        * 2) Scan C code into a temp cscan directory. This generates C sections.
+        *    Move C -sections.txt file to the real output -sections.txt.
+        * 3) Generate and append Vala sections to -sections.txt.
+        * Done. Now we have -decl.txt of the whole code and -sections.txt containing C sections
+        * and Vala sections.
+        */
+       public void process (Settings settings, Api.Tree tree, ErrorReporter reporter) {
+               if (!Config.parse (settings.pluginargs, reporter)) {
+                       return;
+               }
+
+               this.settings = settings;
+               this.reporter = reporter;
+               this.tree = tree;
+
+               var ccomments_dir = Path.build_filename (settings.path, "ccomments");
+               var cscan_dir = Path.build_filename (settings.path, "cscan");
+               DirUtils.create_with_parents (settings.path, 0755);
+               DirUtils.create_with_parents (ccomments_dir, 0755);
+               DirUtils.create_with_parents (cscan_dir, 0755);
+
+               var files = combine_string_arrays (Config.source_files, tree.get_external_c_files ().to_array 
());
+               if (!prepare_files (files, ccomments_dir)) {
+                       return;
+               }
+
+               var all_headers = combine_string_arrays (vala_headers, c_headers);
+               if (!scan (settings.path, all_headers)) {
+                       return;
+               }
+
+               if (!scan (cscan_dir, c_headers)) {
+                       return;
+               }
+
+               FileUtils.rename (Path.build_filename (cscan_dir, "%s-sections.txt".printf 
(settings.pkg_name)),
+                       Path.build_filename (settings.path, "%s-sections.txt".printf (settings.pkg_name)));
+
+               generator = new Gtkdoc.Generator ();
+               if (!generator.execute (settings, tree, reporter)) {
+                       return;
+               }
+
+               if (!scangobj ()) {
+                       return;
+               }
+
+               if (!mkdb ()) {
+                       return;
+               }
+
+               if (!mkhtml ()) {
+                       return;
+               }
+       }
+
+       private void prepare_c_file (string filename, string comments_dir) {
+               if (is_generated_by_vala (filename)) {
+                       return;
+               }
+
+               if (!copy_file (filename, Path.build_filename (comments_dir, Path.get_basename (filename)))) {
+                       reporter.simple_error ("GtkDoc", "Can't copy '%s'", filename);
+               }
+       }
+
+       private void prepare_h_file (string filename) {
+               if (filename in Config.ignore_headers) {
+                       return;
+               }
+
+               if (is_generated_by_vala (filename)) {
+                       vala_headers += filename;
+               } else {
+                       c_headers += filename;
+               }
+       }
+
+       private bool prepare_files (string[] files, string comments_dir) {
+               vala_headers = new string[]{};
+               c_headers = new string[]{};
+
+               string[] prepared = new string[]{};
+
+               foreach (string relative_filename in files) {
+                       var filename = realpath (relative_filename);
+
+                       if (filename in prepared) {
+                               continue;
+                       }
+                       prepared += filename;
+
+                       if (!FileUtils.test (filename, FileTest.EXISTS)) {
+                               reporter.simple_error ("GtkDoc", "'%s' not found", relative_filename);
+                               continue;
+                       }
+
+                       if (filename.has_suffix (".c")) {
+                               prepare_c_file (filename, comments_dir);
+                       } else if (filename.has_suffix (".h")) {
+                               prepare_h_file (filename);
+                       } else {
+                               reporter.simple_error ("GtkDoc",
+                                                                          "'%s' is not a supported source 
file type. Only .h, and .c files are supported.",
+                                                                          relative_filename);
+                       }
+               }
+
+               if (vala_headers.length <= 0) {
+                       reporter.simple_error ("GtkDoc", "No vala header found");
+               }
+
+               return reporter.errors == 0;
+       }
+
+       private bool scan (string output_dir, string[]? headers = null) {
+               if (headers == null) {
+                       // nothing to scan
+                       return true;
+               }
+
+               string[] args = { "gtkdoc-scan",
+                                 "--module", settings.pkg_name,
+                                 "--output-dir", output_dir,
+                                 "--rebuild-sections",
+                                 "--rebuild-types" };
+
+               foreach (var header in headers) {
+                       args += header;
+               }
+
+               if (Config.deprecated_guards != null) {
+                       args += "--deprecated-guards";
+                       args += Config.deprecated_guards;
+               }
+
+               if (Config.ignore_decorators != null) {
+                       args += "--ignore-decorators";
+                       args += Config.ignore_decorators;
+               }
+
+               try {
+                       Process.spawn_sync (settings.path, args, null, SpawnFlags.SEARCH_PATH, null, null, 
null);
+               } catch (Error e) {
+                       reporter.simple_error ("gtkdoc-scan", "%s", e.message);
+                       return false;
+               }
+
+               return true;
+       }
+
+       private bool scangobj () {
+               if (Config.library_filenames == null) {
+                       return true;
+               }
+
+               StringBuilder library_paths = new StringBuilder ();
+               StringBuilder library_dirs = new StringBuilder ();
+               foreach (string library in Config.library_filenames) {
+                       string so_path = realpath (library);
+                       string name = Path.get_dirname (so_path);
+                       library_dirs.append (name);
+                       library_paths.append (so_path);
+                       library_paths.append_c (' ');
+                       library_dirs.append_c (':');
+               }
+
+               string[] pc = new string[] { "pkg-config" };
+
+               foreach (var package in tree.get_package_list()) {
+                       if (package.is_package && package_exists (package.name, reporter)) {
+                               pc += package.name;
+                       }
+               }
+
+               //TODO: find out why var pc_cflags = pc; fails (free, invalid next size)
+               string[] pc_cflags = new string[] {};
+               foreach (var name in pc) {
+                       pc_cflags += name;
+               }
+               pc_cflags += "--cflags";
+
+               string[] pc_libs = new string[] {};
+               foreach (var name in pc) {
+                       pc_libs += name;
+               }
+               pc_libs += "--libs";
+
+               try {
+                       string stderr;
+                       int status;
+
+                       string cflags;
+                       Process.spawn_sync (null, pc_cflags, null, SpawnFlags.SEARCH_PATH, null, out cflags, 
out stderr, out status);
+                       if (status != 0) {
+                               reporter.simple_error ("GtkDoc", "pkg-config cflags error: %s", stderr);
+                               return false;
+                       }
+                       cflags = cflags.strip ();
+
+                       string libs;
+                       Process.spawn_sync (null, pc_libs, null, SpawnFlags.SEARCH_PATH, null, out libs, out 
stderr, out status);
+                       if (status != 0) {
+                               reporter.simple_error ("GtkDoc", "pkg-config libs error: %s", stderr);
+                               return false;
+                       }
+
+                       libs = libs.strip ();
+                       string[] args = { "gtkdoc-scangobj",
+                                                         "--module", settings.pkg_name,
+                                                         "--types", "%s.types".printf (settings.pkg_name),
+                                                         "--output-dir", settings.path };
+
+                       string[] env = { "CFLAGS=%s %s".printf (cflags,
+                                                       Environment.get_variable ("CFLAGS") ?? ""),
+                                                       "LDFLAGS=%s %s %s".printf (libs, library_paths.str,
+                                                       Environment.get_variable ("LDFLAGS") ?? ""),
+                                                       "LD_LIBRARY_PATH=%s%s".printf (library_dirs.str,
+                                                       Environment.get_variable ("LD_LIBRARY_PATH") ?? "")};
+
+                       foreach (var evar in Environment.list_variables()) {
+                               if (evar != "CFLAGS" && evar != "LDFLAGS" && evar != "LD_LIBRARY_PATH") {
+                                       env += "%s=%s".printf (evar, Environment.get_variable(evar));
+                               }
+                       }
+
+                       Process.spawn_sync (settings.path, args, env, SpawnFlags.SEARCH_PATH, null, null, 
null);
+               } catch (Error e) {
+                       reporter.simple_error ("gtkdoc-scangobj", "%s", e.message);
+                       return false;
+               }
+
+               return true;
+       }
+
+       private bool mkdb () {
+               var main_file = Path.build_filename (settings.path, "%s-docs.xml".printf (settings.pkg_name));
+               var code_dir = Path.build_filename (settings.path, "ccomments");
+               var must_update_main_file = !FileUtils.test (main_file, FileTest.EXISTS);
+
+               var args = new string[] { "gtkdoc-mkdb",
+                                         "--module", settings.pkg_name,
+                                         "--source-dir", code_dir,
+                                         "--output-format", "xml",
+                                         "--sgml-mode",
+                                         "--main-sgml-file", "%s-docs.xml".printf (settings.pkg_name),
+                                         "--name-space", settings.pkg_name };
+
+               try {
+                       Process.spawn_sync (settings.path, args, null, SpawnFlags.SEARCH_PATH, null, null, 
null);
+               } catch (Error e) {
+                       reporter.simple_error ("gtkdoc-mkdb", "%s", e.message);
+                       return false;
+               }
+
+               if (must_update_main_file) {
+                       // gtkdoc-mkdb created a template main file, but users expect it to be a bit more 
complete
+                       string contents;
+                       try {
+                               FileUtils.get_contents (main_file, out contents);
+                       } catch (Error e) {
+                               reporter.simple_error ("GtkDoc", "Error while reading main file '%s' 
contents: %s",
+                                                                          main_file, e.message);
+                               return false;
+                       }
+
+                       if (settings.pkg_version != null) {
+                               contents = contents.replace ("[VERSION]", settings.pkg_version);
+                       }
+                       contents = contents.replace ("[Insert title here]", "%s API Reference".printf 
(settings.pkg_name));
+
+                       if (generator.dbus_interfaces.size > 0) {
+                               // hackish but prevents us from re-creating the whole main file,
+                               // which would more even more hackish
+                               var builder = new StringBuilder ();
+                               builder.append_printf ("\n<chapter>\n<title>%s D-Bus API Reference</title>\n",
+                                                                          settings.pkg_name);
+                               foreach (var iface in generator.dbus_interfaces) {
+                                       builder.append_printf ("<xi:include href=\"xml/%s.xml\"/>\n",
+                                               to_docbook_id (iface.name));
+                               }
+
+                               var hierarchy_file = Path.build_filename (settings.path, "%s.hierarchy"
+                                       .printf (settings.pkg_name));
+                               if (FileUtils.test (hierarchy_file, FileTest.EXISTS)) {
+                                       // if hierarchy exists, gtkdoc-mkdb will output it
+                                       builder.append ("</chapter>\n<chapter id=\"object-tree\">");
+                                       contents = contents.replace ("<chapter id=\"object-tree\">", 
builder.str);
+                               } else {
+                                       builder.append ("</chapter>\n<index id=\"api-index-full\">");
+                                       contents = contents.replace ("<index id=\"api-index-full\">", 
builder.str);
+                               }
+                       }
+
+                       try {
+                               FileUtils.set_contents (main_file, contents);
+                       } catch (Error e) {
+                               reporter.simple_error ("GtkDoc", "Error while writing main file '%s' 
contents: %s",
+                                                                          main_file, e.message);
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       private bool mkhtml () {
+               if (Config.nohtml) {
+                       return true;
+               }
+
+               var html_dir = Path.build_filename (settings.path, "html");
+               DirUtils.create_with_parents (html_dir, 0755);
+
+               try {
+                       Process.spawn_sync (html_dir,
+                                               {"gtkdoc-mkhtml",
+                                                 settings.pkg_name, "../%s-docs.xml".printf 
(settings.pkg_name)},
+                                               null, SpawnFlags.SEARCH_PATH, null, null, null);
+               } catch (Error e) {
+                       reporter.simple_error ("gtkdoc-mkhtml", "%s", e.message);
+                       return false;
+               }
+
+               /* fix xrefs for regenerated html */
+               try {
+                       Process.spawn_sync (settings.path,
+                                               { "gtkdoc-fixxref",
+                                                 "--module", settings.pkg_name,
+                                                 "--module-dir", html_dir,
+                                                 "--html-dir", html_dir },
+                                               null, SpawnFlags.SEARCH_PATH, null, null, null);
+               } catch (Error e) {
+                       reporter.simple_error ("gtkdoc-fixxref", "%s", e.message);
+                       return false;
+               }
+
+               return true;
+       }
+}
+
+
+public Type register_plugin (Valadoc.ModuleLoader module_loader) {
+       return typeof (Gtkdoc.Director);
+}
+
+
diff --git a/valadoc/doclets/gtkdoc/gcomment.vala b/valadoc/doclets/gtkdoc/gcomment.vala
new file mode 100644
index 0000000..0cedacc
--- /dev/null
+++ b/valadoc/doclets/gtkdoc/gcomment.vala
@@ -0,0 +1,192 @@
+/* gcomment.vala
+ *
+ * Copyright (C) 2010 Luca Bruno
+ *
+ * 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:
+ *     Luca Bruno <lethalman88 gmail com>
+ */
+
+public class Gtkdoc.Header {
+       public string name;
+       public string[]? annotations;
+       public string? value;
+       public double pos;
+       public bool block;
+
+       public Header (string name, string? value = null, double pos = double.MAX, bool block = true) {
+               this.name = name;
+               this.value = value;
+               this.pos = pos;
+               this.block = block;
+       }
+
+       public int cmp (Header header) {
+               if (pos > header.pos) {
+                       return 1;
+               } else if (pos < header.pos) {
+                       return -1;
+               }
+               return 0;
+       }
+}
+
+public class Gtkdoc.GComment {
+       public string symbol;
+       public string[] symbol_annotations;
+       public Vala.List<Header> headers = new Vala.ArrayList<Header> ();
+       public bool short_description;
+       public string brief_comment;
+       public string long_comment;
+       public string returns;
+       public string[] returns_annotations;
+       public Vala.List<Header> versioning = new Vala.ArrayList<Header> ();
+       public string[] see_also;
+       public bool is_section;
+
+       public string to_string () {
+               var builder = new StringBuilder ();
+
+               builder.append_printf ("/**\n * %s", (is_section ? "SECTION:%s" : "%s:").printf (symbol));
+               if (symbol_annotations != null && symbol_annotations.length > 0) {
+                       foreach (var annotation in symbol_annotations) {
+                               builder.append_printf (" (%s)", annotation);
+                       }
+               }
+
+               if (short_description && brief_comment != null) {
+                       builder.append_printf ("\n * @short_description: %s", commentize (brief_comment));
+               }
+
+               headers.sort ((CompareDataFunc) Header.cmp);
+               foreach (var header in headers) {
+                       builder.append_printf ("\n * @%s:", header.name);
+                       if (header.annotations != null && header.annotations.length > 0) {
+                               foreach (var annotation in header.annotations) {
+                                       builder.append_printf (" (%s)", annotation);
+                               }
+                               builder.append_c (':');
+                       }
+
+                       if (header.value != null) {
+                               builder.append_c (' ');
+                               builder.append (commentize (header.value));
+                       }
+               }
+
+               if (!short_description && brief_comment != null) {
+                       builder.append_printf  ("\n * \n * %s", commentize (brief_comment));
+               }
+               if (long_comment != null) {
+                       builder.append_printf  ("\n * \n * %s", commentize (long_comment));
+               }
+
+               if (see_also.length > 0) {
+                       builder.append_printf ("\n * \n * <emphasis>See also</emphasis>: %s", string.joinv 
(", ", see_also));
+               }
+
+               if (returns != null || returns_annotations.length > 0) {
+                       builder.append ("\n * \n * Returns:");
+                       if (returns_annotations != null) {
+                               foreach (var annotation in returns_annotations) {
+                                       builder.append_printf (" (%s)", annotation);
+                               }
+
+                               if (returns_annotations.length > 0) {
+                                       builder.append_c (':');
+                               }
+                       }
+                       builder.append_c (' ');
+
+                       if (returns != null) {
+                               builder.append (commentize (returns));
+                       }
+               }
+
+               if (versioning.size > 0) {
+                       builder.append ("\n *");
+                       foreach (var version in versioning) {
+                               builder.append_printf ("\n * %s:", version.name);
+                               if (version.value != null) {
+                                       builder.append_printf (" %s", commentize (version.value));
+                               }
+                       }
+               }
+
+               builder.append ("\n */");
+               return builder.str;
+       }
+
+       public string to_docbook (Valadoc.ErrorReporter reporter) {
+               /*
+                * FIXME: this is not how it should be.
+                * The real solution is to create a comment like gtkdoc-mkdb does.
+                * This implies replacing the work of gtkdoc-mkdb and have a more accurate management of 
headers,
+                * (i.e. differentiate between parameters, short_description, see_also, etc.).
+                *
+                * For now we'll assume all headers are parameters.
+                * This is enough for a manually generated xml file only for D-Bus API.
+                *
+                * In other words, we are converting C/gtkdoc comment to a docbook comment.
+                */
+
+               string? deprecated = null;
+               string? since = null;
+               foreach (var header in versioning) {
+                       if (header.name == "Deprecated") {
+                               deprecated = header.value;
+                       } else if (header.name == "Since") {
+                               since = header.value;
+                       } else {
+                               reporter.simple_warning ("GtkDoc", "Unknown versioning tag '%s'", 
header.name);
+                       }
+               }
+
+               var builder = new StringBuilder ();
+               if (deprecated != null) {
+                       builder.append_printf ("""<warning><para><literal>%s</literal> is deprecated and 
should not be used in newly-written code. %s</para></warning>""", symbol, deprecated);
+               }
+
+               if (brief_comment != null) {
+                       builder.append_printf ("<para>%s</para>", brief_comment);
+               }
+               if (long_comment != null) {
+                       builder.append (long_comment);
+               }
+
+               headers.sort ((CompareDataFunc) Header.cmp);
+               if (headers.size > 0 || returns != null) {
+                       builder.append ("""<variablelist role="params">""");
+                       foreach (var header in headers) {
+                               builder.append_printf 
("""<varlistentry><term><parameter>%s</parameter>&#160;:</term>
+<listitem><simpara> %s </simpara></listitem></varlistentry>""",
+                                                                          header.name, header.value);
+                       }
+                       if (returns != null) {
+                               builder.append_printf 
("""<varlistentry><term><emphasis>Returns</emphasis>&#160;:</term>
+<listitem><simpara> %s </simpara></listitem></varlistentry>""", returns);
+                       }
+                       builder.append ("</variablelist>");
+               }
+
+               if (since != null) {
+                       builder.append_printf ("""<para role="since">Since %s</para>""", since);
+               }
+
+               return builder.str;
+       }
+}
+
diff --git a/valadoc/doclets/gtkdoc/generator.vala b/valadoc/doclets/gtkdoc/generator.vala
new file mode 100644
index 0000000..09bab21
--- /dev/null
+++ b/valadoc/doclets/gtkdoc/generator.vala
@@ -0,0 +1,1412 @@
+/* generator.vala
+ *
+ * Copyright (C) 2010 Luca Bruno
+ *
+ * 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:
+ *     Luca Bruno <lethalman88 gmail com>
+ */
+
+using Valadoc;
+using Valadoc.Api;
+using Valadoc.Content;
+
+public class Gtkdoc.Generator : Api.Visitor {
+       class FileData {
+               public string filename;
+               public string title;
+               public GComment section_comment;
+               public Vala.List<GComment> comments;
+               public Vala.List<string> section_lines;
+               public Vala.List<string> standard_section_lines;
+               public Vala.List<string> private_section_lines;
+
+               public void register_section_line (string? line) {
+                       if (line != null) {
+                               section_lines.add (line);
+                       }
+               }
+
+               public void register_standard_section_line (string? line) {
+                       if (line != null) {
+                               standard_section_lines.add (line);
+                       }
+               }
+
+               public void register_private_section_line (string? line) {
+                       if (line != null) {
+                               private_section_lines.add (line);
+                       }
+               }
+       }
+
+       public Vala.List<DBus.Interface> dbus_interfaces = new Vala.ArrayList<DBus.Interface>();
+
+       private ErrorReporter reporter;
+       private Settings settings;
+       private Vala.Map<string, FileData> files_data = new Vala.HashMap<string, FileData> (str_hash, 
str_equal);
+       private string current_cname;
+       private Vala.List<Header> current_headers;
+       private Api.Tree current_tree;
+       private Class current_class;
+       private Method current_method;
+       private Delegate current_delegate;
+       private Api.Signal current_signal;
+       private DBus.Interface current_dbus_interface;
+       private DBus.Member current_dbus_member;
+
+       private string combine_inline_docs (string? str1, string? str2) {
+               StringBuilder builder = new StringBuilder ();
+               if (str1 != null) {
+                       builder.append (str1._chomp ());
+               }
+
+               if (builder.len > 0 && builder.str[builder.len - 1] != '.' && str2 != null) {
+                       builder.append (". ");
+               }
+
+               if (str2 != null) {
+                       builder.append_c (' ');
+                       builder.append (str2);
+               }
+
+               return (owned) builder.str;
+       }
+
+       private Api.Node? current_method_or_delegate {
+               get {
+                       if (current_method != null) {
+                               return current_method;
+                       } else if (current_delegate != null) {
+                               return current_delegate;
+                       }
+                       return null;
+               }
+       }
+
+       public bool execute (Settings settings, Api.Tree tree, ErrorReporter reporter) {
+               this.settings = settings;
+               this.reporter = reporter;
+               this.current_tree = tree;
+               tree.accept (this);
+               var code_dir = Path.build_filename (settings.path, "ccomments");
+               var sections = Path.build_filename (settings.path, "%s-sections.txt".printf 
(settings.pkg_name));
+               DirUtils.create_with_parents (code_dir, 0777);
+
+               var sections_writer = new TextWriter (sections, "a");
+               if (!sections_writer.open ()) {
+                       reporter.simple_error ("GtkDoc", "unable to open '%s' for writing", 
sections_writer.filename);
+                       return false;
+               }
+
+               foreach (var file_data in files_data.get_values ()) {
+                       // C comments
+                       var basename = get_section (file_data.filename);
+                       var cwriter = new TextWriter (Path.build_filename (code_dir, "%s.c".printf 
(basename)), "w");
+
+                       if (!cwriter.open ()) {
+                               reporter.simple_error ("GtkDoc", "unable to open '%s' for writing", 
cwriter.filename);
+                               return false;
+                       }
+
+                       // Gtkdoc SECTION
+                       if (file_data.section_comment != null) {
+                               cwriter.write_line (file_data.section_comment.to_string ());
+                       }
+
+                       foreach (var comment in file_data.comments) {
+                               cwriter.write_line (comment.to_string ());
+                       }
+                       cwriter.close ();
+
+                       // sections
+                       sections_writer.write_line ("<SECTION>");
+                       sections_writer.write_line ("<FILE>%s</FILE>".printf (basename));
+                       if (file_data.title != null) {
+                               sections_writer.write_line ("<TITLE>%s</TITLE>".printf (file_data.title));
+                       }
+
+                       foreach (var section_line in file_data.section_lines) {
+                               sections_writer.write_line (section_line);
+                       }
+
+                       if (file_data.standard_section_lines.size > 0) {
+                               sections_writer.write_line ("<SUBSECTION Standard>");
+
+                               foreach (var section_line in file_data.standard_section_lines) {
+                                       sections_writer.write_line (section_line);
+                               }
+                       }
+
+                       if (file_data.private_section_lines.size > 0) {
+                               sections_writer.write_line ("<SUBSECTION Private>");
+
+                               foreach (var section_line in file_data.private_section_lines) {
+                                       sections_writer.write_line (section_line);
+                               }
+                       }
+
+                       sections_writer.write_line ("</SECTION>");
+               }
+               sections_writer.close ();
+
+               return true;
+       }
+
+       public Vala.Set<string> get_filenames () {
+               return files_data.get_keys ();
+       }
+
+       private FileData get_file_data (string filename) {
+               var file_data = files_data[filename];
+               if (file_data == null) {
+                       file_data = new FileData ();
+                       file_data.filename = filename;
+                       file_data.title = null;
+                       file_data.section_comment = null;
+                       file_data.comments = new Vala.ArrayList<GComment>();
+                       file_data.section_lines = new Vala.ArrayList<string>(str_equal);
+                       file_data.standard_section_lines = new Vala.ArrayList<string>(str_equal);
+                       file_data.private_section_lines = new Vala.ArrayList<string>(str_equal);
+                       files_data[filename] = file_data;
+               }
+               return file_data;
+       }
+
+       private Vala.List<Header> merge_headers (Vala.List<Header> doc_headers,
+                                                                                        Vala.List<Header>? 
lang_headers)
+       {
+               if (lang_headers == null) {
+                       return doc_headers;
+               }
+
+               var headers = new Vala.ArrayList<Header>();
+
+               foreach (var doc_header in doc_headers) {
+                       var header = doc_header;
+                       foreach (var lang_header in lang_headers) {
+                               if (doc_header.name == lang_header.name) {
+                                       header.annotations = lang_header.annotations;
+                                       if (lang_header.value == null) {
+                                               continue;
+                                       }
+
+                                       if (lang_header.block) {
+                                               header.value += "<para>%s</para>".printf (lang_header.value);
+                                       } else {
+                                               header.value = combine_inline_docs (lang_header.value, 
header.value);
+                                       }
+                               }
+                       }
+                       headers.add (header);
+               }
+
+               // add remaining headers
+               foreach (var lang_header in lang_headers) {
+                       bool found = false;
+
+                       foreach (var header in headers) {
+                               if (header.name == lang_header.name) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+
+                       if (!found && lang_header.value != null) {
+                               headers.add (lang_header);
+                       }
+               }
+               return headers;
+       }
+
+       private void set_section_comment (string filename,
+                                                                         string section_name,
+                                                                         Content.Comment? comment,
+                                                                         string symbol_full_name)
+       {
+               var file_data = get_file_data (filename);
+               if (file_data.title == null) {
+                       file_data.title = section_name;
+               }
+               if (comment == null) {
+                       return;
+               }
+               if (file_data.section_comment != null) {
+                       // already have a section comment
+                       return;
+               }
+
+               var gcomment = create_gcomment (get_section (filename), comment);
+               gcomment.is_section = true;
+               gcomment.short_description = true;
+               file_data.section_comment = gcomment;
+
+               /* gtk-doc will warn about missing long descriptions (e.g.
+                * “alias-details:Long_Description” in *-undocumented.txt), so
+                * forward that as a Valadoc warning so that it doesn’t get lost
+                * in the gtk-doc output files. */
+               if (gcomment.long_comment == null || gcomment.long_comment == "") {
+                       reporter.simple_warning ("GtkDoc", "Missing long description in the documentation for 
‘%s’ which forms gtk-doc section ‘%s’.",
+                                                                        symbol_full_name,
+                                                                        section_name);
+               }
+       }
+
+       private GComment create_gcomment (string symbol,
+                                                                         Content.Comment? comment,
+                                                                         string[]? returns_annotations = 
null,
+                                                                         bool is_dbus = false)
+       {
+               var converter = new Gtkdoc.CommentConverter (reporter, current_method_or_delegate);
+
+               if (comment != null) {
+                       converter.convert (comment, is_dbus);
+               }
+
+               var gcomment = new GComment ();
+               gcomment.symbol = symbol;
+               gcomment.returns = converter.returns;
+               gcomment.returns_annotations = returns_annotations;
+               gcomment.see_also = converter.see_also;
+
+               gcomment.brief_comment = converter.brief_comment;
+               gcomment.long_comment = converter.long_comment;
+
+               gcomment.headers.add_all (merge_headers (converter.parameters, current_headers));
+               gcomment.versioning.add_all (converter.versioning);
+               return gcomment;
+       }
+
+       private GComment add_comment (string filename, string symbol, Content.Comment? comment = null) {
+               var file_data = get_file_data (filename);
+               var gcomment = create_gcomment (symbol, comment);
+               file_data.comments.add (gcomment);
+               return gcomment;
+       }
+
+       private GComment add_symbol (string filename,
+                                                                string cname,
+                                                                Content.Comment? comment = null,
+                                                                string? symbol = null,
+                                                                string[]? returns_annotations = null)
+       {
+               var file_data = get_file_data (filename);
+
+               file_data.register_section_line (cname);
+
+               var gcomment = create_gcomment (symbol ?? cname, comment, returns_annotations);
+               file_data.comments.add (gcomment);
+               return gcomment;
+       }
+
+       private Header? add_custom_header (string name,
+                                                                          string? comment,
+                                                                          string[]? annotations = null,
+                                                                          double pos = double.MAX,
+                                                                          bool block = true)
+       {
+               if (comment == null && annotations == null) {
+                       return null;
+               }
+
+               var header = new Header (name, comment, pos, block);
+               header.annotations = annotations;
+               current_headers.add (header);
+               return header;
+       }
+
+       private Header? remove_custom_header (string name) {
+               var it = current_headers.iterator();
+               while (it.next ()) {
+                       var header = it.@get ();
+                       if (header.name == name) {
+                               it.remove ();
+                               return header;
+                       }
+               }
+               return null;
+       }
+
+       private Header? add_header (string name,
+                                                               Content.Comment? comment,
+                                                               string[]? annotations = null,
+                                                               double pos = double.MAX)
+       {
+               if (comment == null && annotations == null) {
+                       return null;
+               }
+
+               var converter = new Gtkdoc.CommentConverter (reporter, current_method_or_delegate);
+               var header = new Header (name);
+               header.pos = pos;
+
+               if (comment != null) {
+                       converter.convert (comment);
+                       if (converter.brief_comment != null) {
+                               header.value = converter.brief_comment;
+                               if (converter.long_comment != null) {
+                                       header.value += converter.long_comment;
+                               }
+                       }
+               }
+
+               header.annotations = annotations;
+               current_headers.add (header);
+               return header;
+       }
+
+       public override void visit_tree (Api.Tree tree) {
+               tree.accept_children (this);
+       }
+
+       public override void visit_package (Api.Package package) {
+               /* we are not (yet?) interested in external packages */
+               if (package.is_package) {
+                       return;
+               }
+
+               package.accept_all_children (this);
+       }
+
+       public override void visit_namespace (Api.Namespace ns) {
+               if (ns.get_filename () != null && ns.documentation != null) {
+                       set_section_comment (ns.get_filename (),
+                                                                get_section (ns.get_filename ()),
+                                                                ns.documentation,
+                                                                ns.get_full_name ());
+               }
+
+               ns.accept_all_children (this);
+       }
+
+       public override void visit_interface (Api.Interface iface) {
+               var old_cname = current_cname;
+               var old_headers = current_headers;
+               var old_dbus_interface = current_dbus_interface;
+               current_cname = iface.get_cname ();
+               current_headers = new Vala.ArrayList<Header>();
+               current_dbus_interface = null;
+
+               if (iface.get_dbus_name () != null) {
+                       current_dbus_interface = new DBus.Interface (settings.pkg_name, iface.get_dbus_name 
());
+               }
+
+               iface.accept_all_children (this);
+
+               var gcomment = add_symbol (iface.get_filename(), iface.get_cname(), iface.documentation, 
null);
+               set_section_comment (iface.get_filename(),
+                                                        iface.get_cname(),
+                                                        iface.documentation,
+                                                        iface.get_full_name ());
+
+               if (current_dbus_interface != null) {
+                       current_dbus_interface.write (settings, reporter);
+                       dbus_interfaces.add (current_dbus_interface);
+               }
+
+               // Handle attributes for things like deprecation.
+               process_attributes (iface, gcomment);
+
+               // Interface struct
+               current_headers.clear ();
+
+               var abstract_methods = iface.get_children_by_types ({NodeType.METHOD}, false);
+               foreach (var m in abstract_methods) {
+                       // List all protected methods, even if they're not marked as browsable
+                       if (m.is_browsable (settings) || ((Symbol) m).is_protected) {
+                               visit_abstract_method ((Api.Method) m);
+                       }
+               }
+
+               var abstract_properties = iface.get_children_by_types ({NodeType.PROPERTY}, false);
+               foreach (var prop in abstract_properties) {
+                       // List all protected properties, even if they're not marked as browsable
+                       if (prop.is_browsable (settings) || ((Symbol) prop).is_protected) {
+                               visit_abstract_property ((Api.Property) prop);
+                       }
+               }
+
+               add_custom_header ("parent_iface", "the parent interface structure");
+               if (iface.get_attribute ("GenericAccessors") != null) {
+                       var type_parameters = iface.get_children_by_type (NodeType.TYPE_PARAMETER, false);
+                       foreach (Api.Node _type in type_parameters) {
+                               var type = _type as Api.TypeParameter;
+                               string type_name_down = type.name.down ();
+                               add_custom_header ("get_%s_type".printf (type_name_down),
+                                                                  "The #GType for %s".printf 
(type_name_down));
+                               add_custom_header ("get_%s_dup_func".printf (type_name_down),
+                                                                  "A dup function for 
#%sIface.get_%s_type()".printf (iface.get_cname (), type_name_down));
+                               add_custom_header ("get_%s_destroy_func".printf (type_name_down),
+                                                                  "A destroy function for 
#%sIface.get_%s_type()".printf (iface.get_cname (), type_name_down));
+                       }
+               }
+               gcomment = add_symbol (iface.get_filename (), iface.get_cname () + "Iface");
+               gcomment.brief_comment = "Interface for creating %s implementations.".printf 
(get_docbook_link (iface));
+
+               // Standard symbols
+               var file_data = get_file_data (iface.get_filename ());
+
+               file_data.register_standard_section_line (iface.get_type_cast_macro_name ());
+               file_data.register_standard_section_line (iface.get_interface_macro_name ());
+               file_data.register_standard_section_line (iface.get_is_type_macro_name ());
+               file_data.register_standard_section_line (iface.get_type_macro_name ());
+               file_data.register_standard_section_line (iface.get_type_function_name ());
+
+               current_cname = old_cname;
+               current_headers = old_headers;
+               current_dbus_interface = old_dbus_interface;
+       }
+
+       public override void visit_class (Api.Class cl) {
+               var old_cname = current_cname;
+               var old_headers = current_headers;
+               var old_class = current_class;
+               var old_dbus_interface = current_dbus_interface;
+               current_cname = cl.get_cname ();
+               current_headers = new Vala.ArrayList<Header>();
+               current_class = cl;
+               current_dbus_interface = null;
+
+               if (cl.get_dbus_name () != null) {
+                       current_dbus_interface = new DBus.Interface (settings.pkg_name, cl.get_dbus_name ());
+               }
+
+               var gcomment = add_symbol (cl.get_filename(), cl.get_type_id());
+               gcomment.brief_comment = "The type for %s.".printf (get_docbook_link (cl));
+
+               cl.accept_all_children (this);
+
+               add_symbol (cl.get_filename(), cl.get_cname(), cl.documentation, null);
+               set_section_comment (cl.get_filename(), cl.get_cname(), cl.documentation, cl.get_full_name 
());
+
+               if (current_dbus_interface != null) {
+                       current_dbus_interface.write (settings, reporter);
+                       dbus_interfaces.add (current_dbus_interface);
+               }
+
+               // Handle attributes for things like deprecation.
+               process_attributes (cl, gcomment);
+
+               if (cl.is_fundamental && cl.base_type == null) {
+                       var filename = cl.get_filename ();
+
+                       // ref
+                       current_headers.clear ();
+                       add_custom_header ("instance", "a %s.".printf (get_docbook_link (cl)));
+                       gcomment = add_symbol (filename, cl.get_ref_function_cname ());
+                       gcomment.brief_comment = "Increases the reference count of @object.";
+                       gcomment.returns = "the same @object";
+
+                       // unref
+                       current_headers.clear ();
+                       add_custom_header ("instance", "a %s.".printf (get_docbook_link (cl)));
+                       gcomment = add_symbol (filename, cl.get_unref_function_cname ());
+                       gcomment.brief_comment = "Decreases the reference count of @object. When its 
reference count drops to 0, the object is finalized (i.e. its memory is freed).";
+
+                       // param_spec
+                       current_headers.clear ();
+                       add_custom_header ("name", "canonical name of the property specified");
+                       add_custom_header ("nick", "nick name for the property specified");
+                       add_custom_header ("blurb", "description of the property specified");
+                       add_custom_header ("object_type", "%s derived type of this property"
+                               .printf (get_docbook_type_link (cl)));
+                       add_custom_header ("flags", "flags for the property specified");
+                       gcomment = add_symbol (filename, cl.get_param_spec_function_cname ());
+                       gcomment.brief_comment = "Creates a new <link 
linkend=\"GParamSpecBoxed\"><type>GParamSpecBoxed</type></link> instance specifying a %s derived property."
+                               .printf (get_docbook_type_link (cl));
+                       gcomment.long_comment = "See <link 
linkend=\"g-param-spec-internal\"><function>g_param_spec_internal()</function></link> for details on property 
names.";
+
+                       // value_set
+                       current_headers.clear ();
+                       add_custom_header ("value", "a valid <link 
linkend=\"GValue\"><type>GValue</type></link> of %s derived type"
+                               .printf (get_docbook_type_link (cl)));
+                       add_custom_header ("v_object", "object value to be set");
+                       gcomment = add_symbol (filename, cl.get_set_value_function_cname ());
+                       gcomment.brief_comment = "Set the contents of a %s derived <link 
linkend=\"GValue\"><type>GValue</type></link> to @v_object."
+                               .printf (get_docbook_type_link (cl));
+                       gcomment.long_comment = "<link linkend=\"%s\"><function>%s()</function></link> 
increases the reference count of @v_object (the <link linkend=\"GValue\"><type>GValue</type></link> holds a 
reference to @v_object). If you do not wish to increase the reference count of the object (i.e. you wish to 
pass your current reference to the <link linkend=\"GValue\"><type>GValue</type></link> because you no longer 
need it), use <link linkend=\"%s\"><function>%s()</function></link> instead.
+
+It is important that your <link linkend=\"GValue\"><type>GValue</type></link> holds a reference to @v_object 
(either its own, or one it has taken) to ensure that the object won't be destroyed while the <link 
linkend=\"GValue\"><type>GValue</type></link> still exists)."
+                               .printf (to_docbook_id (cl.get_set_value_function_cname ()),
+                                                cl.get_set_value_function_cname (),
+                                                to_docbook_id (cl.get_take_value_function_cname ()),
+                                                cl.get_take_value_function_cname ());
+
+                       // value_get
+                       current_headers.clear ();
+                       add_custom_header ("value", "a valid <link 
linkend=\"GValue\"><type>GValue</type></link> of %s derived type"
+                               .printf (get_docbook_type_link (cl)));
+                       gcomment = add_symbol (filename, cl.get_get_value_function_cname ());
+                       gcomment.brief_comment = "Get the contents of a %s derived <link 
linkend=\"GValue\"><type>GValue</type></link>."
+                               .printf (get_docbook_type_link (cl));
+                       gcomment.returns = "object contents of @value";
+
+                       // value_take
+                       current_headers.clear ();
+                       add_custom_header ("value", "a valid <link 
linkend=\"GValue\"><type>GValue</type></link> of %s derived type"
+                               .printf (get_docbook_type_link (cl)));
+                       add_custom_header ("v_object", "object value to be set");
+                       gcomment = add_symbol (filename, cl.get_take_value_function_cname ());
+                       gcomment.brief_comment = "Sets the contents of a %s derived <link 
linkend=\"GValue\"><type>GValue</type></link> to @v_object and takes over the ownership of the callers 
reference to @v_object; the caller doesn't have to unref it any more (i.e. the reference count of the object 
is not increased)."
+                               .printf (get_docbook_type_link (cl));
+                       gcomment.long_comment = "If you want the GValue to hold its own reference to 
@v_object, use <link linkend=\"%s\"><function>%s()</function></link> instead."
+                               .printf (to_docbook_id (cl.get_set_value_function_cname ()), 
cl.get_set_value_function_cname ());
+               }
+
+               // Class struct
+               current_headers.clear ();
+
+               var abstract_methods = cl.get_children_by_types ({NodeType.METHOD}, false);
+               foreach (var m in abstract_methods) {
+                       // List all protected methods, even if they're not marked as browsable
+                       if (m.is_browsable (settings) || ((Symbol) m).is_protected) {
+                               visit_abstract_method ((Api.Method) m);
+                       }
+               }
+
+               var abstract_properties = cl.get_children_by_types ({NodeType.PROPERTY}, false);
+               foreach (var prop in abstract_properties) {
+                       // List all protected properties, even if they're not marked as browsable
+                       if (prop.is_browsable (settings) || ((Symbol) prop).is_protected) {
+                               visit_abstract_property ((Api.Property) prop);
+                       }
+               }
+
+               add_custom_header ("parent_class", "the parent class structure");
+               gcomment = add_symbol (cl.get_filename (), cl.get_cname () + "Class");
+               gcomment.brief_comment = "The class structure for %s. All the fields in this structure are 
private and should never be accessed directly."
+                       .printf (get_docbook_type_link (cl));
+
+               // Standard/Private symbols
+               var file_data = get_file_data (cl.get_filename ());
+
+               file_data.register_standard_section_line (cl.get_is_type_macro_name ());
+               file_data.register_standard_section_line (cl.get_is_class_type_macro_name ());
+               file_data.register_standard_section_line (cl.get_type_cast_macro_name ());
+               file_data.register_standard_section_line (cl.get_class_type_macro_name ());
+               file_data.register_standard_section_line (cl.get_class_macro_name ());
+               file_data.register_standard_section_line (cl.get_type_function_name ());
+
+               file_data.register_private_section_line (cl.get_private_cname ());
+               file_data.register_private_section_line (((cl.nspace.name != null)? cl.nspace.name.down () + 
"_" : "")
+                                                                                                + 
to_lower_case (cl.name)
+                                                                                                + 
"_construct");
+
+               current_cname = old_cname;
+               current_headers = old_headers;
+               current_class = old_class;
+               current_dbus_interface = old_dbus_interface;
+       }
+
+       private string[]? create_see_function_array (string?[] functions) {
+               string[] arr = new string[] {};
+               foreach (string? func in functions) {
+                       if (func != null) {
+                               arr += func + "()";
+                       }
+               }
+
+               return (arr.length > 0)? arr : null;
+       }
+
+       public override void visit_struct (Api.Struct st) {
+               var old_cname = current_cname;
+               var old_headers = current_headers;
+               current_cname = st.get_cname ();
+               current_headers = new Vala.ArrayList<Header>();
+
+               st.accept_all_children (this);
+               var gcomment = add_symbol (st.get_filename(), st.get_cname(), st.documentation);
+
+               // Handle attributes for things like deprecation.
+               process_attributes (st, gcomment);
+
+               current_cname = old_cname;
+               current_headers = old_headers;
+
+               var file_data = get_file_data (st.get_filename ());
+
+               file_data.register_standard_section_line (st.get_type_macro_name ());
+               file_data.register_standard_section_line (st.get_type_function_name ());
+
+               string? dup_function_cname = st.get_dup_function_cname ();
+               string? free_function_cname = st.get_free_function_cname ();
+               string? copy_function_cname = st.get_copy_function_cname ();
+               string? destroy_function_cname = st.get_destroy_function_cname ();
+               if (dup_function_cname != null) {
+                       var dup_gcomment = add_symbol (st.get_filename (), dup_function_cname);
+                       dup_gcomment.headers.add (new Header ("self",
+                                                                                                 "the 
instance to duplicate"));
+                       if (free_function_cname != null) {
+                               dup_gcomment.returns = "a copy of @self, free with %s()"
+                                       .printf (free_function_cname);
+                       } else {
+                               dup_gcomment.returns = "a copy of @self";
+                       }
+
+                       dup_gcomment.brief_comment = "Creates a copy of self.";
+                       dup_gcomment.see_also = create_see_function_array ({copy_function_cname,
+                                                                                                             
                  destroy_function_cname,
+                                                                                                             
                  free_function_cname});
+               }
+
+               if (free_function_cname != null) {
+                       var free_gcomment = add_symbol (st.get_filename (), free_function_cname);
+                       free_gcomment.headers.add (new Header ("self", "the struct to free"));
+                       free_gcomment.brief_comment = "Frees the heap-allocated struct.";
+                       free_gcomment.see_also = create_see_function_array ({dup_function_cname,
+                                                                                                             
                   copy_function_cname,
+                                                                                                             
                   destroy_function_cname});
+               }
+
+               if (copy_function_cname != null) {
+                       var copy_gcomment = add_symbol (st.get_filename (), copy_function_cname);
+                       copy_gcomment.headers.add (new Header ("self",
+                                                                                                  "the 
struct to copy"));
+                       if (destroy_function_cname != null) {
+                               copy_gcomment.headers.add (new Header ("dest",
+                                                                                                          "a 
unused struct. Use %s() to free the content."
+                                                                                                             
  .printf (destroy_function_cname)));
+                       } else {
+                               copy_gcomment.headers.add (new Header ("dest",
+                                                                                                          "a 
unused struct."));
+                       }
+                       copy_gcomment.brief_comment = "Creates a copy of self.";
+                       copy_gcomment.see_also = create_see_function_array ({dup_function_cname,
+                                                                                                             
                   destroy_function_cname,
+                                                                                                             
                   free_function_cname});
+               }
+
+               if (destroy_function_cname != null) {
+                       var destroy_gcomment = add_symbol (st.get_filename (), destroy_function_cname);
+                       destroy_gcomment.headers.add (new Header ("self", "the struct to destroy"));
+                       destroy_gcomment.brief_comment = "Frees the content of the struct pointed by @self.";
+                       destroy_gcomment.see_also = create_see_function_array ({dup_function_cname,
+                                                                                                             
                          copy_function_cname,
+                                                                                                             
                          free_function_cname});
+               }
+       }
+
+       /**
+        * Visit thrown error domains
+        */
+       private void visit_thrown_error_domain (Api.Node error) {
+               // method throws error
+               Header? param_header = null;
+               foreach (var header in current_headers) {
+                       if (header.name == "error") {
+                               param_header = header;
+                               break;
+                       }
+               }
+               var edomain = error as Api.ErrorDomain;
+               if (edomain != null) {
+                       if (param_header == null) {
+                               add_custom_header ("error",
+                                                                  "location to store the error occuring, or 
%NULL to ignore",
+                                                                  {"error-domains %s".printf 
(edomain.get_cname ())},
+                                                                  double.MAX-1);
+                       } else {
+                               // assume the only annotation is error-domains
+                               var annotation = param_header.annotations[0];
+                               annotation += " %s".printf (edomain.get_cname ());
+                               param_header.annotations[0] = annotation;
+                       }
+               } else if (param_header == null) {
+                       add_custom_header ("error",
+                                                          "location to store the error occuring, or %NULL to 
ignore",
+                                                          null,
+                                                          double.MAX - 1);
+               }
+       }
+
+       /**
+        * Visit error domain definitions
+        */
+       public override void visit_error_domain (Api.ErrorDomain edomain) {
+               // error domain definition
+               var old_headers = current_headers;
+               current_headers = new Vala.ArrayList<Header>();
+
+               edomain.accept_all_children (this);
+               var gcomment = add_symbol (edomain.get_filename(),
+                                                                  edomain.get_cname(),
+                                                                  edomain.documentation);
+
+               // Handle attributes for things like deprecation.
+               process_attributes (edomain, gcomment);
+
+               // Standard symbols
+               var file_data = get_file_data (edomain.get_filename ());
+
+               file_data.register_standard_section_line (edomain.get_quark_function_name ());
+               file_data.register_standard_section_line (edomain.get_quark_macro_name ());
+
+               current_headers = old_headers;
+       }
+
+       public override void visit_error_code (Api.ErrorCode ecode) {
+               add_header (ecode.get_cname (), ecode.documentation);
+               ecode.accept_all_children (this);
+       }
+
+       public override void visit_enum (Api.Enum en) {
+               var old_headers = current_headers;
+               current_headers = new Vala.ArrayList<Header>();
+
+               en.accept_all_children (this);
+               var gcomment = add_symbol (en.get_filename(), en.get_cname(), en.documentation);
+       
+               // Handle attributes for things like deprecation.
+               process_attributes (en, gcomment);
+
+               // Standard symbols
+               var file_data = get_file_data (en.get_filename ());
+
+               file_data.register_standard_section_line (en.get_type_macro_name ());
+               file_data.register_standard_section_line (en.get_type_function_name ());
+
+               current_headers = old_headers;
+       }
+
+       public override void visit_enum_value (Api.EnumValue eval) {
+               add_header (eval.get_cname (), eval.documentation);
+               eval.accept_all_children (this);
+       }
+
+       private string combine_comments (string? brief, string? @long) {
+               StringBuilder builder = new StringBuilder ();
+               if (brief != null) {
+                       builder.append (brief.strip ());
+               }
+
+               string _long = (@long != null)? @long.strip () : "";
+               if (builder.len > 0 && _long != "") {
+                       builder.append ("\n\n");
+               }
+
+               if (_long != "") {
+                       builder.append (_long);
+               }
+
+               return (owned) builder.str;
+       }
+
+       public override void visit_property (Api.Property prop) {
+               if (prop.is_override
+                       || prop.is_private
+                       || (!prop.is_abstract && !prop.is_virtual && prop.base_property != null))
+               {
+                       return;
+               }
+
+               var gcomment = add_comment (prop.get_filename(), "%s:%s"
+                       .printf (current_cname, prop.get_cname ()), prop.documentation);
+               prop.accept_all_children (this);
+
+               Api.TypeParameter type_parameter = prop.property_type.data_type as Api.TypeParameter;
+               string? return_type_link = null;
+               if (type_parameter != null) {
+                       if (type_parameter.parent is Api.Class) {
+                               return_type_link = "#%s:%s-type".printf (get_cname (prop.parent), 
type_parameter.name.down ());
+                       } else if (type_parameter.parent is Api.Interface
+                               && ((Api.Symbol) type_parameter.parent).get_attribute ("GenericAccessors") != 
null)
+                       {
+                               return_type_link = "#_%sIface.get_%s_type()"
+                                       .printf (get_cname (type_parameter.parent), type_parameter.name.down 
());
+                       }
+               }
+
+               // Handle attributes for things like deprecation.
+               process_attributes (prop, gcomment);
+
+               if (prop.getter != null && !prop.getter.is_private && prop.getter.is_get) {
+                       var getter_gcomment = add_symbol (prop.get_filename(), prop.getter.get_cname ());
+                       getter_gcomment.headers.add (new Header ("self",
+                                                                                                        "the 
%s instance to query".printf (get_docbook_link (prop.parent)), 1));
+                       getter_gcomment.returns = "the value of the %s property"
+                               .printf (get_docbook_link (prop));
+                       if (return_type_link != null) {
+                               getter_gcomment.returns += " of type " + return_type_link;
+                       }
+                       getter_gcomment.brief_comment = "Get and return the current value of the %s property."
+                               .printf (get_docbook_link (prop));
+                       getter_gcomment.long_comment = combine_comments (gcomment.brief_comment,
+                                                                                                             
           gcomment.long_comment);
+
+                       if (prop.property_type != null && prop.property_type.data_type is Api.Array) {
+                               var array_type = prop.property_type.data_type;
+                               for (uint dim = 1; array_type != null && array_type is Api.Array;
+                                       dim++, array_type = ((Api.Array) array_type).data_type)
+                               {
+                                       gcomment.headers.add (new Header ("result_length%u".printf (dim),
+                                                                                                         
"return location for the length of the property's value"));
+                               }
+                       }
+
+                       /* Copy versioning headers such as deprecation and since lines. */
+                       getter_gcomment.versioning = gcomment.versioning;
+               }
+
+               if (prop.setter != null && !prop.setter.is_private && prop.setter.is_set) {
+                       var setter_gcomment = add_symbol (prop.get_filename(), prop.setter.get_cname ());
+                       setter_gcomment.headers.add (new Header ("self", "the %s instance to modify"
+                               .printf (get_docbook_link (prop.parent)), 1));
+                       string type_desc = (return_type_link != null)? " of type " + return_type_link : "";
+                       setter_gcomment.headers.add (new Header ("value", "the new value of the %s property%s"
+                               .printf (get_docbook_link (prop), type_desc), 2));
+                       setter_gcomment.brief_comment = "Set the value of the %s property to @value."
+                               .printf (get_docbook_link (prop));
+                       setter_gcomment.long_comment = combine_comments (gcomment.brief_comment,
+                                                                                                             
           gcomment.long_comment);
+
+                       if (prop.property_type != null && prop.property_type.data_type is Api.Array) {
+                               var array_type = prop.property_type.data_type;
+                               for (uint dim = 1; array_type != null && array_type is Api.Array;
+                                       dim++, array_type = ((Api.Array) array_type).data_type)
+                               {
+                                       gcomment.headers.add (new Header ("value_length%u".printf (dim),
+                                                                                                         
"length of the property's new value"));
+                               }
+                       }
+
+                       /* Copy versioning headers such as deprecation and since lines. */
+                       setter_gcomment.versioning = gcomment.versioning;
+               }
+
+               if (return_type_link != null) {
+                       string return_type_desc = "<para>Holds a value from type #%s:%s-type.</para>"
+                               .printf (get_cname (prop.parent), type_parameter.name.down ());
+                       gcomment.long_comment = combine_inline_docs (return_type_desc, gcomment.long_comment);
+               }
+       }
+
+       public override void visit_field (Api.Field f) {
+               if (f.is_private) {
+                       return;
+               }
+
+               if (current_headers == null) {
+                       // field not in class/struct/interface
+                       var gcomment = add_symbol (f.get_filename(), f.get_cname(), f.documentation);
+                       f.accept_all_children (this);
+       
+                       // Handle attributes for things like deprecation.
+                       process_attributes (f, gcomment);
+               } else {
+                       add_header (f.get_cname (), f.documentation);
+                       f.accept_all_children (this);
+               }
+       }
+
+       public override void visit_constant (Api.Constant c) {
+               var gcomment = add_symbol (c.get_filename(), c.get_cname(), c.documentation);
+               c.accept_all_children (this);
+
+               // Handle attributes for things like deprecation.
+               process_attributes (c, gcomment);
+       }
+
+       public override void visit_delegate (Api.Delegate d) {
+               var old_headers = current_headers;
+               var old_delegate = current_delegate;
+               current_headers = new Vala.ArrayList<Header>();
+               current_delegate = d;
+
+               d.accept_children ({NodeType.FORMAL_PARAMETER, NodeType.TYPE_PARAMETER}, this);
+               var exceptions = d.get_children_by_types ({NodeType.ERROR_DOMAIN, NodeType.CLASS});
+               foreach (var ex in exceptions) {
+                       visit_thrown_error_domain (ex);
+               }
+
+               if (!d.is_static) {
+                       add_custom_header ("user_data", "data to pass to the delegate function", {"closure"});
+               }
+
+               var gcomment = add_symbol (d.get_filename(), d.get_cname(), d.documentation);
+               Api.TypeParameter type_parameter = d.return_type.data_type as Api.TypeParameter;
+               if (type_parameter != null) {
+                       if (type_parameter.parent is Api.Class) {
+                               string return_type_desc = "A value from type #%s:%s-type."
+                                       .printf (get_cname (d.parent), type_parameter.name.down ());
+                               gcomment.returns = combine_inline_docs (return_type_desc, gcomment.returns);
+                       } else if (type_parameter.parent is Api.Interface
+                               && ((Api.Symbol) type_parameter.parent).get_attribute ("GenericAccessors") != 
null)
+                       {
+                               string return_type_desc = "A value from type #_%sIface.get_%s_type()."
+                                       .printf (get_cname (d.parent), type_parameter.name.down ());
+                               gcomment.returns = combine_inline_docs (return_type_desc, gcomment.returns);
+                       /*
+                       } else if (type_parameter.parent is Api.Struct) {
+                               // type not stored & not allowed
+                       } else if (type_parameter.parent == d) {
+                               // type not available as argument
+                       */
+                       }
+               }
+       
+               // Handle attributes for things like deprecation.
+               process_attributes (d, gcomment);
+
+               current_headers = old_headers;
+               current_delegate = old_delegate;
+       }
+
+       public override void visit_signal (Api.Signal sig) {
+               var old_headers = current_headers;
+               var old_signal = current_signal;
+               var old_dbus_member = current_dbus_member;
+               current_headers = new Vala.ArrayList<Header>();
+               current_signal = sig;
+               current_dbus_member = null;
+
+               if (current_dbus_interface != null && sig.is_dbus_visible) {
+                       current_dbus_member = new DBus.Member (sig.get_dbus_name ());
+               }
+
+               sig.accept_all_children (this);
+
+               var name = sig.get_cname().replace ("_", "-");
+               var gcomment = add_comment (sig.get_filename(), "%s::%s".printf (current_cname, name), 
sig.documentation);
+               // gtkdoc maps parameters by their ordering, so let's customly add the first parameter
+               gcomment.headers.insert (0, new Header (to_lower_case (((Api.Node)sig.parent).name),
+                                                                                               "the %s 
instance that received the signal".printf (get_docbook_link (sig.parent)),
+                                                                                                0.1));
+               if (current_dbus_interface != null && sig.is_dbus_visible) {
+                       var dbuscomment = create_gcomment (sig.get_dbus_name (), sig.documentation, null, 
true);
+                       current_dbus_member.comment = dbuscomment;
+                       current_dbus_interface.add_signal (current_dbus_member);
+               }
+
+               Api.TypeParameter type_parameter = sig.return_type.data_type as Api.TypeParameter;
+               if (type_parameter != null) {
+                       if (type_parameter.parent is Api.Class) {
+                               string return_type_desc = "A value from type #%s:%s-type."
+                                       .printf (get_cname (type_parameter.parent), type_parameter.name.down 
());
+                               gcomment.returns = combine_inline_docs (return_type_desc,
+                                                                                                             
  gcomment.returns);
+                       } else if (type_parameter.parent is Api.Interface
+                               && ((Api.Symbol) type_parameter.parent).get_attribute ("GenericAccessors") != 
null)
+                       {
+                               string return_type_desc = "A value from type #_%sIface.get_%s_type()."
+                                       .printf (get_cname (type_parameter.parent), type_parameter.name.down 
());
+                               gcomment.returns = combine_inline_docs (return_type_desc,
+                                                                                                             
  gcomment.returns);
+                       }
+               }
+
+
+               // Handle attributes for things like deprecation.
+               process_attributes (sig, gcomment);
+
+               current_headers = old_headers;
+               current_signal = old_signal;
+               current_dbus_member = old_dbus_member;
+       }
+
+       public override void visit_method (Api.Method m) {
+               if ((m.is_constructor && current_class != null && current_class.is_abstract)
+                       || m.is_override
+                       || m.is_private
+                       || (!m.is_abstract && !m.is_virtual && m.base_method != null))
+               {
+                       return;
+               }
+
+               var annotations = new string[]{};
+
+               if (m.return_type != null) {
+                       if (m.return_type.data_type is Api.Array) {
+                               annotations += "array length=result_length1";
+                       }
+
+                       if (m.return_type.is_unowned) {
+                               annotations += "transfer none";
+                       }
+               }
+
+               var old_headers = current_headers;
+               var old_method = current_method;
+               var old_dbus_member = current_dbus_member;
+               current_headers = new Vala.ArrayList<Header>();
+               current_method = m;
+               current_dbus_member = null;
+
+               if (current_dbus_interface != null && m.is_dbus_visible && !m.is_constructor) {
+                       current_dbus_member = new DBus.Member (m.get_dbus_name ());
+               }
+
+               if (!m.is_static && !m.is_constructor) {
+                       add_custom_header ("self",
+                                                          "the %s instance".printf (get_docbook_link 
(m.parent)),
+                                                          null,
+                                                          0.1);
+               }
+
+               if (m.is_constructor) {
+                       // parent type parameters:
+                       var type_parameters = ((Api.Node) m.parent).get_children_by_type 
(NodeType.TYPE_PARAMETER, false);
+                       foreach (Api.Node _type in type_parameters) {
+                               var type = _type as Api.TypeParameter;
+                               string type_name_down = type.name.down ();
+                               add_custom_header (type_name_down + "_type",
+                                                                  "A #GType");
+                               add_custom_header (type_name_down + "_dup_func",
+                                                                  "A dup function for @%s_type".printf 
(type_name_down));
+                               add_custom_header (type_name_down + "_destroy_func",
+                                                                  "A destroy function for @%s_type".printf 
(type_name_down));
+                       }
+               }
+
+               // type parameters:
+               var type_parameters = m.get_children_by_type (NodeType.TYPE_PARAMETER, false);
+               foreach (Api.Node _type in type_parameters) {
+                       var type = _type as Api.TypeParameter;
+                       string type_name_down = type.name.down ();
+                       add_custom_header (type_name_down + "_type",
+                                                          "The #GType for @%s".printf (type_name_down),
+                                                          null,
+                                                          0.2);
+                       add_custom_header (type_name_down + "_dup_func",
+                                                          "A dup function for @%s_type".printf 
(type_name_down),
+                                                          null,
+                                                          0.3);
+                       add_custom_header (type_name_down + "_destroy_func",
+                                                          "A destroy function for @%s_type".printf 
(type_name_down),
+                                                          null,
+                                                          0.4);
+               }
+
+               m.accept_children ({NodeType.FORMAL_PARAMETER, NodeType.TYPE_PARAMETER}, this);
+               var exceptions = m.get_children_by_types ({NodeType.ERROR_DOMAIN, NodeType.CLASS});
+               foreach (var ex in exceptions) {
+                       visit_thrown_error_domain (ex);
+               }
+
+               Header error_header = null;
+               GComment gcomment = null;
+               if (m.is_yields) {
+                       add_custom_header ("_callback_",
+                                                          "callback to call when the request is satisfied",
+                                                          {"scope async"});
+                       add_custom_header ("_user_data_",
+                                                          "the data to pass to @_callback_ function",
+                                                          {"closure"});
+                       // remove error from here, put that in the _finish function
+                       error_header = remove_custom_header ("error");
+
+                       gcomment = add_symbol (m.get_filename(), m.get_cname (), m.documentation);
+                       gcomment.returns = null; // async method has no return value
+                       var see_also = gcomment.see_also; // vala bug
+                       see_also += get_docbook_link (m, false, true);
+                       gcomment.see_also = see_also;
+               } else {
+                       gcomment = add_symbol (m.get_filename(),
+                                                                  m.get_cname (),
+                                                                  m.documentation,
+                                                                  null,
+                                                                  annotations);
+               }
+
+               // Handle attributes for things like deprecation.
+               process_attributes (m, gcomment);
+
+               remove_custom_header ("self");
+
+               if (current_dbus_interface != null && m.is_dbus_visible && !m.is_constructor) {
+                       if (m.return_type != null && m.return_type.data_type != null) {
+                               var dresult = new DBus.Parameter (m.get_dbus_result_name (),
+                                                                                                 
m.return_type.get_dbus_type_signature (),
+                                                                                                 
DBus.Parameter.Direction.OUT);
+                               current_dbus_member.add_parameter (dresult);
+                       }
+                       var dbus_gcomment = create_gcomment (m.get_dbus_name (),
+                                                                                                
m.documentation,
+                                                                                                null,
+                                                                                                true);
+                       current_dbus_member.comment = dbus_gcomment;
+                       current_dbus_interface.add_method (current_dbus_member);
+               }
+
+               current_headers = old_headers;
+               current_method = old_method;
+               current_dbus_member = old_dbus_member;
+
+               string? return_type_desc = null;
+               Api.TypeParameter type_parameter = m.return_type.data_type as Api.TypeParameter;
+               if (type_parameter != null) {
+                       if (type_parameter.parent is Api.Class) {
+                               return_type_desc = "A value from type #%s:%s-type."
+                                       .printf (get_cname (m.parent), type_parameter.name.down ());
+                       } else if (type_parameter.parent is Api.Interface
+                               && ((Api.Symbol) type_parameter.parent).get_attribute ("GenericAccessors") != 
null)
+                       {
+                               return_type_desc = "A value from type #_%sIface.get_%s_type()."
+                                       .printf (get_cname (m.parent), type_parameter.name.down ());
+                       } else if (type_parameter.parent is Api.Struct) {
+                               // type not stored
+                       } else if (type_parameter.parent == m) {
+                               return_type_desc = "value from type @%s_type.".printf 
(type_parameter.name.down ());
+                       }
+               }
+
+               if (m.is_yields) {
+                       var finish_gcomment = add_symbol (m.get_filename(),
+                                                                                         
m.get_finish_function_cname (),
+                                                                                         m.documentation);
+                       finish_gcomment.headers.clear ();
+
+                       if (!m.is_static) {
+                               finish_gcomment.headers.add (new Header ("self",
+                                                        "the %s instance".printf (get_docbook_link 
(m.parent))));
+                       }
+                       finish_gcomment.headers.add (new Header ("_res_",
+                                                        "a <link 
linkend=\"GAsyncResult\"><type>GAsyncResult</type></link>"));
+                       if (error_header != null) {
+                               finish_gcomment.headers.add (error_header);
+                       }
+
+                       var see_also = finish_gcomment.see_also; // vala bug
+                       see_also += get_docbook_link (m);
+                       finish_gcomment.see_also = see_also;
+
+                       if (return_type_desc != null) {
+                               finish_gcomment.returns = combine_inline_docs (return_type_desc, 
finish_gcomment.returns);
+                       }
+               } else {
+                       if (return_type_desc != null) {
+                               gcomment.returns = combine_inline_docs (return_type_desc, gcomment.returns);
+                       }
+               }
+
+
+               if (m.is_constructor && !m.get_cname ().has_suffix ("_new")) {
+                       // Hide secondary _construct methods from the documentation
+                       // (the primary _construct method is hidden in visit_class())
+                       var file_data = get_file_data (m.get_filename ());
+                       file_data.private_section_lines.add (m.get_cname ().replace ("_new", "_construct"));
+               }
+       }
+
+       /**
+        * Visit abstract methods
+        */
+       private void visit_abstract_method (Api.Method m) {
+               if (!m.is_abstract && !m.is_virtual) {
+                       return;
+               }
+
+               if (!m.is_private && !m.is_protected && !m.is_internal) {
+                       add_custom_header (m.name, "virtual method called by %s"
+                               .printf (get_docbook_link (m)));
+
+                       if (m.is_yields) {
+                               add_custom_header (m.name + "_finish", "asynchronous finish function for 
<structfield>%s</structfield>, called by %s"
+                                       .printf (m.name, get_docbook_link (m)));
+                       }
+               } else {
+                       add_custom_header (m.name, "virtual method used internally");
+
+                       if (m.is_yields) {
+                               add_custom_header (m.name + "_finish", "asynchronous finish function used 
internally");
+                       }
+               }
+       }
+
+       /**
+        * Visit abstract properties
+        */
+       private void visit_abstract_property (Api.Property prop) {
+               if (!prop.is_abstract && !prop.is_virtual) {
+                       return;
+               }
+
+               if (prop.getter != null && !prop.getter.is_private && !prop.getter.is_internal && 
prop.getter.is_get) {
+                       add_custom_header ("get_" + prop.name, "getter method for the abstract property %s"
+                               .printf (get_docbook_link (prop)));
+               }
+
+               if (prop.setter != null && !prop.setter.is_private && !prop.setter.is_internal && 
prop.setter.is_set && !prop.setter.is_construct) {
+                       add_custom_header ("set_" + prop.name, "setter method for the abstract property %s"
+                               .printf (get_docbook_link (prop)));
+               }
+       }
+
+       public override void visit_formal_parameter (Api.FormalParameter param) {
+               var param_name = param.name ?? "...";
+               var annotations = new string[]{};
+               var direction = "in";
+
+               // Avoid "Parameter description for * is missing" warnings
+               add_custom_header (param_name, "&nbsp;", null, double.MAX, false);
+
+               if (param.is_out) {
+                       direction = "out";
+               } else if (param.is_ref) {
+                       direction = "inout";
+               }
+               annotations += direction;
+
+               TypeParameter type_parameter = param.parameter_type.data_type as TypeParameter;
+               if (type_parameter != null) {
+                       if (type_parameter.parent is Api.Class) {
+                               add_custom_header (param_name, "A parameter from type #%s:%s-type."
+                                       .printf (get_cname (type_parameter.parent), type_parameter.name.down 
()), null, double.MAX, false);
+                       } else if (type_parameter.parent is Api.Interface && ((Api.Symbol) 
type_parameter.parent)
+                                       .get_attribute ("GenericAccessors") != null) {
+                               add_custom_header (param_name, "A parameter from type 
#_%sIface.get_%s_type()."
+                                       .printf (get_cname (type_parameter.parent), type_parameter.name.down 
()), null, double.MAX, false);
+                       } else if (type_parameter.parent is Api.Struct) {
+                               // type not stored
+                       } else if (type_parameter.parent is Method) {
+                               add_custom_header (param_name, "A parameter from type @%s_type."
+                                       .printf (type_parameter.name.down ()), null, double.MAX, false);
+                       }
+               }
+
+               if (param.parameter_type.is_nullable) {
+                       annotations += "allow-none";
+               }
+
+               if (param.parameter_type.is_owned
+                       && !(param.parameter_type.data_type is Api.Delegate))
+               {
+                       annotations += "transfer full";
+               }
+
+               if (param.parameter_type.data_type is Api.Array) {
+                       annotations += "array length=%s_length1".printf (param_name);
+                       add_custom_header ("%s_length1".printf (param_name),
+                                                          "length of the @%s array".printf (param_name),
+                                                          null,
+                                                          get_parameter_pos (current_method_or_delegate, 
param_name)+0.1);
+               }
+
+               if (!param.ellipsis && param.parameter_type.data_type != null
+                       && get_cname (param.parameter_type.data_type) == "GError")
+               {
+                       annotations += "not-error";
+               }
+
+               if (current_signal != null && param.documentation == null) {
+                       // gtkdoc writes arg0, arg1 which is ugly. As a workaround, we always add an header 
for them.
+                       add_custom_header (param_name, "", null);
+               } else {
+                       add_header (param_name, param.documentation, annotations,
+                               get_parameter_pos (current_method_or_delegate, param_name));
+               }
+
+               if (param.parameter_type.data_type is Api.Delegate) {
+                       add_custom_header ("%s_target".printf (param_name), "user data to pass to @%s".printf 
(param_name),
+                               {"allow-none", "closure"}, get_parameter_pos (current_method_or_delegate, 
param_name)+0.1);
+                       if (param.parameter_type.is_owned) {
+                               add_custom_header ("%s_target_destroy_notify".printf (param_name),
+                                                                  "function to call when @%s_target is no 
longer needed".printf (param_name), {"allow-none"},
+                                                                  get_parameter_pos 
(current_method_or_delegate, param_name)+0.2);
+                       }
+               }
+
+               if (current_dbus_member != null) {
+                       var ddirection = DBus.Parameter.Direction.IN;
+                       if (current_signal != null) {
+                               ddirection = DBus.Parameter.Direction.NONE;
+                       } else if (param.is_out) {
+                               ddirection = DBus.Parameter.Direction.OUT;
+                       }
+                       var dparam = new DBus.Parameter (param_name,
+                                                                                        
param.parameter_type.get_dbus_type_signature (),
+                                                                                        ddirection);
+                       current_dbus_member.add_parameter (dparam);
+               }
+               param.accept_all_children (this);
+       }
+
+       private void process_attributes (Symbol sym, GComment gcomment) {
+               // Handle the ‘Deprecated’ attribute.
+               if (sym.is_deprecated) {
+                       Attribute? version;
+                       Attribute? deprecated;
+                       AttributeArgument? deprecated_since;
+                       AttributeArgument? replacement;
+                       if ((version = sym.get_attribute ("Version")) != null) {
+                               deprecated_since = version.get_argument ("deprecated_since");
+                               replacement = version.get_argument ("replacement");
+                       } else if ((deprecated = sym.get_attribute ("Deprecated")) != null) {
+                               deprecated_since = deprecated.get_argument ("since");
+                               replacement = deprecated.get_argument ("replacement");
+                       } else {
+                               assert_not_reached ();
+                       }
+
+                       string? since = null;
+                       if (deprecated_since != null) {
+                               since = deprecated_since.value;
+
+                               // Strip surrounding quotation marks.
+                               if (since.has_prefix ("\"")) {
+                                       since = since[1:since.length - 1];
+                               }
+                               if (since.has_suffix ("\"")) {
+                                       since = since[0:-1];
+                               }
+                       }
+
+                       string? replacement_symbol_name = null;
+                       Api.Node? replacement_symbol = null;
+
+                       if (replacement != null) {
+                               replacement_symbol_name = replacement.value;
+
+                               // Strip surrounding quotation marks.
+                               if (replacement_symbol_name.has_prefix ("\"")) {
+                                       replacement_symbol_name = 
replacement_symbol_name[1:replacement_symbol_name.length - 1];
+                               }
+                               if (replacement_symbol_name.has_suffix ("\"")) {
+                                       replacement_symbol_name = replacement_symbol_name[0:-1];
+                               }
+
+                               // Strip any trailing brackets.
+                               if (replacement_symbol_name.has_suffix ("()")) {
+                                       replacement_symbol_name = replacement_symbol_name[0:-2];
+                               }
+
+                               replacement_symbol = current_tree.search_symbol_str (sym,
+                                                                                                             
                           replacement_symbol_name);
+                       }
+
+                       if (replacement != null && replacement_symbol == null) {
+                               reporter.simple_warning ("GtkDoc", "Couldn’t resolve replacement symbol ‘%s’ 
for ‘Deprecated’ attribute on %s.",
+                                                                                replacement_symbol_name,
+                                                                                sym.get_full_name ());
+                       }
+
+                       var deprecation_string = "No replacement specified.";
+
+                       if (since != null && replacement_symbol != null) {
+                               deprecation_string = "%s: Replaced by %s.".printf (since, get_gtkdoc_link 
(replacement_symbol));
+                       } else if (since != null && replacement_symbol == null) {
+                               deprecation_string = "%s: No replacement specified.".printf (since);
+                       } else if (since == null && replacement_symbol != null) {
+                               deprecation_string = "Replaced by %s.".printf (get_gtkdoc_link 
(replacement_symbol));
+                       } else {
+                               reporter.simple_warning ("GtkDoc", "Missing ‘since’ and ‘replacement’ 
arguments to ‘Deprecated’ attribute on %s.",
+                                                                                sym.get_full_name ());
+                       }
+
+                       gcomment.versioning.add (new Header ("Deprecated", deprecation_string));
+               }
+       }
+}
diff --git a/valadoc/doclets/gtkdoc/utils.vala b/valadoc/doclets/gtkdoc/utils.vala
new file mode 100644
index 0000000..be55172
--- /dev/null
+++ b/valadoc/doclets/gtkdoc/utils.vala
@@ -0,0 +1,265 @@
+/* utils.vala
+ *
+ * Copyright (C) 2010 Luca Bruno
+ * Copyright (C) 2007-2009  Jürg Billeter
+ *
+ * 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:
+ *     Luca Bruno <lethalman88 gmail com>
+ */
+
+using Valadoc;
+using Valadoc.Api;
+using Valadoc.Content;
+
+namespace Gtkdoc {
+       public string get_section (string filename) {
+               return Path.get_basename (filename.substring (0, filename.last_index_of_char ('.')));
+       }
+
+       public string commentize (string comment) {
+               return string.joinv ("\n * ", comment.split ("\n"));
+       }
+
+       public string? get_cname (Api.Item item) {
+               if (item is Api.Method) {
+                       return ((Api.Method)item).get_cname ();
+               } else if (item is Api.FormalParameter) {
+                       return ((Api.FormalParameter)item).name;
+               } else if (item is Api.Constant) {
+                       return ((Api.Constant)item).get_cname ();
+               } else if (item is Api.Property) {
+                       return ((Api.Property)item).get_cname ();
+               } else if (item is Api.Signal) {
+                       var name = ((Api.Signal)item).get_cname ();
+                       return name.replace ("_", "-");
+               } else if (item is Api.Class) {
+                       return ((Api.Class)item).get_cname ();
+               } else if (item is Api.Struct) {
+                       return ((Api.Struct)item).get_cname ();
+               } else if (item is Api.Interface) {
+                       return ((Api.Interface)item).get_cname ();
+               } else if (item is Api.ErrorDomain) {
+                       return ((Api.ErrorDomain)item).get_cname ();
+               } else if (item is Api.ErrorCode) {
+                       return ((Api.ErrorCode)item).get_cname ();
+               } else if (item is Api.Delegate) {
+                       return ((Api.Delegate)item).get_cname ();
+               } else if (item is Api.Enum) {
+                       return ((Api.Enum)item).get_cname ();
+               } else if (item is Api.EnumValue) {
+                       return ((Api.EnumValue)item).get_cname ();
+               }
+               return null;
+       }
+
+       public string? get_dbus_interface (Api.Item item) {
+               if (item is Api.Class) {
+                       return ((Api.Class)item).get_dbus_name ();
+               } else if (item is Api.Interface) {
+                       return ((Api.Interface)item).get_dbus_name ();
+               }
+               return null;
+       }
+
+       public string get_docbook_type_link (Api.Class cls) {
+               return """<link linkend="%s:CAPS"><literal>%s</literal></link>"""
+                       .printf (to_docbook_id (cls.get_type_id ()), cls.get_type_id ());
+       }
+
+       public string? get_gtkdoc_link (Api.Node symbol) {
+               if (symbol is Class || symbol is Interface || symbol is Struct || symbol is Enum
+                       || symbol is ErrorDomain)
+               {
+                       return "#%s".printf (get_cname (symbol));
+               }
+
+               if (symbol is Method) {
+                       return "%s ()".printf (((Method) symbol).get_cname ());
+               }
+
+               if (symbol is Constant || symbol is Api.EnumValue || symbol is ErrorCode) {
+                       return "%%%s".printf (get_cname (symbol));
+               }
+
+               if (symbol is Api.Signal) {
+                       return "#%s::%s".printf (get_cname (symbol.parent), ((Api.Signal) symbol).get_cname 
());
+               }
+
+               if (symbol is Property) {
+                       return "#%s:%s".printf (get_cname (symbol.parent), ((Property) symbol).get_cname ());
+               }
+
+               if (symbol is Field && (symbol.parent is Class || symbol.parent is Struct)) {
+                       var field = symbol as Field;
+                       if (field.is_static) {
+                               return field.get_cname ();
+                       } else {
+                               return "#%s.%s".printf (get_cname (symbol.parent), field.get_cname ());
+                       }
+               }
+
+               return get_cname (symbol) ?? symbol.get_full_name ();
+       }
+
+       public string? get_docbook_link (Api.Item item, bool is_dbus = false, bool is_async_finish = false) {
+               if (item is Api.Method) {
+                       string name;
+                       string parent;
+                       if (is_dbus) {
+                               name = ((Api.Method)item).get_dbus_name ();
+                               parent = "%s-".printf (get_dbus_interface (item.parent));
+                       } else {
+                               if (!is_async_finish) {
+                                       name = ((Api.Method)item).get_cname ();
+                               } else {
+                                       name = ((Api.Method)item).get_finish_function_cname ();
+                               }
+                               parent = "";
+                       }
+                       return """<link linkend="%s%s"><function>%s()</function></link>"""
+                               .printf (to_docbook_id (parent), to_docbook_id (name), name);
+               } else if (item is Api.FormalParameter) {
+                       return "<parameter>%s</parameter>".printf (((Api.FormalParameter)item).name);
+               } else if (item is Api.Constant) {
+                       var cname = ((Api.Constant)item).get_cname ();
+                       return """<link linkend="%s:CAPS"><literal>%s</literal></link>"""
+                               .printf (to_docbook_id (cname), cname);
+               } else if (item is Api.ErrorCode) {
+                       var cname = ((Api.ErrorCode)item).get_cname ();
+                       return """<link linkend="%s:CAPS"><literal>%s</literal></link>"""
+                               .printf (to_docbook_id (cname), cname);
+               } else if (item is Api.Property) {
+                       string name;
+                       string parent;
+                       if (is_dbus) {
+                               name = ((Api.Property)item).get_dbus_name ();
+                               parent = get_dbus_interface (item.parent);
+                       } else {
+                               name = ((Api.Property)item).get_cname ();
+                               parent = get_cname (item.parent);
+                       }
+                       return """<link linkend="%s--%s"><type>"%s"</type></link>"""
+                               .printf (to_docbook_id (parent), to_docbook_id (name), name);
+               } else if (item is Api.Signal) {
+                       string name;
+                       string parent;
+                       if (is_dbus) {
+                               name = ((Api.Signal)item).get_dbus_name ();
+                               parent = get_dbus_interface (item.parent);
+                       } else {
+                               name = ((Api.Signal)item).get_cname ();
+                               name = name.replace ("_", "-");
+                               parent = get_cname (item.parent);
+                       }
+                       return """<link linkend="%s-%s"><type>"%s"</type></link>"""
+                               .printf (to_docbook_id (parent), to_docbook_id (name), name);
+               } else {
+                       var cname = get_cname (item);
+                       if (cname != null) {
+                               return """<link linkend="%s"><type>%s</type></link>"""
+                                       .printf (to_docbook_id (cname), cname);
+                       }
+               }
+               return null;
+       }
+
+       public double get_parameter_pos (Api.Node node, string name) {
+               double pos = 1;
+               foreach (var param in node.get_children_by_type (NodeType.FORMAL_PARAMETER)) {
+                       if (param.name == name) {
+                               return pos;
+                       }
+                       pos++;
+               }
+               return -1;
+       }
+
+       public string to_lower_case (string camel) {
+               var builder = new StringBuilder ();
+               bool last_upper = true;
+               for (int i=0; i < camel.length; i++) {
+                       if (camel[i].isupper ()) {
+                               if (!last_upper) {
+                                       builder.append_c ('_');
+                               }
+                               builder.append_unichar (camel[i].tolower ());
+                               last_upper = true;
+                       } else {
+                               builder.append_unichar (camel[i]);
+                               last_upper = false;
+                       }
+               }
+               return builder.str;
+       }
+
+       public string to_docbook_id (string name) {
+               return name.replace(".", "-").replace("_", "-");
+       }
+
+       public bool package_exists (string package_name, ErrorReporter reporter) {
+               // copied from vala/codegen/valaccodecompiler.vala
+               string pc = "pkg-config --exists " + package_name;
+               int exit_status;
+
+               try {
+                       Process.spawn_command_line_sync (pc, null, null, out exit_status);
+                       return (0 == exit_status);
+               } catch (SpawnError e) {
+                       reporter.simple_warning ("GtkDoc",
+                                                                        "Error pkg-config --exists %s: %s", 
package_name, e.message);
+                       return false;
+               }
+       }
+
+       public bool is_generated_by_vala (string filename) {
+               var stream = FileStream.open (filename, "r");
+               if (stream != null) {
+                       var line = stream.read_line ();
+                       if (line != null) {
+                               return line.index_of ("generated by valac") >= 0;
+                       }
+               }
+               return false;
+       }
+}
+
+
+public class Gtkdoc.TextWriter {
+       public string filename;
+       public string mode;
+
+       private FileStream? stream;
+
+       public TextWriter (string filename, string mode) {
+               this.filename = filename;
+               this.mode = mode;
+       }
+
+       public bool open () {
+               stream = FileStream.open (filename, mode);
+               return stream != null;
+       }
+
+       public void close () {
+               stream = null;
+       }
+       
+       public void write_line (string line) {
+               stream.puts (line);
+               stream.putc ('\n');
+       }
+}
diff --git a/valadoc/doclets/html/Makefile.am b/valadoc/doclets/html/Makefile.am
new file mode 100644
index 0000000..6484bba
--- /dev/null
+++ b/valadoc/doclets/html/Makefile.am
@@ -0,0 +1,53 @@
+include $(top_srcdir)/Makefile.common
+
+NULL =
+
+AM_CFLAGS = \
+       -DPACKAGE_ICONDIR=\"$(datadir)/valadoc/icons/\" \
+       -I$(top_srcdir)/gee/ \
+       -I$(top_srcdir)/libvaladoc/ \
+       $(GLIB_CFLAGS) \
+       $(LIBGVC_CFLAGS) \
+       $(NULL)
+
+BUILT_SOURCES = libdoclet.vala.stamp
+
+doclet_LTLIBRARIES = libdoclet.la
+
+docletdir = $(libdir)/valadoc/doclets/html
+
+libdoclet_la_LDFLAGS = -module -avoid-version -no-undefined
+
+libdoclet_la_VALASOURCES = \
+       doclet.vala \
+       $(NULL)
+
+libdoclet_la_SOURCES = \
+       libdoclet.vala.stamp \
+       $(libdoclet_la_VALASOURCES:.vala=.c) \
+       $(NULL)
+
+libdoclet.vala.stamp: $(libdoclet_la_VALASOURCES)
+       $(VALAC) \
+               $(VALAFLAGS) \
+               -C \
+               --vapidir $(top_srcdir)/vala \
+               --vapidir $(top_srcdir)/vapi \
+               --vapidir $(top_srcdir)/libvaladoc --pkg valadoc@PACKAGE_SUFFIX@ \
+               $(filter %.vala %.c,$^)
+       touch $@
+
+libdoclet_la_LIBADD = \
+       $(top_builddir)/libvaladoc/libvaladoc@PACKAGE_SUFFIX@.la \
+       $(GLIB_LIBS) \
+       $(NULL)
+
+EXTRA_DIST = \
+       $(libdoclet_la_VALASOURCES) \
+       libdoclet.vala.stamp \
+       $(NULL)
+
+MAINTAINERCLEANFILES = \
+       $(libdoclet_la_VALASOURCES:.vala=.c) \
+       $(NULL)
+
diff --git a/valadoc/doclets/html/doclet.vala b/valadoc/doclets/html/doclet.vala
new file mode 100644
index 0000000..237882e
--- /dev/null
+++ b/valadoc/doclets/html/doclet.vala
@@ -0,0 +1,217 @@
+/* doclet.vala
+ *
+ * Copyright (C) 2008-2012 Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Valadoc;
+using Valadoc.Api;
+using Valadoc.Html;
+
+public class Valadoc.Html.Doclet : Valadoc.Html.BasicDoclet {
+       private const string css_path_package = "style.css";
+       private const string css_path_wiki = "../style.css";
+       private const string css_path = "../style.css";
+
+
+       private const string js_path_package = "scripts.js";
+       private const string js_path_wiki = "../scripts.js";
+       private const string js_path = "../scripts.js";
+
+       private class IndexLinkHelper : LinkHelper {
+               protected override string? from_wiki_to_package (WikiPage from, Api.Package to) {
+                       if (from.name != "index.valadoc") {
+                               return base.from_wiki_to_package (from, to);;
+                       }
+
+                       return Path.build_filename (to.name, to.name + ".htm");
+               }
+
+               protected override string? from_wiki_to_wiki (WikiPage from, WikiPage to) {
+                       if (from.name != "index.valadoc") {
+                               return base.from_wiki_to_wiki (from, to);
+                       }
+
+                       return Path.build_filename (_settings.pkg_name, translate_wiki_name (to));
+               }
+
+               protected override string? from_wiki_to_node (WikiPage from, Api.Node to) {
+                       if (from.name != "index.valadoc") {
+                               return base.from_wiki_to_node (from, to);
+                       }
+
+                       if (enable_browsable_check && (!to.is_browsable(_settings) || 
!to.package.is_browsable (_settings))) {
+                               return null;
+                       }
+
+                       return Path.build_filename (to.package.name, to.get_full_name () + ".html");
+               }
+       }
+
+       private string get_real_path ( Api.Node element ) {
+               return GLib.Path.build_filename ( this.settings.path, element.package.name, 
element.get_full_name () + ".html" );
+       }
+
+       public override void process (Settings settings, Api.Tree tree, ErrorReporter reporter) {
+               base.process (settings, tree, reporter);
+
+               DirUtils.create_with_parents (this.settings.path, 0777);
+               copy_directory (icons_dir, settings.path);
+
+               write_wiki_pages (tree, css_path_wiki, js_path_wiki, Path.build_filename(settings.path, 
settings.pkg_name));
+
+               var tmp = _renderer;
+               _renderer = new HtmlRenderer (settings, new IndexLinkHelper (), this.cssresolver);
+               GLib.FileStream file = GLib.FileStream.open (GLib.Path.build_filename (settings.path, 
"index.html"), "w");
+               writer = new Html.MarkupWriter (file);
+               _renderer.set_writer (writer);
+               write_file_header (Valadoc.Html.Doclet.css_path_package, Valadoc.Html.Doclet.js_path_package, 
settings.pkg_name);
+               write_navi_packages (tree);
+               write_package_index_content (tree);
+               write_file_footer ();
+               _renderer = tmp;
+               file = null;
+
+               tree.accept (this);
+       }
+
+       public override void visit_tree (Api.Tree tree) {
+               tree.accept_children (this);
+       }
+
+       public override void visit_package (Package package) {
+               if (!package.is_browsable (settings)) {
+                       return ;
+               }
+
+               string pkg_name = package.name;
+               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);
+
+               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 (Valadoc.Html.Doclet.css_path, Valadoc.Html.Doclet.js_path, pkg_name);
+               write_navi_package (package);
+               write_package_content (package, package);
+               write_file_footer ();
+               file = null;
+
+               package.accept_all_children (this);
+       }
+
+       public override void visit_namespace (Namespace ns) {
+               string rpath = this.get_real_path (ns);
+
+               if (ns.name != null) {
+                       GLib.FileStream file = GLib.FileStream.open (rpath, "w");
+                       writer = new Html.MarkupWriter (file);
+                       _renderer.set_writer (writer);
+                       write_file_header (Valadoc.Html.Doclet.css_path, Valadoc.Html.Doclet.js_path, 
ns.get_full_name () + " &ndash; " + ns.package.name);
+                       write_navi_symbol (ns);
+                       write_namespace_content (ns, ns);
+                       write_file_footer ();
+                       file = null;
+               }
+
+               ns.accept_all_children (this);
+       }
+
+       private void process_node (Api.Node node, bool accept_all_children) {
+               string rpath = this.get_real_path (node);
+
+               GLib.FileStream file = GLib.FileStream.open (rpath, "w");
+               writer = new Html.MarkupWriter (file);
+               _renderer.set_writer (writer);
+               write_file_header (css_path, js_path, node.get_full_name() + " &ndash; " + node.package.name);
+               if (is_internal_node (node)) {
+                       write_navi_symbol (node);
+               } else {
+                       write_navi_leaf_symbol (node);
+               }
+               write_symbol_content (node);
+               write_file_footer ();
+               file = null;
+
+               if (accept_all_children) {
+                       node.accept_all_children (this);
+               }
+       }
+
+       public override void visit_interface (Interface item) {
+               process_node (item, true);
+       }
+
+       public override void visit_class (Api.Class item) {
+               process_node (item, true);
+       }
+
+       public override void visit_struct (Api.Struct item) {
+               process_node (item, true);
+       }
+
+       public override void visit_error_domain (Api.ErrorDomain item) {
+               process_node (item, true);
+       }
+
+       public override void visit_enum (Api.Enum item) {
+               process_node (item, true);
+       }
+
+       public override void visit_property (Api.Property item) {
+               process_node (item, false);
+       }
+
+       public override void visit_constant (Api.Constant item) {
+               process_node (item, false);
+       }
+
+       public override void visit_field (Api.Field item) {
+               process_node (item, false);
+       }
+
+       public override void visit_error_code (Api.ErrorCode item) {
+               process_node (item, false);
+       }
+
+       public override void visit_enum_value (Api.EnumValue item) {
+               process_node (item, false);
+       }
+
+       public override void visit_delegate (Api.Delegate item) {
+               process_node (item, false);
+       }
+
+       public override void visit_signal (Api.Signal item) {
+               process_node (item, false);
+       }
+
+       public override void visit_method (Api.Method item) {
+               process_node (item, false);
+       }
+}
+
+
+public Type register_plugin (Valadoc.ModuleLoader module_loader) {
+       return typeof ( Valadoc.Html.Doclet );
+}
+
diff --git a/valadoc/driver.vala b/valadoc/driver.vala
new file mode 100644
index 0000000..60d00e5
--- /dev/null
+++ b/valadoc/driver.vala
@@ -0,0 +1,68 @@
+/* driver.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.Api;
+
+/**
+ * Creates an simpler, minimized, more abstract AST for valacs AST.
+ */
+public class Valadoc.Drivers.Driver : Object, Valadoc.Driver {
+       private SymbolResolver resolver;
+       private Api.Tree? tree;
+
+       public void write_gir (Settings settings, ErrorReporter reporter) {
+               var gir_writer = new Drivers.GirWriter (resolver);
+
+               // put .gir file in current directory unless -d has been explicitly specified
+               string gir_directory = ".";
+               if (settings.gir_directory != null) {
+                       gir_directory = settings.gir_directory;
+               }
+
+               gir_writer.write_file ((Vala.CodeContext) tree.data,
+                                                          gir_directory,
+                                                          "%s-%s.gir".printf (settings.gir_namespace, 
settings.gir_version),
+                                                          settings.gir_namespace,
+                                                          settings.gir_version,
+                                                          settings.pkg_name);
+       }
+
+       public Api.Tree? build (Settings settings, ErrorReporter reporter) {
+               TreeBuilder builder = new TreeBuilder ();
+               tree = builder.build (settings, reporter);
+               if (reporter.errors > 0) {
+                       return null;
+               }
+
+               resolver = new SymbolResolver (builder);
+               tree.accept (resolver);
+
+               return tree;
+       }
+}
+
+
+public Type register_plugin (Valadoc.ModuleLoader module_loader) {
+       return typeof (Valadoc.Drivers.Driver);
+}
+
diff --git a/valadoc/girwriter.vala b/valadoc/girwriter.vala
new file mode 100644
index 0000000..66deb38
--- /dev/null
+++ b/valadoc/girwriter.vala
@@ -0,0 +1,203 @@
+/* girwriter.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.Api;
+
+/**
+ * Code visitor generating .gir file for the public interface.
+ */
+public class Valadoc.Drivers.GirWriter : Vala.GIRWriter {
+       private GtkdocRenderer renderer;
+       private SymbolResolver resolver;
+
+       public GirWriter (SymbolResolver resolver) {
+               this.renderer = new GtkdocRenderer ();
+               this.resolver = resolver;
+       }
+
+       private string? translate (Content.Comment? documentation) {
+               if (documentation == null) {
+                       return null;
+               }
+
+               renderer.render_symbol (documentation);
+
+               return MarkupWriter.escape (renderer.content);
+       }
+
+       private string? translate_taglet (Content.Taglet? taglet) {
+               if (taglet == null) {
+                       return null;
+               }
+
+               renderer.render_children (taglet);
+
+               return MarkupWriter.escape (renderer.content);
+       }
+
+       protected override string? get_interface_comment (Vala.Interface viface) {
+               Interface iface = resolver.resolve (viface) as Interface;
+               return translate (iface.documentation);
+       }
+
+       protected override string? get_struct_comment (Vala.Struct vst) {
+               Struct st = resolver.resolve (vst) as Struct;
+               return translate (st.documentation);
+       }
+
+       protected override string? get_enum_comment (Vala.Enum ven) {
+               Enum en = resolver.resolve (ven) as Enum;
+               return translate (en.documentation);
+       }
+
+       protected override string? get_class_comment (Vala.Class vc) {
+               Class c = resolver.resolve (vc) as Class;
+               return translate (c.documentation);
+       }
+
+       protected override string? get_error_code_comment (Vala.ErrorCode vecode) {
+               ErrorCode ecode = resolver.resolve (vecode) as ErrorCode;
+               return translate (ecode.documentation);
+       }
+
+       protected override string? get_enum_value_comment (Vala.EnumValue vev) {
+               Api.EnumValue ev = resolver.resolve (vev) as Api.EnumValue;
+               return translate (ev.documentation);
+       }
+
+       protected override string? get_constant_comment (Vala.Constant vc) {
+               Constant c = resolver.resolve (vc) as Constant;
+               return translate (c.documentation);
+       }
+
+       protected override string? get_error_domain_comment (Vala.ErrorDomain vedomain) {
+               ErrorDomain edomain = resolver.resolve (vedomain) as ErrorDomain;
+               return translate (edomain.documentation);
+       }
+
+       protected override string? get_field_comment (Vala.Field vf) {
+               Field f = resolver.resolve (vf) as Field;
+               return translate (f.documentation);
+       }
+
+       protected override string? get_delegate_comment (Vala.Delegate vcb) {
+               Delegate cb = resolver.resolve (vcb) as Delegate;
+               return translate (cb.documentation);
+       }
+
+       protected override string? get_method_comment (Vala.Method vm) {
+               Method m = resolver.resolve (vm) as Method;
+               return translate (m.documentation);
+       }
+
+       protected override string? get_property_comment (Vala.Property vprop) {
+               Property prop = resolver.resolve (vprop) as Property;
+               return translate (prop.documentation);
+       }
+
+       protected override string? get_delegate_return_comment (Vala.Delegate vcb) {
+               Delegate cb = resolver.resolve (vcb) as Delegate;
+               if (cb.documentation == null) {
+                       return null;
+               }
+
+               Content.Comment? documentation = cb.documentation;
+               if (documentation == null) {
+                       return null;
+               }
+
+               Vala.List<Content.Taglet> taglets = documentation.find_taglets (cb, typeof(Taglets.Return));
+               foreach (Content.Taglet taglet in taglets) {
+                       return translate_taglet (taglet);
+               }
+
+               return null;
+       }
+
+       protected override string? get_signal_return_comment (Vala.Signal vsig) {
+               Api.Signal sig = resolver.resolve (vsig) as Api.Signal;
+               if (sig.documentation == null) {
+                       return null;
+               }
+
+               Content.Comment? documentation = sig.documentation;
+               if (documentation == null) {
+                       return null;
+               }
+
+               Vala.List<Content.Taglet> taglets = documentation.find_taglets (sig, typeof(Taglets.Return));
+               foreach (Content.Taglet taglet in taglets) {
+                       return translate_taglet (taglet);
+               }
+
+               return null;
+       }
+
+       protected override string? get_method_return_comment (Vala.Method vm) {
+               Method m = resolver.resolve (vm) as Method;
+               if (m.documentation == null) {
+                       return null;
+               }
+
+               Content.Comment? documentation = m.documentation;
+               if (documentation == null) {
+                       return null;
+               }
+
+               Vala.List<Content.Taglet> taglets = documentation.find_taglets (m, typeof(Taglets.Return));
+               foreach (Content.Taglet taglet in taglets) {
+                       return translate_taglet (taglet);
+               }
+
+               return null;
+       }
+
+       protected override string? get_signal_comment (Vala.Signal vsig) {
+               Api.Signal sig = resolver.resolve (vsig) as Api.Signal;
+               return translate (sig.documentation);
+       }
+
+       protected override string? get_parameter_comment (Vala.Parameter param) {
+               Api.Symbol symbol = resolver.resolve (((Vala.Symbol) param.parent_symbol));
+               if (symbol == null) {
+                       return null;
+               }
+
+               Content.Comment? documentation = symbol.documentation;
+               if (documentation == null) {
+                       return null;
+               }
+
+               Vala.List<Content.Taglet> taglets = documentation.find_taglets (symbol, 
typeof(Taglets.Param));
+               foreach (Content.Taglet _taglet in taglets) {
+                       Taglets.Param taglet = (Taglets.Param) _taglet;
+                       if (taglet.parameter_name == param.name) {
+                               return translate_taglet (taglet);
+                       }
+               }
+
+               return null;
+       }
+}
+
+
diff --git a/valadoc/icons/Makefile.am b/valadoc/icons/Makefile.am
new file mode 100644
index 0000000..454bdba
--- /dev/null
+++ b/valadoc/icons/Makefile.am
@@ -0,0 +1,38 @@
+NULL =
+
+iconsdir = $(datadir)/valadoc/icons
+
+dist_icons_DATA = \
+       abstractclass.png \
+       abstractmethod.png \
+       abstractproperty.png \
+       class.png \
+       coll_close.png \
+       coll_open.png \
+       constant.png \
+       constructor.png \
+       delegate.png \
+       devhelpstyle.css \
+       enum.png \
+       enumvalue.png \
+       errorcode.png \
+       errordomain.png \
+       field.png \
+       interface.png \
+       method.png \
+       namespace.png \
+       package.png \
+       packages.png \
+       property.png \
+       scripts.js \
+       signal.png \
+       staticmethod.png \
+       struct.png \
+       style.css \
+       tip.png \
+       virtualmethod.png \
+       virtualproperty.png \
+       warning.png \
+       wikistyle.css \
+       $(NULL)
+
diff --git a/valadoc/icons/abstractclass.png b/valadoc/icons/abstractclass.png
new file mode 100644
index 0000000..4aaf937
Binary files /dev/null and b/valadoc/icons/abstractclass.png differ
diff --git a/valadoc/icons/abstractmethod.png b/valadoc/icons/abstractmethod.png
new file mode 100644
index 0000000..93003f7
Binary files /dev/null and b/valadoc/icons/abstractmethod.png differ
diff --git a/valadoc/icons/abstractproperty.png b/valadoc/icons/abstractproperty.png
new file mode 100644
index 0000000..ea9e09a
Binary files /dev/null and b/valadoc/icons/abstractproperty.png differ
diff --git a/valadoc/icons/class.png b/valadoc/icons/class.png
new file mode 100644
index 0000000..f8e82b5
Binary files /dev/null and b/valadoc/icons/class.png differ
diff --git a/valadoc/icons/coll_close.png b/valadoc/icons/coll_close.png
new file mode 100644
index 0000000..948573a
Binary files /dev/null and b/valadoc/icons/coll_close.png differ
diff --git a/valadoc/icons/coll_open.png b/valadoc/icons/coll_open.png
new file mode 100644
index 0000000..d2124a2
Binary files /dev/null and b/valadoc/icons/coll_open.png differ
diff --git a/valadoc/icons/constant.png b/valadoc/icons/constant.png
new file mode 100644
index 0000000..85e248d
Binary files /dev/null and b/valadoc/icons/constant.png differ
diff --git a/valadoc/icons/constructor.png b/valadoc/icons/constructor.png
new file mode 100644
index 0000000..eee1738
Binary files /dev/null and b/valadoc/icons/constructor.png differ
diff --git a/valadoc/icons/delegate.png b/valadoc/icons/delegate.png
new file mode 100644
index 0000000..3ad818b
Binary files /dev/null and b/valadoc/icons/delegate.png differ
diff --git a/valadoc/icons/devhelpstyle.css b/valadoc/icons/devhelpstyle.css
new file mode 100644
index 0000000..1fb803d
--- /dev/null
+++ b/valadoc/icons/devhelpstyle.css
@@ -0,0 +1,578 @@
+* {
+       font-family: 'Times New Roman';
+       font-size: 12pt;
+}
+
+ul.external_link {
+}
+
+.main_optional_parameter {
+       font-style: italic;
+}
+
+.main_diagram {
+       border-style: none;
+       display: block;
+       margin: 0px auto;
+}
+
+
+.main_notification {
+       padding-right: 10px;
+       padding-left: 60px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+       min-height: 48px;
+       background-position: 6px 0.5em;
+       background-repeat: no-repeat;
+       background-image: url(warning.png);
+}
+
+.main_table {
+       border-collapse: collapse;
+       border: 1px solid #aaaaff;
+       background: #eeeeff;
+       margin-right:auto;
+       margin-left:auto;
+}
+
+.main_source, .main_sourcesample {
+       padding-right: 10px;
+       padding-left: 5px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       margin: 10px;
+
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+}
+
+
+input {
+       border-color: #aaaaff;
+       border-style: solid;
+       border-width: 1px;
+}
+
+
+
+
+.site_header {
+       font-size: 25px;
+       padding-bottom: 10px;
+       padding-top: 10px;
+       background-color: #aaaaff;
+       width: 100%;
+}
+
+
+div {
+       font-family:'Verdana';
+       font-size: 12;
+}
+
+
+.site_title {
+       text-align: left;
+       font-size: 40;
+}
+
+div.site_footer {
+       text-align: center;
+       background-color: #aaaaff;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       width: 100%;
+       clear: left;
+}
+
+
+div.site_body {
+       font-size: 10;
+}
+
+
+.site_content {
+       font-size: 12px;
+       margin-left: 5px;
+       margin-right: 5px;
+       text-align: left;
+}
+
+
+.main_type {
+       text-decoration: none;
+       font-style: italic;
+       color: #000000;
+}
+
+.main_basic_type {
+       text-decoration: none;
+       font-weight: bold;
+       color: #2e8b57;
+}
+
+.main_keyword {
+       text-decoration: none;
+       font-weight: bold;
+       color: #a52a2a;
+}
+
+.main_source .main_literal {
+       text-decoration: none;
+       color: #ff0000;
+}
+
+.main_comment {
+       text-decoration: none;
+       color: #888a85;
+}
+
+.main_preprocessor {
+       text-decoration: none;
+       color: #ad7fa8;
+}
+
+div.main_code_definition {
+       padding-right: 10px;
+       padding-left: 10px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+
+       font-family: monospace;
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+}
+
+div.main_notification_block {
+       padding-right: 10px;
+       padding-left: 10px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+
+       border-color: #d08717;
+       background-color: #fbf2c3;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+}
+
+span.main_block_headline {
+       background-image:url(tip.png);
+       background-repeat:no-repeat;
+       background-position:center right;
+       font-weight:bold;
+       display:block;
+}
+
+div.main_block_content {
+       margin-left:15px;
+}
+
+span.leaf_code_definition {
+       font-family: monospace;
+}
+
+
+div.leaf_brief_description {
+       display: block;
+       margin-left: 40px;
+}
+
+
+h1.main_title {
+       font-size: 20px;
+       margin-bottom: 0px;
+}
+
+h2.main_title {
+       margin-bottom: 0px;
+}
+
+h3.main_title {
+       margin-bottom: 0px;
+}
+
+.main_hr {
+       border: 0;
+       color: #aaaaff;
+       background-color: #aaaaff;
+       height: 1px;
+       margin-top: 5px;
+       margin-bottom: 5px;
+}
+
+
+
+.main_parameter_table_text, .main_errordomain_table_text, .main_enum_table_text {
+}
+
+.main_parameter_table_unknown_parameter {
+       color: GREY;
+}
+
+.main_parameter_table_name, .main_errordomain_table_name, .main_enum_table_name {
+       vertical-align: top;
+       text-align: right;
+       font-weight: bold;
+       width: 120px;
+       padding-right: 10px;
+}
+
+.main_parameter_table, .main_errordomain_table, .main_enum_table {
+       margin-weight: 20px;
+       margin-left: 20px;
+}
+
+
+
+.description a.constant, .brief_description a.constant {
+       background-image:url(constant.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.namespace, .brief_description a.namespace {
+       background-image:url(namespace.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.struct, .brief_description a.struct {
+       background-image:url(struct.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.interface, .brief_description a.interface {
+       background-image:url(interface.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.enum, .brief_description a.enum {
+       background-image:url(enum.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.errordomain, .brief_description a.errordomain {
+       background-image:url(errordomain.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.delegate, .brief_description a.delegate {
+       background-image:url(delegate.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.signal, .brief_description a.signal {
+       background-image:url(signal.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.field, .brief_description a.field {
+       background-image:url(field.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.enumvalue, .brief_description a.enumvalue {
+       background-image:url(enumvalue.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.errorcode, .brief_description a.errorcode {
+       background-image:url(errorcode.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.class, .brief_description a.class {
+       background-image:url(class.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.abstract_class, .brief_description a.abstract_class {
+       background-image:url(abstractclass.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+       font-style: italic;
+}
+.description a.property, .brief_description a.property {
+       background-image:url(property.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.virtual_property, .brief_description a.virtual_property {
+       background-image:url(virtualproperty.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.abstract_property, .brief_description a.abstract_property {
+       background-image:url(abstractproperty.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.method, .brief_description a.method {
+       background-image:url(method.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.static_method, .brief_description a.static_method {
+       background-image:url(staticmethod.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.virtual_method, .brief_description a.virtual_method {
+       background-image:url(virtualmethod.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.abstract_method, .brief_description a.abstract_method {
+       background-image:url(abstractmethod.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.creation_method, .brief_description a.creation_method {
+       background-image:url(constructor.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+
+.navi_main .errorcode, .navi_inline .errorcode {
+       list-style-image:url(errorcode.png);
+}
+.navi_main .enumvalue, .navi_inline .enumvalue {
+       list-style-image:url(enumvalue.png);
+}
+.navi_main .abstract_class, .navi_inline .abstract_class {
+       list-style-image: url(abstractclass.png);
+}
+.navi_main .abstract_method, .navi_inline .abstract_method {
+       list-style-image: url( abstractmethod.png );
+}
+.navi_main .creation_method, .navi_inline .creation_method, .main_list_m {
+       list-style-image: url(constructor.png);
+}
+.navi_main .static_method, .navi_inline .static_method {
+       list-style-image: url(staticmethod.png);
+}
+.navi_main .package_index {
+       list-style-image: url(packages.png);
+}
+.navi_main .virtual_method, .navi_inline .virtual_method {
+       list-style-image: url(virtualmethod.png);
+}
+.navi_main .errordomain, .navi_inline .errordomain, .main_list_errdom {
+       list-style-image: url(errordomain.png);
+}
+.navi_main .namespace, .navi_inline .namespace, .main_list_ns {
+       list-style-image: url(namespace.png);
+}
+.navi_main .method, .navi_inline .method {
+       list-style-image: url(method.png);
+}
+.navi_main .struct, .navi_inline .struct, .main_list_stru {
+       list-style-image: url(struct.png);
+}
+.navi_main .interface, .navi_inline .interface, .main_list_iface {
+       list-style-image: url(interface.png);
+}
+.navi_main .field, .navi_inline .field, .main_list_field {
+       list-style-image: url(field.png);
+}
+.navi_main .class, .navi_inline .class, .main_list_cl {
+       list-style-image: url(class.png);
+}
+.navi_main .enum, .navi_inline .enum, .main_list_en {
+       list-style-image: url(enum.png);
+}
+.navi_main .property, .navi_inline .property, .main_list_prop {
+       list-style-image: url(property.png);
+}
+.navi_main .abstract_property, .navi_inline .abstract_property {
+       list-style-image: url(abstractproperty.png);
+}
+.navi_main .virtual_property, .navi_inline .virtual_property {
+       list-style-image: url(virtualproperty.png);
+}
+.navi_main .delegate, .navi_inline .delegate, .main_list_del {
+       list-style-image: url(delegate.png);
+}
+.navi_main .signal, .navi_inline .signal, .main_list_sig {
+       list-style-image: url(signal.png);
+}
+.navi_main .package, .navi_inline .package {
+       list-style-image: url(package.png);
+}
+.navi_main .constant, .navi_inline .constant {
+       list-style-image: url(constant.png);
+}
+
+
+.navi_main {
+       margin-top: 10px;
+       margin-bottom: 10px;
+       padding-left: 30px;
+}
+
+.navi_hr {
+       border: 0;
+       color: #aaaaff;
+       background-color: #aaaaff;
+       height: 1px;
+       margin-left: 10px;
+       margin-right: 10px;
+       margin-top: 5px;
+       margin-bottom: 5px;
+}
+
+
+
+.navi_main a, .navi_inline a,
+a.external_link
+{
+       text-decoration: none;
+       color:  #214b87;
+}
+
+.navi_main .abstract_class > a, .navi_inline .abstract_class > a {
+       font-style: italic;
+}
+
+a.navi_link:hover, a.external_link:hover {
+       text-decoration: underline;
+}
+
+ul.no_bullet li {
+       list-style-type: none;
+}
+
+.main_see_list {
+}
+
+.navi_inline {
+}
+
+.css_content_literal {
+       font-family: monospace;
+       color: #ff01ff;
+}
+
+code {
+       font-family: monospace;
+}
+
+.main_code_definition a, .leaf_code_definition a {
+       text-decoration: none;
+       color: inherit;
+}
+
+.main_code_definition a:hover, .leaf_code_definition a:hover {
+       text-decoration: underline;
+}
+
+.box {
+}
+.box .headline {
+       background-image: url("coll_open.png");
+       background-position: calc(100% - 1px) center;
+       background-repeat: no-repeat;
+       background-color: #eeeeff;
+       border-color: #aaaaff;
+       border-style: solid;
+       border-width: 1px;
+       margin: auto;
+       width: 90%;
+       margin-top: 20px;
+       font-weight: bold;  
+}
+.box .content {
+       border-color: #aaaaff;
+       border-width: 0 1 1 1;
+       border-style: solid;
+       overflow: auto;
+       display: none;
+       margin: auto;
+       width: 90%;
+}
+.box .column {
+       float: left;
+       width: 33%;
+}
+
+.namespace_note {
+}
+.package_note {
+}
+
+.deprecated {
+       text-decoration:line-through;
+}
diff --git a/valadoc/icons/enum.png b/valadoc/icons/enum.png
new file mode 100644
index 0000000..9d534b5
Binary files /dev/null and b/valadoc/icons/enum.png differ
diff --git a/valadoc/icons/enumvalue.png b/valadoc/icons/enumvalue.png
new file mode 100644
index 0000000..79aa271
Binary files /dev/null and b/valadoc/icons/enumvalue.png differ
diff --git a/valadoc/icons/errorcode.png b/valadoc/icons/errorcode.png
new file mode 100644
index 0000000..d61c7e9
Binary files /dev/null and b/valadoc/icons/errorcode.png differ
diff --git a/valadoc/icons/errordomain.png b/valadoc/icons/errordomain.png
new file mode 100644
index 0000000..e512827
Binary files /dev/null and b/valadoc/icons/errordomain.png differ
diff --git a/valadoc/icons/field.png b/valadoc/icons/field.png
new file mode 100644
index 0000000..5515f7e
Binary files /dev/null and b/valadoc/icons/field.png differ
diff --git a/valadoc/icons/interface.png b/valadoc/icons/interface.png
new file mode 100644
index 0000000..83a9588
Binary files /dev/null and b/valadoc/icons/interface.png differ
diff --git a/valadoc/icons/method.png b/valadoc/icons/method.png
new file mode 100644
index 0000000..516c2ff
Binary files /dev/null and b/valadoc/icons/method.png differ
diff --git a/valadoc/icons/namespace.png b/valadoc/icons/namespace.png
new file mode 100644
index 0000000..759846f
Binary files /dev/null and b/valadoc/icons/namespace.png differ
diff --git a/valadoc/icons/package.png b/valadoc/icons/package.png
new file mode 100644
index 0000000..cc67187
Binary files /dev/null and b/valadoc/icons/package.png differ
diff --git a/valadoc/icons/packages.png b/valadoc/icons/packages.png
new file mode 100644
index 0000000..d99004a
Binary files /dev/null and b/valadoc/icons/packages.png differ
diff --git a/valadoc/icons/property.png b/valadoc/icons/property.png
new file mode 100644
index 0000000..3b96413
Binary files /dev/null and b/valadoc/icons/property.png differ
diff --git a/valadoc/icons/scripts.js b/valadoc/icons/scripts.js
new file mode 100644
index 0000000..02629ed
--- /dev/null
+++ b/valadoc/icons/scripts.js
@@ -0,0 +1,49 @@
+/* markupwriter.vala
+ *
+ * Copyright (C) 2008-2009 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>
+ */
+
+function get_path (path) {
+       var pos = path.lastIndexOf ('/');
+       if (pos < 0) {
+               return '';
+       }
+
+       return path.substring (pos, -1) + '/';
+}
+
+function toggle_box (self, id) {
+       var element = document.getElementById (id);
+       if (element == null) {
+               return ;
+       }
+
+       var style = self.currentStyle || window.getComputedStyle (self, false);
+       var orig_path = /url[ \t]*\(('(.*)'|"(.*)")\)/.exec (style.backgroundImage)[1].slice(1, -1);
+       var orig_dir = get_path (orig_path);
+       if (element.style.display == 'block') {
+               element.style.display = 'none';
+               self.style.backgroundImage = "url('" + orig_dir + 'coll_open.png' + "')";
+       } else {
+               element.style.display = 'block';
+               self.style.backgroundImage = "url('" + orig_dir + 'coll_close.png' + "')";
+       }
+}
+
diff --git a/valadoc/icons/signal.png b/valadoc/icons/signal.png
new file mode 100644
index 0000000..55f1966
Binary files /dev/null and b/valadoc/icons/signal.png differ
diff --git a/valadoc/icons/staticmethod.png b/valadoc/icons/staticmethod.png
new file mode 100644
index 0000000..4e76a24
Binary files /dev/null and b/valadoc/icons/staticmethod.png differ
diff --git a/valadoc/icons/struct.png b/valadoc/icons/struct.png
new file mode 100644
index 0000000..2acb79a
Binary files /dev/null and b/valadoc/icons/struct.png differ
diff --git a/valadoc/icons/style.css b/valadoc/icons/style.css
new file mode 100644
index 0000000..160cdcb
--- /dev/null
+++ b/valadoc/icons/style.css
@@ -0,0 +1,631 @@
+* {
+       font-family: 'Times New Roman';
+       font-size: 12pt;
+}
+
+ul.external_link {
+}
+
+.main_optional_parameter {
+       font-style: italic;
+}
+
+.main_diagram {
+       border-style: none;
+       display: block;
+       margin: 0px auto;
+}
+
+.site_navi {
+       text-align: right;
+}
+
+.main_notification {
+       padding-right: 10px;
+       padding-left: 60px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+       min-height: 48px;
+       background-position: 6px 0.5em;
+       background-repeat: no-repeat;
+       background-image: url(warning.png);
+}
+
+.main_table {
+       border-collapse: collapse;
+       border: 1px solid #aaaaff;
+       background: #eeeeff;
+       margin-right:auto;
+       margin-left:auto;
+}
+
+.main_source, .main_sourcesample {
+       padding-right: 10px;
+       padding-left: 5px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       margin: 10px;
+
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+}
+
+
+input {
+       border-color: #aaaaff;
+       border-style: solid;
+       border-width: 1px;
+}
+
+
+
+
+.site_header {
+       font-size: 25px;
+       padding-bottom: 10px;
+       padding-top: 10px;
+       background-color: #aaaaff;
+       width: 100%;
+}
+
+
+div {
+       font-family:'Verdana';
+       font-size: 12;
+}
+
+
+.site_title {
+       text-align: left;
+       font-size: 40;
+}
+
+div.site_footer {
+       text-align: center;
+       background-color: #aaaaff;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       width: 100%;
+       clear: left;
+}
+
+
+div.site_body {
+       font-size: 10;
+}
+
+
+div.site_navigation {
+       float: left;
+
+       width: 240px;
+       border-color: #aaaaff;
+       border-style: solid;
+       border-width: 1px;
+       background-color: #eeeeff;
+}
+
+
+.site_content {
+       font-size: 12px;
+       margin-left: 250px;
+       margin-right: 5px;
+       text-align: left;
+}
+
+
+.main_type {
+       text-decoration: none;
+       font-style: italic;
+       color: #000000;
+}
+
+.main_basic_type {
+       text-decoration: none;
+       font-weight: bold;
+       color: #2e8b57;
+}
+
+.main_keyword {
+       text-decoration: none;
+       font-weight: bold;
+       color: #a52a2a;
+}
+
+.main_escape {
+       text-decoration: none;
+       color: #6a5acd;
+}
+
+.xml_cdata {
+       text-decoration: none;
+       font-weight: normal;
+       color: #a020f0;
+}
+
+.xml_escape {
+       text-decoration: none;
+       font-weight: normal;
+       color: #a020f0;
+}
+
+.xml_element {
+       text-decoration: none;
+       font-weight: normal;
+       color: #008a8c;
+}
+
+.xml_attribute {
+       text-decoration: none;
+       font-weight: bold;
+       color: #6a5acd;
+}
+
+.xml_attribute_value {
+       text-decoration: none;
+       font-weight: normal;
+       color: #ff00ff;
+}
+
+.xml_comment {
+       text-decoration: none;
+       font-weight: normal;
+       color: #0202ff;
+}
+
+.main_source .main_literal {
+       text-decoration: none;
+       color: #ff00ff;
+}
+
+.main_comment {
+       text-decoration: none;
+       color: #888a85;
+}
+
+.main_preprocessor {
+       text-decoration: none;
+       color: #ad7fa8;
+}
+
+div.main_code_definition {
+       padding-right: 10px;
+       padding-left: 10px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+
+       font-family: monospace;
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+}
+
+div.main_notification_block {
+       padding-right: 10px;
+       padding-left: 10px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+
+       border-color: #d08717;
+       background-color: #fbf2c3;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+}
+
+span.main_block_headline {
+       background-image:url(tip.png);
+       background-repeat:no-repeat;
+       background-position:center right;
+       font-weight:bold;
+       display:block;
+}
+
+div.main_block_content {
+       margin-left:15px;
+}
+
+span.leaf_code_definition {
+       font-family: monospace;
+}
+
+
+div.leaf_brief_description {
+       display: block;
+       margin-left: 40px;
+}
+
+
+h1.main_title {
+       font-size: 20px;
+       margin-bottom: 0px;
+}
+
+h2.main_title {
+       margin-bottom: 0px;
+}
+
+h3.main_title {
+       margin-bottom: 0px;
+}
+
+.main_hr {
+       border: 0;
+       color: #aaaaff;
+       background-color: #aaaaff;
+       height: 1px;
+       margin-top: 5px;
+       margin-bottom: 5px;
+}
+
+
+
+.main_parameter_table_text, .main_errordomain_table_text, .main_enum_table_text {
+}
+
+.main_parameter_table_unknown_parameter {
+       color: GREY;
+}
+
+.main_parameter_table_name, .main_errordomain_table_name, .main_enum_table_name {
+       vertical-align: top;
+       text-align: right;
+       font-weight: bold;
+       width: 120px;
+       padding-right: 10px;
+}
+
+.main_parameter_table, .main_errordomain_table, .main_enum_table {
+       margin-weight: 20px;
+       margin-left: 20px;
+}
+
+
+
+.description a.constant, .brief_description a.constant {
+       background-image:url(constant.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.namespace, .brief_description a.namespace {
+       background-image:url(namespace.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.struct, .brief_description a.struct {
+       background-image:url(struct.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.interface, .brief_description a.interface {
+       background-image:url(interface.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.enum, .brief_description a.enum {
+       background-image:url(enum.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.errordomain, .brief_description a.errordomain {
+       background-image:url(errordomain.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.delegate, .brief_description a.delegate {
+       background-image:url(delegate.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.signal, .brief_description a.signal {
+       background-image:url(signal.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.field, .brief_description a.field {
+       background-image:url(field.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.enumvalue, .brief_description a.enumvalue {
+       background-image:url(enumvalue.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.errorcode, .brief_description a.errorcode {
+       background-image:url(errorcode.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.class, .brief_description a.class {
+       background-image:url(class.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+a.abstract_class, .description a.abstract_class, .brief_description a.abstract_class {
+       background-image:url(abstractclass.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+       font-style: italic;
+}
+.description a.property, .brief_description a.property {
+       background-image:url(property.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.virtual_property, .brief_description a.virtual_property {
+       background-image:url(virtualproperty.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.abstract_property, .brief_description a.abstract_property {
+       background-image:url(abstractproperty.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.method, .brief_description a.method {
+       background-image:url(method.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.static_method, .brief_description a.static_method {
+       background-image:url(staticmethod.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+a.virtual_method, .description a.virtual_method, .brief_description a.virtual_method {
+       background-image:url(virtualmethod.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.abstract_method, .brief_description a.abstract_method {
+       background-image:url(abstractmethod.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.description a.creation_method, .brief_description a.creation_method {
+       background-image:url(constructor.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+
+.navi_main .errorcode, .navi_inline .errorcode {
+       list-style-image:url(errorcode.png);
+}
+.navi_main .enumvalue, .navi_inline .enumvalue {
+       list-style-image:url(enumvalue.png);
+}
+.navi_main .abstract_class, .navi_inline .abstract_class {
+       list-style-image: url(abstractclass.png);
+}
+.navi_main .abstract_method, .navi_inline .abstract_method {
+       list-style-image: url( abstractmethod.png );
+}
+.navi_main .creation_method, .navi_inline .creation_method, .main_list_m {
+       list-style-image: url(constructor.png);
+}
+.navi_main .static_method, .navi_inline .static_method {
+       list-style-image: url(staticmethod.png);
+}
+.navi_main .package_index {
+       list-style-image: url(packages.png);
+}
+.navi_main .virtual_method, .navi_inline .virtual_method {
+       list-style-image: url(virtualmethod.png);
+}
+.navi_main .errordomain, .navi_inline .errordomain, .main_list_errdom {
+       list-style-image: url(errordomain.png);
+}
+.navi_main .namespace, .navi_inline .namespace, .main_list_ns {
+       list-style-image: url(namespace.png);
+}
+.navi_main .method, .navi_inline .method {
+       list-style-image: url(method.png);
+}
+.navi_main .struct, .navi_inline .struct, .main_list_stru {
+       list-style-image: url(struct.png);
+}
+.navi_main .interface, .navi_inline .interface, .main_list_iface {
+       list-style-image: url(interface.png);
+}
+.navi_main .field, .navi_inline .field, .main_list_field {
+       list-style-image: url(field.png);
+}
+.navi_main .class, .navi_inline .class, .main_list_cl {
+       list-style-image: url(class.png);
+}
+.navi_main .enum, .navi_inline .enum, .main_list_en {
+       list-style-image: url(enum.png);
+}
+.navi_main .property, .navi_inline .property, .main_list_prop {
+       list-style-image: url(property.png);
+}
+.navi_main .abstract_property, .navi_inline .abstract_property {
+       list-style-image: url(abstractproperty.png);
+}
+.navi_main .virtual_property, .navi_inline .virtual_property {
+       list-style-image: url(virtualproperty.png);
+}
+.navi_main .delegate, .navi_inline .delegate, .main_list_del {
+       list-style-image: url(delegate.png);
+}
+.navi_main .signal, .navi_inline .signal, .main_list_sig {
+       list-style-image: url(signal.png);
+}
+.navi_main .package, .navi_inline .package {
+       list-style-image: url(package.png);
+}
+.navi_main .constant, .navi_inline .constant {
+       list-style-image: url(constant.png);
+}
+
+
+.navi_main {
+       margin-top: 10px;
+       margin-bottom: 10px;
+       padding-left: 30px;
+}
+
+.navi_hr {
+       border: 0;
+       color: #aaaaff;
+       background-color: #aaaaff;
+       height: 1px;
+       margin-left: 10px;
+       margin-right: 10px;
+       margin-top: 5px;
+       margin-bottom: 5px;
+}
+
+
+
+.navi_main a, .navi_inline a, a.external_link
+{
+       text-decoration: none;
+       color:  #214b87;
+}
+
+.navi_main .abstract_class > a, .navi_inline .abstract_class > a {
+       font-style: italic;
+}
+
+a.navi_link:hover, a.external_link:hover {
+       text-decoration: underline;
+}
+
+ul.no_bullet li {
+       list-style-type: none;
+}
+
+.main_see_list {
+}
+
+.navi_inline {
+}
+
+.css_content_literal {
+       font-family: monospace;
+       color: #ff01ff;
+}
+
+code {
+       font-family: monospace;
+}
+
+.main_code_definition a, .leaf_code_definition a {
+       text-decoration: none;
+       color: inherit;
+}
+.main_code_definition a:hover, .leaf_code_definition a:hover {
+       text-decoration: underline;
+}
+
+.box {
+}
+.box .headline {
+       background-image: url("coll_open.png");
+       background-position: calc(100% - 1px) center;
+       background-repeat: no-repeat;
+       background-color: #eeeeff;
+       border-color: #aaaaff;
+       border-style: solid;
+       border-width: 1px;
+       margin: auto;
+       width: 90%;
+       margin-top: 20px;
+       font-weight: bold;  
+}
+.box .content {
+       border-color: #aaaaff;
+       border-width: 0 1 1 1;
+       border-style: solid;
+       overflow: auto;
+       display: none;
+       margin: auto;
+       width: 90%;
+}
+.box .column {
+       float: left;
+       width: 33%;
+}
+
+.namespace_note {
+}
+.package_note {
+}
+
+.deprecated {
+       text-decoration:line-through;
+}
diff --git a/valadoc/icons/tip.png b/valadoc/icons/tip.png
new file mode 100644
index 0000000..6ccf512
Binary files /dev/null and b/valadoc/icons/tip.png differ
diff --git a/valadoc/icons/virtualmethod.png b/valadoc/icons/virtualmethod.png
new file mode 100644
index 0000000..5ff14ec
Binary files /dev/null and b/valadoc/icons/virtualmethod.png differ
diff --git a/valadoc/icons/virtualproperty.png b/valadoc/icons/virtualproperty.png
new file mode 100644
index 0000000..7953746
Binary files /dev/null and b/valadoc/icons/virtualproperty.png differ
diff --git a/valadoc/icons/warning.png b/valadoc/icons/warning.png
new file mode 100644
index 0000000..ecdc0f9
Binary files /dev/null and b/valadoc/icons/warning.png differ
diff --git a/valadoc/icons/wikistyle.css b/valadoc/icons/wikistyle.css
new file mode 100644
index 0000000..459f91a
--- /dev/null
+++ b/valadoc/icons/wikistyle.css
@@ -0,0 +1,547 @@
+ul.external_link {
+}
+
+.main_optional_parameter {
+       font-style: italic;
+}
+
+.main_diagram {
+       border-style: none;
+       display: block;
+       margin: 0px auto;
+       width: 100px;
+}
+
+.site_navi {
+       text-align: right;
+}
+
+.main_notification {
+       padding-right: 10px;
+       padding-left: 60px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+       min-height: 48px;
+       background-position: 6px 0.5em;
+       background-repeat: no-repeat;
+       background-image: url(warning.png);
+}
+
+div.main_notification_block {
+       padding-right: 10px;
+       padding-left: 10px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+
+       border-color: #d08717;
+       background-color: #fbf2c3;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+}
+
+span.main_block_headline {
+       background-image:url(tip.png);
+       background-repeat:no-repeat;
+       background-position:center right;
+       font-weight:bold;
+       display:block;
+}
+
+div.main_block_content {
+       margin-left:15px;
+}
+
+.main_source, .main_sourcesample {
+       padding-right: 10px;
+       padding-left: 5px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       margin: 10px;
+
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+}
+
+input {
+       border-color: #aaaaff;
+       border-style: solid;
+       border-width: 1px;
+}
+
+.main_table {
+       border-collapse: collapse;
+       border: 1px solid #aaaaff;
+       background: #eeeeff;
+       margin-right:auto;
+       margin-left:auto;
+}
+
+.site_header {
+       font-size: 25px;
+       padding-bottom: 10px;
+       padding-top: 10px;
+       background-color: #aaaaff;
+       width: 100%;
+}
+
+
+div {
+       font-family:'Verdana';
+       font-size: 12;
+}
+
+
+.site_title {
+       text-align: left;
+       font-size: 40;
+}
+
+div.site_footer {
+       text-align: center;
+       background-color: #aaaaff;
+       padding-bottom: 5px;
+       padding-top: 5px;
+       width: 100%;
+       clear: left;
+}
+
+
+div.site_body {
+       font-size: 10;
+}
+
+
+div.site_navigation {
+       float: left;
+
+       width: 240px;
+       border-color: #aaaaff;
+       border-style: solid;
+       border-width: 1px;
+       background-color: #eeeeff;
+}
+
+
+.site_content {
+       font-size: 12px;
+       margin-left: 5px;
+       margin-right: 5px;
+       text-align: left;
+}
+
+
+.main_type {
+       text-decoration: none;
+       font-style: italic;
+       color: #000000;
+}
+
+.main_basic_type {
+       text-decoration: none;
+       font-weight: bold;
+       color: #2e8b57;
+}
+
+.main_keyword {
+       text-decoration: none;
+       font-weight: bold;
+       color: #a52a2a;
+}
+
+.main_source .main_literal {
+       text-decoration: none;
+       color: #ff0000;
+}
+
+.main_comment {
+       text-decoration: none;
+       color: #888a85;
+}
+
+.main_preprocessor {
+       text-decoration: none;
+       color: #ad7fa8;
+}
+
+div.main_code_definition {
+       padding-right: 10px;
+       padding-left: 10px;
+       padding-bottom: 5px;
+       padding-top: 5px;
+
+       font-family: monospace;
+       font-size: 10;
+       border-color: #aaaaff;
+       background-color: #eeeeff;
+       border-style: solid;
+       border-width: 1px;
+       margin: 10px;
+}
+
+
+
+
+
+h1.main_title {
+       font-size: 20px;
+       margin-bottom: 0px;
+}
+
+h2.main_title {
+       margin-bottom: 0px;
+}
+
+h3.main_title {
+       margin-bottom: 0px;
+}
+
+.main_hr {
+       border: 0;
+       color: #aaaaff;
+       background-color: #aaaaff;
+       height: 1px;
+       margin-top: 5px;
+       margin-bottom: 5px;
+}
+
+
+
+.main_parameter_table_text, .main_errordomain_table_text, .main_enum_table_text {
+}
+
+.main_parameter_table_unknown_parameter {
+       color: GREY;
+}
+
+.main_parameter_table_name, .main_errordomain_table_name, .main_enum_table_name {
+       vertical-align: top;
+       text-align: right;
+       font-weight: bold;
+       width: 120px;
+       padding-right: 10px;
+}
+
+.main_parameter_table, .main_errordomain_table, .main_enum_table {
+       margin-weight: 20px;
+       margin-left: 20px;
+}
+
+
+
+
+.main_inline_navigation_virtual_property {
+       list-style-image: url(virtualproperty.png);
+}
+.main_inline_navigation_abstract_property {
+       list-style-image: url(abstractproperty.png);
+}
+.navi_abstract_prop {
+       list-style-image: url(abstractproperty.png);
+}
+.navi_virtual_prop {
+       list-style-image: url(virtualproperty.png);
+}
+
+
+
+.css_content_link_constant {
+       background-image:url(constant.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_namespace {
+       background-image:url(namespace.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_struct {
+       background-image:url(struct.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_interface {
+       background-image:url(interface.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_enum {
+       background-image:url(enum.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_errordomain {
+       background-image:url(errordomain.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_delegate {
+       background-image:url(delegate.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_signal {
+       background-image:url(signal.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_field {
+       background-image:url(field.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_enumvalue {
+       background-image:url(enumvalue.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_errorcode {
+       background-image:url(errorcode.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_class {
+       background-image:url(class.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_abstract_class {
+       background-image:url(abstractclass.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_property {
+       background-image:url(property.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_virtual_property {
+       background-image:url(virtualproperty.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_abstract_property {
+       background-image:url(abstractproperty.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_method {
+       background-image:url(method.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_static_method {
+       background-image:url(staticmethod.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_virtual_method {
+       background-image:url(virtualmethod.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_abstract_method {
+       background-image:url( abstractmethod.png );
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+.css_content_link_construction_method {
+       background-image:url(constructor.png);
+       display:inline-block;
+       padding-right:17px;
+       background-repeat:no-repeat;
+       background-position:center right;
+       border:0px;
+}
+
+.main_inline_navigation_virtual_method {
+       list-style-image:url(virtualmethod.png);
+}
+.main_inline_navigation_errorcode {
+       list-style-image:url(errorcode.png);
+}
+.main_inline_navigation_enumvalue {
+       list-style-image:url(enumvalue.png);
+}
+.navi_abstract_class, .main_inline_navigation_abstract_class {
+       list-style-image: url(abstractclass.png);
+}
+.main_inline_navigation_abstract_method, .navi_abstract_method {
+       list-style-image: url( abstractmethod.png );
+}
+.navi_construction_method, .main_list_m, .main_inline_navigation_construction_method {
+       list-style-image: url(constructor.png);
+}
+.navi_static_method, .main_inline_navigation_static_method {
+       list-style-image: url(staticmethod.png);
+}
+
+.navi_package_index, .main_inline_navigation_package {
+       list-style-image: url(packages.png);
+}
+.main_navi_enval {
+       list-style-image: url(enumvalue.png);
+}
+.main_navi_errdomcode {
+       list-style-image: url(errorcode.png);
+}
+.navi_error_domain, .main_list_errdom, .main_inline_navigation_errordomain {
+       list-style-image: url(errordomain.png);
+}
+.navi_namespace, .main_list_ns, .main_inline_navigation_namespace {
+       list-style-image: url(namespace.png);
+}
+.navi_method, .main_inline_navigation_method {
+       list-style-image: url(method.png);
+}
+.navi_virtual_method {
+       list-style-image: url(virtualmethod.png);
+}
+.navi_struct, .main_list_stru, .main_inline_navigation_struct {
+       list-style-image: url(struct.png);
+}
+.navi_iface, .main_navigation_interface, .main_list_iface {
+       list-style-image: url(interface.png);
+}
+.navi_field, .main_inline_navigation_fields, .main_list_field {
+       list-style-image: url(field.png);
+}
+.navi_class, .main_inline_navigation_class, .main_list_cl {
+       list-style-image: url(class.png);
+}
+.navi_enum, .main_list_en, .main_inline_navigation_enum {
+       list-style-image: url(enum.png);
+}
+.navi_prop, .main_inline_navigation_property, .main_list_prop {
+       list-style-image: url(property.png);
+}
+.navi_del, .main_list_del, .main_inline_navigation_delegate {
+       list-style-image: url(delegate.png);
+}
+.navi_sig, .main_inline_navigation_signal, .main_list_sig {
+       list-style-image: url(signal.png);
+}
+.navi_package, .main_inline_navigation_package {
+       list-style-image: url(package.png);
+}
+
+.main_inline_navigation_constant, .navi_constant {
+       list-style-image: url(constant.png);
+}
+
+
+.navi_main {
+       margin-top: 10px;
+       margin-bottom: 10px;
+       padding-left: 30px;
+}
+
+.navi_hr {
+       border: 0;
+       color: #aaaaff;
+       background-color: #aaaaff;
+       height: 1px;
+       margin-left: 10px;
+       margin-right: 10px;
+       margin-top: 5px;
+       margin-bottom: 5px;
+}
+
+a.navi_link, a.external_link {
+       text-decoration: none;
+       color:  #214b87;
+}
+
+a.navi_link:hover, a.external_link:hover {
+       text-decoration: underline;
+}
+
+ul.no_bullet li {
+       list-style-type: none;
+}
+
+.main_see_list {
+}
+
+.main_inline_navigation {
+}
+
+.css_content_literal {
+       font-family: monospace;
+       color: #ff01ff;
+}
+
+code {
+       font-family: monospace;
+}
+
+.deprecated {
+       text-decoration:line-through;
+}
diff --git a/valadoc/initializerbuilder.vala b/valadoc/initializerbuilder.vala
new file mode 100644
index 0000000..d95b7fe
--- /dev/null
+++ b/valadoc/initializerbuilder.vala
@@ -0,0 +1,667 @@
+/* initializerbuilder.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;
+
+private class Valadoc.Api.InitializerBuilder : Vala.CodeVisitor {
+       private Vala.HashMap<Vala.Symbol, Symbol> symbol_map;
+       private SignatureBuilder signature;
+
+       private Symbol? resolve (Vala.Symbol symbol) {
+               return symbol_map.get (symbol);
+       }
+
+       private void write_node (Vala.Symbol vsymbol) {
+               signature.append_symbol (resolve (vsymbol));
+       }
+
+       private void write_type (Vala.DataType vsymbol) {
+               if (vsymbol.data_type != null) {
+                       write_node (vsymbol.data_type);
+               } else {
+                       signature.append_literal ("null");
+               }
+
+               var type_args = vsymbol.get_type_arguments ();
+               if (type_args.size > 0) {
+                       signature.append ("<");
+                       bool first = true;
+                       foreach (Vala.DataType type_arg in type_args) {
+                               if (!first) {
+                                       signature.append (",");
+                               } else {
+                                       first = false;
+                               }
+                               if (!type_arg.value_owned) {
+                                       signature.append_keyword ("weak");
+                               }
+                               signature.append (type_arg.to_qualified_string (null));
+                       }
+                       signature.append (">");
+               }
+
+               if (vsymbol.nullable) {
+                       signature.append ("?");
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_array_creation_expression (Vala.ArrayCreationExpression expr) {
+               signature.append_keyword ("new");
+               write_type (expr.element_type);
+               signature.append ("[", false);
+
+               bool first = true;
+               foreach (Vala.Expression size in expr.get_sizes ()) {
+                       if (!first) {
+                               signature.append (", ", false);
+                       }
+                       size.accept (this);
+                       first = false;
+               }
+
+               signature.append ("]", false);
+
+               if (expr.initializer_list != null) {
+                       signature.append (" ", false);
+                       expr.initializer_list.accept (this);
+               }
+       }
+
+       public InitializerBuilder (SignatureBuilder signature, Vala.HashMap<Vala.Symbol, Symbol> symbol_map) {
+               this.symbol_map = symbol_map;
+               this.signature = signature;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_binary_expression (Vala.BinaryExpression expr) {
+               expr.left.accept (this);
+
+               switch (expr.operator) {
+               case Vala.BinaryOperator.PLUS:
+                       signature.append ("+ ");
+                       break;
+
+               case Vala.BinaryOperator.MINUS:
+                       signature.append ("- ");
+                       break;
+
+               case Vala.BinaryOperator.MUL:
+                       signature.append ("* ");
+                       break;
+
+               case Vala.BinaryOperator.DIV:
+                       signature.append ("/ ");
+                       break;
+
+               case Vala.BinaryOperator.MOD:
+                       signature.append ("% ");
+                       break;
+
+               case Vala.BinaryOperator.SHIFT_LEFT:
+                       signature.append ("<< ");
+                       break;
+
+               case Vala.BinaryOperator.SHIFT_RIGHT:
+                       signature.append (">> ");
+                       break;
+
+               case Vala.BinaryOperator.LESS_THAN:
+                       signature.append ("< ");
+                       break;
+
+               case Vala.BinaryOperator.GREATER_THAN:
+                       signature.append ("> ");
+                       break;
+
+               case Vala.BinaryOperator.LESS_THAN_OR_EQUAL:
+                       signature.append ("<= ");
+                       break;
+
+               case Vala.BinaryOperator.GREATER_THAN_OR_EQUAL:
+                       signature.append (">= ");
+                       break;
+
+               case Vala.BinaryOperator.EQUALITY:
+                       signature.append ("== ");
+                       break;
+
+               case Vala.BinaryOperator.INEQUALITY:
+                       signature.append ("!= ");
+                       break;
+
+               case Vala.BinaryOperator.BITWISE_AND:
+                       signature.append ("& ");
+                       break;
+
+               case Vala.BinaryOperator.BITWISE_OR:
+                       signature.append ("| ");
+                       break;
+
+               case Vala.BinaryOperator.BITWISE_XOR:
+                       signature.append ("^ ");
+                       break;
+
+               case Vala.BinaryOperator.AND:
+                       signature.append ("&& ");
+                       break;
+
+               case Vala.BinaryOperator.OR:
+                       signature.append ("|| ");
+                       break;
+
+               case Vala.BinaryOperator.IN:
+                       signature.append_keyword ("in");
+                       signature.append (" ");
+                       break;
+
+               case Vala.BinaryOperator.COALESCE:
+                       signature.append ("?? ");
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+
+               expr.right.accept (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_unary_expression (Vala.UnaryExpression expr) {
+               switch (expr.operator) {
+               case Vala.UnaryOperator.PLUS:
+                       signature.append ("+");
+                       break;
+
+               case Vala.UnaryOperator.MINUS:
+                       signature.append ("-");
+                       break;
+
+               case Vala.UnaryOperator.LOGICAL_NEGATION:
+                       signature.append ("!");
+                       break;
+
+               case Vala.UnaryOperator.BITWISE_COMPLEMENT:
+                       signature.append ("~");
+                       break;
+
+               case Vala.UnaryOperator.INCREMENT:
+                       signature.append ("++");
+                       break;
+
+               case Vala.UnaryOperator.DECREMENT:
+                       signature.append ("--");
+                       break;
+
+               case Vala.UnaryOperator.REF:
+                       signature.append_keyword ("ref");
+                       break;
+
+               case Vala.UnaryOperator.OUT:
+                       signature.append_keyword ("out");
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+               expr.inner.accept (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_assignment (Vala.Assignment a) {
+               a.left.accept (this);
+
+               switch (a.operator) {
+               case Vala.AssignmentOperator.SIMPLE:
+                       signature.append ("=");
+                       break;
+
+               case Vala.AssignmentOperator.BITWISE_OR:
+                       signature.append ("|");
+                       break;
+
+               case Vala.AssignmentOperator.BITWISE_AND:
+                       signature.append ("&");
+                       break;
+
+               case Vala.AssignmentOperator.BITWISE_XOR:
+                       signature.append ("^");
+                       break;
+
+               case Vala.AssignmentOperator.ADD:
+                       signature.append ("+");
+                       break;
+
+               case Vala.AssignmentOperator.SUB:
+                       signature.append ("-");
+                       break;
+
+               case Vala.AssignmentOperator.MUL:
+                       signature.append ("*");
+                       break;
+
+               case Vala.AssignmentOperator.DIV:
+                       signature.append ("/");
+                       break;
+
+               case Vala.AssignmentOperator.PERCENT:
+                       signature.append ("%");
+                       break;
+
+               case Vala.AssignmentOperator.SHIFT_LEFT:
+                       signature.append ("<<");
+                       break;
+
+               case Vala.AssignmentOperator.SHIFT_RIGHT:
+                       signature.append (">>");
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+
+               a.right.accept (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_cast_expression (Vala.CastExpression expr) {
+               if (expr.is_non_null_cast) {
+                       signature.append ("(!)");
+                       expr.inner.accept (this);
+                       return;
+               }
+
+               if (!expr.is_silent_cast) {
+                       signature.append ("(", false);
+                       write_type (expr.type_reference);
+                       signature.append (")", false);
+               }
+
+               expr.inner.accept (this);
+
+               if (expr.is_silent_cast) {
+                       signature.append_keyword ("as");
+                       write_type (expr.type_reference);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_initializer_list (Vala.InitializerList list) {
+               signature.append ("{", false);
+
+               bool first = true;
+               foreach (Vala.Expression initializer in list.get_initializers ()) {
+                       if (!first) {
+                               signature.append (", ", false);
+                       }
+                       first = false;
+                       initializer.accept (this);
+               }
+
+               signature.append ("}", false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_member_access (Vala.MemberAccess expr) {
+               if (expr.symbol_reference != null) {
+                       expr.symbol_reference.accept (this);
+               } else {
+                       signature.append (expr.member_name);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_element_access (Vala.ElementAccess expr) {
+               expr.container.accept (this);
+               signature.append ("[", false);
+
+               bool first = true;
+               foreach (Vala.Expression index in expr.get_indices ()) {
+                       if (!first) {
+                               signature.append (", ", false);
+                       }
+                       first = false;
+
+                       index.accept (this);
+               }
+
+               signature.append ("]", false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_pointer_indirection (Vala.PointerIndirection expr) {
+               signature.append ("*", false);
+               expr.inner.accept (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_addressof_expression (Vala.AddressofExpression expr) {
+               signature.append ("&", false);
+               expr.inner.accept (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_reference_transfer_expression (Vala.ReferenceTransferExpression expr) {
+               signature.append ("(", false).append_keyword ("owned", false).append (")", false);
+               expr.inner.accept (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_type_check (Vala.TypeCheck expr) {
+               expr.expression.accept (this);
+               signature.append_keyword ("is");
+               write_type (expr.type_reference);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_method_call (Vala.MethodCall expr) {
+               // symbol-name:
+               expr.call.symbol_reference.accept (this);
+
+               // parameters:
+               signature.append (" (", false);
+               bool first = true;
+               foreach (Vala.Expression literal in expr.get_argument_list ()) {
+                       if (!first) {
+                               signature.append (", ", false);
+                       }
+
+                       literal.accept (this);
+                       first = false;
+               }
+               signature.append (")", false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_slice_expression (Vala.SliceExpression expr) {
+               expr.container.accept (this);
+               signature.append ("[", false);
+               expr.start.accept (this);
+               signature.append (":", false);
+               expr.stop.accept (this);
+               signature.append ("]", false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_base_access (Vala.BaseAccess expr) {
+               signature.append_keyword ("base", false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_postfix_expression (Vala.PostfixExpression expr) {
+               expr.inner.accept (this);
+               if (expr.increment) {
+                       signature.append ("++", false);
+               } else {
+                       signature.append ("--", false);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_object_creation_expression (Vala.ObjectCreationExpression expr) {
+               if (!expr.struct_creation) {
+                       signature.append_keyword ("new");
+               }
+
+               signature.append_symbol (resolve (expr.symbol_reference));
+
+               signature.append (" (", false);
+
+               //TODO: rm conditional space
+               bool first = true;
+               foreach (Vala.Expression arg in expr.get_argument_list ()) {
+                       if (!first) {
+                               signature.append (", ", false);
+                       }
+                       arg.accept (this);
+                       first = false;
+               }
+
+               signature.append (")", false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_sizeof_expression (Vala.SizeofExpression expr) {
+               signature.append_keyword ("sizeof", false).append (" (", false);
+               write_type (expr.type_reference);
+               signature.append (")", false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_typeof_expression (Vala.TypeofExpression expr) {
+               signature.append_keyword ("typeof", false).append (" (", false);
+               write_type (expr.type_reference);
+               signature.append (")", false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_lambda_expression (Vala.LambdaExpression expr) {
+               signature.append ("(", false);
+
+               bool first = true;
+               foreach (Vala.Parameter param in expr.get_parameters ()) {
+                       if (!first) {
+                               signature.append (", ", false);
+                       }
+                       signature.append (param.name, false);
+                       first = false;
+               }
+
+
+               signature.append (") => {", false);
+               signature.append_highlighted (" [...] ", false);
+               signature.append ("}", false);
+       }
+
+
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_boolean_literal (Vala.BooleanLiteral lit) {
+               signature.append_literal (lit.to_string (), false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_character_literal (Vala.CharacterLiteral lit) {
+               signature.append_literal (lit.to_string (), false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_integer_literal (Vala.IntegerLiteral lit) {
+               signature.append_literal (lit.to_string (), false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_real_literal (Vala.RealLiteral lit) {
+               signature.append_literal (lit.to_string (), false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_regex_literal (Vala.RegexLiteral lit) {
+               signature.append_literal (lit.to_string (), false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_string_literal (Vala.StringLiteral lit) {
+               signature.append_literal (lit.to_string (), false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_null_literal (Vala.NullLiteral lit) {
+               signature.append_literal (lit.to_string (), false);
+       }
+
+
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_field (Vala.Field field) {
+               write_node (field);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_constant (Vala.Constant constant) {
+               write_node (constant);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_enum_value (Vala.EnumValue ev) {
+               write_node (ev);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_error_code (Vala.ErrorCode ec) {
+               write_node (ec);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_delegate (Vala.Delegate d) {
+               write_node (d);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_method (Vala.Method m) {
+               write_node (m);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_creation_method (Vala.CreationMethod m) {
+               write_node (m);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_signal (Vala.Signal sig) {
+               write_node (sig);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_class (Vala.Class c) {
+               write_node (c);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_struct (Vala.Struct s) {
+               write_node (s);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_interface (Vala.Interface i) {
+               write_node (i);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_enum (Vala.Enum en) {
+               write_node (en);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_error_domain (Vala.ErrorDomain ed) {
+               write_node (ed);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_property (Vala.Property prop) {
+               write_node (prop);
+       }
+}
+
diff --git a/valadoc/symbolresolver.vala b/valadoc/symbolresolver.vala
new file mode 100644
index 0000000..b60de16
--- /dev/null
+++ b/valadoc/symbolresolver.vala
@@ -0,0 +1,322 @@
+/* symbolresolver.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.Api;
+
+public class Valadoc.Drivers.SymbolResolver : Visitor {
+       private Vala.HashMap<Vala.Symbol, Symbol> symbol_map;
+       private Valadoc.Api.Class glib_error;
+       private Api.Tree root;
+
+       public SymbolResolver (TreeBuilder builder) {
+               this.symbol_map = builder.get_symbol_map ();
+               this.glib_error = builder.get_glib_error ();
+       }
+
+       public Symbol? resolve (Vala.Symbol symbol) {
+               return symbol_map.get (symbol);
+       }
+
+       private void resolve_thrown_list (Symbol symbol, Vala.List<Vala.DataType> types) {
+               foreach (Vala.DataType type in types) {
+                       Vala.ErrorDomain vala_edom = (Vala.ErrorDomain) type.data_type;
+                       Symbol? edom = symbol_map.get (vala_edom);
+                       symbol.add_child (edom ?? glib_error);
+               }
+       }
+
+       private void resolve_array_type_references (Api.Array ptr) {
+               Api.Item data_type = ptr.data_type;
+               if (data_type == null) {
+                       // void
+               } else if (data_type is Api.Array) {
+                       resolve_array_type_references ((Api.Array) data_type);
+               } else if (data_type is Pointer) {
+                       resolve_pointer_type_references ((Api.Pointer) data_type);
+               } else {
+                       resolve_type_reference ((TypeReference) data_type);
+               }
+       }
+
+       private void resolve_pointer_type_references (Pointer ptr) {
+               Api.Item type = ptr.data_type;
+               if (type == null) {
+                       // void
+               } else if (type is Api.Array) {
+                       resolve_array_type_references ((Api.Array) type);
+               } else if (type is Pointer) {
+                       resolve_pointer_type_references ((Pointer) type);
+               } else {
+                       resolve_type_reference ((TypeReference) type);
+               }
+       }
+
+       private void resolve_type_reference (TypeReference reference) {
+               Vala.DataType vtyperef = (Vala.DataType) reference.data;
+               if (vtyperef is Vala.ErrorType) {
+                       Vala.ErrorDomain verrdom = ((Vala.ErrorType) vtyperef).error_domain;
+                       if (verrdom != null) {
+                               reference.data_type = resolve (verrdom);
+                       } else {
+                               reference.data_type = glib_error;
+                       }
+               } else if (vtyperef is Vala.DelegateType) {
+                       reference.data_type = resolve (((Vala.DelegateType) vtyperef).delegate_symbol);
+               } else if (vtyperef is Vala.GenericType) {
+                       reference.data_type = resolve (((Vala.GenericType) vtyperef).type_parameter);
+               } else if (vtyperef.data_type != null) {
+                       reference.data_type = resolve (vtyperef.data_type);
+               }
+
+               // Type parameters:
+               foreach (TypeReference type_param_ref in reference.get_type_arguments ()) {
+                       resolve_type_reference (type_param_ref);
+               }
+
+               if (reference.data_type is Pointer) {
+                       resolve_pointer_type_references ((Pointer)reference.data_type);
+               } else if (reference.data_type is Api.Array) {
+                       resolve_array_type_references ((Api.Array)reference.data_type);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_tree (Api.Tree item) {
+               this.root = item;
+               item.accept_children (this);
+               this.root = null;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_package (Package item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_namespace (Namespace item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_interface (Interface item) {
+               Vala.Collection<TypeReference> interfaces = item.get_implemented_interface_list ();
+               foreach (var type_ref in interfaces) {
+                       resolve_type_reference (type_ref);
+               }
+
+               if (item.base_type != null) {
+                       resolve_type_reference (item.base_type);
+               }
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_class (Class item) {
+               Vala.Collection<TypeReference> interfaces = item.get_implemented_interface_list ();
+               foreach (TypeReference type_ref in interfaces) {
+                       resolve_type_reference (type_ref);
+               }
+
+               if (item.base_type != null)     {
+                       resolve_type_reference (item.base_type);
+               }
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_struct (Struct item) {
+               if (item.base_type != null) {
+                       resolve_type_reference (item.base_type);
+               }
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_property (Property item) {
+               Vala.Property vala_property = item.data as Vala.Property;
+               Vala.Property? base_vala_property = null;
+
+               if (vala_property.base_property != null) {
+                       base_vala_property = vala_property.base_property;
+               } else if (vala_property.base_interface_property != null) {
+                       base_vala_property = vala_property.base_interface_property;
+               }
+               if (base_vala_property == vala_property && vala_property.base_interface_property != null) {
+                       base_vala_property = vala_property.base_interface_property;
+               }
+               if (base_vala_property != null) {
+                       item.base_property = (Property?) resolve (base_vala_property);
+               }
+
+               resolve_type_reference (item.property_type);
+               
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_field (Field item) {
+               resolve_type_reference (item.field_type);
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_constant (Constant item) {
+               resolve_type_reference (item.constant_type);
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_delegate (Delegate item) {
+               Vala.Delegate vala_delegate = item.data as Vala.Delegate;
+
+               resolve_type_reference (item.return_type);
+
+               resolve_thrown_list (item, vala_delegate.get_error_types ());
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_signal (Api.Signal item) {
+               resolve_type_reference (item.return_type);
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_method (Method item) {
+               Vala.Method vala_method = item.data as Vala.Method;
+               Vala.Method? base_vala_method = null;
+               if (vala_method.base_method != null) {
+                       base_vala_method = vala_method.base_method;
+               } else if (vala_method.base_interface_method != null) {
+                       base_vala_method = vala_method.base_interface_method;
+               }
+               if (base_vala_method == vala_method && vala_method.base_interface_method != null) {
+                       base_vala_method = vala_method.base_interface_method;
+               }
+               if (base_vala_method != null) {
+                       item.base_method = (Method?) resolve (base_vala_method);
+               }
+
+               resolve_thrown_list (item, vala_method.get_error_types ());
+
+               resolve_type_reference (item.return_type);
+
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_type_parameter (TypeParameter item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_formal_parameter (FormalParameter item) {
+               if (item.ellipsis) {
+                       return;
+               }
+
+               if (((Vala.Parameter) item.data).initializer != null) {
+                       SignatureBuilder signature = new SignatureBuilder ();
+                       InitializerBuilder ibuilder = new InitializerBuilder (signature, symbol_map);
+                       ((Vala.Parameter) item.data).initializer.accept (ibuilder);
+                       item.default_value = signature.get ();
+               }
+
+               resolve_type_reference (item.parameter_type);
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_error_domain (ErrorDomain item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_error_code (ErrorCode item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_enum (Enum item) {
+               item.accept_all_children (this, false);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_enum_value (Api.EnumValue item) {
+
+               if (((Vala.EnumValue) item.data).value != null) {
+                       SignatureBuilder signature = new SignatureBuilder ();
+                       InitializerBuilder ibuilder = new InitializerBuilder (signature, symbol_map);
+                       ((Vala.EnumValue) item.data).value.accept (ibuilder);
+                       item.default_value = signature.get ();
+               }
+
+               item.accept_all_children (this, false);
+       }
+}
+
+
+
diff --git a/valadoc/tests/Makefile.am b/valadoc/tests/Makefile.am
new file mode 100644
index 0000000..8ce2e69
--- /dev/null
+++ b/valadoc/tests/Makefile.am
@@ -0,0 +1,34 @@
+NULL =
+
+AM_CPPFLAGS = \
+       $(GLIB_CFLAGS) \
+       $(NULL)
+
+AM_LDFLAGS = \
+       $(GLIB_LIBS) \
+       $(NULL)
+
+TESTS_ENVIRONMENT = EXEEXT=$(EXEEXT) PACKAGE_SUFFIX=$(PACKAGE_SUFFIX) TOPBUILDDIR=$(abs_top_builddir) 
TOPSRCDIR=$(abs_top_srcdir) $(srcdir)/testrunner.sh
+
+TESTS = \
+       libvaladoc/errorreporter.vala \
+       libvaladoc/markupreader.vala \
+       libvaladoc/gtkdoc-scanner.vala \
+       libvaladoc/parser/manyrule.vala \
+       libvaladoc/parser/oneofrule.vala \
+       libvaladoc/parser/sequencerule.vala \
+       libvaladoc/parser/optionalrule.vala \
+       libvaladoc/parser/stubrule.vala \
+       $(NULL)
+
+check-TESTS: $(TESTS)
+       @EXEEXT=$(EXEEXT) PACKAGE_SUFFIX=$(PACKAGE_SUFFIX) TOPBUILDDIR=$(abs_top_builddir) 
TOPSRCDIR=$(abs_top_srcdir) $(srcdir)/testrunner.sh $(TESTS)
+
+EXTRA_DIST = \
+       testrunner.sh \
+       drivers/api-test.data.vapi \
+       drivers/generic-api-test.vala \
+       libvaladoc/parser/generic-scanner.vala \
+       $(TESTS) \
+       $(NULL)
+
diff --git a/valadoc/tests/drivers/api-test.data.vapi b/valadoc/tests/drivers/api-test.data.vapi
new file mode 100644
index 0000000..3c696f4
--- /dev/null
+++ b/valadoc/tests/drivers/api-test.data.vapi
@@ -0,0 +1,151 @@
+
+
+using GLib;
+
+/*
+       Todo:
+               - private / protected / internal
+               - comments
+               - parent
+               - inheritance, interface impl
+                       - virtual, abstract, override
+               - generics
+*/
+
+
+// global tests:
+public delegate void test_delegate_global ();
+public void test_function_global ();
+public int test_field_global;
+public const int test_const_global;
+
+
+// Checked
+public errordomain TestErrDomGlobal {
+       ERROR1,
+       ERROR2;
+
+       public void method ();
+       public static void static_method ();
+}
+
+
+// Checked
+public enum TestEnumGlobal {
+       ENVAL1 = 100,
+       ENVAL2;
+
+       public void method ();
+       public static void static_method ();
+}
+
+
+// Checked
+public class TestClassGlobal {
+       public class InnerClass {
+       }
+
+       public struct InnerStruct {
+       }
+
+       public const int constant;
+       public static int field1;
+       public int field2;
+       public TestClassGlobal ();
+       public TestClassGlobal.named ();
+       public void method ();
+       public static void static_method ();
+       public int property1 { get; set; }
+       public int property2 { get; }
+       public int property3 { owned get; construct set; }
+       public delegate int Foo ();
+       public signal int sig ();
+}
+
+
+// Checked
+public interface TestInterfaceGlobal {
+       public const int constant;
+       public void method ();
+       public static void static_method ();
+       public int property1 { get; set; }
+       public int property2 { get; }
+       public int property3 { owned get; construct set; }
+       public delegate int Foo ();
+       public signal int sig ();
+}
+
+
+// Checked
+public struct TestStructGlobal {
+       public static int field1;
+       public int field2;
+       public TestStructGlobal ();
+       public TestStructGlobal.named ();
+       public void method ();
+       public static void static_method ();
+       public const int constant;
+}
+
+
+namespace ParamTest {
+       public void test_function_param_1 ();
+       public void test_function_param_2 (int a);
+       public void test_function_param_3 (ref int a);
+       public void test_function_param_4 (out int a);
+       public void test_function_param_5 (owned Object o);
+       public void test_function_param_6 (int? a);
+       public void test_function_param_7 (...);
+       public void test_function_param_8 (int a = 1);
+       public void test_function_param_9 (int a, ref int b, out int c, owned Object d, int? e, int f = 1, 
...);
+
+       public void test_function_param_10 (int* a);
+       public void test_function_param_11 (int** a);
+
+       public void test_function_param_12 (int[] a);
+       public void test_function_param_13 (int[,,] a);
+       public void test_function_param_14 (int[][] a);
+}
+
+
+namespace ReturnTest {
+       public void test_function_1 ();
+       public int test_function_2 ();
+       public int? test_function_3 ();
+       public unowned string test_function_4 ();
+
+       public int* test_function_5 ();
+       public int** test_function_6 ();
+
+       public int[] test_function_7 ();
+       public int[,,] test_function_8 ();
+       public int[][] test_function_9 ();
+}
+
+
+namespace VersionTest {
+       [Deprecated]
+       public void test_function_1 ();
+       [Deprecated (since = "1.0", replacement = "test_function_4")]
+       public void test_function_2 ();
+
+       [Experimental]
+       public void test_function_3 ();
+
+#if VALA_0_32
+       [Version (since = "2.0")]
+       public void test_function_4 ();
+       [Version (deprecated = true)]
+       public void test_function_5 ();
+       [Version (deprecated = true, deprecated_since = "2.0", replacement = "test_function_4", since = 
"1.0")]
+       public void test_function_6 ();
+       [Version (deprecated_since = "2.0")]
+       public void test_function_7 ();
+       [Version (deprecated = false)]
+       public void test_function_8 ();
+       [Version (experimental = true)]
+       public void test_function_9 ();
+#endif
+}
+
+
diff --git a/valadoc/tests/drivers/generic-api-test.vala b/valadoc/tests/drivers/generic-api-test.vala
new file mode 100644
index 0000000..3347bcb
--- /dev/null
+++ b/valadoc/tests/drivers/generic-api-test.vala
@@ -0,0 +1,2786 @@
+/* api-test.vala
+ *
+ * Copyright (C) 2013  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;
+
+[CCode (name = "TOP_SRC_DIR")]
+extern const string TOP_SRC_DIR;
+
+
+public static void test_enum_global (Api.Enum? en, Api.Package pkg, Api.Namespace global_ns) {
+       assert (en != null);
+
+       // (.Enum check)
+       assert (en.get_cname () == "TestEnumGlobal");
+       // (.TypeSymbol check)
+       assert (en.is_basic_type == false);
+       // (.Symbol check)
+       assert (en.is_deprecated == false);
+       assert (en.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (en.get_full_name () == "TestEnumGlobal");
+       assert (en.get_filename () == "api-test.data.vapi");
+       assert (en.name == "TestEnumGlobal");
+       assert (en.nspace == global_ns);
+       assert (en.package == pkg);
+
+
+       Vala.List<Api.Node> enumvalues = en.get_children_by_type (Api.NodeType.ENUM_VALUE, false);
+       assert (enumvalues.size == 2);
+
+
+       bool enval1 = false;
+       bool enval2 = false;
+
+       foreach (Api.Node node in enumvalues) {
+               Api.EnumValue enval = node as Api.EnumValue;
+               assert (enval != null);
+
+               switch (enval.name) {
+               case "ENVAL1":
+                       // (.EnumValue)
+                       assert (enval.default_value != null);
+                       assert (enval.has_default_value == true);
+                       assert (enval.get_cname () == "TEST_ENUM_GLOBAL_ENVAL1");
+                       // (.Symbol check)
+                       assert (enval.is_deprecated == false);
+                       assert (enval.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (enval.get_full_name () == "TestEnumGlobal.ENVAL1");
+                       assert (enval.get_filename () == "api-test.data.vapi");
+                       assert (enval.nspace == global_ns);
+                       assert (enval.package == pkg);
+
+                       enval1 = true;
+                       break;
+
+               case "ENVAL2":
+                       // (.EnumValue)
+                       assert (enval.default_value == null);
+                       assert (enval.has_default_value == false);
+                       assert (enval.get_cname () == "TEST_ENUM_GLOBAL_ENVAL2");
+                       // (.Symbol check)
+                       assert (enval.is_deprecated == false);
+                       assert (enval.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (enval.get_full_name () == "TestEnumGlobal.ENVAL2");
+                       assert (enval.get_filename () == "api-test.data.vapi");
+                       assert (enval.nspace == global_ns);
+                       assert (enval.package == pkg);
+
+                       enval2 = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (enval1 == true);
+       assert (enval2 == true);
+
+
+
+       Vala.List<Api.Node> methods = en.get_children_by_type (Api.NodeType.METHOD, false);
+       assert (methods.size == 1);
+
+       Api.Method method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_enum_global_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == false);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestEnumGlobal.method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+
+       methods = en.get_children_by_type (Api.NodeType.STATIC_METHOD, false);
+       assert (methods.size == 1);
+
+       method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_enum_global_static_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == true);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestEnumGlobal.static_method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "static_method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+       Api.NodeType[] forbidden = {
+                       Api.NodeType.CLASS,
+                       Api.NodeType.CONSTANT,
+                       Api.NodeType.CREATION_METHOD,
+                       Api.NodeType.DELEGATE,
+                       Api.NodeType.ENUM,
+                       Api.NodeType.ERROR_CODE,
+                       Api.NodeType.ERROR_DOMAIN,
+                       Api.NodeType.FIELD,
+                       Api.NodeType.FORMAL_PARAMETER,
+                       Api.NodeType.INTERFACE,
+                       Api.NodeType.NAMESPACE,
+                       Api.NodeType.PACKAGE,
+                       Api.NodeType.PROPERTY,
+                       Api.NodeType.PROPERTY_ACCESSOR,
+                       Api.NodeType.SIGNAL,
+                       Api.NodeType.STRUCT,
+                       Api.NodeType.TYPE_PARAMETER
+               };
+
+       Vala.List<Api.Node> nodes = en.get_children_by_types (forbidden, false);        
+       assert (nodes.size == 0);
+}
+
+
+public static void test_erroromain_global (Api.ErrorDomain? err, Api.Package pkg, Api.Namespace global_ns) {
+       assert (err != null);
+
+       // (.ErrorDomain check)
+       assert (err.get_cname () == "TestErrDomGlobal");
+       //assert (err.get_dbus_name () == "");
+       // (.TypeSymbol check)
+       assert (err.is_basic_type == false);
+       // (.Symbol check)
+       assert (err.is_deprecated == false);
+       assert (err.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (err.get_full_name () == "TestErrDomGlobal");
+       assert (err.get_filename () == "api-test.data.vapi");
+       assert (err.name == "TestErrDomGlobal");
+       assert (err.nspace == global_ns);
+       assert (err.package == pkg);
+
+
+       Vala.List<Api.Node> errcodes = err.get_children_by_type (Api.NodeType.ERROR_CODE, false);
+       assert (errcodes.size == 2);
+
+
+       bool errc1 = false;
+       bool errc2 = false;
+
+       foreach (Api.Node node in errcodes) {
+               Api.ErrorCode errc = node as Api.ErrorCode;
+               assert (errc != null);
+
+               switch (errc.name) {
+               case "ERROR1":
+                       // (.EnumValue)
+                       assert (errc.get_cname () == "TEST_ERR_DOM_GLOBAL_ERROR1");
+                       // (.Symbol check)
+                       assert (errc.is_deprecated == false);
+                       assert (errc.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (errc.get_full_name () == "TestErrDomGlobal.ERROR1");
+                       assert (errc.get_filename () == "api-test.data.vapi");
+                       assert (errc.nspace == global_ns);
+                       assert (errc.package == pkg);
+
+                       errc1 = true;
+                       break;
+
+               case "ERROR2":
+                       // (.EnumValue)
+                       assert (errc.get_cname () == "TEST_ERR_DOM_GLOBAL_ERROR2");
+                       // (.Symbol check)
+                       assert (errc.is_deprecated == false);
+                       assert (errc.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (errc.get_full_name () == "TestErrDomGlobal.ERROR2");
+                       assert (errc.get_filename () == "api-test.data.vapi");
+                       assert (errc.nspace == global_ns);
+                       assert (errc.package == pkg);
+
+                       errc2 = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (errc1 == true);
+       assert (errc2 == true);
+
+
+
+       Vala.List<Api.Node> methods = err.get_children_by_type (Api.NodeType.METHOD, false);
+       assert (methods.size == 1);
+
+       Api.Method method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_err_dom_global_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == false);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestErrDomGlobal.method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+
+       methods = err.get_children_by_type (Api.NodeType.STATIC_METHOD, false);
+       assert (methods.size == 1);
+
+       method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_err_dom_global_static_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == true);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestErrDomGlobal.static_method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "static_method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+       Api.NodeType[] forbidden = {
+                       Api.NodeType.CLASS,
+                       Api.NodeType.CONSTANT,
+                       Api.NodeType.CREATION_METHOD,
+                       Api.NodeType.DELEGATE,
+                       Api.NodeType.ENUM,
+                       Api.NodeType.ENUM_VALUE,
+                       Api.NodeType.ERROR_DOMAIN,
+                       Api.NodeType.FIELD,
+                       Api.NodeType.FORMAL_PARAMETER,
+                       Api.NodeType.INTERFACE,
+                       Api.NodeType.NAMESPACE,
+                       Api.NodeType.PACKAGE,
+                       Api.NodeType.PROPERTY,
+                       Api.NodeType.PROPERTY_ACCESSOR,
+                       Api.NodeType.SIGNAL,
+                       Api.NodeType.STRUCT,
+                       Api.NodeType.TYPE_PARAMETER
+               };
+
+       Vala.List<Api.Node> nodes = err.get_children_by_types (forbidden, false);       
+       assert (nodes.size == 0);
+}
+
+
+public static void test_class_global (Api.Class? cl, Api.Package pkg, Api.Namespace global_ns) {
+       assert (cl != null);
+
+       // (.Class check)
+       assert (cl.base_type == null);
+       assert (cl.get_cname () == "TestClassGlobal");
+       assert (cl.get_type_id () == "TYPE_TEST_CLASS_GLOBAL");
+       assert (cl.get_ref_function_cname () == "test_class_global_ref");
+       assert (cl.get_unref_function_cname () == "test_class_global_unref");
+       assert (cl.get_param_spec_function_cname () == "param_spec_test_class_global");
+       assert (cl.get_set_value_function_cname () == "value_set_test_class_global");
+       assert (cl.get_get_value_function_cname () == "value_get_test_class_global");
+       assert (cl.get_take_value_function_cname () == "value_take_test_class_global");
+       assert (cl.get_dbus_name () == null);
+       assert (cl.get_implemented_interface_list ().size == 0);
+       assert (cl.get_full_implemented_interface_list ().size == 0);
+       assert (cl.is_abstract == false);
+       assert (cl.is_fundamental == true);
+       // (.Symbol check)
+       assert (cl.is_deprecated == false);
+       assert (cl.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       //assert (property.getter.get_full_name () == "TestClassGlobal.property3");
+       assert (cl.get_full_name () == "TestClassGlobal");
+       assert (cl.get_filename () == "api-test.data.vapi");
+       assert (cl.name == "TestClassGlobal");
+       assert (cl.nspace == global_ns);
+       assert (cl.package == pkg);
+
+
+       Vala.List<Api.Node> methods = cl.get_children_by_type (Api.NodeType.METHOD, false);
+       assert (methods.size == 1);
+
+       Api.Method method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_class_global_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == false);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestClassGlobal.method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+
+       methods = cl.get_children_by_type (Api.NodeType.STATIC_METHOD, false);
+       assert (methods.size == 1);
+
+       method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_class_global_static_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == true);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestClassGlobal.static_method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "static_method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+
+       methods = cl.get_children_by_type (Api.NodeType.CREATION_METHOD, false);
+       bool default_constr = false;
+       bool named_constr = false;
+
+       foreach (Api.Node node in methods) {
+               method = node as Api.Method;
+               assert (method != null);
+
+               switch (method.name) {
+                       case "TestClassGlobal":
+                               // (.Method check)
+                               assert (method.get_cname () == "test_class_global_new");
+                               //assert (method.get_dbus_name () == null);
+                               //assert (method.get_dbus_result_name () == null);
+                               //assert (method.is_dbus_visible == false);
+                               assert (method.base_method == null);
+                               assert (method.is_yields == false);
+                               assert (method.is_abstract == false);
+                               assert (method.is_virtual == false);
+                               assert (method.is_override == false);
+                               assert (method.is_static == false);
+                               assert (method.is_constructor == true);
+                               assert (method.is_inline == false);
+                               // (.Symbol check)
+                               assert (method.is_deprecated == false);
+                               assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+                               // (.Node)
+                               assert (method.get_full_name () == "TestClassGlobal.TestClassGlobal");
+                               assert (method.get_filename () == "api-test.data.vapi");
+                               assert (method.nspace == global_ns);
+                               assert (method.package == pkg);
+
+                               default_constr = true;
+                               break;
+
+                       case "TestClassGlobal.named":
+                               // (.Method check)
+                               assert (method.get_cname () == "test_class_global_new_named");
+                               //assert (method.get_dbus_name () == null);
+                               //assert (method.get_dbus_result_name () == null);
+                               //assert (method.is_dbus_visible == false);
+                               assert (method.base_method == null);
+                               assert (method.is_yields == false);
+                               assert (method.is_abstract == false);
+                               assert (method.is_virtual == false);
+                               assert (method.is_override == false);
+                               assert (method.is_static == false);
+                               assert (method.is_constructor == true);
+                               assert (method.is_inline == false);
+                               // (.Symbol check)
+                               assert (method.is_deprecated == false);
+                               assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+                               // (.Node)
+                               assert (method.get_full_name () == "TestClassGlobal.TestClassGlobal.named");
+                               assert (method.get_filename () == "api-test.data.vapi");
+                               assert (method.nspace == global_ns);
+                               assert (method.package == pkg);
+
+                               named_constr = true;
+                               break;
+
+                       default:
+                               assert_not_reached ();
+               }
+       }
+
+       assert (default_constr == true);
+       assert (named_constr == true);
+
+
+
+       Vala.List<Api.Node> properties = cl.get_children_by_type (Api.NodeType.PROPERTY, false);
+       bool prop1 = false;
+       bool prop2 = false;
+       bool prop3 = false;
+
+       foreach (Api.Node node in properties) {
+               Api.Property property = node as Api.Property;
+               assert (property != null);
+
+               switch (property.name) {
+               case "property1":
+                       assert (property.get_cname () == "property1");
+                       assert (property.property_type != null);
+                       assert (property.is_virtual == false);
+                       assert (property.is_abstract == false);
+                       assert (property.is_override == false);
+                       assert (property.is_dbus_visible == true);
+                       assert (property.setter != null);
+                       assert (property.getter != null);
+                       assert (property.base_property == null);
+                       // (.Symbol check)
+                       assert (property.is_deprecated == false);
+                       assert (property.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (property.get_full_name () == "TestClassGlobal.property1");
+                       assert (property.get_filename () == "api-test.data.vapi");
+                       assert (property.nspace == global_ns);
+                       assert (property.package == pkg);
+
+
+                       assert (property.getter.get_cname () == "test_class_global_get_property1");
+                       assert (property.getter.is_construct == false);
+                       assert (property.getter.is_set == false);
+                       assert (property.getter.is_get == true);
+                       assert (property.getter.is_owned == false);
+                       // (.Symbol check)
+                       assert (property.getter.is_deprecated == false);
+                       assert (property.getter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestClassGlobal.property2");
+                       assert (property.getter.get_filename () == "api-test.data.vapi");
+                       assert (property.getter.nspace == global_ns);
+                       assert (property.getter.package == pkg);
+
+
+                       assert (property.setter.get_cname () == "test_class_global_set_property1");
+                       assert (property.setter.is_construct == false);
+                       assert (property.setter.is_get == false);
+                       assert (property.setter.is_set == true);
+                       assert (property.setter.is_owned == false);
+                       // (.Symbol check)
+                       assert (property.setter.is_deprecated == false);
+                       assert (property.setter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestClassGlobal.property2");
+                       assert (property.setter.get_filename () == "api-test.data.vapi");
+                       assert (property.setter.nspace == global_ns);
+                       assert (property.setter.package == pkg);
+
+                       prop1 = true;
+                       break;
+
+               case "property2":
+                       assert (property.get_cname () == "property2");
+                       assert (property.property_type != null);
+                       assert (property.is_virtual == false);
+                       assert (property.is_abstract == false);
+                       assert (property.is_override == false);
+                       assert (property.is_dbus_visible == true);
+                       assert (property.setter == null);
+                       assert (property.getter != null);
+                       assert (property.base_property == null);
+                       // (.Symbol check)
+                       assert (property.is_deprecated == false);
+                       assert (property.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (property.get_full_name () == "TestClassGlobal.property2");
+                       assert (property.get_filename () == "api-test.data.vapi");
+                       assert (property.nspace == global_ns);
+                       assert (property.package == pkg);
+
+                       assert (property.getter.get_cname () == "test_class_global_get_property2");
+                       assert (property.getter.is_construct == false);
+                       assert (property.getter.is_set == false);
+                       assert (property.getter.is_get == true);
+                       assert (property.getter.is_owned == false);
+                       // (.Symbol check)
+                       assert (property.getter.is_deprecated == false);
+                       assert (property.getter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestClassGlobal.property2");
+                       assert (property.getter.get_filename () == "api-test.data.vapi");
+                       assert (property.getter.nspace == global_ns);
+                       assert (property.getter.package == pkg);
+
+                       prop2 = true;
+                       break;
+
+
+               case "property3":
+                       assert (property.get_cname () == "property3");
+                       assert (property.property_type != null);
+                       assert (property.is_virtual == false);
+                       assert (property.is_abstract == false);
+                       assert (property.is_override == false);
+                       assert (property.is_dbus_visible == true);
+                       assert (property.setter != null);
+                       assert (property.getter != null);
+                       assert (property.base_property == null);
+                       // (.Symbol check)
+                       assert (property.is_deprecated == false);
+                       assert (property.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (property.get_full_name () == "TestClassGlobal.property3");
+                       assert (property.get_filename () == "api-test.data.vapi");
+                       assert (property.nspace == global_ns);
+                       assert (property.package == pkg);
+
+                       assert (property.getter.get_cname () == "test_class_global_get_property3");
+                       assert (property.getter.is_construct == false);
+                       assert (property.getter.is_set == false);
+                       assert (property.getter.is_get == true);
+                       assert (property.getter.is_owned == true);
+                       // (.Symbol check)
+                       assert (property.getter.is_deprecated == false);
+                       assert (property.getter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestClassGlobal.property3");
+                       assert (property.getter.get_filename () == "api-test.data.vapi");
+                       assert (property.getter.nspace == global_ns);
+                       assert (property.getter.package == pkg);
+
+
+                       assert (property.setter.get_cname () == "test_class_global_set_property3");
+                       assert (property.setter.is_construct == true);
+                       assert (property.setter.is_get == false);
+                       assert (property.setter.is_set == true);
+                       assert (property.setter.is_owned == false);
+                       // (.Symbol check)
+                       assert (property.setter.is_deprecated == false);
+                       assert (property.setter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestClassGlobal.property3");
+                       assert (property.setter.get_filename () == "api-test.data.vapi");
+                       assert (property.setter.nspace == global_ns);
+                       assert (property.setter.package == pkg);
+
+
+                       prop3 = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+       assert (prop1);
+       assert (prop2);
+       assert (prop3);
+
+
+       Vala.List<Api.Node> delegates = cl.get_children_by_type (Api.NodeType.DELEGATE, false);
+       assert (delegates.size == 1);
+
+       Api.Delegate del = delegates.get (0) as Api.Delegate;
+       assert (del != null);
+
+       // (.Delegate check)
+       assert (del.get_cname () == "TestClassGlobalFoo");
+       assert (del.return_type != null);
+       assert (del.is_static == false);
+       // (.Symbol check)
+       assert (del.is_deprecated == false);
+       assert (del.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       //assert (property.getter.get_full_name () == "TestClassGlobal.property3");
+       assert (del.get_filename () == "api-test.data.vapi");
+       assert (del.nspace == global_ns);
+       assert (del.package == pkg);
+
+
+
+       Vala.List<Api.Node> signals = cl.get_children_by_type (Api.NodeType.SIGNAL, false);
+       assert (signals.size == 1);
+
+       Api.Signal sig = signals.get (0) as Api.Signal;
+       assert (sig != null);
+
+       // (.Signal check)
+       assert (sig.get_cname () == "sig");
+       assert (sig.is_virtual == false);
+       assert (sig.return_type != null);
+       //assert (sig.is_static == false);
+       // (.Symbol check)
+       assert (sig.is_deprecated == false);
+       assert (sig.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       //assert (sig.get_full_name () == "TestClassGlobal.property3");
+       assert (sig.get_filename () == "api-test.data.vapi");
+       assert (sig.nspace == global_ns);
+       assert (sig.package == pkg);
+
+
+
+       Vala.List<Api.Node> constants = cl.get_children_by_type (Api.NodeType.CONSTANT, false);
+       assert (constants.size == 1);
+
+       Api.Constant constant = constants.get (0) as Api.Constant;
+       assert (constant != null);
+       // (.Constant check)
+       assert (constant.get_cname () == "TEST_CLASS_GLOBAL_constant");
+       // (.Symbol check)
+       assert (constant.is_deprecated == false);
+       assert (constant.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (constant.get_full_name () == "TestClassGlobal.constant");
+       assert (constant.get_filename () == "api-test.data.vapi");
+       assert (constant.name == "constant");
+       assert (constant.nspace == global_ns);
+       assert (constant.package == pkg);
+
+
+       Vala.List<Api.Node> fields = cl.get_children_by_type (Api.NodeType.FIELD, false);
+
+       bool field1 = false;
+       bool field2 = false;
+       foreach (Api.Node node in fields) {
+               Api.Field field = node as Api.Field;
+               assert (field != null);
+
+               switch (field.name) {
+               case "field1":
+                       // (.Field check)
+                       assert (field.get_cname () == "test_class_global_field1");
+                       assert (field.is_static == true);
+                       assert (field.is_volatile == false);
+                       // (.Symbol check)
+                       assert (field.is_deprecated == false);
+                       assert (field.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (field.get_full_name () == "TestClassGlobal.field1");
+                       assert (field.get_filename () == "api-test.data.vapi");
+                       assert (field.nspace == global_ns);
+                       assert (field.package == pkg);
+
+                       field1 = true;
+                       break;
+
+               case "field2":
+                       // (.Field check)
+                       assert (field.get_cname () == "field2");        
+                       assert (field.is_static == false);
+                       assert (field.is_volatile == false);
+                       // (.Symbol check)
+                       assert (field.is_deprecated == false);
+                       assert (field.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (field.get_full_name () == "TestClassGlobal.field2");
+                       assert (field.get_filename () == "api-test.data.vapi");
+                       assert (field.nspace == global_ns);
+                       assert (field.package == pkg);
+
+                       field2 = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (field1 == true);
+       assert (field2 == true);
+
+
+
+       Vala.List<Api.Node> classes = cl.get_children_by_type (Api.NodeType.CLASS, false);
+       assert (classes.size == 1);
+
+       Api.Class? subcl = classes.get (0) as Api.Class;
+       assert (subcl != null);
+       assert (subcl.base_type == null);
+       // (.Symbol check)
+       assert (subcl.is_deprecated == false);
+       assert (subcl.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (subcl.get_full_name () == "TestClassGlobal.InnerClass");
+       assert (subcl.get_filename () == "api-test.data.vapi");
+       assert (subcl.nspace == global_ns);
+       assert (subcl.package == pkg);
+
+
+
+       Vala.List<Api.Node> structs = cl.get_children_by_type (Api.NodeType.STRUCT, false);
+       assert (structs.size == 1);
+
+       Api.Struct? substru = structs.get (0) as Api.Struct;
+       assert (substru != null);
+       // (.Struct check)
+       assert (substru.base_type == null);
+       assert (substru.get_cname () == "TestClassGlobalInnerStruct");
+       assert (substru.get_free_function_cname () == null);
+       assert (substru.get_dup_function_cname () == null);
+       assert (substru.get_type_id () == null);
+       // (.Symbol check)
+       assert (substru.is_deprecated == false);
+       assert (substru.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (substru.get_full_name () == "TestClassGlobal.InnerStruct");
+       assert (substru.get_filename () == "api-test.data.vapi");
+       assert (substru.name == "InnerStruct");
+       assert (substru.nspace == global_ns);
+       assert (substru.package == pkg);
+
+
+       Api.NodeType[] forbidden = {
+                       Api.NodeType.ENUM,
+                       Api.NodeType.ENUM_VALUE,
+                       Api.NodeType.ERROR_CODE,
+                       Api.NodeType.ERROR_DOMAIN,
+                       Api.NodeType.FORMAL_PARAMETER,
+                       Api.NodeType.INTERFACE,
+                       Api.NodeType.NAMESPACE,
+                       Api.NodeType.PACKAGE,
+                       Api.NodeType.PROPERTY_ACCESSOR,
+                       Api.NodeType.TYPE_PARAMETER
+               };
+
+       Vala.List<Api.Node> nodes = cl.get_children_by_types (forbidden, false);        
+       assert (nodes.size == 0);
+}
+
+
+public static void test_interface_global (Api.Interface? iface, Api.Package pkg, Api.Namespace global_ns) {
+       assert (iface != null);
+
+       // (.Interface check)
+       assert (iface.base_type == null);
+       assert (iface.get_implemented_interface_list ().size == 0);
+       assert (iface.get_full_implemented_interface_list ().size == 0);
+       assert (iface.get_cname () == "TestInterfaceGlobal");
+       assert (iface.get_dbus_name () == null);
+       // (.Symbol check)
+       assert (iface.is_deprecated == false);
+       assert (iface.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (iface.get_full_name () == "TestInterfaceGlobal");
+       assert (iface.get_filename () == "api-test.data.vapi");
+       assert (iface.name == "TestInterfaceGlobal");
+       assert (iface.nspace == global_ns);
+       assert (iface.package == pkg);
+
+
+       Vala.List<Api.Node> methods = iface.get_children_by_type (Api.NodeType.METHOD, false);
+       assert (methods.size == 1);
+
+       Api.Method method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_interface_global_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == false);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestInterfaceGlobal.method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+
+       methods = iface.get_children_by_type (Api.NodeType.STATIC_METHOD, false);
+       assert (methods.size == 1);
+
+       method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_interface_global_static_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == true);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestInterfaceGlobal.static_method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "static_method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+       Vala.List<Api.Node> properties = iface.get_children_by_type (Api.NodeType.PROPERTY, false);
+       bool prop1 = false;
+       bool prop2 = false;
+       bool prop3 = false;
+
+       foreach (Api.Node node in properties) {
+               Api.Property property = node as Api.Property;
+               assert (property != null);
+
+               switch (property.name) {
+               case "property1":
+                       assert (property.get_cname () == "property1");
+                       assert (property.property_type != null);
+                       assert (property.is_virtual == false);
+                       assert (property.is_abstract == false);
+                       assert (property.is_override == false);
+                       assert (property.is_dbus_visible == true);
+                       assert (property.setter != null);
+                       assert (property.getter != null);
+                       assert (property.base_property == null);
+                       // (.Symbol check)
+                       assert (property.is_deprecated == false);
+                       assert (property.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (property.get_full_name () == "TestInterfaceGlobal.property1");
+                       assert (property.get_filename () == "api-test.data.vapi");
+                       assert (property.nspace == global_ns);
+                       assert (property.package == pkg);
+
+
+                       assert (property.getter.get_cname () == "test_interface_global_get_property1");
+                       assert (property.getter.is_construct == false);
+                       assert (property.getter.is_set == false);
+                       assert (property.getter.is_get == true);
+                       assert (property.getter.is_owned == false);
+                       // (.Symbol check)
+                       assert (property.getter.is_deprecated == false);
+                       assert (property.getter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestInterfaceGlobal.property2");
+                       assert (property.getter.get_filename () == "api-test.data.vapi");
+                       assert (property.getter.nspace == global_ns);
+                       assert (property.getter.package == pkg);
+
+
+                       assert (property.setter.get_cname () == "test_interface_global_set_property1");
+                       assert (property.setter.is_construct == false);
+                       assert (property.setter.is_get == false);
+                       assert (property.setter.is_set == true);
+                       assert (property.setter.is_owned == false);
+                       // (.Symbol check)
+                       assert (property.setter.is_deprecated == false);
+                       assert (property.setter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestInterfaceGlobal.property2");
+                       assert (property.setter.get_filename () == "api-test.data.vapi");
+                       assert (property.setter.nspace == global_ns);
+                       assert (property.setter.package == pkg);
+
+                       prop1 = true;
+                       break;
+
+               case "property2":
+                       assert (property.get_cname () == "property2");
+                       assert (property.property_type != null);
+                       assert (property.is_virtual == false);
+                       assert (property.is_abstract == false);
+                       assert (property.is_override == false);
+                       assert (property.is_dbus_visible == true);
+                       assert (property.setter == null);
+                       assert (property.getter != null);
+                       assert (property.base_property == null);
+                       // (.Symbol check)
+                       assert (property.is_deprecated == false);
+                       assert (property.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (property.get_full_name () == "TestInterfaceGlobal.property2");
+                       assert (property.get_filename () == "api-test.data.vapi");
+                       assert (property.nspace == global_ns);
+                       assert (property.package == pkg);
+
+                       assert (property.getter.get_cname () == "test_interface_global_get_property2");
+                       assert (property.getter.is_construct == false);
+                       assert (property.getter.is_set == false);
+                       assert (property.getter.is_get == true);
+                       assert (property.getter.is_owned == false);
+                       // (.Symbol check)
+                       assert (property.getter.is_deprecated == false);
+                       assert (property.getter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestInterfaceGlobal.property2");
+                       assert (property.getter.get_filename () == "api-test.data.vapi");
+                       assert (property.getter.nspace == global_ns);
+                       assert (property.getter.package == pkg);
+
+                       prop2 = true;
+                       break;
+
+
+               case "property3":
+                       assert (property.get_cname () == "property3");
+                       assert (property.property_type != null);
+                       assert (property.is_virtual == false);
+                       assert (property.is_abstract == false);
+                       assert (property.is_override == false);
+                       assert (property.is_dbus_visible == true);
+                       assert (property.setter != null);
+                       assert (property.getter != null);
+                       assert (property.base_property == null);
+                       // (.Symbol check)
+                       assert (property.is_deprecated == false);
+                       assert (property.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (property.get_full_name () == "TestInterfaceGlobal.property3");
+                       assert (property.get_filename () == "api-test.data.vapi");
+                       assert (property.nspace == global_ns);
+                       assert (property.package == pkg);
+
+                       assert (property.getter.get_cname () == "test_interface_global_get_property3");
+                       assert (property.getter.is_construct == false);
+                       assert (property.getter.is_set == false);
+                       assert (property.getter.is_get == true);
+                       assert (property.getter.is_owned == true);
+                       // (.Symbol check)
+                       assert (property.getter.is_deprecated == false);
+                       assert (property.getter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestInterfaceGlobal.property3");
+                       assert (property.getter.get_filename () == "api-test.data.vapi");
+                       assert (property.getter.nspace == global_ns);
+                       assert (property.getter.package == pkg);
+
+
+                       assert (property.setter.get_cname () == "test_interface_global_set_property3");
+                       assert (property.setter.is_construct == true);
+                       assert (property.setter.is_get == false);
+                       assert (property.setter.is_set == true);
+                       assert (property.setter.is_owned == false);
+                       // (.Symbol check)
+                       assert (property.setter.is_deprecated == false);
+                       assert (property.setter.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       //assert (property.getter.get_full_name () == "TestInterfaceGlobal.property3");
+                       assert (property.setter.get_filename () == "api-test.data.vapi");
+                       assert (property.setter.nspace == global_ns);
+                       assert (property.setter.package == pkg);
+
+
+                       prop3 = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+       assert (prop1);
+       assert (prop2);
+       assert (prop3);
+
+
+
+       Vala.List<Api.Node> delegates = iface.get_children_by_type (Api.NodeType.DELEGATE, false);
+       assert (delegates.size == 1);
+
+       Api.Delegate del = delegates.get (0) as Api.Delegate;
+       assert (del != null);
+
+       // (.Delegate check)
+       assert (del.get_cname () == "TestInterfaceGlobalFoo");
+       assert (del.return_type != null);
+       assert (del.is_static == false);
+       // (.Symbol check)
+       assert (del.is_deprecated == false);
+       assert (del.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       //assert (del.get_full_name () == "TestClassGlobal.property3");
+       assert (del.get_filename () == "api-test.data.vapi");
+       assert (del.nspace == global_ns);
+       assert (del.package == pkg);
+
+
+
+       Vala.List<Api.Node> signals = iface.get_children_by_type (Api.NodeType.SIGNAL, false);
+       assert (signals.size == 1);
+
+       Api.Signal sig = signals.get (0) as Api.Signal;
+       assert (sig != null);
+
+       // (.Signal check)
+       assert (sig.get_cname () == "sig");
+       assert (sig.is_virtual == false);
+       assert (sig.return_type != null);
+       //assert (sig.is_static == false);
+       // (.Symbol check)
+       assert (sig.is_deprecated == false);
+       assert (sig.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       //assert (sig.get_full_name () == "TestClassGlobal.property3");
+       assert (sig.get_filename () == "api-test.data.vapi");
+       assert (sig.nspace == global_ns);
+       assert (sig.package == pkg);
+
+
+
+       Vala.List<Api.Node> constants = iface.get_children_by_type (Api.NodeType.CONSTANT, false);
+       assert (constants.size == 1);
+
+       Api.Constant constant = constants.get (0) as Api.Constant;
+       assert (constant != null);
+       // (.Constant check)
+       assert (constant.get_cname () == "TEST_INTERFACE_GLOBAL_constant");
+       // (.Symbol check)
+       assert (constant.is_deprecated == false);
+       assert (constant.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (constant.get_full_name () == "TestInterfaceGlobal.constant");
+       assert (constant.get_filename () == "api-test.data.vapi");
+       assert (constant.name == "constant");
+       assert (constant.nspace == global_ns);
+       assert (constant.package == pkg);
+
+
+       Api.NodeType[] forbidden = {
+                       Api.NodeType.CREATION_METHOD,
+                       Api.NodeType.ENUM,
+                       Api.NodeType.ENUM_VALUE,
+                       Api.NodeType.ERROR_CODE,
+                       Api.NodeType.ERROR_DOMAIN,
+                       Api.NodeType.FIELD,
+                       Api.NodeType.FORMAL_PARAMETER,
+                       Api.NodeType.INTERFACE,
+                       Api.NodeType.NAMESPACE,
+                       Api.NodeType.PACKAGE,
+                       Api.NodeType.PROPERTY_ACCESSOR,
+                       Api.NodeType.STRUCT,
+                       Api.NodeType.TYPE_PARAMETER
+               };
+
+       Vala.List<Api.Node> nodes = iface.get_children_by_types (forbidden, false);     
+       assert (nodes.size == 0);
+}
+
+
+public static void test_struct_global (Api.Struct? stru, Api.Package pkg, Api.Namespace global_ns) {
+       assert (stru != null);
+       // (.Struct check)
+       assert (stru.base_type == null);
+       assert (stru.get_cname () == "TestStructGlobal");
+       assert (stru.get_free_function_cname () == null);
+       assert (stru.get_dup_function_cname () == null);
+       assert (stru.get_type_id () == null);
+       // (.Symbol check)
+       assert (stru.is_deprecated == false);
+       assert (stru.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       //assert (property.getter.get_full_name () == "TestClassGlobal.property3");
+       assert (stru.get_full_name () == "TestStructGlobal");
+       assert (stru.get_filename () == "api-test.data.vapi");
+       assert (stru.name == "TestStructGlobal");
+       assert (stru.nspace == global_ns);
+       assert (stru.package == pkg);
+
+
+       Vala.List<Api.Node> methods = stru.get_children_by_type (Api.NodeType.METHOD, false);
+       assert (methods.size == 1);
+
+       Api.Method method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_struct_global_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == false);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestStructGlobal.method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+
+       methods = stru.get_children_by_type (Api.NodeType.STATIC_METHOD, false);
+       assert (methods.size == 1);
+
+       method = methods.get (0) as Api.Method;
+       assert (method != null);
+
+       // (.Method check)
+       assert (method.get_cname () == "test_struct_global_static_method");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == true);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "TestStructGlobal.static_method");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "static_method");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+
+       methods = stru.get_children_by_type (Api.NodeType.CREATION_METHOD, false);
+       bool default_constr = false;
+       bool named_constr = false;
+
+       foreach (Api.Node node in methods) {
+               method = node as Api.Method;
+               assert (method != null);
+
+               switch (method.name) {
+                       case "TestStructGlobal":
+                               // (.Method check)
+                               assert (method.get_cname () == "test_struct_global_init");
+                               //assert (method.get_dbus_name () == null);
+                               //assert (method.get_dbus_result_name () == null);
+                               //assert (method.is_dbus_visible == false);
+                               assert (method.base_method == null);
+                               assert (method.is_yields == false);
+                               assert (method.is_abstract == false);
+                               assert (method.is_virtual == false);
+                               assert (method.is_override == false);
+                               assert (method.is_static == false);
+                               assert (method.is_constructor == true);
+                               assert (method.is_inline == false);
+                               // (.Symbol check)
+                               assert (method.is_deprecated == false);
+                               assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+                               // (.Node)
+                               assert (method.get_full_name () == "TestStructGlobal.TestStructGlobal");
+                               assert (method.get_filename () == "api-test.data.vapi");
+                               assert (method.nspace == global_ns);
+                               assert (method.package == pkg);
+
+                               default_constr = true;
+                               break;
+
+                       case "TestStructGlobal.named":
+                               // (.Method check)
+                               assert (method.get_cname () == "test_struct_global_init_named");
+                               //assert (method.get_dbus_name () == null);
+                               //assert (method.get_dbus_result_name () == null);
+                               //assert (method.is_dbus_visible == false);
+                               assert (method.base_method == null);
+                               assert (method.is_yields == false);
+                               assert (method.is_abstract == false);
+                               assert (method.is_virtual == false);
+                               assert (method.is_override == false);
+                               assert (method.is_static == false);
+                               assert (method.is_constructor == true);
+                               assert (method.is_inline == false);
+                               // (.Symbol check)
+                               assert (method.is_deprecated == false);
+                               assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+                               // (.Node)
+                               assert (method.get_full_name () == "TestStructGlobal.TestStructGlobal.named");
+                               assert (method.get_filename () == "api-test.data.vapi");
+                               assert (method.nspace == global_ns);
+                               assert (method.package == pkg);
+
+                               named_constr = true;
+                               break;
+
+                       default:
+                               assert_not_reached ();
+               }
+       }
+
+       assert (default_constr == true);
+       assert (named_constr == true);
+
+
+
+       Vala.List<Api.Node> constants = stru.get_children_by_type (Api.NodeType.CONSTANT, false);
+       assert (constants.size == 1);
+
+       Api.Constant constant = constants.get (0) as Api.Constant;
+       assert (constant != null);
+       // (.Constant check)
+       assert (constant.get_cname () == "TEST_STRUCT_GLOBAL_constant");
+       // (.Symbol check)
+       assert (constant.is_deprecated == false);
+       assert (constant.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (constant.get_full_name () == "TestStructGlobal.constant");
+       assert (constant.get_filename () == "api-test.data.vapi");
+       assert (constant.name == "constant");
+       assert (constant.nspace == global_ns);
+       assert (constant.package == pkg);
+
+
+
+       Vala.List<Api.Node> fields = stru.get_children_by_type (Api.NodeType.FIELD, false);
+
+       bool field1 = false;
+       bool field2 = false;
+       foreach (Api.Node node in fields) {
+               Api.Field field = node as Api.Field;
+               assert (field != null);
+
+               switch (field.name) {
+               case "field1":
+                       // (.Field check)
+                       assert (field.get_cname () == "test_struct_global_field1");
+                       assert (field.is_static == true);
+                       assert (field.is_volatile == false);
+                       // (.Symbol check)
+                       assert (field.is_deprecated == false);
+                       assert (field.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (field.get_full_name () == "TestStructGlobal.field1");
+                       assert (field.get_filename () == "api-test.data.vapi");
+                       assert (field.nspace == global_ns);
+                       assert (field.package == pkg);
+
+                       field1 = true;
+                       break;
+
+               case "field2":
+                       // (.Field check)
+                       assert (field.get_cname () == "field2");        
+                       assert (field.is_static == false);
+                       assert (field.is_volatile == false);
+                       // (.Symbol check)
+                       assert (field.is_deprecated == false);
+                       assert (field.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (field.get_full_name () == "TestStructGlobal.field2");
+                       assert (field.get_filename () == "api-test.data.vapi");
+                       assert (field.nspace == global_ns);
+                       assert (field.package == pkg);
+
+                       field2 = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (field1 == true);
+       assert (field2 == true);
+
+
+
+       Api.NodeType[] forbidden = {
+                       Api.NodeType.CLASS,
+                       Api.NodeType.DELEGATE,
+                       Api.NodeType.ENUM,
+                       Api.NodeType.ENUM_VALUE,
+                       Api.NodeType.ERROR_CODE,
+                       Api.NodeType.ERROR_DOMAIN,
+                       Api.NodeType.FORMAL_PARAMETER,
+                       Api.NodeType.INTERFACE,
+                       Api.NodeType.NAMESPACE,
+                       Api.NodeType.PACKAGE,
+                       Api.NodeType.PROPERTY,
+                       Api.NodeType.PROPERTY_ACCESSOR,
+                       Api.NodeType.SIGNAL,
+                       Api.NodeType.STRUCT,
+                       Api.NodeType.TYPE_PARAMETER
+               };
+
+       Vala.List<Api.Node> nodes = stru.get_children_by_types (forbidden, false);      
+       assert (nodes.size == 0);
+}
+
+
+public static void param_test (Api.Namespace ns, Api.Package pkg) {
+       Vala.List<Api.Node> methods = ns.get_children_by_type (Api.NodeType.METHOD, false);
+
+       bool func1 = false;
+       bool func2 = false;
+       bool func3 = false;
+       bool func4 = false;
+       bool func5 = false;
+       bool func6 = false;
+       bool func7 = false;
+       bool func8 = false;
+       bool func9 = false;
+       bool func10 = false;
+       bool func11 = false;
+       bool func12 = false;
+       bool func13 = false;
+       bool func14 = false;
+
+       foreach (Api.Node node in methods) {
+               Api.Method m = node as Api.Method;
+               assert (m != null);
+
+               Api.NodeType[] forbidden = {
+                               Api.NodeType.CLASS,
+                               Api.NodeType.CONSTANT,
+                               Api.NodeType.CREATION_METHOD,
+                               Api.NodeType.DELEGATE,
+                               Api.NodeType.ENUM,
+                               Api.NodeType.ENUM_VALUE,
+                               Api.NodeType.ERROR_CODE,
+                               Api.NodeType.ERROR_DOMAIN,
+                               Api.NodeType.FIELD,
+                               Api.NodeType.INTERFACE,
+                               Api.NodeType.METHOD,
+                               Api.NodeType.NAMESPACE,
+                               Api.NodeType.PACKAGE,
+                               Api.NodeType.PROPERTY,
+                               Api.NodeType.PROPERTY_ACCESSOR,
+                               Api.NodeType.SIGNAL,
+                               Api.NodeType.STATIC_METHOD,
+                               Api.NodeType.STRUCT,
+                               Api.NodeType.TYPE_PARAMETER
+                       };
+
+               Vala.List<Api.Node> nodes = m.get_children_by_types (forbidden, false); 
+               assert (nodes.size == 0);
+
+               Vala.List<Api.Node> params = m.get_children_by_type (Api.NodeType.FORMAL_PARAMETER, false);
+
+               switch (m.name) {
+               case "test_function_param_1":
+                       assert (params.size == 0);
+
+                       func1 = true;
+                       break;
+
+               case "test_function_param_2":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_2.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func2 = true;
+                       break;
+
+               case "test_function_param_3":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == true);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_3.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func3 = true;
+                       break;
+
+               case "test_function_param_4":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == true);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_4.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func4 = true;
+                       break;
+
+               case "test_function_param_5":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_5.o");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "o");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Class);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == 
"GLib.Object");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == true);
+                       assert (param.parameter_type.is_owned == true);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func5 = true;
+                       break;
+
+               case "test_function_param_6":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_6.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == true);
+
+                       func6 = true;
+                       break;
+
+               case "test_function_param_7":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == true);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == null);
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == null);
+                       // param type:
+                       assert (param.parameter_type.data_type == null);
+
+                       func7 = true;
+                       break;
+
+               case "test_function_param_8":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value != null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == true);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_8.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func8 = true;
+                       break;
+
+               case "test_function_param_9":
+                       assert (params.size == 7);
+
+                       Api.FormalParameter? param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_9.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+
+
+                       param = params.get (1) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == true);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_9.b");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "b");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+
+
+                       param = params.get (2) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == true);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_9.c");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "c");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+
+
+                       param = params.get (3) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_9.d");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "d");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Class);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == 
"GLib.Object");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == true);
+                       assert (param.parameter_type.is_owned == true);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+
+
+                       param = params.get (4) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_9.e");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "e");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == true);
+
+
+
+                       param = params.get (5) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value != null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == true);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_9.f");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "f");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Struct);
+                       assert (((Api.Symbol) param.parameter_type.data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+
+
+                       param = params.get (6) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == true);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == null);
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == null);
+                       // param type:
+                       assert (param.parameter_type.data_type == null);
+
+                       func9 = true;
+                       break;
+
+               case "test_function_param_10":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_10.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Pointer);
+                       assert (((Api.Pointer) param.parameter_type.data_type).data_type is 
Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Pointer) 
param.parameter_type.data_type).data_type).data_type is Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Pointer) 
param.parameter_type.data_type).data_type).data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func10 = true;
+                       break;
+
+               case "test_function_param_11":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_11.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Pointer);
+                       assert (((Api.Pointer) param.parameter_type.data_type).data_type is Api.Pointer);
+                       assert (((Api.Pointer) ((Api.Pointer) 
param.parameter_type.data_type).data_type).data_type is Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Pointer) ((Api.Pointer) 
param.parameter_type.data_type).data_type).data_type).data_type is Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Pointer) ((Api.Pointer) 
param.parameter_type.data_type).data_type).data_type).data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func11 = true;
+                       break;
+
+               case "test_function_param_12":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_12.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Array);
+                       //assert (((Api.Array) param.parameter_type.data_type).dimension == 1);
+                       assert (((Api.Array) param.parameter_type.data_type).data_type is Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Array) 
param.parameter_type.data_type).data_type).data_type is Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Array) 
param.parameter_type.data_type).data_type).data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func12 = true;
+                       break;
+
+               case "test_function_param_13":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_13.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Array);
+                       //assert (((Api.Array) param.parameter_type.data_type).dimension == 2);
+                       assert (((Api.Array) param.parameter_type.data_type).data_type is Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Array) 
param.parameter_type.data_type).data_type).data_type is Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Array) 
param.parameter_type.data_type).data_type).data_type).get_full_name () == "int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func13 = true;
+                       break;
+
+               case "test_function_param_14":
+                       assert (params.size == 1);
+
+                       Api.FormalParameter param = params.get (0) as Api.FormalParameter;
+                       assert (param != null);
+                       // (.FormalParameter)
+                       assert (param.default_value == null);
+                       assert (param.is_out == false);
+                       assert (param.is_ref == false);
+                       assert (param.has_default_value == false);
+                       assert (param.parameter_type != null);
+                       assert (param.ellipsis == false);
+                       // (.Symbol check)
+                       assert (param.is_deprecated == false);
+                       assert (param.accessibility == Api.SymbolAccessibility.PUBLIC);
+                       // (.Node)
+                       assert (param.get_full_name () == "ParamTest.test_function_param_14.a");
+                       assert (param.get_filename () == "api-test.data.vapi");
+                       assert (param.nspace == ns);
+                       assert (param.package == pkg);
+                       assert (param.name == "a");
+                       // param type:
+                       assert (param.parameter_type.data_type != null);
+                       assert (param.parameter_type.data_type is Api.Array);
+                       //assert (((Api.Array) param.parameter_type.data_type).dimension == 1);
+                       assert (((Api.Array) param.parameter_type.data_type).data_type is Api.TypeReference);
+                       //assert (((Api.Array) ((Api.Array) 
param.parameter_type.data_type).data_type).dimension == 1);
+                       assert (((Api.TypeReference) ((Api.Array) 
param.parameter_type.data_type).data_type).data_type is Api.Array);
+                       assert (((Api.Array) ((Api.TypeReference) ((Api.Array) 
param.parameter_type.data_type).data_type).data_type).data_type is Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Array) ((Api.TypeReference) ((Api.Array) 
param.parameter_type.data_type).data_type).data_type).data_type).data_type is Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Array) ((Api.TypeReference) 
((Api.Array) param.parameter_type.data_type).data_type).data_type).data_type).data_type).get_full_name () == 
"int");
+                       assert (param.parameter_type.get_type_arguments ().size == 0);
+                       assert (param.parameter_type.pass_ownership == false);
+                       assert (param.parameter_type.is_owned == false);
+                       assert (param.parameter_type.is_unowned == false);
+                       assert (param.parameter_type.is_weak == false);
+                       assert (param.parameter_type.is_dynamic == false);
+                       assert (param.parameter_type.is_nullable == false);
+
+                       func14 = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (func1 == true);
+       assert (func2 == true);
+       assert (func3 == true);
+       assert (func4 == true);
+       assert (func5 == true);
+       assert (func6 == true);
+       assert (func7 == true);
+       assert (func8 == true);
+       assert (func9 == true);
+       assert (func10 == true);
+       assert (func11 == true);
+       assert (func12 == true);
+       assert (func13 == true);
+       assert (func14 == true);
+
+
+       Api.NodeType[] forbidden = {
+                       Api.NodeType.CLASS,
+                       Api.NodeType.CONSTANT,
+                       Api.NodeType.CREATION_METHOD,
+                       Api.NodeType.DELEGATE,
+                       Api.NodeType.ENUM,
+                       Api.NodeType.ENUM_VALUE,
+                       Api.NodeType.ERROR_CODE,
+                       Api.NodeType.ERROR_DOMAIN,
+                       Api.NodeType.FIELD,
+                       Api.NodeType.FORMAL_PARAMETER,
+                       Api.NodeType.INTERFACE,
+                       Api.NodeType.NAMESPACE,
+                       Api.NodeType.PACKAGE,
+                       Api.NodeType.PROPERTY,
+                       Api.NodeType.PROPERTY_ACCESSOR,
+                       Api.NodeType.SIGNAL,
+                       Api.NodeType.STATIC_METHOD,
+                       Api.NodeType.STRUCT,
+                       Api.NodeType.TYPE_PARAMETER
+               };
+
+       Vala.List<Api.Node> nodes = ns.get_children_by_types (forbidden, false);        
+       assert (nodes.size == 0);
+}
+
+
+public static void return_test (Api.Namespace ns, Api.Package pkg) {
+       Vala.List<Api.Node> methods = ns.get_children_by_type (Api.NodeType.METHOD, false);
+
+       bool func1 = false;
+       bool func2 = false;
+       bool func3 = false;
+       bool func4 = false;
+       bool func5 = false;
+       bool func6 = false;
+       bool func7 = false;
+       bool func8 = false;
+       bool func9 = false;
+
+       foreach (Api.Node node in methods) {
+               Api.Method m = node as Api.Method;
+               assert (m != null);
+
+               Api.NodeType[] forbidden = {
+                               Api.NodeType.CLASS,
+                               Api.NodeType.CONSTANT,
+                               Api.NodeType.CREATION_METHOD,
+                               Api.NodeType.DELEGATE,
+                               Api.NodeType.ENUM,
+                               Api.NodeType.ENUM_VALUE,
+                               Api.NodeType.ERROR_CODE,
+                               Api.NodeType.ERROR_DOMAIN,
+                               Api.NodeType.FIELD,
+                               Api.NodeType.INTERFACE,
+                               Api.NodeType.METHOD,
+                               Api.NodeType.NAMESPACE,
+                               Api.NodeType.PACKAGE,
+                               Api.NodeType.PROPERTY,
+                               Api.NodeType.PROPERTY_ACCESSOR,
+                               Api.NodeType.SIGNAL,
+                               Api.NodeType.STATIC_METHOD,
+                               Api.NodeType.STRUCT,
+                               Api.NodeType.FORMAL_PARAMETER,
+                               Api.NodeType.TYPE_PARAMETER
+                       };
+
+               Vala.List<Api.Node> nodes = m.get_children_by_types (forbidden, false); 
+               assert (nodes.size == 0);
+
+               Api.TypeReference? ret = m.return_type;
+               assert (ret != null);
+
+               switch (m.name) {
+               case "test_function_1":
+                       assert (ret.data_type == null);
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == false);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == false);
+
+                       func1 = true;
+                       break;
+
+               case "test_function_2":
+                       assert (ret.data_type is Api.Struct);
+                       assert (((Api.Struct) ret.data_type).get_full_name () == "int");
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == false);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == false);
+
+                       func2 = true;
+                       break;
+
+               case "test_function_3":
+                       assert (ret.data_type is Api.Struct);
+                       assert (((Api.Struct) ret.data_type).get_full_name () == "int");
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == false);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == true);
+
+                       func3 = true;
+                       break;
+
+               case "test_function_4":
+                       assert (ret.data_type is Api.Class);
+                       assert (((Api.Class) ret.data_type).get_full_name () == "string");
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == true);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == false);
+
+                       func4 = true;
+                       break;
+
+               case "test_function_5":
+                       assert (ret.data_type is Api.Pointer);
+                       assert (((Api.Pointer) ret.data_type).data_type is Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Pointer) ret.data_type).data_type).data_type is 
Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Pointer) 
ret.data_type).data_type).data_type).get_full_name () == "int");
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == false);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == false);
+
+                       func5 = true;
+                       break;
+
+               case "test_function_6":
+                       assert (ret.data_type is Api.Pointer);
+                       assert (((Api.Pointer) ret.data_type).data_type is Api.Pointer);
+                       assert (((Api.Pointer) ((Api.Pointer) ret.data_type).data_type).data_type is 
Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Pointer) ((Api.Pointer) 
ret.data_type).data_type).data_type).data_type is Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Pointer) ((Api.Pointer) 
ret.data_type).data_type).data_type).data_type).get_full_name () == "int");
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == false);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == false);
+
+                       func6 = true;
+                       break;
+
+               case "test_function_7":
+                       assert (ret.data_type is Api.Array);
+                       assert (((Api.Array) ret.data_type).data_type is Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Array) ret.data_type).data_type).data_type is 
Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Array) 
ret.data_type).data_type).data_type).get_full_name () == "int");
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == false);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == false);
+
+                       func7 = true;
+                       break;
+
+               case "test_function_8":
+                       assert (ret.data_type is Api.Array);
+                       //assert (((Api.Array) ret.data_type).dimension == 1);
+                       assert (((Api.Array) ret.data_type).data_type is Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Array) ret.data_type).data_type).data_type is 
Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Array) 
ret.data_type).data_type).data_type).get_full_name () == "int");
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == false);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == false);
+
+                       func8 = true;
+                       break;
+
+               case "test_function_9":
+                       assert (ret.data_type is Api.Array);
+                       //assert (((Api.Array) ret.data_type).dimension == 1);
+                       assert (((Api.Array) ret.data_type).data_type is Api.TypeReference);
+                       //assert (((Api.Array) ((Api.Array) ret.data_type).data_type).dimension == 1);
+                       assert (((Api.TypeReference) ((Api.Array) ret.data_type).data_type).data_type is 
Api.Array);
+                       assert (((Api.Array) ((Api.TypeReference) ((Api.Array) 
ret.data_type).data_type).data_type).data_type is Api.TypeReference);
+                       assert (((Api.TypeReference) ((Api.Array) ((Api.TypeReference) ((Api.Array) 
ret.data_type).data_type).data_type).data_type).data_type is Api.Struct);
+                       assert (((Api.Struct) ((Api.TypeReference) ((Api.Array) ((Api.TypeReference) 
((Api.Array) ret.data_type).data_type).data_type).data_type).data_type).get_full_name () == "int");
+                       assert (ret.get_type_arguments ().size == 0);
+                       assert (ret.pass_ownership == false);
+                       assert (ret.is_owned == false);
+                       assert (ret.is_unowned == false);
+                       assert (ret.is_weak == false);
+                       assert (ret.is_dynamic == false);
+                       assert (ret.is_nullable == false);
+
+                       func9 = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (func1 == true);
+       assert (func2 == true);
+       assert (func3 == true);
+       assert (func4 == true);
+       assert (func5 == true);
+       assert (func6 == true);
+       assert (func7 == true);
+       assert (func8 == true);
+       assert (func9 == true);
+}
+
+
+public static void version_test (Api.Namespace ns, Api.Package pkg) {
+       Vala.List<Api.Node> methods = ns.get_children_by_type (Api.NodeType.METHOD, false);
+
+       bool func1 = false;
+       bool func2 = false;
+       bool func3 = false;
+#if VALA_0_32
+       bool func4 = false;
+       bool func5 = false;
+       bool func6 = false;
+       bool func7 = false;
+       bool func8 = false;
+       bool func9 = false;
+#endif
+
+       foreach (Api.Node node in methods) {
+               Api.Method m = node as Api.Method;
+               assert (m != null);
+
+               Api.NodeType[] forbidden = {
+                               Api.NodeType.CLASS,
+                               Api.NodeType.CONSTANT,
+                               Api.NodeType.CREATION_METHOD,
+                               Api.NodeType.DELEGATE,
+                               Api.NodeType.ENUM,
+                               Api.NodeType.ENUM_VALUE,
+                               Api.NodeType.ERROR_CODE,
+                               Api.NodeType.ERROR_DOMAIN,
+                               Api.NodeType.FIELD,
+                               Api.NodeType.INTERFACE,
+                               Api.NodeType.METHOD,
+                               Api.NodeType.NAMESPACE,
+                               Api.NodeType.PACKAGE,
+                               Api.NodeType.PROPERTY,
+                               Api.NodeType.PROPERTY_ACCESSOR,
+                               Api.NodeType.SIGNAL,
+                               Api.NodeType.STATIC_METHOD,
+                               Api.NodeType.STRUCT,
+                               Api.NodeType.FORMAL_PARAMETER,
+                               Api.NodeType.TYPE_PARAMETER
+                       };
+
+               Vala.List<Api.Node> nodes = m.get_children_by_types (forbidden, false);
+               assert (nodes.size == 0);
+
+               Api.TypeReference? ret = m.return_type;
+               assert (ret != null);
+
+               switch (m.name) {
+               case "test_function_1":
+                       assert (m.get_attribute ("Deprecated") != null);
+                       assert (m.is_deprecated == true);
+
+                       func1 = true;
+                       break;
+
+               case "test_function_2":
+                       assert (m.get_attribute ("Deprecated").get_argument ("since").get_value_as_string () 
== "\"1.0\"");
+                       assert (m.get_attribute ("Deprecated").get_argument 
("replacement").get_value_as_string () == "\"test_function_4\"");
+                       assert (m.is_deprecated == true);
+
+                       func2 = true;
+                       break;
+
+               case "test_function_3":
+                       //assert (m.get_attribute ("Experimental") != null);
+
+                       func3 = true;
+                       break;
+
+#if VALA_0_32
+               case "test_function_4":
+                       assert (m.get_attribute ("Version").get_argument ("since").get_value_as_string () == 
"\"2.0\"");
+                       assert (m.is_deprecated == false);
+
+                       func4 = true;
+                       break;
+
+               case "test_function_5":
+                       assert (m.get_attribute ("Version").get_argument ("deprecated").get_value_as_boolean 
() == true);
+                       assert (m.is_deprecated == true);
+
+                       func5 = true;
+                       break;
+
+               case "test_function_6":
+                       assert (m.get_attribute ("Version").get_argument ("deprecated").get_value_as_boolean 
() == true);
+                       assert (m.get_attribute ("Version").get_argument 
("deprecated_since").get_value_as_string () == "\"2.0\"");
+                       assert (m.get_attribute ("Version").get_argument ("replacement").get_value_as_string 
() == "\"test_function_4\"");
+                       assert (m.get_attribute ("Version").get_argument ("since").get_value_as_string () == 
"\"1.0\"");
+                       assert (m.is_deprecated == true);
+
+                       func6 = true;
+                       break;
+
+               case "test_function_7":
+                       assert (m.get_attribute ("Version").get_argument 
("deprecated_since").get_value_as_string () == "\"2.0\"");
+                       assert (m.is_deprecated == true);
+
+                       func7 = true;
+                       break;
+
+               case "test_function_8":
+                       assert (m.get_attribute ("Version").get_argument ("deprecated").get_value_as_boolean 
() == false);
+                       assert (m.is_deprecated == false);
+
+                       func8 = true;
+                       break;
+
+               case "test_function_9":
+                       //assert (m.get_attribute ("Version").get_argument 
("experimental").get_value_as_boolean () == true);
+
+                       func9 = true;
+                       break;
+#endif
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (func1 == true);
+       assert (func2 == true);
+       assert (func3 == true);
+#if VALA_0_32
+       assert (func4 == true);
+       assert (func5 == true);
+       assert (func6 == true);
+       assert (func7 == true);
+       assert (func8 == true);
+       assert (func9 == true);
+#endif
+}
+
+
+public static void test_global_ns (Api.Namespace global_ns, Api.Package pkg) {
+       Vala.List<Api.Node> methods = global_ns.get_children_by_type (Api.NodeType.METHOD, false);
+       assert (methods.size == 1);
+
+       Api.Method method = methods.get (0) as Api.Method;
+       assert (method != null);
+       // (.Method check)
+       assert (method.get_cname () == "test_function_global");
+       //assert (method.get_dbus_name () == null);
+       //assert (method.get_dbus_result_name () == null);
+       //assert (method.is_dbus_visible == false);
+       assert (method.base_method == null);
+       assert (method.is_yields == false);
+       assert (method.is_abstract == false);
+       assert (method.is_virtual == false);
+       assert (method.is_override == false);
+       assert (method.is_static == false);
+       assert (method.is_constructor == false);
+       assert (method.is_inline == false);
+       // (.Symbol check)
+       assert (method.is_deprecated == false);
+       assert (method.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (method.get_full_name () == "test_function_global");
+       assert (method.get_filename () == "api-test.data.vapi");
+       assert (method.name == "test_function_global");
+       assert (method.nspace == global_ns);
+       assert (method.package == pkg);
+
+
+
+       Vala.List<Api.Node> delegates = global_ns.get_children_by_type (Api.NodeType.DELEGATE, false);
+       assert (delegates.size == 1);
+
+       Api.Delegate del = delegates.get (0) as Api.Delegate;
+       assert (del != null);
+       // (.Delegate check)
+       assert (del.get_cname () == "test_delegate_global");
+       assert (del.is_static == false);
+       // (.TypeSymbol check)
+       assert (del.is_basic_type == false);
+       // (.Symbol check)
+       assert (del.is_deprecated == false);
+       assert (del.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (del.get_full_name () == "test_delegate_global");
+       assert (del.get_filename () == "api-test.data.vapi");
+       assert (del.name == "test_delegate_global");
+       assert (del.nspace == global_ns);
+       assert (del.package == pkg);
+
+
+
+       Vala.List<Api.Node> fields = global_ns.get_children_by_type (Api.NodeType.FIELD, false);
+       assert (fields.size == 1);
+
+       Api.Field field = fields.get (0) as Api.Field;
+       assert (field != null);
+       // (.Field check)
+       assert (field.get_cname () == "test_field_global");     
+       assert (field.is_static == false);
+       assert (field.is_volatile == false);
+       // (.Symbol check)
+       assert (field.is_deprecated == false);
+       assert (field.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (field.get_full_name () == "test_field_global");
+       assert (field.get_filename () == "api-test.data.vapi");
+       assert (field.name == "test_field_global");
+       assert (field.nspace == global_ns);
+       assert (field.package == pkg);
+
+
+
+       Vala.List<Api.Node> constants = global_ns.get_children_by_type (Api.NodeType.CONSTANT, false);
+       assert (constants.size == 1);
+
+       Api.Constant constant = constants.get (0) as Api.Constant;
+       assert (constant != null);
+       // (.Constant check)
+       assert (constant.get_cname () == "test_const_global");  
+       // (.Symbol check)
+       assert (constant.is_deprecated == false);
+       assert (constant.accessibility == Api.SymbolAccessibility.PUBLIC);
+       // (.Node)
+       assert (constant.get_full_name () == "test_const_global");
+       assert (constant.get_filename () == "api-test.data.vapi");
+       assert (constant.name == "test_const_global");
+       assert (constant.nspace == global_ns);
+       assert (constant.package == pkg);
+
+
+
+       Vala.List<Api.Node> enums = global_ns.get_children_by_type (Api.NodeType.ENUM, false);
+       assert (enums.size == 1);
+
+       Api.Enum en = enums.get (0) as Api.Enum;
+       test_enum_global (en, pkg, global_ns);
+
+
+
+       Vala.List<Api.Node> errordomains = global_ns.get_children_by_type (Api.NodeType.ERROR_DOMAIN, false);
+       assert (errordomains.size == 1);
+
+       Api.ErrorDomain err = errordomains.get (0) as Api.ErrorDomain;
+       test_erroromain_global (err, pkg, global_ns);
+
+
+
+       Vala.List<Api.Node> classes = global_ns.get_children_by_type (Api.NodeType.CLASS, false);
+       assert (classes.size == 1);
+
+       Api.Class cl = classes.get (0) as Api.Class;
+       test_class_global (cl, pkg, global_ns);
+
+
+
+       Vala.List<Api.Node> interfaces = global_ns.get_children_by_type (Api.NodeType.INTERFACE, false);
+       assert (interfaces.size == 1);
+
+       Api.Interface iface = interfaces.get (0) as Api.Interface;
+       test_interface_global (iface, pkg, global_ns);
+
+
+
+       Vala.List<Api.Node> structs = global_ns.get_children_by_type (Api.NodeType.STRUCT, false);
+       assert (structs.size == 1);
+
+       Api.Struct stru = structs.get (0) as Api.Struct;
+       test_struct_global (stru, pkg, global_ns);
+
+
+
+       Vala.List<Api.Node> namespaces = global_ns.get_children_by_type (Api.NodeType.NAMESPACE, false);
+
+
+       bool returntest = false;
+       bool paramtest = false;
+       bool versiontest = false;
+
+       foreach (Api.Node node in namespaces) {
+               Api.Namespace ns = node as Api.Namespace;
+               assert (ns != null);
+
+               switch (ns.name) {
+               case "ParamTest":
+                       param_test (ns, pkg);
+                       paramtest = true;
+                       break;
+
+               case "ReturnTest":
+                       return_test (ns, pkg);
+                       returntest = true;
+                       break;
+
+               case "VersionTest":
+                       version_test (ns, pkg);
+                       versiontest = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (returntest == true);
+       assert (paramtest == true);
+       assert (versiontest == true);
+
+}
+
+
+public static void test_package_out (Api.Package pkg) {
+       assert (pkg.is_package == false);
+       assert (pkg.nspace == null);
+       assert (pkg.package == pkg);
+       //assert (pkg.get_full_name () == null);
+
+       // TODO: check .get_source_file ()
+
+
+       Vala.List<Api.Node> namespaces = pkg.get_children_by_type (Api.NodeType.NAMESPACE, false);
+       assert (namespaces != null);
+       assert (namespaces.size == 1);
+
+       Api.Namespace global_ns = namespaces.get (0) as Api.Namespace;
+       assert (global_ns != null);
+       assert (global_ns.name == null);
+       assert (global_ns.get_full_name () == null);
+       assert (global_ns.is_deprecated == false);
+       assert (global_ns.get_attributes ().size == 0);
+       assert (global_ns.accessibility == Api.SymbolAccessibility.PUBLIC);
+       assert (global_ns.package == pkg);
+       //assert (global_ns.nspace == null);
+
+       test_global_ns (global_ns, pkg);
+}
+
+
+public static void test_driver (string driver_path) {
+       if (!FileUtils.test (driver_path, FileTest.EXISTS)) {
+               message ("Driver '%s' is not available", Valadoc.realpath (driver_path));
+               assert_not_reached ();
+       }
+
+       var settings = new Valadoc.Settings ();
+       var reporter = new ErrorReporter ();
+
+       settings.source_files = {
+                       TOP_SRC_DIR + "/valadoc/tests/drivers/api-test.data.vapi"
+               };
+
+       settings._protected = false;
+       settings._internal = false;
+       settings._private = true;
+       settings.with_deps = false;
+       settings.verbose = false;
+       settings.wiki_directory = null;
+       settings.pkg_name = "out";
+       settings.path = "out";
+
+
+       ModuleLoader modules = ModuleLoader.get_instance ();
+       var driver = null; //modules.create_driver (driver_path);
+       assert (driver != null);
+
+
+       Api.Tree? doctree = null; //driver.build (settings, reporter);
+       assert (reporter.errors == 0);
+       assert (doctree != null);
+
+
+       bool tmp = doctree.create_tree ();
+       assert (tmp);
+
+
+       Vala.Collection<Api.Package> packages = doctree.get_package_list ();
+       assert (packages != null);
+
+       bool glib = false;
+       bool gobj = false;
+       bool test = false;
+
+       foreach (Api.Package pkg in packages) {
+               switch (pkg.name) {
+               case "glib-2.0":
+                       assert (pkg.is_package);
+                       glib = true;
+                       break;
+
+               case "gobject-2.0":
+                       assert (pkg.is_package);
+                       gobj = true;
+                       break;
+
+               case "@out":
+                       test_package_out (pkg);
+                       test = true;
+                       break;
+
+               default:
+                       assert_not_reached ();
+               }
+       }
+
+       assert (glib == true);
+       assert (gobj == true);
+       assert (test == true);
+}
+
+
diff --git a/valadoc/tests/libvaladoc/errorreporter.vala b/valadoc/tests/libvaladoc/errorreporter.vala
new file mode 100644
index 0000000..59e5e53
--- /dev/null
+++ b/valadoc/tests/libvaladoc/errorreporter.vala
@@ -0,0 +1,70 @@
+/* errorreporter.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Valadoc;
+
+void main () {
+       var reporter = new Valadoc.ErrorReporter ();
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+
+       // simple errors:
+       reporter.simple_error ("test", "error 1 %d %s", 1, "foo");
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 1);
+
+       reporter.simple_error (null, "error 2");
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 2);
+
+
+       // simple warnings:
+       reporter.simple_warning ("test", "warning 1 %d %s", 1, "foo");
+       assert (reporter.warnings == 1);
+       assert (reporter.errors == 2);
+
+       reporter.simple_warning (null, "warning 2");
+       assert (reporter.warnings == 2);
+       assert (reporter.errors == 2);
+
+
+       // errors:
+       reporter.error ("file", 1, 1, 1, "line", "error, complex, 1 %d %s", 1, "foo");
+       assert (reporter.warnings == 2);
+       assert (reporter.errors == 3);
+
+       reporter.error ("file", 1, 1, 1, "line", "error, complex, 2");
+       assert (reporter.warnings == 2);
+       assert (reporter.errors == 4);
+
+
+       // warnngs:
+       reporter.warning ("file", 1, 1, 1, "line", "warning, complex, 1 %d %s", 1, "foo");
+       assert (reporter.warnings == 3);
+       assert (reporter.errors == 4);
+
+       reporter.warning ("file", 1, 1, 1, "line", "warning, complex, 2");
+       assert (reporter.warnings == 4);
+       assert (reporter.errors == 4);
+}
+
diff --git a/valadoc/tests/libvaladoc/gtkdoc-scanner.vala b/valadoc/tests/libvaladoc/gtkdoc-scanner.vala
new file mode 100644
index 0000000..164a2a5
--- /dev/null
+++ b/valadoc/tests/libvaladoc/gtkdoc-scanner.vala
@@ -0,0 +1,225 @@
+/* gtkdoc-scanner.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+
+using Valadoc;
+
+
+void main () {
+       var scanner = new Gtkdoc.Scanner ();
+       scanner.reset ("""<element1>
+<element2 a="a-val" b="b-val">
+</element3>
+<element4 />
+<element5 a="a-val" b="b-val"/>
+<!---->
+<!--
+AAAA
+-->
+foo_bar ()
+%aaa
+@param
+#TypeName
+myword      
+
+|[]|
+::my-signal
+:my-property
+""");
+
+       var token = scanner.next ();
+
+       assert (token.type == Gtkdoc.TokenType.XML_OPEN);
+       assert (token.content == "element1");
+       assert (((Vala.Map) token.attributes).size == 0);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.XML_OPEN);
+       assert (token.content == "element2");
+       assert (token.attributes.get ("a") == "a-val");
+       assert (token.attributes.get ("b") == "b-val");
+       assert (((Vala.Map) token.attributes).size == 2);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.XML_CLOSE);
+       assert (token.content == "element3");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.XML_OPEN);
+       assert (token.content == "element4");
+       assert (((Vala.Map) token.attributes).size == 0);
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.XML_CLOSE);
+       assert (token.content == "element4");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.XML_OPEN);
+       assert (token.content == "element5");
+       assert (token.attributes.get ("a") == "a-val");
+       assert (token.attributes.get ("b") == "b-val");
+       assert (((Vala.Map) token.attributes).size == 2);
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.XML_CLOSE);
+       assert (token.content == "element5");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.XML_COMMENT);
+       assert (token.content == "");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.XML_COMMENT);
+       assert (token.content == "");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_FUNCTION);
+       assert (token.content == "foo_bar");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_CONST);
+       assert (token.content == "aaa");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_PARAM);
+       assert (token.content == "param");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_TYPE);
+       assert (token.content == "TypeName");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.WORD);
+       assert (token.content == "myword");
+       assert (token.attributes == null);
+       
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.SPACE);
+       assert (token.content == "      ");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_PARAGRAPH);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_SOURCE_OPEN);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_SOURCE_CLOSE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_SIGNAL);
+       assert (token.content == "my-signal");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.GTKDOC_PROPERTY);
+       assert (token.content == "my-property");
+       assert (token.attributes == null);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.NEWLINE);
+
+
+       token = scanner.next ();
+       assert (token.type == Gtkdoc.TokenType.EOF);
+
+}
diff --git a/valadoc/tests/libvaladoc/markupreader.vala b/valadoc/tests/libvaladoc/markupreader.vala
new file mode 100644
index 0000000..d38b4d4
--- /dev/null
+++ b/valadoc/tests/libvaladoc/markupreader.vala
@@ -0,0 +1,207 @@
+/* markupreader.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+using Valadoc;
+
+
+public static void positive_1 () {
+       var reporter = new ErrorReporter ();
+
+       string content = 
+"""<?xml version="1.0" ?>
+<root-element>
+       <subelement level="1" nested="true">my text</subelement>
+       <simpletag1 level="2" nested="false" />
+       <simpletag2 level="3"/>
+       <simpletag3/>
+</root-element>""";
+
+
+       var reader = new MarkupReader.from_string ("testfile", content, reporter);
+       assert (reader.filename == "testfile");
+
+       MarkupSourceLocation begin;
+       MarkupSourceLocation end;
+       MarkupTokenType token;
+
+
+       token = reader.read_token (out begin, out end);
+       token = reader.read_token (out begin, out end);
+
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.START_ELEMENT);
+       assert (reader.name == "root-element");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 2);
+       assert (end.line == 2);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.START_ELEMENT);
+       assert (reader.name == "subelement");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 2);
+       assert (reader.get_attribute ("nested") == "true");
+       assert (reader.get_attribute ("level") == "1");
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 3);
+       assert (end.line == 3);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.TEXT);
+       assert (reader.name == null);
+       assert (reader.content == "my text");
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 3);
+       assert (end.line == 3);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.END_ELEMENT);
+       assert (reader.name == "subelement");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 3);
+       assert (end.line == 3);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.START_ELEMENT);
+       assert (reader.name == "simpletag1");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 2);
+       assert (reader.get_attribute ("nested") == "false");
+       assert (reader.get_attribute ("level") == "2");
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 4);
+       assert (end.line == 4);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.END_ELEMENT);
+       assert (reader.name == "simpletag1");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 4);
+       assert (end.line == 4);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.START_ELEMENT);
+       assert (reader.name == "simpletag2");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 1);
+       assert (reader.get_attribute ("level") == "3");
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 5);
+       assert (end.line == 5);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.END_ELEMENT);
+       assert (reader.name == "simpletag2");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 5);
+       assert (end.line == 5);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.START_ELEMENT);
+       assert (reader.name == "simpletag3");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 6);
+       assert (end.line == 6);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.END_ELEMENT);
+       assert (reader.name == "simpletag3");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 6);
+       assert (end.line == 6);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.END_ELEMENT);
+       assert (reader.name == "root-element");
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 7);
+       assert (end.line == 7);
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.EOF);
+       assert (reader.name == null);
+       assert (reader.content == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 7);
+       assert (end.line == 7);
+}
+
+
+public static void positive_2 () {
+       var reporter = new ErrorReporter ();
+
+       string content = "AA BB &amp; &quot;&apos; &lt; &gt; &percnt;";
+
+       var reader = new MarkupReader.from_string ("testfile", content, reporter);
+       assert (reader.filename == "testfile");
+
+       MarkupSourceLocation begin;
+       MarkupSourceLocation end;
+       MarkupTokenType token;
+
+       token = reader.read_token (out begin, out end);
+       assert (token == MarkupTokenType.TEXT);
+       assert (reader.content == "AA BB & \"' < > >");
+       assert (reader.name == null);
+       assert (reader.get_attributes ().size == 0);
+       assert (reporter.warnings == 0);
+       assert (reporter.errors == 0);
+       assert (begin.line == 1);
+       assert (end.line == 1);
+
+}
+
+
+public static void main () {
+       positive_1 ();
+       positive_2 ();
+}
+
diff --git a/valadoc/tests/libvaladoc/parser/generic-scanner.vala 
b/valadoc/tests/libvaladoc/parser/generic-scanner.vala
new file mode 100644
index 0000000..183bd5e
--- /dev/null
+++ b/valadoc/tests/libvaladoc/parser/generic-scanner.vala
@@ -0,0 +1,70 @@
+/* helpers.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+using Valadoc;
+
+
+public class TestScanner : Object, Valadoc.Scanner {
+       Valadoc.Parser parser;
+
+       Valadoc.TokenType[] seq = {};
+       bool _stop = false;
+       int pos = 0;
+
+       public void set_pattern (Valadoc.TokenType[] seq) {
+               this.seq = seq;
+       }
+
+       private void emit_token (Valadoc.TokenType type) throws Valadoc.ParserError {
+               Valadoc.SourceLocation loc = SourceLocation (pos, pos);
+               parser.accept_token (new Token.from_type (type, loc, loc));
+       }
+
+       public void set_parser (Valadoc.Parser parser) {
+               this.parser = parser;
+       }
+
+       public void reset () {
+               _stop = false;
+               pos = 0;
+       }
+
+       public void scan (string content) throws Valadoc.ParserError {
+               while (!_stop && pos < seq.length) {
+                       emit_token (seq[pos]);
+                       pos++;
+               }
+       }
+
+       public void end () throws Valadoc.ParserError {
+               emit_token (Valadoc.TokenType.EOF);
+       }
+
+       public void stop () {
+               _stop = true;
+       }
+
+       public string get_line_content () {
+               return "";
+       }
+}
+
diff --git a/valadoc/tests/libvaladoc/parser/manyrule.vala b/valadoc/tests/libvaladoc/parser/manyrule.vala
new file mode 100644
index 0000000..2af76d3
--- /dev/null
+++ b/valadoc/tests/libvaladoc/parser/manyrule.vala
@@ -0,0 +1,90 @@
+/* manyrule.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+using Valadoc;
+
+
+public static void main () {
+       var settings = new Valadoc.Settings ();
+       var scanner = new TestScanner ();
+       var reporter = new ErrorReporter ();
+       var parser = new Parser (settings, scanner, reporter);
+       scanner.set_parser (parser);
+
+       Rule rule = Rule.many ({
+                       Valadoc.TokenType.EQUAL_1
+               });
+
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_1
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // negative test:
+       bool reached = false;
+       try {
+               parser.set_root_rule (rule);
+               reached = false;
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_2
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               reached = true;
+       }
+
+       assert (reached);
+}
+
+
diff --git a/valadoc/tests/libvaladoc/parser/oneofrule.vala b/valadoc/tests/libvaladoc/parser/oneofrule.vala
new file mode 100644
index 0000000..5da7526
--- /dev/null
+++ b/valadoc/tests/libvaladoc/parser/oneofrule.vala
@@ -0,0 +1,99 @@
+/* oneofrule.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+using Valadoc;
+
+
+public static void main () {
+       var settings = new Valadoc.Settings ();
+       var scanner = new TestScanner ();
+       var reporter = new ErrorReporter ();
+       var parser = new Parser (settings, scanner, reporter);
+       scanner.set_parser (parser);
+
+       Rule rule = Rule.one_of ({
+                       Valadoc.TokenType.EQUAL_1,
+                       Valadoc.TokenType.EQUAL_2,
+                       Valadoc.TokenType.EQUAL_3
+               });
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_2
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_3
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // negative test:
+       bool reached = false;
+       try {
+               parser.set_root_rule (rule);
+               reached = false;
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_4
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               reached = true;
+       }
+
+       assert (reached);
+}
+
diff --git a/valadoc/tests/libvaladoc/parser/optionalrule.vala 
b/valadoc/tests/libvaladoc/parser/optionalrule.vala
new file mode 100644
index 0000000..b7b68ea
--- /dev/null
+++ b/valadoc/tests/libvaladoc/parser/optionalrule.vala
@@ -0,0 +1,84 @@
+/* optionalrule.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+using Valadoc;
+
+
+public static void main () {
+       var settings = new Valadoc.Settings ();
+       var scanner = new TestScanner ();
+       var reporter = new ErrorReporter ();
+       var parser = new Parser (settings, scanner, reporter);
+       scanner.set_parser (parser);
+
+       Rule rule = Rule.option ({
+                       Valadoc.TokenType.EQUAL_1
+               });
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // negative test:
+       bool reached = false;
+       try {
+               parser.set_root_rule (rule);
+               reached = false;
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_2
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               reached = true;
+       }
+
+       assert (reached);
+}
+
+
diff --git a/valadoc/tests/libvaladoc/parser/sequencerule.vala 
b/valadoc/tests/libvaladoc/parser/sequencerule.vala
new file mode 100644
index 0000000..13b4eec
--- /dev/null
+++ b/valadoc/tests/libvaladoc/parser/sequencerule.vala
@@ -0,0 +1,103 @@
+/* sequencerule.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+using Valadoc;
+
+
+public static void main () {
+       var settings = new Valadoc.Settings ();
+       var scanner = new TestScanner ();
+       var reporter = new ErrorReporter ();
+       var parser = new Parser (settings, scanner, reporter);
+       scanner.set_parser (parser);
+
+       Rule rule = Rule.seq ({
+                       Valadoc.TokenType.EQUAL_1,
+                       Valadoc.TokenType.EQUAL_2,
+                       Valadoc.TokenType.EQUAL_3,
+                       Valadoc.TokenType.EQUAL_4,
+                       Valadoc.TokenType.EQUAL_5
+               });
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_2,
+                               Valadoc.TokenType.EQUAL_3,
+                               Valadoc.TokenType.EQUAL_4,
+                               Valadoc.TokenType.EQUAL_5
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // negative test:
+       bool reached = false;
+       try {
+               parser.set_root_rule (rule);
+               reached = false;
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_2,
+                               Valadoc.TokenType.EQUAL_3
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               reached = true;
+       }
+
+       assert (reached);
+
+
+
+       // negative test:
+       try {
+               parser.set_root_rule (rule);
+               reached = false;
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_2,
+                               Valadoc.TokenType.EQUAL_4,
+                               Valadoc.TokenType.EQUAL_3,
+                               Valadoc.TokenType.EQUAL_5
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               reached = true;
+       }
+
+       assert (reached);
+
+}
+
+
diff --git a/valadoc/tests/libvaladoc/parser/stubrule.vala b/valadoc/tests/libvaladoc/parser/stubrule.vala
new file mode 100644
index 0000000..6a097fd
--- /dev/null
+++ b/valadoc/tests/libvaladoc/parser/stubrule.vala
@@ -0,0 +1,92 @@
+/* stubrule.vala
+ *
+ * Copyright (C) 2012       Florian Brosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Florian Brosch <flo brosch gmail com>
+ */
+
+using Valadoc;
+
+
+public static void main () {
+       var settings = new Valadoc.Settings ();
+       var scanner = new TestScanner ();
+       var reporter = new ErrorReporter ();
+       var parser = new Parser (settings, scanner, reporter);
+       scanner.set_parser (parser);
+
+       StubRule rule = new StubRule ();
+
+       Rule inner_rule = Rule.many ({
+                       Valadoc.TokenType.EQUAL_1
+               });
+
+       rule.set_rule (inner_rule);
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_1
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // positive test:
+       try {
+               parser.set_root_rule (rule);
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               assert_not_reached ();
+       }
+
+
+       // negative test:
+       bool reached = false;
+       try {
+               parser.set_root_rule (rule);
+               reached = false;
+
+               scanner.set_pattern ({
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_1,
+                               Valadoc.TokenType.EQUAL_2
+                       });
+
+               parser.parse ("", "", 0, 0);
+       } catch (Error e) {
+               reached = true;
+       }
+
+       assert (reached);
+}
+
+
diff --git a/valadoc/tests/testrunner.sh b/valadoc/tests/testrunner.sh
new file mode 100755
index 0000000..6f299df
--- /dev/null
+++ b/valadoc/tests/testrunner.sh
@@ -0,0 +1,129 @@
+#!/usr/bin/env bash
+# testrunner.sh
+#
+# Copyright (C) 2006-2008  Jürg Billeter
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+#
+# Author:
+#      Jürg Billeter <j bitron ch>
+
+builddir=$PWD
+topbuilddir=$TOPBUILDDIR
+topsrcdir=$TOPSRCDIR
+vapidir=$topsrcdir/vapi
+
+export G_DEBUG=fatal_warnings
+export PKG_CONFIG_PATH=$topbuilddir/libvaladoc
+export LD_LIBRARY_PATH=$topbuilddir/gee/.libs:$topbuilddir/libvaladoc/.libs
+
+VALAC=$topbuilddir/compiler/valac$EXEEXT
+VALAFLAGS="-X -D -X TOP_SRC_DIR=\"$topsrcdir\" --vapidir $vapidir --pkg libgvc --vapidir $topsrcdir/vala 
--pkg libvala$PACKAGE_SUFFIX --vapidir $topsrcdir/libvaladoc --pkg valadoc$PACKAGE_SUFFIX --disable-warnings 
--main main --save-temps -X -g -X -O0 -X -pipe -X -lm -X -Werror=return-type -X -Werror=init-self -X 
-Werror=implicit -X -Werror=sequence-point -X -Werror=return-type -X -Werror=uninitialized -X 
-Werror=pointer-arith -X -Werror=int-to-pointer-cast -X -Werror=pointer-to-int-cast -X -Wformat -X 
-Werror=format-security -X -Werror=format-nonliteral -X -Werror=redundant-decls -X -Werror=int-conversion -X 
-L$topbuilddir/gee/.libs -X -lgee -X -L$topbuilddir/libvaladoc/.libs -X -lvaladoc$PACKAGE_SUFFIX -X 
-I$topsrcdir/gee -X -I$topsrcdir/libvaladoc $topsrcdir/valadoc/tests/libvaladoc/parser/generic-scanner.vala 
$topsrcdir/valadoc/tests/drivers/generic-api-test.vala"
+
+# Incorporate the user's CFLAGS. Matters if the user decided to insert
+# -m32 in CFLAGS, for example.
+for cflag in ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}; do
+    VALAFLAGS="${VALAFLAGS} -X ${cflag}"
+done
+
+testdir=_test
+rm -rf $testdir
+mkdir $testdir
+cd $testdir
+
+echo -n -e "TEST: Building...\033[72G"
+
+cat << "EOF" > checkall
+all=0
+fail=0
+EOF
+
+cat << "EOF" > main.vala
+void main (string[] args) {
+       switch (args[1]) {
+EOF
+
+PACKAGES=gio-2.0
+SOURCEFILES=
+for testfile in "$@"; do
+       rm -f prepare check
+       echo 'set -e' >> prepare
+
+       case "$testfile" in
+       *.vala)
+               testpath=${testfile/.vala/}
+               ns=${testpath//\//.}
+               ns=${ns//-/_}
+               SOURCEFILE=$ns.vala
+               SOURCEFILES="$SOURCEFILES $SOURCEFILE"
+
+               echo "  case \"/$testpath\": $ns.main (); break;" >> main.vala
+               echo "namespace $ns {" > $SOURCEFILE
+               cat "$topsrcdir/valadoc/tests/$testfile" >> $SOURCEFILE
+               echo "}" >> $SOURCEFILE
+
+               echo "./test$EXEEXT /$testpath" > check
+               ;;
+       esac
+
+       cat prepare check > $ns.check
+       cat << EOF >> checkall
+echo -n -e "  /$testpath: \033[72G"
+((all++))
+if bash $ns.check &>log; then
+       echo -e "\033[0;32mOK\033[m"
+else
+       ((fail++))
+       echo -e "\033[0;31mFAIL\033[m"
+       cat log
+fi
+EOF
+done
+
+cat << "EOF" >> checkall
+if [ $fail -eq 0 ]; then
+       echo "All $all tests passed"
+else
+       echo "$fail of $all tests failed"
+       exit 1
+fi
+EOF
+
+cat << "EOF" >> main.vala
+       default: assert_not_reached ();
+       }
+}
+EOF
+
+cat $SOURCEFILES >> main.vala
+
+if $VALAC $VALAFLAGS -o test$EXEEXT $([ -z "$PACKAGES" ] || echo $PACKAGES | xargs -n 1 echo -n " --pkg") 
main.vala &>log; then
+       echo -e "\033[0;32mOK\033[m"
+else
+       echo -e "\033[0;31mFAIL\033[m"
+       cat log
+
+       cd $builddir
+       exit 1
+fi
+
+if bash checkall; then
+       cd $builddir
+       rm -rf $testdir
+else
+       cd $builddir
+       exit 1
+fi
+
diff --git a/valadoc/treebuilder.vala b/valadoc/treebuilder.vala
new file mode 100644
index 0000000..7615eb8
--- /dev/null
+++ b/valadoc/treebuilder.vala
@@ -0,0 +1,1535 @@
+/* treebuilder.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.Api;
+
+/**
+ * Creates an simpler, minimized, more abstract AST for valacs AST.
+ */
+public class Valadoc.Drivers.TreeBuilder : Vala.CodeVisitor {
+       private Vala.ArrayList<PackageMetaData> packages = new Vala.ArrayList<PackageMetaData> ();
+       private PackageMetaData source_package;
+
+       private Vala.HashMap<Vala.SourceFile, SourceFile> files = new Vala.HashMap<Vala.SourceFile, 
SourceFile> ();
+       private Vala.HashMap<Vala.Symbol, Symbol> symbol_map = new Vala.HashMap<Vala.Symbol, Symbol> ();
+
+       private ErrorReporter reporter;
+       private Settings settings;
+
+       private Api.Node current_node;
+       private Api.Tree tree;
+
+       private Valadoc.Api.Class glib_error = null;
+
+
+       //
+       // Accessors
+       //
+
+       public Api.Class get_glib_error () {
+               return glib_error;
+       }
+
+       public Vala.HashMap<Vala.Symbol, Symbol> get_symbol_map () {
+               return symbol_map;
+       }
+
+
+       //
+       //
+       //
+
+       private class PackageMetaData {
+               public Package package;
+               public Vala.HashMap<Vala.Namespace, Namespace> namespaces = new Vala.HashMap<Vala.Namespace, 
Namespace> ();
+               public Vala.ArrayList<Vala.SourceFile> files = new Vala.ArrayList<Vala.SourceFile> ();
+
+               public PackageMetaData (Package package) {
+                       this.package = package;
+               }
+
+               public Namespace get_namespace (Vala.Namespace vns, SourceFile file) {
+                       Namespace? ns = namespaces.get (vns);
+                       if (ns != null) {
+                               return ns;
+                       }
+
+                       // find documentation comment if existing:
+                       SourceComment? comment = null;
+                       if (vns.source_reference != null) {
+                               foreach (Vala.Comment c in vns.get_comments()) {
+                                       if (c.source_reference.file == file.data ||
+                                               (c.source_reference.file.file_type == 
Vala.SourceFileType.SOURCE
+                                                && ((Vala.SourceFile) file.data).file_type == 
Vala.SourceFileType.SOURCE)
+                                       ) {
+                                               Vala.SourceReference pos = c.source_reference;
+                                               if (c is Vala.GirComment) {
+                                                       comment = new GirSourceComment (c.content,
+                                                                                                             
          file,
+                                                                                                             
          pos.begin.line,
+                                                                                                             
          pos.begin.column,
+                                                                                                             
          pos.end.line,
+                                                                                                             
          pos.end.column);
+                                               } else {
+                                                       comment = new SourceComment (c.content,
+                                                                                                             
   file,
+                                                                                                             
   pos.begin.line,
+                                                                                                             
   pos.begin.column,
+                                                                                                             
   pos.end.line,
+                                                                                                             
   pos.end.column);
+                                               }
+                                               break;
+                                       }
+                               }
+                       }
+
+                       // find parent if existing
+                       var parent_vns = vns.parent_symbol;
+
+                       if (parent_vns == null) {
+                               ns = new Namespace (package, file, vns.name, comment, vns);
+                               package.add_child (ns);
+                       } else {
+                               Namespace parent_ns = get_namespace ((Vala.Namespace) parent_vns, file);
+                               ns = new Namespace (parent_ns, file, vns.name, comment, vns);
+                               parent_ns.add_child (ns);
+                       }
+
+                       namespaces.set (vns, ns);
+                       return ns;
+               }
+
+               public void register_source_file (Vala.SourceFile file) {
+                       files.add (file);
+               }
+
+               public bool is_package_for_file (Vala.SourceFile source_file) {
+                       if (source_file.file_type == Vala.SourceFileType.SOURCE && !package.is_package) {
+                               return true;
+                       }
+
+                       return files.contains (source_file);
+               }
+       }
+
+
+       //
+       // Type constructor translation helpers:
+       //
+
+       private Pointer create_pointer (Vala.PointerType vtyperef, Item parent, Api.Node caller) {
+               Pointer ptr = new Pointer (parent, vtyperef);
+
+               Vala.DataType vntype = vtyperef.base_type;
+               if (vntype is Vala.PointerType) {
+                       ptr.data_type = create_pointer ((Vala.PointerType) vntype, ptr, caller);
+               } else if (vntype is Vala.ArrayType) {
+                       ptr.data_type = create_array ((Vala.ArrayType) vntype, ptr, caller);
+               } else {
+                       ptr.data_type = create_type_reference (vntype, ptr, caller);
+               }
+
+               return ptr;
+       }
+
+       private Api.Array create_array (Vala.ArrayType vtyperef, Item parent, Api.Node caller) {
+               Api.Array arr = new Api.Array (parent, vtyperef);
+
+               Vala.DataType vntype = vtyperef.element_type;
+               if (vntype is Vala.ArrayType) {
+                       arr.data_type = create_type_reference (vntype, arr, caller);
+               } else {
+                       arr.data_type = create_type_reference (vntype, arr, caller);
+               }
+
+               return arr;
+       }
+
+       private TypeReference create_type_reference (Vala.DataType? vtyperef, Item parent, Api.Node caller) {
+               bool is_nullable = vtyperef != null
+                       && vtyperef.nullable
+                       && !(vtyperef is Vala.GenericType)
+                       && !(vtyperef is Vala.PointerType);
+               string? signature = (vtyperef != null
+                       && vtyperef.data_type != null)? Vala.GVariantModule.get_dbus_signature 
(vtyperef.data_type) : null;
+               bool pass_ownership = type_reference_pass_ownership (vtyperef);
+               Ownership ownership = get_type_reference_ownership (vtyperef);
+               bool is_dynamic = vtyperef != null && vtyperef.is_dynamic;
+
+               TypeReference type_ref = new TypeReference (parent,
+                                                                                                       
ownership,
+                                                                                                       
pass_ownership,
+                                                                                                       
is_dynamic,
+                                                                                                       
is_nullable,
+                                                                                                       
signature,
+                                                                                                       
vtyperef);
+
+               if (vtyperef is Vala.PointerType) {
+                       type_ref.data_type = create_pointer ((Vala.PointerType) vtyperef,  type_ref, caller);
+               } else if (vtyperef is Vala.ArrayType) {
+                       type_ref.data_type = create_array ((Vala.ArrayType) vtyperef,  type_ref, caller);
+               //} else if (vtyperef is Vala.GenericType) {
+               //      type_ref.data_type = new TypeParameter (caller,
+               //                                                                                      
caller.get_source_file (),
+               //                                                                                      
((Vala.GenericType) vtyperef).type_parameter.name,
+               //                                                                                      
vtyperef);
+               }
+
+               // type parameters:
+               if (vtyperef != null) {
+                       foreach (Vala.DataType vdtype in vtyperef.get_type_arguments ()) {
+                               var type_param = create_type_reference (vdtype, type_ref, caller);
+                               type_ref.add_type_argument (type_param);
+                       }
+               }
+
+               return type_ref;
+       }
+
+
+
+       //
+       // Translation helpers:
+       //
+
+       private void process_attributes (Api.Symbol parent, GLib.List<Vala.Attribute> lst) {
+               // attributes without arguments:
+               string[] attributes = {
+                               "ReturnsModifiedPointer",
+                               "DestroysInstance",
+                               "GenericAccessors",
+                               "NoAccessorMethod",
+                               "NoArrayLength",
+                               "Experimental",
+                               "Diagnostics",
+                               "PrintfFormat",
+                               "PointerType",
+                               "ScanfFormat",
+                               "ThreadLocal",
+                               "SimpleType",
+                               "HasEmitter",
+                               "ModuleInit",
+                               "NoWrapper",
+                               "Immutable",
+                               "ErrorBase",
+                               "NoReturn",
+                               "NoThrow",
+                               "Compact",
+                               "Assert",
+                               "Flags"
+                       };
+
+               string? tmp = "";
+
+               foreach (Vala.Attribute att in lst) {
+                       if (att.name == "CCode" && (tmp = att.args.get ("has_target")) != null && tmp == 
"false") {
+                               Attribute new_attribute = new Attribute (parent, parent.get_source_file (), 
att.name, att);
+                               new_attribute.add_boolean ("has_target", false, att);
+                               parent.add_attribute (new_attribute);
+                       } else if (att.name == "Version") {
+                               Attribute new_attribute = new Attribute (parent, parent.get_source_file (), 
att.name, att);
+                               if ((tmp = att.args.get ("deprecated")) != null) {
+                                       new_attribute.add_boolean ("deprecated", bool.parse (tmp), att);
+                               }
+                               if ((tmp = att.args.get ("since")) != null) {
+                                       new_attribute.add_string ("since", tmp, att);
+                               }
+                               if ((tmp = att.args.get ("deprecated_since")) != null) {
+                                       new_attribute.add_string ("deprecated_since", tmp, att);
+                                       if (att.args.get ("deprecated") == null) {
+                                               new_attribute.add_boolean ("deprecated", true, att);
+                                       }
+                               }
+                               if ((tmp = att.args.get ("replacement")) != null) {
+                                       new_attribute.add_string ("replacement", tmp, att);
+                               }
+                               parent.add_attribute (new_attribute);
+                       } else if (att.name == "Deprecated") {
+                               Attribute new_attribute = new Attribute (parent, parent.get_source_file (), 
att.name, att);
+                               if ((tmp = att.args.get ("since")) != null) {
+                                       new_attribute.add_string ("since", tmp, att);
+                               }
+                               if ((tmp = att.args.get ("replacement")) != null) {
+                                       new_attribute.add_string ("replacement", tmp, att);
+                               }
+                               parent.add_attribute (new_attribute);
+                       } else if (att.name in attributes) {
+                               Attribute new_attribute = new Attribute (parent, parent.get_source_file (), 
att.name, att);
+                               parent.add_attribute (new_attribute);
+                       }
+               }
+       }
+
+       private string? get_ccode_type_id (Vala.CodeNode node) {
+               return Vala.CCodeBaseModule.get_ccode_type_id (node);
+       }
+
+       private bool is_reference_counting (Vala.TypeSymbol sym) {
+               return Vala.CCodeBaseModule.is_reference_counting (sym);
+       }
+
+       private string? get_ref_function (Vala.Class sym) {
+               return Vala.CCodeBaseModule.get_ccode_ref_function (sym);
+       }
+
+       private string? get_unref_function (Vala.Class sym) {
+               return Vala.CCodeBaseModule.get_ccode_unref_function (sym);
+       }
+
+       private string? get_finalize_function_name (Vala.Class element) {
+               if (!element.is_fundamental ()) {
+                       return null;
+               }
+
+               return "%s_finalize".printf (Vala.CCodeBaseModule.get_ccode_lower_case_name (element, null));
+       }
+
+       private string? get_free_function_name (Vala.Class element) {
+               if (!element.is_compact) {
+                       return null;
+               }
+
+               return Vala.CCodeBaseModule.get_ccode_free_function (element);
+       }
+
+       private string? get_finish_name (Vala.Method m) {
+               return Vala.CCodeBaseModule.get_ccode_finish_name (m);
+       }
+
+       private string? get_take_value_function (Vala.Class sym) {
+               return Vala.CCodeBaseModule.get_ccode_take_value_function (sym);
+       }
+
+       private string? get_get_value_function (Vala.Class sym) {
+               return Vala.CCodeBaseModule.get_ccode_get_value_function (sym);
+       }
+
+       private string? get_set_value_function (Vala.Class sym) {
+               return Vala.CCodeBaseModule.get_ccode_set_value_function (sym);
+       }
+
+
+       private string? get_param_spec_function (Vala.CodeNode sym) {
+               return Vala.CCodeBaseModule.get_ccode_param_spec_function (sym);
+       }
+
+       private string? get_dup_function (Vala.TypeSymbol sym) {
+               return Vala.CCodeBaseModule.get_ccode_dup_function (sym);
+       }
+
+       private string? get_copy_function (Vala.TypeSymbol sym) {
+               return Vala.CCodeBaseModule.get_ccode_copy_function (sym);
+       }
+
+       private string? get_destroy_function (Vala.TypeSymbol sym) {
+               return Vala.CCodeBaseModule.get_ccode_destroy_function (sym);
+       }
+
+       private string? get_free_function (Vala.TypeSymbol sym) {
+               return Vala.CCodeBaseModule.get_ccode_free_function (sym);
+       }
+
+       private string? get_cname (Vala.Symbol symbol) {
+               return Vala.CCodeBaseModule.get_ccode_name (symbol);
+       }
+
+       private SourceComment? create_comment (Vala.Comment? comment) {
+               if (comment != null) {
+                       Vala.SourceReference pos = comment.source_reference;
+                       SourceFile file = files.get (pos.file);
+                       if (comment is Vala.GirComment) {
+                               var tmp = new GirSourceComment (comment.content,
+                                                                                               file,
+                                                                                               
pos.begin.line,
+                                                                                               
pos.begin.column,
+                                                                                               pos.end.line,
+                                                                                               
pos.end.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.begin.line,
+                                                                                                             
          return_pos.begin.column,
+                                                                                                             
          return_pos.end.line,
+                                                                                                             
          return_pos.end.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.begin.line,
+                                                                                                             
     param_pos.begin.column,
+                                                                                                             
     param_pos.end.line,
+                                                                                                             
     param_pos.end.column);
+                                       tmp.add_parameter_content (it.get_key (), param_comment);
+                               }
+                               return tmp;
+                       } else {
+                               return new SourceComment (comment.content,
+                                                                                 file,
+                                                                                 pos.begin.line,
+                                                                                 pos.begin.column,
+                                                                                 pos.end.line,
+                                                                                 pos.end.column);
+                       }
+               }
+
+               return null;
+       }
+
+       private string get_method_name (Vala.Method element) {
+               if (element is Vala.CreationMethod) {
+                       if (element.name == ".new") {
+                               return element.parent_symbol.name;
+                       } else {
+                               return element.parent_symbol.name + "." + element.name;
+                       }
+               }
+
+               return element.name;
+       }
+
+       private string? get_quark_macro_name (Vala.ErrorDomain element) {
+               return Vala.CCodeBaseModule.get_ccode_upper_case_name (element, null);
+       }
+
+       private string? get_private_cname (Vala.Class element) {
+               if (element.is_compact) {
+                       return null;
+               }
+
+               string? cname = get_cname (element);
+               return (cname != null)? cname + "Private" : null;
+       }
+
+       private string? get_class_macro_name (Vala.Class element) {
+               if (element.is_compact) {
+                       return null;
+               }
+
+               return "%s_GET_CLASS".printf (Vala.CCodeBaseModule.get_ccode_upper_case_name (element, null));
+       }
+
+       private string? get_class_type_macro_name (Vala.Class element) {
+               if (element.is_compact) {
+                       return null;
+               }
+
+               return "%s_CLASS".printf (Vala.CCodeBaseModule.get_ccode_upper_case_name (element, null));
+       }
+
+       private string? get_is_type_macro_name (Vala.TypeSymbol element) {
+               string? name = Vala.CCodeBaseModule.get_ccode_type_check_function (element);
+               return (name != null && name != "")? name : null;
+       }
+
+       private string? get_is_class_type_macro_name (Vala.TypeSymbol element) {
+               string? name = get_is_type_macro_name (element);
+               return (name != null)? name + "_CLASS" : null;
+       }
+
+       private string? get_type_function_name (Vala.TypeSymbol element) {
+               if ((element is Vala.Class
+                       && ((Vala.Class) element).is_compact)
+                       || element is Vala.ErrorDomain
+                       || element is Vala.Delegate)
+               {
+                       return null;
+               }
+
+               return "%s_get_type".printf (Vala.CCodeBaseModule.get_ccode_lower_case_name (element, null));
+       }
+
+       private string? get_type_macro_name (Vala.TypeSymbol element) {
+               if ((element is Vala.Class
+                       && ((Vala.Class) element).is_compact)
+                       || element is Vala.ErrorDomain
+                       || element is Vala.Delegate)
+               {
+                       return null;
+               }
+
+               return Vala.CCodeBaseModule.get_ccode_type_id (element);
+       }
+
+       private string? get_type_cast_macro_name (Vala.TypeSymbol element) {
+               if ((element is Vala.Class
+                       && !((Vala.Class) element).is_compact)
+                       || element is Vala.Interface)
+               {
+                       return Vala.CCodeBaseModule.get_ccode_upper_case_name (element, null);
+               } else {
+                       return null;
+               }
+       }
+
+       private string? get_interface_macro_name (Vala.Interface element) {
+               return "%s_GET_INTERFACE".printf (Vala.CCodeBaseModule.get_ccode_upper_case_name (element, 
null));
+       }
+
+       private string get_quark_function_name (Vala.ErrorDomain element) {
+               return Vala.CCodeBaseModule.get_ccode_lower_case_prefix (element) + "quark";
+       }
+
+       private PackageMetaData? get_package_meta_data (Package pkg) {
+               foreach (PackageMetaData data in packages) {
+                       if (data.package == pkg) {
+                               return data;
+                       }
+               }
+
+               return null;
+       }
+
+       private PackageMetaData register_package (Package package) {
+               PackageMetaData meta_data = new PackageMetaData (package);
+               tree.add_package (package);
+               packages.add (meta_data);
+               return meta_data;
+       }
+
+       private SourceFile register_source_file (PackageMetaData meta_data, Vala.SourceFile source_file) {
+               SourceFile file = new SourceFile (meta_data.package,
+                                                                                 
source_file.get_relative_filename (),
+                                                                                 
source_file.get_csource_filename (),
+                                                                                 source_file);
+               files.set (source_file, file);
+
+               meta_data.register_source_file (source_file);
+               return file;
+       }
+
+       private SourceFile? get_source_file (Vala.Symbol symbol) {
+               Vala.SourceReference source_ref = symbol.source_reference;
+               if (source_ref == null) {
+                       return null;
+               }
+
+               SourceFile? file = files.get (source_ref.file);
+               assert (file != null);
+               return file;
+       }
+
+       private Package? find_package_for_file (Vala.SourceFile source_file) {
+               foreach (PackageMetaData pkg in this.packages) {
+                       if (pkg.is_package_for_file (source_file)) {
+                               return pkg.package;
+                       }
+               }
+
+               return null;
+       }
+
+
+       private Namespace get_namespace (Package pkg, Vala.Symbol symbol, SourceFile? file) {
+               // Find the closest namespace in our vala-tree
+               Vala.Symbol namespace_symbol = symbol;
+               while (!(namespace_symbol is Vala.Namespace)) {
+                       namespace_symbol = namespace_symbol.parent_symbol;
+               }
+
+               PackageMetaData? meta_data = get_package_meta_data (pkg);
+               assert (meta_data != null);
+
+               return meta_data.get_namespace ((Vala.Namespace) namespace_symbol, file);
+       }
+
+       private MethodBindingType get_method_binding_type (Vala.Method element) {
+               if (element.is_inline) {
+                       return MethodBindingType.INLINE;
+               } else if (element.is_abstract) {
+                       return MethodBindingType.ABSTRACT;
+               } else if (element.is_virtual) {
+                       return MethodBindingType.VIRTUAL;
+               } else if (element.overrides) {
+                       return MethodBindingType.OVERRIDE;
+               } else if (element.is_inline) {
+                       return MethodBindingType.INLINE;
+               } else if (element.binding != Vala.MemberBinding.INSTANCE) {
+                       return MethodBindingType.STATIC;
+               }
+               return MethodBindingType.UNMODIFIED;
+       }
+
+
+       private SymbolAccessibility get_access_modifier(Vala.Symbol symbol) {
+               switch (symbol.access) {
+               case Vala.SymbolAccessibility.PROTECTED:
+                       return SymbolAccessibility.PROTECTED;
+
+               case Vala.SymbolAccessibility.INTERNAL:
+                       return SymbolAccessibility.INTERNAL;
+
+               case Vala.SymbolAccessibility.PRIVATE:
+                       return SymbolAccessibility.PRIVATE;
+
+               case Vala.SymbolAccessibility.PUBLIC:
+                       return SymbolAccessibility.PUBLIC;
+
+               default:
+                       error ("Unknown symbol accessibility modifier found");
+               }
+       }
+
+       private PropertyAccessorType get_property_accessor_type (Vala.PropertyAccessor element) {
+               if (element.construction) {
+                       if (element.writable) {
+                               return (PropertyAccessorType.CONSTRUCT | PropertyAccessorType.SET);
+                       }
+                       return PropertyAccessorType.CONSTRUCT;
+               } else if (element.writable) {
+                       return PropertyAccessorType.SET;
+               } else if (element.readable) {
+                       return PropertyAccessorType.GET;
+               }
+
+               error ("Unknown symbol accessibility type");
+       }
+
+       private bool type_reference_pass_ownership (Vala.DataType? element) {
+               if (element == null) {
+                       return false;
+               }
+
+               weak Vala.CodeNode? node = element.parent_node;
+               if (node == null) {
+                       return false;
+               }
+               if (node is Vala.Parameter) {
+                       return (((Vala.Parameter)node).direction == Vala.ParameterDirection.IN &&
+                               ((Vala.Parameter)node).variable_type.value_owned);
+               }
+               if (node is Vala.Property) {
+                       return ((Vala.Property)node).property_type.value_owned;
+               }
+
+               return false;
+       }
+
+       private bool is_type_reference_unowned (Vala.DataType? element) {
+                       if (element == null) {
+                               return false;
+                       }
+
+                       // non ref counted types are weak, not unowned
+                       if (element.data_type is Vala.TypeSymbol
+                               && is_reference_counting ((Vala.TypeSymbol) element.data_type) == true)
+                       {
+                               return false;
+                       }
+
+                       // FormalParameters are weak by default
+                       return (element.parent_node is Vala.Parameter == false)
+                               ? element.is_weak ()
+                               : false;
+       }
+
+       private bool is_type_reference_owned (Vala.DataType? element) {
+               if (element == null) {
+                       return false;
+               }
+
+               weak Vala.CodeNode parent = element.parent_node;
+
+               // parameter:
+               if (parent is Vala.Parameter) {
+                       if (((Vala.Parameter)parent).direction != Vala.ParameterDirection.IN) {
+                               return false;
+                       }
+                       return ((Vala.Parameter)parent).variable_type.value_owned;
+               }
+
+               return false;
+       }
+
+       private bool is_type_reference_weak (Vala.DataType? element) {
+               if (element == null) {
+                       return false;
+               }
+
+               // non ref counted types are unowned, not weak
+               if (element.data_type is Vala.TypeSymbol
+                       && is_reference_counting ((Vala.TypeSymbol) element.data_type) == false)
+               {
+                       return false;
+               }
+
+               // arrays are unowned, not weak
+               if (element is Vala.ArrayType) {
+                       return false;
+               }
+
+               // FormalParameters are weak by default
+               return (element.parent_node is Vala.Parameter == false)? element.is_weak () : false;
+       }
+
+       private Ownership get_type_reference_ownership (Vala.DataType? element) {
+               if (is_type_reference_owned (element)) {
+                       return Ownership.OWNED;
+               } else if (is_type_reference_weak (element)) {
+                       return Ownership.WEAK;
+               } else if (is_type_reference_unowned (element)) {
+                       return Ownership.UNOWNED;
+               }
+
+               return Ownership.DEFAULT;
+       }
+
+       private Ownership get_property_ownership (Vala.PropertyAccessor element) {
+               if (element.value_type.value_owned) {
+                       return Ownership.OWNED;
+               }
+
+               // the exact type (weak, unowned) does not matter
+               return Ownership.UNOWNED;
+       }
+
+       private PropertyBindingType get_property_binding_type (Vala.Property element) {
+               if (element.is_abstract) {
+                       return PropertyBindingType.ABSTRACT;
+               } else if (element.is_virtual) {
+                       return PropertyBindingType.VIRTUAL;
+               } else if (element.overrides) {
+                       return PropertyBindingType.OVERRIDE;
+               }
+
+               return PropertyBindingType.UNMODIFIED;
+       }
+
+       private FormalParameterType get_formal_parameter_type (Vala.Parameter element) {
+               if (element.direction == Vala.ParameterDirection.OUT) {
+                       return FormalParameterType.OUT;
+               } else if (element.direction == Vala.ParameterDirection.REF) {
+                       return FormalParameterType.REF;
+               } else if (element.direction == Vala.ParameterDirection.IN) {
+                       return FormalParameterType.IN;
+               }
+
+               error ("Unknown formal parameter type");
+       }
+
+
+       //
+       // 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)) {
+                       return true;
+               }
+
+               string vapi_name = pkg + ".vapi";
+               string gir_name = pkg + ".gir";
+               foreach (string source_file in settings.source_files) {
+                       string basename = Path.get_basename (source_file);
+                       if (basename == vapi_name || basename == gir_name) {
+                               return true;
+                       }
+               }
+
+
+               var package_path = context.get_vapi_path (pkg) ?? context.get_gir_path (pkg);
+               if (package_path == null) {
+                       Vala.Report.error (null, "Package `%s' not found in specified Vala API directories or 
GObject-Introspection GIR directories".printf (pkg));
+                       return false;
+               }
+
+               context.add_package (pkg);
+
+               var vfile = new Vala.SourceFile (context, Vala.SourceFileType.PACKAGE, package_path);
+               context.add_source_file (vfile);
+               Package vdpkg = new Package (pkg, true, null);
+               register_source_file (register_package (vdpkg), vfile);
+
+               add_deps (context, Path.build_filename (Path.get_dirname (package_path), "%s.deps".printf 
(pkg)), pkg);
+               return true;
+       }
+
+       private void add_deps (Vala.CodeContext context, 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 = dep.strip ();
+                                       if (dep != "") {
+                                               if (!add_package (context, 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));
+                       }
+               }
+       }
+
+       /**
+        * Adds the specified packages to the list of used packages.
+        *
+        * @param context The code context
+        * @param packages a list of package names
+        */
+       private void add_depencies (Vala.CodeContext context, string[] packages) {
+               foreach (string package in packages) {
+                       if (!add_package (context, package)) {
+                               Vala.Report.error (null, "Package `%s' not found in specified Vala API 
directories or GObject-Introspection GIR directories".printf (package));
+                       }
+               }
+       }
+
+       /**
+        * Add the specified source file to the context. Only .vala, .vapi, .gs,
+        * and .c files are supported.
+        */
+       private void add_documented_files (Vala.CodeContext context, string[] sources) {
+               if (sources == null) {
+                       return;
+               }
+
+               foreach (string source in sources) {
+                       if (FileUtils.test (source, FileTest.EXISTS)) {
+                               var rpath = realpath (source);
+                               if (source.has_suffix (".vala") || source.has_suffix (".gs")) {
+                                       var source_file = new Vala.SourceFile (context, 
Vala.SourceFileType.SOURCE, rpath);
+
+                                       if (source_package == null) {
+                                               source_package = register_package (new Package 
(settings.pkg_name, false, null));
+                                       }
+
+                                       register_source_file (source_package, source_file);
+
+                                       if (context.profile == Vala.Profile.GOBJECT) {
+                                               // import the GLib namespace by default (namespace of 
backend-specific standard library)
+                                               var ns_ref = new Vala.UsingDirective (new 
Vala.UnresolvedSymbol (null, "GLib", null));
+                                               source_file.add_using_directive (ns_ref);
+                                               context.root.add_using_directive (ns_ref);
+                                       }
+
+                                       context.add_source_file (source_file);
+                               } else if (source.has_suffix (".vapi") || source.has_suffix (".gir")) {
+                                       string file_name = get_package_name (source);
+
+                                       var vfile = new Vala.SourceFile (context, 
Vala.SourceFileType.PACKAGE, rpath);
+                                       context.add_source_file (vfile);
+
+                                       if (source_package == null) {
+                                               source_package = register_package (new Package 
(settings.pkg_name, false, null));
+                                       }
+
+                                       register_source_file (source_package, vfile);
+
+                                       add_deps (context, 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);
+                                       tree.add_external_c_files (rpath);
+                               } else {
+                                       Vala.Report.error (null, "%s is not a supported source file type. 
Only .vala, .vapi, .gs, and .c files are supported.".printf (source));
+                               }
+                       } else {
+                               Vala.Report.error (null, "%s not found".printf (source));
+                       }
+               }
+       }
+
+       private Vala.CodeContext create_valac_tree (Settings settings) {
+               // init context:
+               var context = new Vala.CodeContext ();
+               Vala.CodeContext.push (context);
+
+
+               // settings:
+               context.experimental = settings.experimental;
+               context.experimental_non_null = settings.experimental || settings.experimental_non_null;
+               context.vapi_directories = settings.vapi_directories;
+               context.report.enable_warnings = settings.verbose;
+               context.metadata_directories = settings.metadata_directories;
+               context.gir_directories = settings.gir_directories;
+
+               if (settings.basedir == null) {
+                       context.basedir = realpath (".");
+               } else {
+                       context.basedir = realpath (settings.basedir);
+               }
+
+               if (settings.directory != null) {
+                       context.directory = realpath (settings.directory);
+               } else {
+                       context.directory = context.basedir;
+               }
+
+
+               // add default packages:
+               if (settings.profile == "gobject-2.0" || settings.profile == "gobject" || settings.profile == 
null) {
+                       context.profile = Vala.Profile.GOBJECT;
+                       context.add_define ("GOBJECT");
+               }
+
+
+               if (settings.defines != null) {
+                       foreach (string define in settings.defines) {
+                               context.add_define (define);
+                       }
+               }
+
+               for (int i = 2; i <= 38; i += 2) {
+                       context.add_define ("VALA_0_%d".printf (i));
+               }
+
+               if (context.profile == Vala.Profile.GOBJECT) {
+                       int glib_major = 2;
+                       int glib_minor = 24;
+
+                       context.target_glib_major = glib_major;
+                       context.target_glib_minor = glib_minor;
+                       if (context.target_glib_major != 2) {
+                               Vala.Report.error (null, "This version of valac only supports GLib 2");
+                       }
+
+                       if (settings.target_glib != null && settings.target_glib.scanf ("%d.%d", out 
glib_major, out glib_minor) != 2) {
+                               Vala.Report.error (null, "Invalid format for --target-glib");
+                       }
+
+                       context.target_glib_major = glib_major;
+                       context.target_glib_minor = glib_minor;
+                       if (context.target_glib_major != 2) {
+                               Vala.Report.error (null, "This version of valac only supports GLib 2");
+                       }
+
+                       for (int i = 16; i <= glib_minor; i += 2) {
+                               context.add_define ("GLIB_2_%d".printf (i));
+                       }
+
+                       // default packages
+                       if (!this.add_package (context, "glib-2.0")) { //
+                               Vala.Report.error (null, "glib-2.0 not found in specified Vala API 
directories");
+                       }
+
+                       if (!this.add_package (context, "gobject-2.0")) { //
+                               Vala.Report.error (null, "gobject-2.0 not found in specified Vala API 
directories");
+                       }
+               }
+
+               // add user defined files:
+               add_depencies (context, settings.packages);
+               if (reporter.errors > 0) {
+                       return context;
+               }
+
+               add_documented_files (context, settings.source_files);
+               if (reporter.errors > 0) {
+                       return context;
+               }
+
+
+               // parse vala-code:
+               Vala.Parser parser = new Vala.Parser ();
+
+               parser.parse (context);
+               if (context.report.get_errors () > 0) {
+                       return context;
+               }
+
+               // parse gir:
+               Vala.GirParser gir_parser = new Vala.GirParser ();
+
+               gir_parser.parse (context);
+               if (context.report.get_errors () > 0) {
+                       return context;
+               }
+
+
+
+               // check context:
+               context.check ();
+               if (context.report.get_errors () > 0) {
+                       return context;
+               }
+
+               return context;
+       }
+
+
+
+       //
+       // Valadoc tree creation:
+       //
+
+       private void process_children (Api.Node node, Vala.CodeNode element) {
+               Api.Node old_node = current_node;
+               current_node = node;
+               element.accept_children (this);
+               current_node = old_node;
+       }
+
+       private Api.Node get_parent_node_for (Vala.Symbol element) {
+               if (current_node != null) {
+                       return current_node;
+               }
+
+               Vala.SourceFile vala_source_file = element.source_reference.file;
+               Package package = find_package_for_file (vala_source_file);
+               SourceFile? source_file = get_source_file (element);
+
+               return get_namespace (package, element, source_file);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_namespace (Vala.Namespace element) {
+               element.accept_children (this);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_class (Vala.Class element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               bool is_basic_type = element.base_class == null && element.name == "string";
+
+               Class node = new Class (parent,
+                                                               file,
+                                                               element.name,
+                                                               get_access_modifier (element),
+                                                               comment,
+                                                               get_cname (element),
+                                                               get_private_cname (element),
+                                                               get_class_macro_name (element),
+                                                               get_type_macro_name (element),
+                                                               get_is_type_macro_name (element),
+                                                               get_type_cast_macro_name (element),
+                                                               get_type_function_name (element),
+                                                               get_class_type_macro_name (element),
+                                                               get_is_class_type_macro_name (element),
+                                                               Vala.GDBusModule.get_dbus_name (element),
+                                                               get_ccode_type_id (element),
+                                                               get_param_spec_function (element),
+                                                               get_ref_function (element),
+                                                               get_unref_function (element),
+                                                               get_free_function_name (element),
+                                                               get_finalize_function_name (element),
+                                                               get_take_value_function (element),
+                                                               get_get_value_function (element),
+                                                               get_set_value_function (element),
+                                                               element.is_fundamental (),
+                                                               element.is_abstract,
+                                                               is_basic_type,
+                                                               element);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               // relations
+               foreach (Vala.DataType vala_type_ref in element.get_base_types ()) {
+                       var type_ref = create_type_reference (vala_type_ref, node, node);
+
+                       if (vala_type_ref.data_type is Vala.Interface) {
+                               node.add_interface (type_ref);
+                       } else if (vala_type_ref.data_type is Vala.Class) {
+                               node.base_type = type_ref;
+                       }
+               }
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+
+               // save GLib.Error
+               if (glib_error == null && node.get_full_name () == "GLib.Error") {
+                       glib_error = node;
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_interface (Vala.Interface element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Interface node = new Interface (parent,
+                                                                               file,
+                                                                               element.name,
+                                                                               get_access_modifier (element),
+                                                                               comment,
+                                                                               get_cname (element),
+                                                                               get_type_macro_name (element),
+                                                                               get_is_type_macro_name 
(element),
+                                                                               get_type_cast_macro_name 
(element),
+                                                                               get_type_function_name 
(element),
+                                                                               get_interface_macro_name 
(element),
+                                                                               
Vala.GDBusModule.get_dbus_name (element),
+                                                                               element);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               // prerequisites:
+               foreach (Vala.DataType vala_type_ref in element.get_prerequisites ()) {
+                       TypeReference type_ref = create_type_reference (vala_type_ref, node, node);
+                       if (vala_type_ref.data_type is Vala.Interface) {
+                               node.add_interface (type_ref);
+                       } else {
+                               node.base_type = type_ref;
+                       }
+               }
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_struct (Vala.Struct element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               bool is_basic_type = element.base_type == null
+                       && (element.is_boolean_type ()
+                       || element.is_floating_type ()
+                       || element.is_integer_type ());
+
+               Struct node = new Struct (parent,
+                                                                 file,
+                                                                 element.name,
+                                                                 get_access_modifier (element),
+                                                                 comment,
+                                                                 get_cname (element),
+                                                                 get_type_macro_name (element),
+                                                                 get_type_function_name (element),
+                                                                 get_ccode_type_id (element),
+                                                                 get_dup_function (element),
+                                                                 get_copy_function (element),
+                                                                 get_destroy_function (element),
+                                                                 get_free_function (element),
+                                                                 is_basic_type,
+                                                                 element);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               // parent type:
+               Vala.ValueType? basetype = element.base_type as Vala.ValueType;
+               if (basetype != null) {
+                       node.base_type = create_type_reference (basetype, node, node);
+               }
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_field (Vala.Field element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Field node = new Field (parent,
+                                                               file,
+                                                               element.name,
+                                                               get_access_modifier (element),
+                                                               comment,
+                                                               get_cname (element),
+                                                               element.binding == Vala.MemberBinding.STATIC,
+                                                               element.is_volatile,
+                                                               element);
+               node.field_type = create_type_reference (element.variable_type, node, node);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_property (Vala.Property element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Property node = new Property (parent,
+                                                                         file,
+                                                                         element.name,
+                                                                         get_access_modifier (element),
+                                                                         comment,
+                                                                         element.nick,
+                                                                         
Vala.GDBusModule.get_dbus_name_for_member (element),
+                                                                         Vala.GDBusModule.is_dbus_visible 
(element),
+                                                                         get_property_binding_type (element),
+                                                                         element);
+               node.property_type = create_type_reference (element.property_type, node, node);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               // Process property type
+               if (element.get_accessor != null) {
+                       var accessor = element.get_accessor;
+                       node.getter = new PropertyAccessor (node,
+                                                                                               file,
+                                                                                               element.name,
+                                                                                               
get_access_modifier (accessor),
+                                                                                               get_cname 
(accessor),
+                                                                                               
get_property_accessor_type (accessor),
+                                                                                               
get_property_ownership (accessor),
+                                                                                               accessor);
+               }
+
+               if (element.set_accessor != null) {
+                       var accessor = element.set_accessor;
+                       node.setter = new PropertyAccessor (node,
+                                                                                               file,
+                                                                                               element.name,
+                                                                                               
get_access_modifier (accessor),
+                                                                                               get_cname 
(accessor),
+                                                                                               
get_property_accessor_type (accessor),
+                                                                                               
get_property_ownership (accessor),
+                                                                                               accessor);
+               }
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_creation_method (Vala.CreationMethod element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Method node = new Method (parent,
+                                                                 file,
+                                                                 get_method_name (element),
+                                                                 get_access_modifier (element),
+                                                                 comment,
+                                                                 get_cname (element),
+                                                                 Vala.GDBusModule.get_dbus_name_for_member 
(element),
+                                                                 Vala.GDBusModule.dbus_result_name (element),
+                                                                 (element.coroutine)? get_finish_name 
(element) : null,
+                                                                 get_method_binding_type (element),
+                                                                 element.coroutine,
+                                                                 Vala.GDBusModule.is_dbus_visible (element),
+                                                                 element is Vala.CreationMethod,
+                                                                 element);
+               node.return_type = create_type_reference (element.return_type, node, node);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_method (Vala.Method element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Method node = new Method (parent,
+                                                                 file,
+                                                                 get_method_name (element),
+                                                                 get_access_modifier (element),
+                                                                 comment,
+                                                                 get_cname (element),
+                                                                 Vala.GDBusModule.get_dbus_name_for_member 
(element),
+                                                                 Vala.GDBusModule.dbus_result_name (element),
+                                                                 (element.coroutine)? get_finish_name 
(element) : null,
+                                                                 get_method_binding_type (element),
+                                                                 element.coroutine,
+                                                                 Vala.GDBusModule.is_dbus_visible (element),
+                                                                 element is Vala.CreationMethod,
+                                                                 element);
+               node.return_type = create_type_reference (element.return_type, node, node);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_signal (Vala.Signal element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Api.Signal node = new Api.Signal (parent,
+                                                                                 file,
+                                                                                 element.name,
+                                                                                 get_access_modifier 
(element),
+                                                                                 comment,
+                                                                                 get_cname (element),
+                                                                                 (element.default_handler != 
null)? get_cname (element.default_handler) : null,
+                                                                                 
Vala.GDBusModule.get_dbus_name_for_member (element),
+                                                                                 
Vala.GDBusModule.is_dbus_visible (element),
+                                                                                 element.is_virtual,
+                                                                                 element);
+               node.return_type = create_type_reference (element.return_type, node, node);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_delegate (Vala.Delegate element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Delegate node = new Delegate (parent,
+                                                                         file,
+                                                                         element.name,
+                                                                         get_access_modifier (element),
+                                                                         comment,
+                                                                         get_cname (element),
+                                                                         !element.has_target,
+                                                                         element);
+               node.return_type = create_type_reference (element.return_type, node, node);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_enum (Vala.Enum element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Symbol node = new Enum (parent,
+                                                               file,
+                                                               element.name,
+                                                               get_access_modifier (element),
+                                                               comment,
+                                                               get_cname (element),
+                                                               get_type_macro_name (element),
+                                                               get_type_function_name (element),
+                                                               element);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_enum_value (Vala.EnumValue element) {
+               Api.Enum parent = (Enum) get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Symbol node = new Api.EnumValue (parent,
+                                                                                file,
+                                                                                element.name,
+                                                                                comment,
+                                                                                get_cname (element),
+                                                                                element);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_constant (Vala.Constant element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Constant node = new Constant (parent,
+                                                                         file,
+                                                                         element.name,
+                                                                         get_access_modifier (element),
+                                                                         comment,
+                                                                         get_cname (element),
+                                                                         element);
+               node.constant_type = create_type_reference (element.type_reference, node, node);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_error_domain (Vala.ErrorDomain element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               SourceComment? comment = create_comment (element.comment);
+
+               Symbol node = new ErrorDomain (parent,
+                                                                          file,
+                                                                          element.name,
+                                                                          get_access_modifier (element),
+                                                                          comment,
+                                                                          get_cname (element),
+                                                                          get_quark_macro_name (element),
+                                                                          get_quark_function_name (element),
+                                                                          Vala.GDBusModule.get_dbus_name 
(element),
+                                                                         element);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_error_code (Vala.ErrorCode element) {
+               Api.ErrorDomain parent = (ErrorDomain) get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+               if (file == null) {
+                       file = parent.get_source_file ();
+               }
+
+               SourceComment? comment = create_comment (element.comment);
+
+               Symbol node = new Api.ErrorCode (parent,
+                                                                                file,
+                                                                                element.name,
+                                                                                comment,
+                                                                                get_cname (element),
+                                                                                
Vala.GDBusModule.get_dbus_name_for_member (element),
+                                                                                element);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_attributes (node, element.attributes);
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_type_parameter (Vala.TypeParameter element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+
+               Symbol node = new TypeParameter (parent,
+                                                                                file,
+                                                                                element.name,
+                                                                                element);
+               symbol_map.set (element, node);
+               parent.add_child (node);
+
+               process_children (node, element);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public override void visit_formal_parameter (Vala.Parameter element) {
+               Api.Node parent = get_parent_node_for (element);
+               SourceFile? file = get_source_file (element);
+
+               FormalParameter node = new FormalParameter (parent,
+                                                                                                       file,
+                                                                                                       
element.name,
+                                                                                                       
get_access_modifier(element),
+                                                                                                       
get_formal_parameter_type (element),
+                                                                                                       
element.ellipsis,
+                                                                                                       
element);
+               node.parameter_type = create_type_reference (element.variable_type, node, node);
+               parent.add_child (node);
+
+               process_children (node, element);
+       }       
+
+
+       //
+       // startpoint:
+       //
+
+       public Api.Tree? build (Settings settings, ErrorReporter reporter) {
+               this.settings = settings;
+               this.reporter = reporter;
+
+               this.tree = new Api.Tree (reporter, settings);
+               var context = create_valac_tree (settings);
+               this.tree.data = context;
+
+               reporter.warnings_offset = context.report.get_warnings ();
+               reporter.errors_offset = context.report.get_errors ();
+
+               if (context == null) {
+                       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/valadoc/valadoc.vala b/valadoc/valadoc.vala
new file mode 100644
index 0000000..d1727c8
--- /dev/null
+++ b/valadoc/valadoc.vala
@@ -0,0 +1,403 @@
+/* valadoc.vala
+ *
+ * Copyright (C) 2008-2014 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.Importer;
+using Valadoc;
+
+public class ValaDoc : Object {
+       private const string DEFAULT_COLORS = 
"error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01";
+
+       private static string wikidirectory = null;
+       private static string pkg_version = null;
+       private static string docletpath = null;
+       [CCode (array_length = false, array_null_terminated = true)]
+       private static string[] pluginargs;
+       private static string directory = null;
+       private static string pkg_name = null;
+       private static string gir_name = null;
+       private static string gir_namespace = null;
+       private static string gir_version = null;
+       private static string driverpath = null;
+
+       private static bool add_inherited = false;
+       private static bool _protected = true;
+       private static bool _internal = false;
+       private static bool with_deps = false;
+       private static bool _private = false;
+       private static bool version = false;
+       private static bool use_svg_images = false;
+
+       private static bool disable_diagnostic_colors = false;
+       private static bool verbose = false;
+       private static bool force = false;
+
+       private static string basedir = null;
+       [CCode (array_length = false, array_null_terminated = true)]
+       private static string[] defines;
+       private static bool experimental;
+       private static bool experimental_non_null = false;
+       private static string profile;
+       [CCode (array_length = false, array_null_terminated = true)]
+       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)]
+       private static string[] metadata_directories;
+       [CCode (array_length = false, array_null_terminated = true)]
+       private static string[] gir_directories;
+       [CCode (array_length = false, array_null_terminated = true)]
+       private static string[] tsources;
+       [CCode (array_length = false, array_null_terminated = true)]
+       private static string[] packages;
+       [CCode (array_length = false, array_null_terminated = true)]
+       private static string[] alternative_resource_dirs;
+       static string target_glib;
+
+       private const GLib.OptionEntry[] options = {
+               { "directory", 'o', 0, OptionArg.FILENAME, ref directory, "Output directory", "DIRECTORY" },
+
+               { "basedir", 'b', 0, OptionArg.FILENAME, ref basedir, "Base source directory", "DIRECTORY" },
+               { "define", 'D', 0, OptionArg.STRING_ARRAY, ref defines, "Define SYMBOL", "SYMBOL..." },
+               { "profile", 0, 0, OptionArg.STRING, ref profile, "Use the given profile instead of the 
default", "PROFILE" },
+
+               { "enable-experimental", 0, 0, OptionArg.NONE, ref experimental, "Enable experimental 
features", null },
+               { "enable-experimental-non-null", 0, 0, OptionArg.NONE, ref experimental_non_null, "Enable 
experimental enhancements for non-null types", null },
+
+               { "metadatadir", 0, 0, OptionArg.FILENAME_ARRAY, ref metadata_directories, "Look for GIR 
.metadata files in DIRECTORY", "DIRECTORY..." },
+               { "girdir", 0, 0, OptionArg.FILENAME_ARRAY, ref gir_directories, "Look for .gir files in 
DIRECTORY", "DIRECTORY..." },
+               { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, ref vapi_directories, "Look for package bindings 
in DIRECTORY", "DIRECTORY..." },
+               { "pkg", 0, 0, OptionArg.STRING_ARRAY, ref packages, "Include binding for PACKAGE", 
"PACKAGE..." },
+
+               { "driver", 0, 0, OptionArg.STRING, ref driverpath, "Name of an driver or path to a custom 
driver", null },
+
+               { "importdir", 0, 0, OptionArg.FILENAME_ARRAY, ref import_directories, "Look for external 
documentation in DIRECTORY", "DIRECTORY..." },
+               { "import", 0, 0, OptionArg.STRING_ARRAY, ref import_packages, "Include binding for PACKAGE", 
"PACKAGE..." },
+               { "alternative-resource-dir", 0, 0, OptionArg.STRING_ARRAY, ref alternative_resource_dirs, 
"Alternative resource directories", "DIRECTORY..." },
+
+               { "wiki", 0, 0, OptionArg.FILENAME, ref wikidirectory, "Wiki directory", "DIRECTORY" },
+
+               { "deps", 0, 0, OptionArg.NONE, ref with_deps, "Adds packages to the documentation", null },
+
+               { "doclet", 0, 0, OptionArg.STRING, ref docletpath, "Name of an included doclet or path to 
custom doclet", "PLUGIN"},
+               { "doclet-arg", 'X', 0, OptionArg.STRING_ARRAY, ref pluginargs, "Pass arguments to the 
doclet", "ARG" },
+
+               { "no-protected", 0, OptionFlags.REVERSE, OptionArg.NONE, ref _protected, "Removes protected 
elements from documentation", null },
+               { "internal", 0, 0, OptionArg.NONE, ref _internal, "Adds internal elements to documentation", 
null },
+               { "private", 0, 0, OptionArg.NONE, ref _private, "Adds private elements to documentation", 
null },
+               { "use-svg-images", 0, 0, OptionArg.NONE, ref use_svg_images, "Generate SVG image charts 
instead of PNG", null },
+
+               { "package-name", 0, 0, OptionArg.STRING, ref pkg_name, "package name", "NAME" },
+               { "package-version", 0, 0, OptionArg.STRING, ref pkg_version, "package version", "VERSION" },
+               { "gir", 0, 0, OptionArg.STRING, ref gir_name, "GObject-Introspection repository file name", 
"NAME-VERSION.gir" },
+
+               { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null },
+
+               { "force", 0, 0, OptionArg.NONE, ref force, "force", null },
+               { "verbose", 0, 0, OptionArg.NONE, ref verbose, "Show all warnings", null },
+               { "no-color", 0, 0, OptionArg.NONE, ref disable_diagnostic_colors, "Disable colored output", 
null },
+               { "target-glib", 0, 0, OptionArg.STRING, ref target_glib, "Target version of glib for code 
generation", "MAJOR.MINOR" },
+               { "", 0, 0, OptionArg.FILENAME_ARRAY, ref tsources, null, "FILE..." },
+
+               { null }
+       };
+
+       private static int quit (ErrorReporter reporter) {
+               if (reporter.errors == 0) {
+                       stdout.printf ("Succeeded - %d warning(s)\n", reporter.warnings);
+                       return 0;
+               } else {
+                       stdout.printf ("Failed: %d error(s), %d warning(s)\n", reporter.errors, 
reporter.warnings);
+                       return 1;
+               }
+       }
+
+       private static bool check_pkg_name () {
+               if (pkg_name == null) {
+                       return true;
+               }
+
+               if (pkg_name == "glib-2.0" || pkg_name == "gobject-2.0") {
+                       return false;
+               }
+
+               foreach (string package in tsources) {
+                       if (pkg_name == package) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       private string get_pkg_name () {
+               if (ValaDoc.pkg_name == null) {
+                       if (ValaDoc.directory.has_suffix ("/")) {
+                               ValaDoc.pkg_name = GLib.Path.get_dirname (ValaDoc.directory);
+                       } else {
+                               ValaDoc.pkg_name = GLib.Path.get_basename (ValaDoc.directory);
+                       }
+               }
+
+               return ValaDoc.pkg_name;
+       }
+
+       private ModuleLoader? create_module_loader (ErrorReporter reporter, out Doclet? doclet, out Driver? 
driver) {
+               ModuleLoader modules = ModuleLoader.get_instance ();
+
+               doclet = null;
+               driver = null;
+
+               // doclet:
+               string? pluginpath = ModuleLoader.get_doclet_path (docletpath, reporter);
+               if (pluginpath == null) {
+                       return null;
+               }
+
+               doclet = modules.create_doclet (pluginpath);
+               if (doclet == null) {
+                       reporter.simple_error (null, "failed to load doclet");
+                       return null;
+               }
+
+
+               // driver:
+               driver = new Valadoc.Drivers.Driver ();
+
+               assert (driver != null && doclet != null);
+
+               return modules;
+       }
+
+       private int run (ErrorReporter reporter) {
+               // settings:
+               var settings = new Valadoc.Settings ();
+               reporter.settings = settings;
+
+               settings.pkg_name = this.get_pkg_name ();
+               settings.gir_namespace = ValaDoc.gir_namespace;
+               settings.gir_version = ValaDoc.gir_version;
+               if (ValaDoc.gir_name != null) {
+                       settings.gir_name = GLib.Path.get_basename (ValaDoc.gir_name);
+                       settings.gir_directory = GLib.Path.get_dirname (ValaDoc.gir_name);
+                       if (settings.gir_directory == "") {
+                               settings.gir_directory = GLib.Path.get_dirname (ValaDoc.directory);
+                       }
+               }
+               settings.pkg_version = ValaDoc.pkg_version;
+               settings.add_inherited = ValaDoc.add_inherited;
+               settings._protected = ValaDoc._protected;
+               settings._internal = ValaDoc._internal;
+               settings.with_deps = ValaDoc.with_deps;
+               settings._private = ValaDoc._private;
+               settings.path = realpath (ValaDoc.directory);
+               settings.verbose = ValaDoc.verbose;
+               settings.wiki_directory = ValaDoc.wikidirectory;
+               settings.pluginargs = ValaDoc.pluginargs;
+
+               settings.experimental = experimental;
+               settings.experimental_non_null = experimental_non_null;
+               settings.basedir = basedir;
+               settings.directory = directory;
+               settings.vapi_directories = vapi_directories;
+               settings.metadata_directories = metadata_directories;
+               settings.gir_directories = gir_directories;
+               settings.target_glib = target_glib;
+               settings.use_svg_images = use_svg_images;
+
+               settings.source_files = tsources;
+               settings.packages = packages;
+
+               settings.profile = profile;
+               settings.defines = defines;
+
+               settings.alternative_resource_dirs = alternative_resource_dirs;
+
+
+               // load plugins:
+               Doclet? doclet = null;
+               Driver? driver = null;
+
+               ModuleLoader? modules = create_module_loader (reporter, out doclet, out driver);
+               if (reporter.errors > 0 || modules == null) {
+                       return quit (reporter);
+               }
+
+
+               // Create tree:
+               Valadoc.Api.Tree doctree = driver.build (settings, reporter);
+               if (reporter.errors > 0) {
+                       driver = null;
+                       doclet = null;
+                       return quit (reporter);
+               }
+
+               // register child symbols:
+               Valadoc.Api.ChildSymbolRegistrar registrar = new Valadoc.Api.ChildSymbolRegistrar ();
+               doctree.accept (registrar);
+
+               // process documentation
+               Valadoc.DocumentationParser docparser = new Valadoc.DocumentationParser (settings, reporter, 
doctree, modules);
+               if (!doctree.create_tree()) {
+                       return quit (reporter);
+               }
+
+               DocumentationImporter[] importers = {
+                       new ValadocDocumentationImporter (doctree, docparser, modules, settings, reporter),
+                       new GirDocumentationImporter (doctree, docparser, modules, settings, reporter)
+               };
+
+               doctree.parse_comments (docparser);
+               if (reporter.errors > 0) {
+                       return quit (reporter);
+               }
+
+               doctree.import_comments (importers, import_packages, import_directories);
+               if (reporter.errors > 0) {
+                       return quit (reporter);
+               }
+
+               doctree.check_comments (docparser);
+               if (reporter.errors > 0) {
+                       return quit (reporter);
+               }
+
+               if (ValaDoc.gir_name != null) {
+                       driver.write_gir (settings, reporter);
+                       if (reporter.errors > 0) {
+                               return quit (reporter);
+                       }
+               }
+
+               doclet.process (settings, doctree, reporter);
+               return quit (reporter);
+       }
+
+       static int main (string[] args) {
+               Intl.setlocale (LocaleCategory.ALL, "");
+               ErrorReporter reporter = new ErrorReporter();
+
+               try {
+                       var opt_context = new OptionContext ("- Vala Documentation Tool");
+                       opt_context.set_help_enabled (true);
+                       opt_context.add_main_entries (options, null);
+                       opt_context.parse (ref args);
+               } catch (OptionError e) {
+                       reporter.simple_error (null, "%s", e.message);
+                       stdout.printf ("Run '%s --help' to see a full list of available command line 
options.\n", args[0]);
+                       return quit (reporter);
+               }
+
+               if (disable_diagnostic_colors == false) {
+                       unowned string env_colors = Environment.get_variable ("VALA_COLORS");
+                       if (env_colors != null) {
+                               reporter.set_colors (env_colors);
+                       } else {
+                               reporter.set_colors (DEFAULT_COLORS);
+                       }
+               }
+
+               if (version) {
+                       stdout.printf ("Valadoc %s\n", Config.BUILD_VERSION);
+                       return 0;
+               }
+
+               if (directory == null) {
+                       reporter.simple_error (null, "No output directory specified.");
+                       return quit (reporter);
+               }
+
+               if (!check_pkg_name ()) {
+                       reporter.simple_error (null, "File already exists");
+                       return quit (reporter);
+               }
+
+               if (FileUtils.test (directory, FileTest.EXISTS)) {
+                       if (force == true) {
+                               bool tmp = remove_directory (directory);
+                               if (tmp == false) {
+                                       reporter.simple_error (null, "Can't remove directory.");
+                                       return quit (reporter);
+                               }
+                       } else {
+                               reporter.simple_error (null, "File already exists");
+                               return quit (reporter);
+                       }
+               }
+
+               if (wikidirectory != null) {
+                       if (!FileUtils.test(wikidirectory, FileTest.IS_DIR)) {
+                               reporter.simple_error (null, "Wiki-directory does not exist.");
+                               return quit (reporter);
+                       }
+               }
+
+               foreach (unowned string dir in alternative_resource_dirs) {
+                       if (!FileUtils.test(dir, FileTest.IS_DIR)) {
+                               reporter.simple_error (null, "alternative resource directory '%s' does not 
exist.".printf (dir));
+                               return quit (reporter);
+                       }
+               }
+               if (reporter.errors > 0) {
+                       return quit (reporter);
+               }
+
+               if (gir_name != null) {
+                       long gir_len = gir_name.length;
+                       int last_hyphen = gir_name.last_index_of_char ('-');
+
+                       if (last_hyphen == -1 || !gir_name.has_suffix (".gir")) {
+                               reporter.simple_error (null, "GIR file name '%s' is not well-formed, expected 
NAME-VERSION.gir", gir_name);
+                               return quit (reporter);
+                       }
+
+                       gir_namespace = gir_name.substring (0, last_hyphen);
+                       gir_version = gir_name.substring (last_hyphen + 1, gir_len - last_hyphen - 5);
+                       gir_version.canon ("0123456789.", '?');
+
+                       if (gir_namespace == "" || gir_version == "" || !gir_version[0].isdigit () || 
gir_version.contains ("?")) {
+                               reporter.simple_error (null, "GIR file name '%s' is not well-formed, expected 
NAME-VERSION.gir", gir_name);
+                               return quit (reporter);
+                       }
+
+
+                       bool report_warning = true;
+                       foreach (string source in tsources) {
+                               if (source.has_suffix (".vala") || source.has_suffix (".gs")) {
+                                       report_warning = false;
+                                       break;
+                               }
+                       }
+
+                       if (report_warning == true) {
+                               reporter.simple_error (null, "No source file specified to be compiled to 
gir.");
+                               return quit (reporter);
+                       }
+               }
+
+
+               var valadoc = new ValaDoc( );
+               return valadoc.run (reporter);
+       }
+}
+
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]