[gobject-introspection] giscanner: add AnnotationParser tests



commit af2e146f5f24b93322ad0112d37a8e41222c3085
Author: Dieter Verfaillie <dieterv optionexplicit be>
Date:   Wed Jul 4 11:58:13 2012 +0200

    giscanner: add AnnotationParser tests
    
    The tests in giscanner/annotationpatters.py only test the regular
    expression programs used when parsing GTK-Doc comment blocks but
    do not test the structure of the resulting "parse tree".
    
    This patch adds 193 GTK-Doc comment blocks and the expected
    results AnnotationParser should return (with it's current level
    of understanding of GTK-Doc comment block syntax). These are
    compared by tests/scanner/annotationparser/test_parser.py which
    complains with a diff on failure.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=688897

 Makefile.am                                        |    2 +
 tests/scanner/annotationparser/README              |   40 +
 .../annotationparser/gi/annotation_allow_none.xml  |   47 ++
 .../annotationparser/gi/annotation_array.xml       |  277 +++++++
 .../annotationparser/gi/annotation_closure.xml     |   74 ++
 .../annotationparser/gi/annotation_constructor.xml |   21 +
 .../annotationparser/gi/annotation_destroy.xml     |   46 ++
 .../gi/annotation_element_type.xml                 |  126 ++++
 .../annotationparser/gi/annotation_foreign.xml     |   22 +
 .../gi/annotation_get_value_func.xml               |   30 +
 .../scanner/annotationparser/gi/annotation_in.xml  |   52 ++
 .../annotationparser/gi/annotation_in_out.xml      |   54 ++
 .../annotationparser/gi/annotation_method.xml      |   28 +
 .../scanner/annotationparser/gi/annotation_out.xml |  110 +++
 .../annotationparser/gi/annotation_ref_func.xml    |   30 +
 .../annotationparser/gi/annotation_rename_to.xml   |   52 ++
 .../annotationparser/gi/annotation_scope.xml       |  106 +++
 .../gi/annotation_set_value_func.xml               |   30 +
 .../annotationparser/gi/annotation_skip.xml        |   43 ++
 .../annotationparser/gi/annotation_transfer.xml    |  162 +++++
 .../annotationparser/gi/annotation_type.xml        |   84 +++
 .../annotationparser/gi/annotation_unref_func.xml  |   30 +
 .../annotationparser/gi/annotation_value.xml       |   30 +
 .../annotationparser/gi/annotation_virtual.xml     |   47 ++
 tests/scanner/annotationparser/gi/syntax.xml       |   98 +++
 .../annotationparser/gi/syntax_identifier.xml      |  286 ++++++++
 .../gi/syntax_paragraph_breaks.xml                 |  122 ++++
 .../scanner/annotationparser/gi/tag_deprecated.xml |   43 ++
 .../annotationparser/gi/tag_description.xml        |   21 +
 tests/scanner/annotationparser/gi/tag_returns.xml  |   76 ++
 tests/scanner/annotationparser/gi/tag_since.xml    |   43 ++
 .../scanner/annotationparser/gi/tag_stability.xml  |   81 ++
 .../gtkdoc/annotations/tester.c.xml                |  344 +++++++++
 .../gtkdoc/annotations/tester.h.xml                |   31 +
 .../annotationparser/gtkdoc/bugs/tester.c.xml      |  765 ++++++++++++++++++++
 .../annotationparser/gtkdoc/bugs/tester.h.xml      |  677 +++++++++++++++++
 .../annotationparser/gtkdoc/empty/tester.c.xml     |   53 ++
 .../annotationparser/gtkdoc/fail/tester.c.xml      |  162 +++++
 .../annotationparser/gtkdoc/fail/tester.h.xml      |  205 ++++++
 .../annotationparser/gtkdoc/gobject/giface.c.xml   |  147 ++++
 .../annotationparser/gtkdoc/gobject/giface.h.xml   |  119 +++
 .../annotationparser/gtkdoc/gobject/gobject.c.xml  |  416 +++++++++++
 .../annotationparser/gtkdoc/gobject/gobject.h.xml  |  158 ++++
 .../annotationparser/gtkdoc/gobject/gtypes.c.xml   |   36 +
 .../annotationparser/gtkdoc/gobject/gtypes.h.xml   |   57 ++
 tests/scanner/annotationparser/test_parser.py      |  297 ++++++++
 46 files changed, 5780 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 2059b98..7683755 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -66,6 +66,8 @@ check-local:
 	@find $(top_srcdir)/giscanner -name \*.py | sort | uniq | xargs $(PYTHON) $(top_srcdir)/misc/pep8.py --repeat --exclude=config.py
 	@echo "TEST: Annotation pattern programs"
 	$(PYTHON) $(top_srcdir)/giscanner/annotationpatterns.py
+	@echo "TEST: GTK-Doc Annotation Parser"
+	PYTHONPATH="$(top_builddir):$(top_srcdir)" $(PYTHON) $(top_srcdir)/tests/scanner/annotationparser/test_parser.py
 	@touch $(top_builddir)/.make-check-passed
 
 check-pyflakes:
diff --git a/tests/scanner/annotationparser/README b/tests/scanner/annotationparser/README
new file mode 100644
index 0000000..1f621a5
--- /dev/null
+++ b/tests/scanner/annotationparser/README
@@ -0,0 +1,40 @@
+test_parser.py
+==============
+
+Notes
+-----
+
+- the names of directories containing test .xml and the .xml files themselves should
+  not contain the hyphen ('-') character. This because we use the directory and file
+  names to generate valid Python method names (where the hyphen character is illegal).
+
+- GTK-Doc comment blocks can contain XML fragments on their own. You can wrap such
+  comment blocks into a CDATA section to prevent the tests XML parser from doing the
+  wrong thing.
+  Occasionally, GTK-Doc comment blocks containing XML fragments can also contain CDATA
+  sections on their own. This can be handled by wrapping the GTK-Doc comment block into
+  a CDATA section as described above, and escape the embedded GTK-Doc CDATA section's
+  opening bracket "<!" with "{{!" and the matching close bracket ">" with "!}}".
+
+- *Note well* that the trailing whitespace in gi/syntax_paragraph_breaks.xml *is* expected.
+  Whatever your text editor of choice or scm du jour might claim, trailing whitespace
+  are required for these tests!
+
+
+Tests
+-----
+
+gtk-doc/*.xml:
+  The GTK-Doc comment block tests in this directory are copied verbatim from the GTK-Doc
+  test suite. Not all of these tests make sense from GTK-Doc's point of view without the
+  actual C sources they document, but are great for testing the level of understanding
+  AnnotationParser has about the GTK-Doc comment block syntax.
+
+  GTK-Doc tests originally taken at revision:
+  http://git.gnome.org/browse/gtk-doc/tree/tests?id=2a6b01253fe41412172a60f26705114b953d0a95
+
+
+gobject-introspection/*.xml:
+  GTK-Doc comment blocks specifically designed to ensure AnnotationParser does the
+  right thing and continues to function correctly. The goal is to exercise all possible
+  combinations of tags, parameters and annotations (both current and deprecated syntax).
diff --git a/tests/scanner/annotationparser/gi/annotation_allow_none.xml b/tests/scanner/annotationparser/gi/annotation_allow_none.xml
new file mode 100644
index 0000000..02db79a
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_allow_none.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_object_inout:
+ * @object: a #GObject
+ * @inoutarg: (inout) (allow-none): This is an argument test
+ *
+ * This is a test for out arguments
+ *
+ * Return value: an int
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_inout</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #GObject</description>
+      </parameter>
+      <parameter>
+        <name>inoutarg</name>
+        <annotations>
+          <annotation>
+            <name>inout</name>
+          </annotation>
+          <annotation>
+            <name>allow-none</name>
+          </annotation>
+        </annotations>
+        <description>This is an argument test</description>
+      </parameter>
+    </parameters>
+    <description>This is a test for out arguments</description>
+  <tags>
+    <tag>
+      <name>returns</name>
+      <description>an int</description>
+    </tag>
+  </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_array.xml b/tests/scanner/annotationparser/gi/annotation_array.xml
new file mode 100644
index 0000000..26bb110
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_array.xml
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_object_compute_sum:
+ * @nums: (array): Sequence of numbers
+ *
+ * Test taking a zero-terminated array
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_compute_sum</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>nums</name>
+        <annotations>
+          <annotation>
+            <name>array</name>
+          </annotation>
+        </annotations>
+        <description>Sequence of numbers</description>
+      </parameter>
+    </parameters>
+    <description>Test taking a zero-terminated array</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_object_compute_sum_n:
+ * @object: a #AnnotationObject
+ * @nums: (array length=n_nums zero-terminated=0): Sequence of
+ *   numbers that are zero-terminated
+ * @n_nums: Length of number array
+ *
+ * Test taking an array with length parameter
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_compute_sum_n</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #AnnotationObject</description>
+      </parameter>
+      <parameter>
+        <name>nums</name>
+        <annotations>
+          <annotation>
+            <name>array</name>
+            <options>
+              <option>
+                <name>length</name>
+                <value>n_nums</value>
+              </option>
+              <option>
+                <name>zero-terminated</name>
+                <value>0</value>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>Sequence of numbers that are zero-terminated</description>
+      </parameter>
+      <parameter>
+        <name>n_nums</name>
+        <description>Length of number array</description>
+      </parameter>
+    </parameters>
+    <description>Test taking an array with length parameter</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_object_compute_sum_nz:
+ * @object: a #AnnotationObject
+ * @nums: (array length=n_nums zero-terminated=1): Sequence of numbers that
+ * are zero-terminated
+ * @n_nums: Length of number array
+ *
+ * Test taking a zero-terminated array with length parameter
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_compute_sum_nz</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #AnnotationObject</description>
+      </parameter>
+      <parameter>
+        <name>nums</name>
+        <annotations>
+          <annotation>
+            <name>array</name>
+            <options>
+              <option>
+                <name>length</name>
+                <value>n_nums</value>
+              </option>
+              <option>
+                <name>zero-terminated</name>
+                <value>1</value>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>Sequence of numbers that are zero-terminated</description>
+      </parameter>
+      <parameter>
+        <name>n_nums</name>
+        <description>Length of number array</description>
+      </parameter>
+    </parameters>
+    <description>Test taking a zero-terminated array with length parameter</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_object_parse_args:
+ * @object: a #AnnotationObject
+ * @argc: (inout): Length of the argument vector
+ * @argv: (inout) (array length=argc zero-terminated=1): Argument vector
+ *
+ * Test taking a zero-terminated array with length parameter
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_parse_args</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #AnnotationObject</description>
+      </parameter>
+      <parameter>
+        <name>argc</name>
+        <annotations>
+          <annotation>
+            <name>inout</name>
+          </annotation>
+        </annotations>
+        <description>Length of the argument vector</description>
+      </parameter>
+      <parameter>
+        <name>argv</name>
+        <annotations>
+          <annotation>
+            <name>inout</name>
+          </annotation>
+          <annotation>
+            <name>array</name>
+            <options>
+              <option>
+                <name>length</name>
+                <value>argc</value>
+              </option>
+              <option>
+                <name>zero-terminated</name>
+                <value>1</value>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>Argument vector</description>
+      </parameter>
+    </parameters>
+    <description>Test taking a zero-terminated array with length parameter</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_object_set_data:
+ * @object: a #AnnotationObject
+ * @data: (array length=length): The data
+ * @length: Length of the data
+ *
+ * Test taking a guchar * with a length.
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_set_data</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #AnnotationObject</description>
+      </parameter>
+      <parameter>
+        <name>data</name>
+        <annotations>
+          <annotation>
+            <name>array</name>
+            <options>
+              <option>
+                <name>length</name>
+                <value>length</value>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>The data</description>
+      </parameter>
+      <parameter>
+        <name>length</name>
+        <description>Length of the data</description>
+      </parameter>
+    </parameters>
+    <description>Test taking a guchar * with a length.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_string_zero_terminated:
+ * @data: (array fixed-size=2): a third value
+ *
+ * Return value: (transfer full) (array zero-terminated=1): The return value
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_string_zero_terminated</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>data</name>
+        <annotations>
+          <annotation>
+            <name>array</name>
+            <options>
+              <option>
+                <name>fixed-size</name>
+                <value>2</value>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>a third value</description>
+      </parameter>
+    </parameters>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <annotations>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>full</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>array</name>
+            <options>
+              <option>
+                <name>zero-terminated</name>
+                <value>1</value>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>The return value</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_closure.xml b/tests/scanner/annotationparser/gi/annotation_closure.xml
new file mode 100644
index 0000000..8211dc7
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_closure.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * AnnotationNotifyFunc:
+ * @data: (closure): The user data
+ *
+ * This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>AnnotationNotifyFunc</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>data</name>
+        <annotations>
+          <annotation>
+            <name>closure</name>
+          </annotation>
+        </annotations>
+        <description>The user data</description>
+      </parameter>
+    </parameters>
+    <description>This is a callback with a 'closure' argument that is not named
+'user_data' and hence has to be annotated.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_custom_destroy:
+ * @callback: (destroy destroy) (closure data): Destroy notification
+ *
+ * Test messing up the heuristic of closure/destroy-notification
+ * detection, and fixing it via annotations.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_custom_destroy</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>callback</name>
+        <annotations>
+          <annotation>
+            <name>destroy</name>
+            <options>
+              <option>
+                <name>destroy</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>closure</name>
+            <options>
+              <option>
+                <name>data</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>Destroy notification</description>
+      </parameter>
+    </parameters>
+    <description>Test messing up the heuristic of closure/destroy-notification
+detection, and fixing it via annotations.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_constructor.xml b/tests/scanner/annotationparser/gi/annotation_constructor.xml
new file mode 100644
index 0000000..4bf3b03
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_constructor.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * regress_constructor: (constructor)
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>regress_constructor</name>
+      <annotations>
+        <annotation>
+          <name>constructor</name>
+        </annotation>
+      </annotations>
+    </identifier>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_destroy.xml b/tests/scanner/annotationparser/gi/annotation_destroy.xml
new file mode 100644
index 0000000..449dd8e
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_destroy.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_custom_destroy:
+ * @callback: (destroy destroy) (closure data): Destroy notification
+ *
+ * Test messing up the heuristic of closure/destroy-notification
+ * detection, and fixing it via annotations.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_custom_destroy</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>callback</name>
+        <annotations>
+          <annotation>
+            <name>destroy</name>
+            <options>
+              <option>
+                <name>destroy</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>closure</name>
+            <options>
+              <option>
+                <name>data</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>Destroy notification</description>
+      </parameter>
+    </parameters>
+    <description>Test messing up the heuristic of closure/destroy-notification
+detection, and fixing it via annotations.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_element_type.xml b/tests/scanner/annotationparser/gi/annotation_element_type.xml
new file mode 100644
index 0000000..d03c426
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_element_type.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * foo_test_array:
+ *
+ * Returns: (element-type utf8) (transfer container): returns %NULL.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>foo_test_array</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <annotations>
+          <annotation>
+            <name>element-type</name>
+            <options>
+              <option>
+                <name>utf8</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>container</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>returns %NULL.</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * RegressTestObj::sig-with-hash-prop:
+ * @self: an object
+ * @hash: (element-type utf8 GObject.Value):
+ *
+ * This test signal is like TelepathyGlib's
+ *  TpAccount::status-changed
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>RegressTestObj::sig-with-hash-prop</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>self</name>
+        <description>an object</description>
+      </parameter>
+      <parameter>
+        <name>hash</name>
+        <annotations>
+          <annotation>
+            <name>element-type</name>
+            <options>
+              <option>
+                <name>utf8</name>
+              </option>
+              <option>
+                <name>GObject.Value</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+      </parameter>
+    </parameters>
+    <description>This test signal is like TelepathyGlib's
+ TpAccount::status-changed</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock><![CDATA[/**
+ * regress_test_ghash_nested_everything_return2:
+ *
+ * Another way of specifying nested parameterized types: using the
+ * element-type annotation.
+ *
+ * Return value: (element-type utf8 GLib.HashTable<utf8,utf8>) (transfer full):
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>regress_test_ghash_nested_everything_return2</name>
+    </identifier>
+    <description>Another way of specifying nested parameterized types: using the
+element-type annotation.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <annotations>
+          <annotation>
+            <name>element-type</name>
+            <options>
+              <option>
+                <name>utf8</name>
+              </option>
+              <option>
+                <name><![CDATA[GLib.HashTable<utf8,utf8>]]></name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>full</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_foreign.xml b/tests/scanner/annotationparser/gi/annotation_foreign.xml
new file mode 100644
index 0000000..11e589c
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_foreign.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * FooForeignStruct: (foreign)
+ *
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>FooForeignStruct</name>
+      <annotations>
+        <annotation>
+          <name>foreign</name>
+        </annotation>
+      </annotations>
+    </identifier>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_get_value_func.xml b/tests/scanner/annotationparser/gi/annotation_get_value_func.xml
new file mode 100644
index 0000000..bc77994
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_get_value_func.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  "Get value func:" tag syntax
+  -->
+  <commentblock>/**
+ * RegressTestFundamentalObject:
+ *
+ * This object tests regressions...
+ *
+ * Get value func: regress_test_value_get_fundamental_object
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>RegressTestFundamentalObject</name>
+    </identifier>
+    <description>This object tests regressions...</description>
+    <tags>
+      <tag>
+        <name>get value func</name>
+        <description>regress_test_value_get_fundamental_object</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_in.xml b/tests/scanner/annotationparser/gi/annotation_in.xml
new file mode 100644
index 0000000..517f1a3
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_in.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_object_in:
+ * @object: a #GObject
+ * @inarg: (in) (transfer none): This is an argument test
+ *
+ * This is a test for in arguments
+ *
+ * Return value: an int
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_in</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #GObject</description>
+      </parameter>
+      <parameter>
+        <name>inarg</name>
+        <annotations>
+          <annotation>
+            <name>in</name>
+          </annotation>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>none</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>This is an argument test</description>
+      </parameter>
+    </parameters>
+    <description>This is a test for in arguments</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>an int</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_in_out.xml b/tests/scanner/annotationparser/gi/annotation_in_out.xml
new file mode 100644
index 0000000..c8d36f4
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_in_out.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_object_inout:
+ * @object: a #GObject
+ * @inoutarg: (inout): This is an argument test
+ * @inoutarg2: (in-out): This is an argument test
+ *
+ * This is a test for inout arguments
+ *
+ * Return value: an int
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_inout</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #GObject</description>
+      </parameter>
+      <parameter>
+        <name>inoutarg</name>
+        <annotations>
+          <annotation>
+            <name>inout</name>
+          </annotation>
+        </annotations>
+        <description>This is an argument test</description>
+      </parameter>
+      <parameter>
+        <name>inoutarg2</name>
+        <annotations>
+          <annotation>
+            <name>in-out</name>
+          </annotation>
+        </annotations>
+        <description>This is an argument test</description>
+      </parameter>
+    </parameters>
+    <description>This is a test for inout arguments</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>an int</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_method.xml b/tests/scanner/annotationparser/gi/annotation_method.xml
new file mode 100644
index 0000000..e4d4438
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_method.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * regress_forced_method: (method)
+ * @obj: A #RegressTestObj
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>regress_forced_method</name>
+      <annotations>
+        <annotation>
+          <name>method</name>
+        </annotation>
+      </annotations>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>obj</name>
+        <description>A #RegressTestObj</description>
+      </parameter>
+    </parameters>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_out.xml b/tests/scanner/annotationparser/gi/annotation_out.xml
new file mode 100644
index 0000000..cca5e12
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_out.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_object_out:
+ * @object: a #GObject
+ * @outarg: (out): This is an argument test
+ *
+ * This is a test for out arguments
+ *
+ * Return value: an int
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_out</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #GObject</description>
+      </parameter>
+      <parameter>
+        <name>outarg</name>
+        <annotations>
+          <annotation>
+            <name>out</name>
+          </annotation>
+        </annotations>
+        <description>This is an argument test</description>
+      </parameter>
+    </parameters>
+    <description>This is a test for out arguments</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>an int</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * regress_test_struct_a_clone:
+ * @a: the structure
+ * @a_out: (out caller-allocates): the cloned structure
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>regress_test_struct_a_clone</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>the structure</description>
+      </parameter>
+      <parameter>
+        <name>a_out</name>
+        <annotations>
+          <annotation>
+            <name>out</name>
+            <options>
+              <option>
+                <name>caller-allocates</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>the cloned structure</description>
+      </parameter>
+    </parameters>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * regress_test_struct_a_clone:
+ * @a: the structure
+ * @a_out: (out callee-allocates): the cloned structure
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>regress_test_struct_a_clone</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>the structure</description>
+      </parameter>
+      <parameter>
+        <name>a_out</name>
+        <annotations>
+          <annotation>
+            <name>out</name>
+            <options>
+              <option>
+                <name>callee-allocates</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>the cloned structure</description>
+      </parameter>
+    </parameters>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_ref_func.xml b/tests/scanner/annotationparser/gi/annotation_ref_func.xml
new file mode 100644
index 0000000..7850fc3
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_ref_func.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  "Ref func:" tag syntax
+  -->
+  <commentblock>/**
+ * RegressTestFundamentalObject:
+ *
+ * This object tests regressions...
+ *
+ * Ref func: regress_test_fundamental_object_ref
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>RegressTestFundamentalObject</name>
+    </identifier>
+    <description>This object tests regressions...</description>
+    <tags>
+      <tag>
+        <name>ref func</name>
+        <description>regress_test_fundamental_object_ref</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_rename_to.xml b/tests/scanner/annotationparser/gi/annotation_rename_to.xml
new file mode 100644
index 0000000..390f487
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_rename_to.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  "Rename to:" tag syntax
+  -->
+  <commentblock>/**
+ * annotation_object_watch_full:
+ * @object: A #AnnotationObject
+ * @func: The callback
+ * @user_data: The callback data
+ * @destroy: Destroy notification
+ *
+ * Test overriding via the "Rename To" annotation.
+ *
+ * Rename to: annotation_object_watch
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_watch_full</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>A #AnnotationObject</description>
+      </parameter>
+      <parameter>
+        <name>func</name>
+        <description>The callback</description>
+      </parameter>
+      <parameter>
+        <name>user_data</name>
+        <description>The callback data</description>
+      </parameter>
+      <parameter>
+        <name>destroy</name>
+        <description>Destroy notification</description>
+      </parameter>
+    </parameters>
+    <description>Test overriding via the "Rename To" annotation.</description>
+    <tags>
+      <tag>
+        <name>rename to</name>
+        <description>annotation_object_watch</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_scope.xml b/tests/scanner/annotationparser/gi/annotation_scope.xml
new file mode 100644
index 0000000..7f05a4c
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_scope.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_object_foreach:
+ * @object: a #AnnotationObject
+ * @func: (scope call): Callback to invoke
+ * @user_data: Callback user data
+ *
+ * Test taking a call-scoped callback
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_foreach</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #AnnotationObject</description>
+      </parameter>
+      <parameter>
+        <name>func</name>
+        <annotations>
+          <annotation>
+            <name>scope</name>
+            <options>
+              <option>
+                <name>call</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>Callback to invoke</description>
+      </parameter>
+      <parameter>
+        <name>user_data</name>
+        <description>Callback user data</description>
+      </parameter>
+    </parameters>
+    <description>Test taking a call-scoped callback</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * regress_test_callback_destroy_notify:
+ * @callback: (scope notified):
+ *
+ * Notified - callback persists until a DestroyNotify delegate
+ * is invoked.
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>regress_test_callback_destroy_notify</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>callback</name>
+        <annotations>
+          <annotation>
+            <name>scope</name>
+            <options>
+              <option>
+                <name>notified</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+      </parameter>
+    </parameters>
+    <description>Notified - callback persists until a DestroyNotify delegate
+is invoked.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * regress_test_callback_async:
+ * @callback: (scope async):
+ *
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>regress_test_callback_async</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>callback</name>
+        <annotations>
+          <annotation>
+            <name>scope</name>
+            <options>
+              <option>
+                <name>async</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+      </parameter>
+    </parameters>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_set_value_func.xml b/tests/scanner/annotationparser/gi/annotation_set_value_func.xml
new file mode 100644
index 0000000..1f3a44d
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_set_value_func.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  "Set value func:" tag syntax
+  -->
+  <commentblock>/**
+ * RegressTestFundamentalObject:
+ *
+ * This object tests regressions...
+ *
+ * Set value func: regress_test_value_set_fundamental_object
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>RegressTestFundamentalObject</name>
+    </identifier>
+    <description>This object tests regressions...</description>
+    <tags>
+      <tag>
+        <name>set value func</name>
+        <description>regress_test_value_set_fundamental_object</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_skip.xml b/tests/scanner/annotationparser/gi/annotation_skip.xml
new file mode 100644
index 0000000..030b0c4
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_skip.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_object_watch: (skip)
+ * @object: A #AnnotationObject
+ * @func: The callback
+ * @user_data: The callback data
+ *
+ * This is here just for the sake of being overriden by its
+ * annotation_object_watch_full().
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_watch</name>
+      <annotations>
+        <annotation>
+          <name>skip</name>
+        </annotation>
+      </annotations>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>A #AnnotationObject</description>
+      </parameter>
+      <parameter>
+        <name>func</name>
+        <description>The callback</description>
+      </parameter>
+      <parameter>
+        <name>user_data</name>
+        <description>The callback data</description>
+      </parameter>
+    </parameters>
+    <description>This is here just for the sake of being overriden by its
+annotation_object_watch_full().</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_transfer.xml b/tests/scanner/annotationparser/gi/annotation_transfer.xml
new file mode 100644
index 0000000..49df32f
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_transfer.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * AnnotationObject::list-signal:
+ * @annotation: the annotation object
+ * @list: (type GLib.List) (element-type utf8) (transfer container): a list of strings
+ *
+ * This is a signal which takes a list of strings, but it's not
+ * known by GObject as it's only marked as G_TYPE_POINTER
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>AnnotationObject::list-signal</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>annotation</name>
+        <description>the annotation object</description>
+      </parameter>
+      <parameter>
+        <name>list</name>
+        <annotations>
+          <annotation>
+            <name>type</name>
+            <options>
+              <option>
+                <name>GLib.List</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>element-type</name>
+            <options>
+              <option>
+                <name>utf8</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>container</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>a list of strings</description>
+      </parameter>
+    </parameters>
+    <description>This is a signal which takes a list of strings, but it's not
+known by GObject as it's only marked as G_TYPE_POINTER</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_object_in:
+ * @object: a #GObject
+ * @inarg: (in) (transfer none): This is an argument test
+ *
+ * This is a test for in arguments
+ *
+ * Return value: an int
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_in</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>a #GObject</description>
+      </parameter>
+      <parameter>
+        <name>inarg</name>
+        <annotations>
+          <annotation>
+            <name>in</name>
+          </annotation>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>none</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>This is an argument test</description>
+      </parameter>
+    </parameters>
+    <description>This is a test for in arguments</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>an int</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_transfer_floating:
+ *
+ * Returns: (transfer floating): A floating object
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_transfer_floating</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <annotations>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>floating</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>A floating object</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  "Transfer:" tag syntax
+  -->
+  <commentblock>/**
+ * FsSession:codecs-without-config:
+ *
+ * This is the same list of codecs as #FsSession:codecs
+ * without....
+ *
+ * Transfer: full
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>FsSession:codecs-without-config</name>
+    </identifier>
+    <description>This is the same list of codecs as #FsSession:codecs
+without....</description>
+    <tags>
+      <tag>
+        <name>transfer</name>
+        <description>full</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_type.xml b/tests/scanner/annotationparser/gi/annotation_type.xml
new file mode 100644
index 0000000..d357423
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_type.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * AnnotationObject::list-signal:
+ * @annotation: the annotation object
+ * @list: (type GLib.List) (element-type utf8) (transfer container): a list of strings
+ *
+ * This is a signal which takes a list of strings, but it's not
+ * known by GObject as it's only marked as G_TYPE_POINTER
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>AnnotationObject::list-signal</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>annotation</name>
+        <description>the annotation object</description>
+      </parameter>
+      <parameter>
+        <name>list</name>
+        <annotations>
+          <annotation>
+            <name>type</name>
+            <options>
+              <option>
+                <name>GLib.List</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>element-type</name>
+            <options>
+              <option>
+                <name>utf8</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>container</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>a list of strings</description>
+      </parameter>
+    </parameters>
+    <description>This is a signal which takes a list of strings, but it's not
+known by GObject as it's only marked as G_TYPE_POINTER</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  "Type:" tag syntax
+  -->
+  <commentblock>/**
+   * RegressTestObj:hash-table:
+   *
+   * Test.
+   *
+   * Type: GLib.HashTable(utf8,gint8)
+   */</commentblock>
+  <docblock>
+    <identifier>
+      <name>RegressTestObj:hash-table</name>
+    </identifier>
+    <description>Test.</description>
+    <tags>
+      <tag>
+        <name>type</name>
+        <description>GLib.HashTable(utf8,gint8)</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_unref_func.xml b/tests/scanner/annotationparser/gi/annotation_unref_func.xml
new file mode 100644
index 0000000..98ac0a3
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_unref_func.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  "Unref func:" tag syntax
+  -->
+  <commentblock>/**
+ * RegressTestFundamentalObject:
+ *
+ * This object tests regressions...
+ *
+ * Unref func: regress_test_fundamental_object_unref
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>RegressTestFundamentalObject</name>
+    </identifier>
+    <description>This object tests regressions...</description>
+    <tags>
+      <tag>
+        <name>unref func</name>
+        <description>regress_test_fundamental_object_unref</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_value.xml b/tests/scanner/annotationparser/gi/annotation_value.xml
new file mode 100644
index 0000000..4a1a078
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_value.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  "Value:" tag syntax
+  -->
+  <commentblock>/**
+ * ANNOTATION_CALCULATED_LARGE:
+ *
+ * Constant to define a calculated large value
+ *
+ * Value: 10000000000UL
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>ANNOTATION_CALCULATED_LARGE</name>
+    </identifier>
+    <description>Constant to define a calculated large value</description>
+    <tags>
+      <tag>
+       <name>value</name>
+       <description>10000000000UL</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_virtual.xml b/tests/scanner/annotationparser/gi/annotation_virtual.xml
new file mode 100644
index 0000000..f2b6b23
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_virtual.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  "Virtual:" tag syntax
+  -->
+  <commentblock>/**
+ * foo_object_read:
+ * @object: obj
+ * @offset: offset
+ * @length: length
+ *
+ * Read some stuff.
+ *
+ * Virtual: read_fn
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>foo_object_read</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>object</name>
+        <description>obj</description>
+      </parameter>
+      <parameter>
+        <name>offset</name>
+        <description>offset</description>
+      </parameter>
+      <parameter>
+        <name>length</name>
+        <description>length</description>
+      </parameter>
+    </parameters>
+    <description>Read some stuff.</description>
+    <tags>
+      <tag>
+        <name>virtual</name>
+        <description>read_fn</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/syntax.xml b/tests/scanner/annotationparser/gi/syntax.xml
new file mode 100644
index 0000000..67224de
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>//Test</commentblock>
+</test>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>// Test</commentblock>
+</test>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>/*Test*/</commentblock>
+</test>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>/* Test */</commentblock>
+</test>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>/* Test
+something */</commentblock>
+</test>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>/*
+Test
+something */</commentblock>
+</test>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>/**Test*/</commentblock>
+</test>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>/** Test */</commentblock>
+</test>
+
+<test>
+  <!--
+  Not GTK-Doc
+  -->
+  <commentblock>/** Test
+something */</commentblock>
+</test>
+
+<test>
+  <!--
+  Broken comment block, signal the start of the comment block description followed
+  by a parameter instead.
+  -->
+  <commentblock>/**
+ * SECTION:meepapp
+ *
+ * @short_description: the application class
+ *
+ * The application class handles ...
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:meepapp</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>the application class</description>
+      </parameter>
+    </parameters>
+    <description>The application class handles ...</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/syntax_identifier.xml b/tests/scanner/annotationparser/gi/syntax_identifier.xml
new file mode 100644
index 0000000..4c1e0b1
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_identifier.xml
@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  Identifier part not on the first line.
+  -->
+  <commentblock>/**
+*
+* SECTION:meepapp
+*/</commentblock>
+</test>
+
+<test>
+  <!--
+  Multiple identifier parts
+  -->
+  <commentblock>/**
+ * SECTION:meepapp
+ * SECTION:meepapp2
+ * @short_description: the application class
+ *
+ * The application class handles ...
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:meepapp</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>the application class</description>
+      </parameter>
+    </parameters>
+    <description>SECTION:meepapp2
+The application class handles ...</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  Section documentation including all optional metadata.
+  -->
+  <commentblock>/**
+ * SECTION:meepapp
+ * @short_description: the application class
+ * @title: Meep application
+ * @section_id:
+ * @see_also: #MeepSettings
+ * @stability: Stable
+ * @include: meep/app.h
+ * @image: application.png
+ *
+ * The application class handles ...
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:meepapp</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>the application class</description>
+      </parameter>
+      <parameter>
+        <name>title</name>
+        <description>Meep application</description>
+      </parameter>
+      <parameter>
+        <name>section_id</name>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#MeepSettings</description>
+      </parameter>
+      <parameter>
+        <name>stability</name>
+        <description>Stable</description>
+      </parameter>
+      <parameter>
+        <name>include</name>
+        <description>meep/app.h</description>
+      </parameter>
+      <parameter>
+        <name>image</name>
+        <description>application.png</description>
+      </parameter>
+    </parameters>
+    <description>The application class handles ...</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  Broken comment block with empty line between identifier and parameters parts.
+  -->
+  <commentblock>/**
+ * SECTION:meepapp
+ *
+ * @short_description: the application class
+ * @title: Meep application
+ * @section_id:
+ * @see_also: #MeepSettings
+ * @stability: Stable
+ * @include: meep/app.h
+ * @image: application.png
+ *
+ * The application class handles ...
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:meepapp</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>the application class</description>
+      </parameter>
+      <parameter>
+        <name>title</name>
+        <description>Meep application</description>
+      </parameter>
+      <parameter>
+        <name>section_id</name>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#MeepSettings</description>
+      </parameter>
+      <parameter>
+        <name>stability</name>
+        <description>Stable</description>
+      </parameter>
+      <parameter>
+        <name>include</name>
+        <description>meep/app.h</description>
+      </parameter>
+      <parameter>
+        <name>image</name>
+        <description>application.png</description>
+      </parameter>
+    </parameters>
+    <description>The application class handles ...</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  Broken comment block with description part before parameters part, without empty line.
+  -->
+  <commentblock>/**
+ * SECTION:meepapp
+ *
+ * The application class handles ...
+ * @short_description: the application class
+ * @title: Meep application
+ * @section_id:
+ * @see_also: #MeepSettings
+ * @stability: Stable
+ * @include: meep/app.h
+ * @image: application.png
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:meepapp</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>the application class</description>
+      </parameter>
+      <parameter>
+        <name>title</name>
+        <description>Meep application</description>
+      </parameter>
+      <parameter>
+        <name>section_id</name>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#MeepSettings</description>
+      </parameter>
+      <parameter>
+        <name>stability</name>
+        <description>Stable</description>
+      </parameter>
+      <parameter>
+        <name>include</name>
+        <description>meep/app.h</description>
+      </parameter>
+      <parameter>
+        <name>image</name>
+        <description>application.png</description>
+      </parameter>
+    </parameters>
+    <description>The application class handles ...</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  Broken comment block with description part before parameters part, with empty line.
+  -->
+  <commentblock>/**
+ * SECTION:meepapp
+ *
+ * The application class handles ...
+ *
+ * @short_description: the application class
+ * @title: Meep application
+ * @section_id:
+ * @see_also: #MeepSettings
+ * @stability: Stable
+ * @include: meep/app.h
+ * @image: application.png
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:meepapp</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>the application class</description>
+      </parameter>
+      <parameter>
+        <name>title</name>
+        <description>Meep application</description>
+      </parameter>
+      <parameter>
+        <name>section_id</name>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#MeepSettings</description>
+      </parameter>
+      <parameter>
+        <name>stability</name>
+        <description>Stable</description>
+      </parameter>
+      <parameter>
+        <name>include</name>
+        <description>meep/app.h</description>
+      </parameter>
+      <parameter>
+        <name>image</name>
+        <description>application.png</description>
+      </parameter>
+    </parameters>
+    <description>The application class handles ...</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  Old style implicit returns.
+  https://bugzilla.gnome.org/show_bug.cgi?id=457077
+  -->
+  <commentblock>/**
+ * SECTION:tester
+ * @short_description: module for gtk-doc unit test
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ *
+ * As described in http://bugzilla.gnome.org/show_bug.cgi?id=457077 it
+ * returns nothing.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:tester</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>module for gtk-doc unit test</description>
+      </parameter>
+    </parameters>
+    <description>This file contains non-sense code for the sole purpose of testing the docs.
+
+As described in http://bugzilla.gnome.org/show_bug.cgi?id=457077 it
+returns nothing.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml b/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml
new file mode 100644
index 0000000..6291493
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  All lines (outside program- listings and CDATA sections) just containing
+  a ' *' (blank-asterisk) are converted to paragraph breaks.
+  -->
+  <commentblock>/**
+ * SECTION:test
+ *
+ * The following line is ' *' (blank-asterisk).
+ *
+ * So this is considered a new paragraph.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:test</name>
+    </identifier>
+    <description>The following line is ' *' (blank-asterisk).
+
+So this is considered a new paragraph.</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  ' * ' (blank-asterisk-blank) are also converted to paragraph breaks.
+  -->
+  <commentblock>/**
+ * SECTION:test
+ *
+ * The following line is ' * ' (blank-asterisk-blank).
+ * 
+ * So this is considered a new paragraph.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:test</name>
+    </identifier>
+    <description>The following line is ' * ' (blank-asterisk-blank).
+
+So this is considered a new paragraph.</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  If you want an "empty line" but not a paragraph break, change that into ' *  '
+  (blank-asterisk-blank-blank). The "empty line" can be easily recognized in the
+  output as it contains a single space character.
+  -->
+  <commentblock>/**
+ * SECTION:test
+ *
+ * The following line is (blank-asterisk-blank-blank).
+ *  
+ * So this is preceded by an empty line and is not considered a new paragraph.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:test</name>
+    </identifier>
+    <description>The following line is (blank-asterisk-blank-blank).
+ 
+So this is preceded by an empty line and is not considered a new paragraph.</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  If you want an "empty line" but not a paragraph break, change that into ' *  '
+  (blank-asterisk-blank-blank). The "empty line" can be easily recognized in the
+  output as it contains a single space character.
+  -->
+  <commentblock><![CDATA[/**
+ * SECTION:test
+ *
+ * <example>
+ * <title>Iterating over attributes</title>
+ * <programlisting>
+ * void
+ * print_attributes (GIBaseInfo *info)
+ * {
+ *   GIAttributeIter iter = { 0, };
+ *   char *name;
+ *   char *value;
+ *  
+ *   while (g_base_info_iterate_attributes (info, &iter, &name, &value))
+ *     {
+ *       g_print ("attribute name: %s value: %s", name, value);
+ *     }
+ * }
+ * </programlisting>
+ * </example>
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:test</name>
+    </identifier>
+    <description><![CDATA[<example>
+<title>Iterating over attributes</title>
+<programlisting>
+void
+print_attributes (GIBaseInfo *info)
+{
+  GIAttributeIter iter = { 0, };
+  char *name;
+  char *value;
+ 
+  while (g_base_info_iterate_attributes (info, &iter, &name, &value))
+    {
+      g_print ("attribute name: %s value: %s", name, value);
+    }
+}
+</programlisting>
+</example>]]></description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/tag_deprecated.xml b/tests/scanner/annotationparser/gi/tag_deprecated.xml
new file mode 100644
index 0000000..6374bf8
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_deprecated.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_versioned:
+ *
+ * Deprecated: 0.6: Use something else instead
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_versioned</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>deprecated</name>
+        <description>0.6: Use something else instead</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_versioned:
+ *
+ * Deprecated: 0.6
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_versioned</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>deprecated</name>
+        <description>0.6</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/tag_description.xml b/tests/scanner/annotationparser/gi/tag_description.xml
new file mode 100644
index 0000000..75860f6
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_description.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * shiny_function:
+ *
+ * Description: This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>shiny_function</name>
+    </identifier>
+    <description>This is a callback with a 'closure' argument that is not named
+'user_data' and hence has to be annotated.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/tag_returns.xml b/tests/scanner/annotationparser/gi/tag_returns.xml
new file mode 100644
index 0000000..302d8cf
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_returns.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns: some boolean
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_string_out</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>some boolean</description>
+      </tag>
+    </tags>
+    <description>Test returning a string as an out parameter</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  Deprecated "Return value:" tag
+  -->
+  <commentblock>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Return value: some boolean
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_string_out</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>some boolean</description>
+      </tag>
+    </tags>
+    <description>Test returning a string as an out parameter</description>
+  </docblock>
+</test>
+
+<test>
+  <!--
+  Deprecated "@returns" as a parameter
+  -->
+  <commentblock>/**
+ * annotation_object_string_out:
+ * @returns: some boolean
+ *
+ * Test returning a string as an out parameter
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_object_string_out</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>some boolean</description>
+      </tag>
+    </tags>
+    <description>Test returning a string as an out parameter</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/tag_since.xml b/tests/scanner/annotationparser/gi/tag_since.xml
new file mode 100644
index 0000000..2bd8c5c
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_since.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_versioned:
+ *
+ * Since: 0.6
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_versioned</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>since</name>
+        <description>0.6</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_versioned:
+ *
+ * Since: this function is available since version 0.6
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_versioned</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>since</name>
+        <description>this function is available since version 0.6</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/tag_stability.xml b/tests/scanner/annotationparser/gi/tag_stability.xml
new file mode 100644
index 0000000..154b838
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_stability.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * annotation_versioned:
+ *
+ * Stability: Stable
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_versioned</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>stability</name>
+        <description>Stable</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_versioned:
+ *
+ * Stability: Unstable
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_versioned</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>stability</name>
+        <description>Unstable</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_versioned:
+ *
+ * Stability: Private
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_versioned</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>stability</name>
+        <description>Private</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_versioned:
+ *
+ * Stability: behavior tends to vary depending on the phase of the moon.
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_versioned</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>stability</name>
+        <description>behavior tends to vary depending on the phase of the moon.</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/annotations/tester.c.xml b/tests/scanner/annotationparser/gtkdoc/annotations/tester.c.xml
new file mode 100644
index 0000000..9be3db7
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/annotations/tester.c.xml
@@ -0,0 +1,344 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * SECTION:tester
+ * @short_description: module for gtk-doc unit test
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:tester</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>module for gtk-doc unit test</description>
+      </parameter>
+    </parameters>
+    <description>This file contains non-sense code for the sole purpose of testing the docs.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_array_length:
+ * @list: a #GtkListStore
+ * @n_columns: number of columns
+ * @types: (array length=n_columns): list of types
+ *
+ * Document parameter relation for array length.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_array_length</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>list</name>
+        <description>a #GtkListStore</description>
+      </parameter>
+      <parameter>
+        <name>n_columns</name>
+        <description>number of columns</description>
+      </parameter>
+      <parameter>
+        <name>types</name>
+        <annotations>
+          <annotation>
+            <name>array</name>
+            <options>
+              <option>
+                <name>length</name>
+                <value>n_columns</value>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>list of types</description>
+      </parameter>
+    </parameters>
+    <description>Document parameter relation for array length.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_nullable:
+ * @uri: a uri
+ * @label: (allow-none): an optional string, which is used in ways too
+ *  complicated to describe in a single line, making it necessary to wrap it
+ *
+ * Document optional parameters.
+ *
+ * Returns: (transfer full) (allow-none): Returns stuff which you have to
+ *  free after use, whose description is also rather long
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_nullable</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>uri</name>
+        <description>a uri</description>
+      </parameter>
+      <parameter>
+        <name>label</name>
+        <annotations>
+          <annotation>
+            <name>allow-none</name>
+          </annotation>
+        </annotations>
+        <description>an optional string, which is used in ways too complicated to describe in a single line, making it necessary to wrap it</description>
+      </parameter>
+    </parameters>
+    <description>Document optional parameters.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <annotations>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>full</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>allow-none</name>
+          </annotation>
+        </annotations>
+        <description>Returns stuff which you have to free after use, whose description is also rather long</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_elementtype:
+ * @list: (element-type GObject): list of #GObject instances to search
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_elementtype</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>list</name>
+        <annotations>
+          <annotation>
+            <name>element-type</name>
+            <options>
+              <option>
+                <name>GObject</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>list of #GObject instances to search</description>
+      </parameter>
+    </parameters>
+    <description>Document optional parameters.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>%TRUE for success</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_elementtype_transfer:
+ * @list: (element-type utf8) (transfer full): list of #GObject instances to search
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_elementtype_transfer</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>list</name>
+        <annotations>
+          <annotation>
+            <name>element-type</name>
+            <options>
+              <option>
+                <name>utf8</name>
+              </option>
+            </options>
+          </annotation>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>full</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>list of #GObject instances to search</description>
+      </parameter>
+    </parameters>
+    <description>Document optional parameters.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>%TRUE for success</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_elementtype_returns:
+ *
+ * Document optional parameters.
+ *
+ * Returns: (element-type GObject): A list of #GObject instances.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_elementtype_returns</name>
+    </identifier>
+    <description>Document optional parameters.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <annotations>
+          <annotation>
+            <name>element-type</name>
+            <options>
+              <option>
+                <name>GObject</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>A list of #GObject instances.</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_outparams:
+ * @list: (out) (transfer none): a pointer to take a list
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_outparams</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>list</name>
+        <annotations>
+          <annotation>
+            <name>out</name>
+          </annotation>
+          <annotation>
+            <name>transfer</name>
+            <options>
+              <option>
+                <name>none</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>a pointer to take a list</description>
+      </parameter>
+    </parameters>
+    <description>Document optional parameters.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>%TRUE for success</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_skip: (skip)
+ * @list: a pointer to take a list
+ *
+ * Documentation for this function.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_skip</name>
+      <annotations>
+        <annotation>
+          <name>skip</name>
+        </annotation>
+      </annotations>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>list</name>
+        <description>a pointer to take a list</description>
+      </parameter>
+    </parameters>
+    <description>Documentation for this function.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * annotation_scope:
+ * @callback: (scope async): a callback
+ * @user_data: data to pass to callback
+ *
+ * Documentation for this function.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>annotation_scope</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>callback</name>
+        <annotations>
+          <annotation>
+            <name>scope</name>
+            <options>
+              <option>
+                <name>async</name>
+              </option>
+            </options>
+          </annotation>
+        </annotations>
+        <description>a callback</description>
+      </parameter>
+      <parameter>
+        <name>user_data</name>
+        <description>data to pass to callback</description>
+      </parameter>
+    </parameters>
+    <description>Documentation for this function.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/annotations/tester.h.xml b/tests/scanner/annotationparser/gtkdoc/annotations/tester.h.xml
new file mode 100644
index 0000000..b79e1bc
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/annotations/tester.h.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * GtkdocAnnotation:
+ * @that: (allow-none): eventualy points to something
+ *
+ * small struct
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocAnnotation</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>that</name>
+        <annotations>
+          <annotation>
+            <name>allow-none</name>
+          </annotation>
+        </annotations>
+        <description>eventualy points to something</description>
+      </parameter>
+    </parameters>
+    <description>small struct</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/bugs/tester.c.xml b/tests/scanner/annotationparser/gtkdoc/bugs/tester.c.xml
new file mode 100644
index 0000000..f0a2b22
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/bugs/tester.c.xml
@@ -0,0 +1,765 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock><![CDATA[/**
+ * SECTION:tester
+ * @short_description: module for gtk-doc unit test
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ *
+ * As described in http://bugzilla.gnome.org/show_bug.cgi?id=457077 it
+ * returns nothing.
+ *
+ * Some special characters need escaping. The tests should pass 100\%.
+ * Try a <ulink url="http://www.gtk.org/gtk-doc/#Top";>link containing a # char</ulink>.
+ *
+ * <refsect2 id="dummy-id">
+ * <title>more details</title>
+ * <para>
+ * Second paragraph inside subsection.
+ * </para>
+ * </refsect2>
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:tester</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>module for gtk-doc unit test</description>
+      </parameter>
+    </parameters>
+    <description><![CDATA[This file contains non-sense code for the sole purpose of testing the docs.
+
+As described in http://bugzilla.gnome.org/show_bug.cgi?id=457077 it
+returns nothing.
+
+Some special characters need escaping. The tests should pass 100\%.
+Try a <ulink url="http://www.gtk.org/gtk-doc/#Top";>link containing a # char</ulink>.
+
+<refsect2 id="dummy-id">
+<title>more details</title>
+<para>
+Second paragraph inside subsection.
+</para>
+</refsect2>]]></description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_141869_a:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=141869
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_141869_a</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>pid</name>
+        <description>arg</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=141869</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_141869_b:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=141869
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_141869_b</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>pid</name>
+        <description>arg</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=141869</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_379466:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=379466
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_379466</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>pid</name>
+        <description>arg</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=379466</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_380824:
+ * @arg: arg
+ *
+ * Returns a value.
+ * http://bugzilla.gnome.org/show_bug.cgi?id=380824
+ *
+ * Since: 0.1
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_380824</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>arg</name>
+        <description>arg</description>
+      </parameter>
+    </parameters>
+    <description>Returns a value.
+http://bugzilla.gnome.org/show_bug.cgi?id=380824</description>
+    <tags>
+      <tag>
+        <name>since</name>
+        <description>0.1</description>
+      </tag>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_411739:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=411739
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_411739</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=411739</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_419997:
+ * @const_values: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=419997
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_419997</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>const_values</name>
+        <description>arg</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=419997</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_445693:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=445693
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_445693</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>pid</name>
+        <description>arg</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=445693</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_471014:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=471014
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_471014</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=471014</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * Bug446648:
+ * @BUG_446648_FOO: foo
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=446648
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug446648</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>BUG_446648_FOO</name>
+        <description>foo</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=446648</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_552602:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=552602
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_552602</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=552602</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_574654a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=574654
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_574654a</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=574654</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_574654b:
+ * @offset: skip this many items
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=574654
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_574654b</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>offset</name>
+        <description>skip this many items</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=574654</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_580300a_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_580300a_get_type</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=580300</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_580300b_get_type:
+ * @a: value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_580300b_get_type</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>value</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=580300</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_580300c_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_580300c_get_type</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=580300</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_580300d_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_580300d_get_type</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=580300</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_597937:
+ * @function_arg: value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=597937
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_597937</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>function_arg</name>
+        <description>value</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=597937</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_602518a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_602518a</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=602518</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_602518b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_602518b</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=602518</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_602518c:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_602518c</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=602518</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_607445:
+ * @a: parameter
+ * @n: parameter
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=607445
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_607445</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>parameter</description>
+      </parameter>
+      <parameter>
+        <name>n</name>
+        <description>parameter</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=607445</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_610257:
+ * @der: parameter
+ * @len: parameter
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=610257
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_610257</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>der</name>
+        <description>parameter</description>
+      </parameter>
+      <parameter>
+        <name>len</name>
+        <description>parameter</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=610257</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock><![CDATA[/**
+ * bug_623968a:
+ *
+ * <para>test</para>
+ * <refsect3>
+ *   <title>subsect</title>
+ *   <para>test</para>
+ * </refsect3>
+ **/]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_623968a</name>
+    </identifier>
+    <description><![CDATA[<para>test</para>
+<refsect3>
+  <title>subsect</title>
+  <para>test</para>
+</refsect3>]]></description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock><![CDATA[/**
+ * bug_623968b:
+ *
+ * test
+ *
+ * <refsect3>
+ *   <title>subsect</title>
+ *   <para>test</para>
+ * </refsect3>
+ **/]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_623968b</name>
+    </identifier>
+    <description><![CDATA[test
+
+<refsect3>
+  <title>subsect</title>
+  <para>test</para>
+</refsect3>]]></description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock><![CDATA[/**
+ * bug_623968c:
+ *
+ * <para>test</para>
+ **/]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_623968c</name>
+    </identifier>
+    <description><![CDATA[<para>test</para>]]></description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_624200a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624200
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_624200a</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=624200</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_624200b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624200
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_624200b</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=624200</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_638330:
+ * @arg1: arg1
+ * @data: data
+ * @length: length
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=638330
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_638330</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>arg1</name>
+        <description>arg1</description>
+      </parameter>
+      <parameter>
+        <name>data</name>
+        <description>data</description>
+      </parameter>
+      <parameter>
+        <name>length</name>
+        <description>length</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=638330</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_000000_va1:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_000000_va1</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>name</name>
+        <description>a name</description>
+      </parameter>
+      <parameter>
+        <name>...</name>
+        <description>A printf-style message to output</description>
+      </parameter>
+    </parameters>
+    <description>Outputs a message.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_624001a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_624001a</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_624001b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_624001b</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_624001c:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_624001c</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_624001d:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_624001d</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_624001e:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_624001e</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/bugs/tester.h.xml b/tests/scanner/annotationparser/gtkdoc/bugs/tester.h.xml
new file mode 100644
index 0000000..da7c791
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/bugs/tester.h.xml
@@ -0,0 +1,677 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * Bug324535:
+ * @BUG_324535_A: enum 1
+ * @BUG_324535_B: enum 2
+ * @BUG_324535_C: enum 3
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=324535
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug324535</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>BUG_324535_A</name>
+        <description>enum 1</description>
+      </parameter>
+      <parameter>
+        <name>BUG_324535_B</name>
+        <description>enum 2</description>
+      </parameter>
+      <parameter>
+        <name>BUG_324535_C</name>
+        <description>enum 3</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=324535</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_481811:
+ * @x: argument
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=481811
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_481811</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>x</name>
+        <description>argument</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=481811</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_501038:
+ * @a: value
+ * @b: deprecated value
+ * @_b: scrambled deprecated value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=501038
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_501038</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>value</description>
+      </parameter>
+      <parameter>
+        <name>b</name>
+        <description>deprecated value</description>
+      </parameter>
+      <parameter>
+        <name>_b</name>
+        <description>scrambled deprecated value</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=501038</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_460127:
+ * @a: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=460127
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_460127</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>field</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=460127</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_477532:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=477532
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_477532</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=477532</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * Bug446648:
+ * @BUG_446648_FOO: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=446648
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug446648</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>BUG_446648_FOO</name>
+        <description>field</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=446648</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * Bug512154:
+ * @index: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512154
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug512154</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>index</name>
+        <description>field</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=512154</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_512155a_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_512155a_function_pointer_t</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>arg1</name>
+        <description>param 1</description>
+      </parameter>
+      <parameter>
+        <name>arg2</name>
+        <description>param 1</description>
+      </parameter>
+      <parameter>
+        <name>arg3</name>
+        <description>param 1</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=512155</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_512155b_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_512155b_function_pointer_t</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>arg1</name>
+        <description>param 1</description>
+      </parameter>
+      <parameter>
+        <name>arg2</name>
+        <description>param 1</description>
+      </parameter>
+      <parameter>
+        <name>arg3</name>
+        <description>param 1</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=512155</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_512155c_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_512155c_function_pointer_t</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>arg1</name>
+        <description>param 1</description>
+      </parameter>
+      <parameter>
+        <name>arg2</name>
+        <description>param 1</description>
+      </parameter>
+      <parameter>
+        <name>arg3</name>
+        <description>param 1</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=512155</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock><![CDATA[/**
+ * BUG_530758:
+ *
+ * {{![CDATA[http://bugzilla.gnome.org/show_bug.cgi?id=530758#c1]]!}}
+ *
+ * <ulink url="http://bugzilla.gnome.org/show_bug.cgi?id=530758#c1";>Test</ulink>
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>BUG_530758</name>
+    </identifier>
+    <description><![CDATA[{{![CDATA[http://bugzilla.gnome.org/show_bug.cgi?id=530758#c1]]!}}
+
+<ulink url="http://bugzilla.gnome.org/show_bug.cgi?id=530758#c1";>Test</ulink>]]></description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_532395a:
+ * @number: a number
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=532395
+ *
+ * Returns: number
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_532395a</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>number</name>
+        <description>a number</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=532395</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>number</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_532395b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=532395
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_532395b</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=532395</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_544172:
+ * @self: object pointer.
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=544172
+ *
+ * Returns: result or %NULL.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_544172</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>self</name>
+        <description>object pointer.</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=544172</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result or %NULL.</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_554833:
+ * @i: value;
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=554833
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_554833</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>i</name>
+        <description>value;</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=554833</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * bug_554833_new:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=554833
+ *
+ * Returns: result
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>bug_554833_new</name>
+    </identifier>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=554833</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>result</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * Bug165425a:
+ * @i: data as int
+ * @f: data as float
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=165425
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug165425a</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>i</name>
+        <description>data as int</description>
+      </parameter>
+      <parameter>
+        <name>f</name>
+        <description>data as float</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=165425</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * Bug165425b:
+ * @i: data as int
+ * @f: data as float
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=165425
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug165425b</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>i</name>
+        <description>data as int</description>
+      </parameter>
+      <parameter>
+        <name>f</name>
+        <description>data as float</description>
+      </parameter>
+    </parameters>
+    <description>http://bugzilla.gnome.org/show_bug.cgi?id=165425</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * Bug642998:
+ * @red: red color intensity, from 0â255
+ * @green: green color intensity, from 0â255
+ * @blue: blue color intensity, from 0â255
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=642998
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug642998</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>red</name>
+        <description>red color intensity, from 0â255</description>
+      </parameter>
+      <parameter>
+        <name>green</name>
+        <description>green color intensity, from 0â255</description>
+      </parameter>
+      <parameter>
+        <name>blue</name>
+        <description>blue color intensity, from 0â255</description>
+      </parameter>
+    </parameters>
+    <description>https://bugzilla.gnome.org/show_bug.cgi?id=642998</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * Bug644291:
+ * @BUG_644291_START: foo
+ * @BUG_644291_TEXT: bar
+ * @BUG_644291_END: milk
+ * @BUG_644291_ATTRIBUTE: comes
+ * @BUG_644291_XMLNS: from
+ * @BUG_644291_ASSIGN_TO: cows
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=644291
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug644291</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>BUG_644291_START</name>
+        <description>foo</description>
+      </parameter>
+      <parameter>
+        <name>BUG_644291_TEXT</name>
+        <description>bar</description>
+      </parameter>
+      <parameter>
+        <name>BUG_644291_END</name>
+        <description>milk</description>
+      </parameter>
+      <parameter>
+        <name>BUG_644291_ATTRIBUTE</name>
+        <description>comes</description>
+      </parameter>
+      <parameter>
+        <name>BUG_644291_XMLNS</name>
+        <description>from</description>
+      </parameter>
+      <parameter>
+        <name>BUG_644291_ASSIGN_TO</name>
+        <description>cows</description>
+      </parameter>
+    </parameters>
+    <description>https://bugzilla.gnome.org/show_bug.cgi?id=644291</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * BUG_000000_VA2:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>BUG_000000_VA2</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>name</name>
+        <description>a name</description>
+      </parameter>
+      <parameter>
+        <name>...</name>
+        <description>A printf-style message to output</description>
+      </parameter>
+    </parameters>
+    <description>Outputs a message.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * BUG_000000_VA3:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>BUG_000000_VA3</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>name</name>
+        <description>a name</description>
+      </parameter>
+      <parameter>
+        <name>...</name>
+        <description>A printf-style message to output</description>
+      </parameter>
+    </parameters>
+    <description>Outputs a message.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * Bug000000Scope:
+ *
+ * Opaque structure.
+ * "warning: Field descriptions for Bug000000Scope are missing in source code comment block."
+ * but not if we remove the blank line before "int b";
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>Bug000000Scope</name>
+    </identifier>
+    <description>Opaque structure.
+"warning: Field descriptions for Bug000000Scope are missing in source code comment block."
+but not if we remove the blank line before "int b";</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * gst_play_marshal_BUFFER__BOXED:
+ * @closure: test
+ * @return_value: test
+ * @marshal_data: test
+ *
+ * test.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>gst_play_marshal_BUFFER__BOXED</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>closure</name>
+        <description>test</description>
+      </parameter>
+      <parameter>
+        <name>return_value</name>
+        <description>test</description>
+      </parameter>
+      <parameter>
+        <name>marshal_data</name>
+        <description>test</description>
+      </parameter>
+    </parameters>
+    <description>test.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * BUG_656773a:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>BUG_656773a</name>
+    </identifier>
+    <description>https://bugzilla.gnome.org/show_bug.cgi?id=656773</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * BUG_656773b:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>BUG_656773b</name>
+    </identifier>
+    <description>https://bugzilla.gnome.org/show_bug.cgi?id=656773</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * BUG_656773c:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>BUG_656773c</name>
+    </identifier>
+    <description>https://bugzilla.gnome.org/show_bug.cgi?id=656773</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * BUG_656946:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656946
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>BUG_656946</name>
+    </identifier>
+    <description>https://bugzilla.gnome.org/show_bug.cgi?id=656946</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/empty/tester.c.xml b/tests/scanner/annotationparser/gtkdoc/empty/tester.c.xml
new file mode 100644
index 0000000..c18e29f
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/empty/tester.c.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock><![CDATA[/**
+ * SECTION:tester
+ * @short_description: module for gtk-doc unit test
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ *
+ * As described in http://bugzilla.gnome.org/show_bug.cgi?id=457077 it
+ * returns nothing.
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:tester</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>short_description</name>
+        <description>module for gtk-doc unit test</description>
+      </parameter>
+    </parameters>
+    <description><![CDATA[This file contains non-sense code for the sole purpose of testing the docs.
+
+As described in http://bugzilla.gnome.org/show_bug.cgi?id=457077 it
+returns nothing.]]></description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * test:
+ * @a: arg
+ *
+ * lonely function
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>test</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>arg</description>
+      </parameter>
+    </parameters>
+    <description>lonely function</description>
+  </docblock>
+ </test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/fail/tester.c.xml b/tests/scanner/annotationparser/gtkdoc/fail/tester.c.xml
new file mode 100644
index 0000000..7ebf440
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/fail/tester.c.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/*
+ * SECTION:tester_nodocs
+ * @short_description: module for gtk-doc unit test
+ * @title: GtkdocTesterNoDocs
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</commentblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * SECTION:tester_nolongdesc
+ * @short_description: module for gtk-doc unit test
+ * @title: GtkdocTesterNoLongDesc
+ */</commentblock>
+ <docblock>
+   <identifier>
+     <name>SECTION:tester_nolongdesc</name>
+   </identifier>
+   <parameters>
+     <parameter>
+       <name>short_description</name>
+       <description>module for gtk-doc unit test</description>
+     </parameter>
+     <parameter>
+       <name>title</name>
+       <description>GtkdocTesterNoLongDesc</description>
+     </parameter>
+   </parameters>
+ </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * SECTION:tester_noshortdesc
+ * @title: GtkdocTesterNoShortDesc
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</commentblock>
+ <docblock>
+   <identifier>
+     <name>SECTION:tester_noshortdesc</name>
+   </identifier>
+   <parameters>
+     <parameter>
+       <name>title</name>
+       <description>GtkdocTesterNoShortDesc</description>
+     </parameter>
+   </parameters>
+   <description>This file contains non-sense code for the sole purpose of testing the docs.</description>
+ </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * SECTION:tester_brokendocs
+ * @short_description: module for gtk-doc unit test
+ * @title: GtkdocTesterBrokenDocs
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</commentblock>
+ <docblock>
+   <identifier>
+     <name>SECTION:tester_brokendocs</name>
+   </identifier>
+   <parameters>
+     <parameter>
+       <name>short_description</name>
+       <description>module for gtk-doc unit test</description>
+     </parameter>
+     <parameter>
+       <name>title</name>
+       <description>GtkdocTesterBrokenDocs</description>
+     </parameter>
+   </parameters>
+   <description>This file contains non-sense code for the sole purpose of testing the docs.</description>
+ </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * func_no_docs:
+ */</commentblock>
+ <docblock>
+   <identifier>
+     <name>func_no_docs</name>
+   </identifier>
+ </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * func_no_item_docs:
+ *
+ * Here we document the function but not the parameters.
+ */</commentblock>
+ <docblock>
+   <identifier>
+     <name>func_no_item_docs</name>
+   </identifier>
+   <description>Here we document the function but not the parameters.</description>
+ </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * func_incomplete_docs:
+ * @a: a value
+ *
+ * Here we document the function but not all the parameters.
+ */</commentblock>
+ <docblock>
+   <identifier>
+     <name>func_incomplete_docs</name>
+   </identifier>
+   <parameters>
+     <parameter>
+       <name>a</name>
+       <description>a value</description>
+     </parameter>
+   </parameters>
+   <description>Here we document the function but not all the parameters.</description>
+ </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * func_unused_docs:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the function and more than the actual parameters.
+ */</commentblock>
+ <docblock>
+   <identifier>
+     <name>func_unused_docs</name>
+   </identifier>
+   <parameters>
+     <parameter>
+       <name>a</name>
+       <description>a value</description>
+     </parameter>
+     <parameter>
+       <name>b</name>
+       <description>a value</description>
+     </parameter>
+     <parameter>
+       <name>c</name>
+       <description>an unexisting value</description>
+     </parameter>
+   </parameters>
+   <description>Here we document the function and more than the actual parameters.</description>
+ </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/fail/tester.h.xml b/tests/scanner/annotationparser/gtkdoc/fail/tester.h.xml
new file mode 100644
index 0000000..3e51b76
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/fail/tester.h.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+<commentblock>/**
+ * MACRO_NO_ITEM_DOCS:
+ *
+ * Here we document the macro but not the parameters.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>MACRO_NO_ITEM_DOCS</name>
+    </identifier>
+    <description>Here we document the macro but not the parameters.</description>
+  </docblock>
+</test>
+
+<test>
+<commentblock>/**
+ * MACRO_INCOMPLETE_DOCS:
+ * @a: a value
+ *
+ * Here we document the macro but not all the parameters.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>MACRO_INCOMPLETE_DOCS</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>a value</description>
+      </parameter>
+    </parameters>
+    <description>Here we document the macro but not all the parameters.</description>
+  </docblock>
+</test>
+
+<test>
+<commentblock>/**
+ * MACRO_UNUSED_DOCS:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the macro and more than the actual parameters.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>MACRO_UNUSED_DOCS</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>a value</description>
+      </parameter>
+      <parameter>
+        <name>b</name>
+        <description>a value</description>
+      </parameter>
+      <parameter>
+        <name>c</name>
+        <description>an unexisting value</description>
+      </parameter>
+    </parameters>
+    <description>Here we document the macro and more than the actual parameters.</description>
+  </docblock>
+</test>
+
+<test>
+<commentblock>/**
+ * EnumNoItemDocs:
+ *
+ * Here we document the enum but not the values.
+ * http://bugzilla.gnome.org/show_bug.cgi?id=568711
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>EnumNoItemDocs</name>
+    </identifier>
+    <description>Here we document the enum but not the values.
+http://bugzilla.gnome.org/show_bug.cgi?id=568711</description>
+  </docblock>
+</test>
+
+<test>
+<commentblock>/**
+ * EnumIncompleteDocs:
+ * @ENUM_INCOMPLETE_DOCS_1: a value
+ *
+ * Here we document the enum but not all the values.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>EnumIncompleteDocs</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>ENUM_INCOMPLETE_DOCS_1</name>
+        <description>a value</description>
+      </parameter>
+    </parameters>
+    <description>Here we document the enum but not all the values.</description>
+  </docblock>
+</test>
+
+<test>
+<commentblock>/**
+ * EnumUnusedDocs:
+ * @ENUM_UNUSED_DOCS_1: a value
+ * @ENUM_UNUSED_DOCS_2: a value
+ * @ENUM_UNUSED_DOCS_3: an unexisting value
+ *
+ * Here we document the enum and more than the actual values.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>EnumUnusedDocs</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>ENUM_UNUSED_DOCS_1</name>
+        <description>a value</description>
+      </parameter>
+      <parameter>
+        <name>ENUM_UNUSED_DOCS_2</name>
+        <description>a value</description>
+      </parameter>
+      <parameter>
+        <name>ENUM_UNUSED_DOCS_3</name>
+        <description>an unexisting value</description>
+      </parameter>
+    </parameters>
+    <description>Here we document the enum and more than the actual values.</description>
+  </docblock>
+</test>
+
+<test>
+<commentblock>/**
+ * StructNoItemDocs:
+ *
+ * Here we document the struct but not the values.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>StructNoItemDocs</name>
+    </identifier>
+    <description>Here we document the struct but not the values.</description>
+  </docblock>
+</test>
+
+<test>
+<commentblock>/**
+ * StructIncompleteDocs:
+ * @a: a value
+ *
+ * Here we document the struct but not all the values.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>StructIncompleteDocs</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>a value</description>
+      </parameter>
+    </parameters>
+    <description>Here we document the struct but not all the values.</description>
+  </docblock>
+</test>
+
+<test>
+<commentblock>/**
+ * StructUnusedDocs:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the struct and more than the actual values.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>StructUnusedDocs</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>a</name>
+        <description>a value</description>
+      </parameter>
+      <parameter>
+        <name>b</name>
+        <description>a value</description>
+      </parameter>
+      <parameter>
+        <name>c</name>
+        <description>an unexisting value</description>
+      </parameter>
+    </parameters>
+    <description>Here we document the struct and more than the actual values.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/gobject/giface.c.xml b/tests/scanner/annotationparser/gtkdoc/gobject/giface.c.xml
new file mode 100644
index 0000000..ea09d12
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/giface.c.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock><![CDATA[/**
+ * SECTION:iface
+ * @title: GtkdocIface
+ * @short_description: interface for gtk-doc unit test
+ * @see_also: #GtkdocObject
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ * We can link to the #GtkdocIface:itest property and the #GtkdocIface::itest
+ * signal.
+ * An instance can be configured using the gtkdoc_iface_configure() function.
+ *
+ * I can haz pictures too!
+ * <mediaobject>
+ *   <imageobject><imagedata fileref="home.png" format="PNG"/></imageobject>
+ *   <caption><para>Home sweet home.</para></caption>
+ * </mediaobject>
+ *
+ * Just incase you wonder, special caracters can be escaped with a \ like in \%
+ * or \# or even \  
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:iface</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>title</name>
+        <description>GtkdocIface</description>
+      </parameter>
+      <parameter>
+        <name>short_description</name>
+        <description>interface for gtk-doc unit test</description>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#GtkdocObject</description>
+      </parameter>
+    </parameters>
+    <description><![CDATA[This file contains non-sense code for the sole purpose of testing the docs.
+We can link to the #GtkdocIface:itest property and the #GtkdocIface::itest
+signal.
+An instance can be configured using the gtkdoc_iface_configure() function.
+
+I can haz pictures too!
+<mediaobject>
+  <imageobject><imagedata fileref="home.png" format="PNG"/></imageobject>
+  <caption><para>Home sweet home.</para></caption>
+</mediaobject>
+
+Just incase you wonder, special caracters can be escaped with a \ like in \%
+or \# or even \  ]]></description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * SECTION:iface2
+ * @title: GtkdocIface2
+ * @short_description: interface with a prerequisite for gtk-doc unit test
+ * @see_also: #GtkdocObject, #GtkdocIface
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:iface2</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>title</name>
+        <description>GtkdocIface2</description>
+      </parameter>
+      <parameter>
+        <name>short_description</name>
+        <description>interface with a prerequisite for gtk-doc unit test</description>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#GtkdocObject, #GtkdocIface</description>
+      </parameter>
+    </parameters>
+    <description>This file contains non-sense code for the sole purpose of testing the docs.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * gtkdoc_iface_configure:
+ * @config: settings
+ *
+ * Configure a new instance
+ *
+ * Returns: %TRUE for sucess or %FALSE in case of an error
+ *
+ * Since: 0.1
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>gtkdoc_iface_configure</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>config</name>
+        <description>settings</description>
+      </parameter>
+    </parameters>
+    <description>Configure a new instance</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>%TRUE for sucess or %FALSE in case of an error</description>
+      </tag>
+      <tag>
+        <name>since</name>
+        <description>0.1</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+     * GtkdocIface::itest:
+     * @self: myself
+     *
+     * The event has been triggered.
+     */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocIface::itest</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>self</name>
+        <description>myself</description>
+      </parameter>
+    </parameters>
+    <description>The event has been triggered.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/gobject/giface.h.xml b/tests/scanner/annotationparser/gtkdoc/gobject/giface.h.xml
new file mode 100644
index 0000000..7185ad0
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/giface.h.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * GtkdocIface:
+ *
+ * opaque instance of gtk-doc unit test interface
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocIface</name>
+    </identifier>
+    <description>opaque instance of gtk-doc unit test interface</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GtkdocIface2:
+ *
+ * opaque instance of gtk-doc unit test interface
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocIface2</name>
+    </identifier>
+    <description>opaque instance of gtk-doc unit test interface</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GtkdocIfaceInterface:
+ * @parent: this is a bug :/
+ * @test: overideable method
+ *
+ * class data of gtk-doc unit test interface
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocIfaceInterface</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>parent</name>
+        <description>this is a bug :/</description>
+      </parameter>
+      <parameter>
+        <name>test</name>
+        <description>overideable method</description>
+      </parameter>
+    </parameters>
+    <description>class data of gtk-doc unit test interface</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GTKDOC_IFACE_MACRO_DUMMY:
+ * @parameter_1: first arg
+ * @parameter_2: second arg
+ *
+ * This macro does nothing.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GTKDOC_IFACE_MACRO_DUMMY</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>parameter_1</name>
+        <description>first arg</description>
+      </parameter>
+      <parameter>
+        <name>parameter_2</name>
+        <description>second arg</description>
+      </parameter>
+    </parameters>
+    <description>This macro does nothing.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GTKDOC_IFACE_MACRO_SUM:
+ * @parameter_1: first arg
+ * @parameter_2: second arg
+ *
+ * This macro adds its args.
+ *
+ * Returns: the sum of @parameter_1 and @parameter_2
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GTKDOC_IFACE_MACRO_SUM</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>parameter_1</name>
+        <description>first arg</description>
+      </parameter>
+      <parameter>
+        <name>parameter_2</name>
+        <description>second arg</description>
+      </parameter>
+    </parameters>
+    <description>This macro adds its args.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>the sum of @parameter_1 and @parameter_2</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/gobject/gobject.c.xml b/tests/scanner/annotationparser/gtkdoc/gobject/gobject.c.xml
new file mode 100644
index 0000000..e6ac5f9
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gobject.c.xml
@@ -0,0 +1,416 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock><![CDATA[/**
+ * SECTION:object
+ * @title: GtkdocObject
+ * @short_description: class for gtk-doc unit test
+ * @see_also: #GtkdocIface
+ * @Image: object.png
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ * We can link to the #GtkdocObject:otest property and the #GtkdocObject::otest
+ * signal.
+ *
+ * When subclassing it is useful to override the #GtkdocObjectClass.test()
+ * method. The #GtkdocObjectClass.foo_bar() vmethod lets you refine your
+ * frobnicator.
+ *
+ * A new instance can be created using the gtkdoc_object_new() function. The
+ * whole lifecycle usualy looks like shown in this example:
+ * |[{{!-- language="C" --!}}
+ * GObject *myobj;
+ *
+ * myobj = gtkdoc_object_new();
+ * // do somehing
+ * g_object_unref (myobj);
+ * ]|
+ *
+ * # Examples #
+ *
+ * You can also change parameters:
+ * <informalexample>
+ * <programlisting language="c"><xi:include xmlns:xi="http://www.w3.org/2003/XInclude"; parse="text" href="../../examples/gobject.c" /></programlisting>
+ * </informalexample>
+ *
+ * This example serves two main purposes:
+ * - testing conversion (long description
+ *   follows here)
+ * - catching bugs
+ * - having an example
+ *
+ * Nothing more to say.
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:object</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>title</name>
+        <description>GtkdocObject</description>
+      </parameter>
+      <parameter>
+        <name>short_description</name>
+        <description>class for gtk-doc unit test</description>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#GtkdocIface</description>
+      </parameter>
+      <parameter>
+        <name>Image</name>
+        <description>object.png</description>
+      </parameter>
+    </parameters>
+    <description><![CDATA[This file contains non-sense code for the sole purpose of testing the docs.
+We can link to the #GtkdocObject:otest property and the #GtkdocObject::otest
+signal.
+
+When subclassing it is useful to override the #GtkdocObjectClass.test()
+method. The #GtkdocObjectClass.foo_bar() vmethod lets you refine your
+frobnicator.
+
+A new instance can be created using the gtkdoc_object_new() function. The
+whole lifecycle usualy looks like shown in this example:
+|[{{!-- language="C" --!}}
+GObject *myobj;
+
+myobj = gtkdoc_object_new();
+// do somehing
+g_object_unref (myobj);
+]|
+
+# Examples #
+
+You can also change parameters:
+<informalexample>
+<programlisting language="c"><xi:include xmlns:xi="http://www.w3.org/2003/XInclude"; parse="text" href="../../examples/gobject.c" /></programlisting>
+</informalexample>
+
+This example serves two main purposes:
+- testing conversion (long description
+  follows here)
+- catching bugs
+- having an example
+
+Nothing more to say.]]></description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * SECTION:object2
+ * @title: GtkdocObject2
+ * @short_description: class with interface for gtk-doc unit test
+ * @see_also: #GtkdocIface
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ *
+ * Internals
+ * =========
+ *
+ * All the internal details go here or not:
+ * - single item list
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:object2</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>title</name>
+        <description>GtkdocObject2</description>
+      </parameter>
+      <parameter>
+        <name>short_description</name>
+        <description>class with interface for gtk-doc unit test</description>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#GtkdocIface</description>
+      </parameter>
+    </parameters>
+    <description>This file contains non-sense code for the sole purpose of testing the docs.
+
+Internals
+=========
+
+All the internal details go here or not:
+- single item list</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock><![CDATA[/**
+ * gtkdoc_object_new:
+ *
+ * Create a new instance
+ * <note><para>
+ *   This will only work if you have called g_type_init() before.
+ * </para></note>
+ * Returns: the instance or %NULL in case of an error
+ *
+ * Since: 0.1
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>gtkdoc_object_new</name>
+    </identifier>
+    <description><![CDATA[Create a new instance
+<note><para>
+  This will only work if you have called g_type_init() before.
+</para></note>]]></description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>the instance or %NULL in case of an error</description>
+      </tag>
+      <tag>
+        <name>since</name>
+        <description>0.1</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock><![CDATA[/**
+ * gtkdoc_object_set_otest:
+ * @self: the object
+ * @value: the new otest value, whose description extends further than one
+ *  line will allow
+ *
+ * Set the #GtkdocObject:otest property.
+ *
+ * Deprecated: Use g_object_set(obj,&quot;otest&quot;,value,NULL); instead.
+ *
+ * Since: 0.5
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>gtkdoc_object_set_otest</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>self</name>
+        <description>the object</description>
+      </parameter>
+      <parameter>
+        <name>value</name>
+        <description>the new otest value, whose description extends further than one line will allow</description>
+      </parameter>
+    </parameters>
+    <description>Set the #GtkdocObject:otest property.</description>
+    <tags>
+      <tag>
+        <name>deprecated</name>
+        <description><![CDATA[Use g_object_set(obj,&quot;otest&quot;,value,NULL); instead.]]></description>
+      </tag>
+      <tag>
+        <name>since</name>
+        <description>0.5</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock><![CDATA[/**
+ * gtkdoc_object_frobnicate:
+ * @self: the object
+ * @n: number of iterations
+ *
+ * Frobnicate the content of @self @n times. This implements a
+ * complex algorithm (http://en.wikipedia.org/wiki/Algorithm).
+ * <footnote>
+ *  <para>
+ *    Negative frobnication can lead to unexpected behaviour.
+ *  </para>
+ * </footnote>
+ *
+ * Since: 0.5
+ */]]></commentblock>
+  <docblock>
+    <identifier>
+      <name>gtkdoc_object_frobnicate</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>self</name>
+        <description>the object</description>
+      </parameter>
+      <parameter>
+        <name>n</name>
+        <description>number of iterations</description>
+      </parameter>
+    </parameters>
+    <description><![CDATA[Frobnicate the content of @self @n times. This implements a
+complex algorithm (http://en.wikipedia.org/wiki/Algorithm).
+<footnote>
+ <para>
+   Negative frobnication can lead to unexpected behaviour.
+ </para>
+</footnote>]]></description>
+    <tags>
+      <tag>
+        <name>since</name>
+        <description>0.5</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * gtkdoc_object_fooify:
+ * @self: the object
+ * @...: a NULL terminated list of arguments
+ *
+ * Fooify the content of @self.
+ *
+ * Returns: %TRUE for success
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>gtkdoc_object_fooify</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>self</name>
+        <description>the object</description>
+      </parameter>
+      <parameter>
+        <name>...</name>
+        <description>a NULL terminated list of arguments</description>
+      </parameter>
+    </parameters>
+    <description>Fooify the content of @self.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>%TRUE for success</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+   * GtkdocObject::otest:
+   * @self: myself
+   *
+   * The event has been triggered.
+   */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject::otest</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>self</name>
+        <description>myself</description>
+      </parameter>
+    </parameters>
+    <description>The event has been triggered.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+   * GtkdocObject::dep-otest:
+   * @self: myself
+   *
+   * The event has been triggered.
+   *
+   * Deprecated: Use the #GtkdocObject::otest signal instead.
+   */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject::dep-otest</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>self</name>
+        <description>myself</description>
+      </parameter>
+    </parameters>
+    <description>The event has been triggered.</description>
+    <tags>
+      <tag>
+        <name>deprecated</name>
+        <description>Use the #GtkdocObject::otest signal instead.</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+   * GtkdocObject::strings-changed:
+   *
+   * Something has happened.
+   */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject::strings-changed</name>
+    </identifier>
+    <description>Something has happened.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+   * GtkdocObject::variant-changed:
+   *
+   * Something has happened.
+   */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject::variant-changed</name>
+    </identifier>
+    <description>Something has happened.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+   * GtkdocObject:otest:
+   *
+   * Since: 0.1
+   */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject:otest</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>since</name>
+        <description>0.1</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+   * GtkdocObject:dep-otest:
+   *
+   * Deprecated: use #GtkdocObject:otest property
+   */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject:dep-otest</name>
+    </identifier>
+    <tags>
+      <tag>
+        <name>deprecated</name>
+        <description>use #GtkdocObject:otest property</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/gobject/gobject.h.xml b/tests/scanner/annotationparser/gtkdoc/gobject/gobject.h.xml
new file mode 100644
index 0000000..42fcc66
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gobject.h.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * GtkdocObject:
+ *
+ * instance data of gtk-doc unit test class
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject</name>
+    </identifier>
+    <description>instance data of gtk-doc unit test class</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GtkdocObjectClass:
+ * @parent: this is a bug :/
+ * @test: overideable method
+ * @ping: can be used before calling the @test() function
+ * @foo_bar: lets you refine your frobnicator
+ *
+ * class data of gtk-doc unit test class
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObjectClass</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>parent</name>
+        <description>this is a bug :/</description>
+      </parameter>
+      <parameter>
+        <name>test</name>
+        <description>overideable method</description>
+      </parameter>
+      <parameter>
+        <name>ping</name>
+        <description>can be used before calling the @test() function</description>
+      </parameter>
+      <parameter>
+        <name>foo_bar</name>
+        <description>lets you refine your frobnicator</description>
+      </parameter>
+    </parameters>
+    <description>class data of gtk-doc unit test class</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GtkdocObject2:
+ *
+ * instance data of gtk-doc unit test class
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject2</name>
+    </identifier>
+    <description>instance data of gtk-doc unit test class</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GtkdocObject2Class:
+ * @parent: this is a bug :/
+ *
+ * class data of gtk-doc unit test class
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocObject2Class</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>parent</name>
+        <description>this is a bug :/</description>
+      </parameter>
+    </parameters>
+    <description>class data of gtk-doc unit test class</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GTKDOC_OBJECT_MACRO_DUMMY:
+ * @parameter_1: first arg
+ * @parameter_2: second arg
+ *
+ * This macro does nothing.
+ *
+ * Since: 0.1
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GTKDOC_OBJECT_MACRO_DUMMY</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>parameter_1</name>
+        <description>first arg</description>
+      </parameter>
+      <parameter>
+        <name>parameter_2</name>
+        <description>second arg</description>
+      </parameter>
+    </parameters>
+    <description>This macro does nothing.</description>
+    <tags>
+      <tag>
+        <name>since</name>
+        <description>0.1</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GTKDOC_OBJECT_MACRO_SUM:
+ * @parameter_1: first arg
+ * @parameter_2: second arg
+ *
+ * This macro adds its args.
+ *
+ * Returns: the sum of @parameter_1 and @parameter_2
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GTKDOC_OBJECT_MACRO_SUM</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>parameter_1</name>
+        <description>first arg</description>
+      </parameter>
+      <parameter>
+        <name>parameter_2</name>
+        <description>second arg</description>
+      </parameter>
+    </parameters>
+    <description>This macro adds its args.</description>
+    <tags>
+      <tag>
+        <name>returns</name>
+        <description>the sum of @parameter_1 and @parameter_2</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.c.xml b/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.c.xml
new file mode 100644
index 0000000..72dcdf9
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.c.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * SECTION:types
+ * @title: GtkdocTypes
+ * @short_description: other gobject types for gtk-doc unit test
+ * @see_also: #GtkdocObject, #GtkdocIface
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>SECTION:types</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>title</name>
+        <description>GtkdocTypes</description>
+      </parameter>
+      <parameter>
+        <name>short_description</name>
+        <description>other gobject types for gtk-doc unit test</description>
+      </parameter>
+      <parameter>
+        <name>see_also</name>
+        <description>#GtkdocObject, #GtkdocIface</description>
+      </parameter>
+    </parameters>
+    <description>This file contains non-sense code for the sole purpose of testing the docs.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.h.xml b/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.h.xml
new file mode 100644
index 0000000..f4e76e5
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.h.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <commentblock>/**
+ * GtkdocPlainOldData:
+ * @n: Some integer member.
+ * @x: Some floating point member.
+ *
+ * Unboxed plain old data that should default to public members.
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocPlainOldData</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>n</name>
+        <description>Some integer member.</description>
+      </parameter>
+      <parameter>
+        <name>x</name>
+        <description>Some floating point member.</description>
+      </parameter>
+    </parameters>
+    <description>Unboxed plain old data that should default to public members.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
+ * GtkdocBoxedPlainOldData:
+ * @n: Some integer member.
+ * @x: Some floating point member.
+ *
+ * Boxed plain old data that should default to public members.
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocBoxedPlainOldData</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>n</name>
+        <description>Some integer member.</description>
+      </parameter>
+      <parameter>
+        <name>x</name>
+        <description>Some floating point member.</description>
+      </parameter>
+    </parameters>
+    <description>Boxed plain old data that should default to public members.</description>
+  </docblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/test_parser.py b/tests/scanner/annotationparser/test_parser.py
new file mode 100644
index 0000000..86cd41a
--- /dev/null
+++ b/tests/scanner/annotationparser/test_parser.py
@@ -0,0 +1,297 @@
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2012 Dieter Verfaillie <dieterv optionexplicit be>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+
+'''
+test_parser.py
+
+Tests ensuring the "parse tree" built by annotationparser.py
+continues to function correctly.
+'''
+
+
+import difflib
+import os
+import xml.etree.ElementTree as etree
+import unittest
+
+from giscanner.annotationparser import AnnotationParser
+from giscanner.ast import Namespace
+from giscanner.message import MessageLogger
+
+
+def parsed2tree(docblock):
+    parsed = ''
+
+    if docblock is not None:
+        parsed += '<docblock>\n'
+
+        parsed += '  <identifier>\n'
+        # An identifier name is always required, but we can't trust our
+        # own parser to ensure this when testing so fall back to an empty
+        # string when no name has been parsed...
+        parsed += '    <name>%s</name>\n' % (docblock.name or '', )
+        if docblock.options.values:
+            parsed += '    <annotations>\n'
+            for key, value in docblock.options.values:
+                parsed += '      <annotation>\n'
+                parsed += '        <name>%s</name>\n' % (key, )
+                if value is not None:
+                    options = value.all()
+                    parsed += '        <options>\n'
+                    for option in options:
+                        parsed += '          <option>\n'
+                        parsed += '            <name>%s</name>\n' % (option, )
+                        if options[option] is not None:
+                            parsed += '            <value>%s</value>\n' % (options[option], )
+                        parsed += '          </option>\n'
+                    parsed += '        </options>\n'
+                parsed += '      </annotation>\n'
+            parsed += '    </annotations>\n'
+        parsed += '  </identifier>\n'
+
+        if docblock.params:
+            parsed += '  <parameters>\n'
+            for param_name in docblock.params:
+                param = docblock.params.get(param_name)
+                parsed += '    <parameter>\n'
+                parsed += '      <name>%s</name>\n' % (param_name, )
+                if param.options.values:
+                    parsed += '      <annotations>\n'
+                    for key, value in param.options.values:
+                        parsed += '        <annotation>\n'
+                        parsed += '          <name>%s</name>\n' % (key, )
+                        if value is not None:
+                            options = value.all()
+                            parsed += '          <options>\n'
+                            for option in options:
+                                parsed += '            <option>\n'
+                                parsed += '              <name>%s</name>\n' % (option, )
+                                if options[option] is not None:
+                                    parsed += '              <value>%s</value>\n' % (options[option], )
+                                parsed += '            </option>\n'
+                            parsed += '          </options>\n'
+                        parsed += '        </annotation>\n'
+                    parsed += '      </annotations>\n'
+                if param.comment or param.value:
+                    parsed += '      <description>%s</description>\n' % (param.comment or param.value, )
+                parsed += '    </parameter>\n'
+            parsed += '  </parameters>\n'
+
+        if docblock.comment or docblock.value:
+            parsed += '  <description>%s</description>\n' % (docblock.comment or docblock.value, )
+
+        if docblock.tags:
+            parsed += '  <tags>\n'
+            for tag_name in docblock.tags:
+                tag = docblock.tags.get(tag_name)
+                parsed += '    <tag>\n'
+                parsed += '      <name>%s</name>\n' % (tag_name, )
+                if tag.options.values:
+                    parsed += '      <annotations>\n'
+                    for key, value in tag.options.values:
+                        parsed += '        <annotation>\n'
+                        parsed += '          <name>%s</name>\n' %(key, )
+                        if value is not None:
+                            options = value.all()
+                            parsed += '          <options>\n'
+                            for option in options:
+                                parsed += '            <option>\n'
+                                parsed += '              <name>%s</name>\n' % (option, )
+                                if options[option] is not None:
+                                    parsed += '              <value>%s</value>\n' % (options[option], )
+                                parsed += '            </option>\n'
+                            parsed += '          </options>\n'
+                        parsed += '        </annotation>\n'
+                    parsed += '      </annotations>\n'
+                if tag.comment or tag.value:
+                    parsed += '      <description>%s</description>\n' % (tag.comment or tag.value, )
+                parsed += '    </tag>\n'
+            parsed += '  </tags>\n'
+
+        parsed += '<docblock>'
+
+    return parsed
+
+def expected2tree(docblock):
+    # Note: this sucks, but we can't rely on etree.tostring() to generate useable output :(
+
+    expected = ''
+
+    if docblock is not None:
+        expected += '<docblock>\n'
+
+        if docblock.find('identifier') is not None:
+            expected += '  <identifier>\n'
+            # Expecting an identifier name is required, don't bother checking if it's there or not
+            expected += '    <name>%s</name>\n' % (docblock.find('identifier/name').text, )
+            annotations = docblock.find('identifier/annotations')
+            if annotations is not None:
+                expected += '    <annotations>\n'
+                for annotation in annotations.iterfind('annotation'):
+                    expected += '      <annotation>\n'
+                    expected += '        <name>%s</name>\n' % (annotation.find('name').text, )
+                    if annotation.find('options') is not None:
+                        expected += '        <options>\n'
+                        for option in annotation.iterfind('options/option'):
+                            expected += '          <option>\n'
+                            expected += '            <name>%s</name>\n' % (option.find('name').text, )
+                            if option.find('value') is not None:
+                                expected += '            <value>%s</value>\n' % (option.find('value').text, )
+                            expected += '          </option>\n'
+                        expected += '        </options>\n'
+                    expected += '      </annotation>\n'
+                expected += '    </annotations>\n'
+            expected += '  </identifier>\n'
+
+        parameters = docblock.find('parameters')
+        if parameters is not None:
+            expected += '  <parameters>\n'
+            for parameter in parameters.iterfind('parameter'):
+                expected += '    <parameter>\n'
+                expected += '      <name>%s</name>\n' % (parameter.find('name').text, )
+                annotations = parameter.find('annotations')
+                if annotations is not None:
+                    expected += '      <annotations>\n'
+                    for annotation in parameter.iterfind('annotations/annotation'):
+                        expected += '        <annotation>\n'
+                        expected += '          <name>%s</name>\n' % (annotation.find('name').text, )
+                        if annotation.find('options') is not None:
+                            expected += '          <options>\n'
+                            for option in annotation.iterfind('options/option'):
+                                expected += '            <option>\n'
+                                expected += '              <name>%s</name>\n' % (option.find('name').text, )
+                                if option.find('value') is not None:
+                                    expected += '              <value>%s</value>\n' % (option.find('value').text, )
+                                expected += '            </option>\n'
+                            expected += '          </options>\n'
+                        expected += '        </annotation>\n'
+                    expected += '      </annotations>\n'
+                if parameter.find('description') is not None:
+                    expected += '      <description>%s</description>\n' % (parameter.find('description').text, )
+                expected += '    </parameter>\n'
+            expected += '  </parameters>\n'
+
+        description = docblock.find('description')
+        if description is not None:
+            expected += '  <description>%s</description>\n' % (description.text, )
+
+        tags = docblock.find('tags')
+        if tags is not None:
+            expected += '  <tags>\n'
+            for tag in tags.iterfind('tag'):
+                expected += '    <tag>\n'
+                expected += '      <name>%s</name>\n' % (tag.find('name').text, )
+                annotations = tag.find('annotations')
+                if annotations is not None:
+                    expected += '      <annotations>\n'
+                    for annotation in tag.iterfind('annotations/annotation'):
+                        expected += '        <annotation>\n'
+                        expected += '          <name>%s</name>\n' % (annotation.find('name').text, )
+                        if annotation.find('options') is not None:
+                            expected += '          <options>\n'
+                            for option in annotation.iterfind('options/option'):
+                                expected += '            <option>\n'
+                                expected += '              <name>%s</name>\n' % (option.find('name').text, )
+                                if option.find('value') is not None:
+                                    expected += '              <value>%s</value>\n' % (option.find('value').text, )
+                                expected += '            </option>\n'
+                            expected += '          </options>\n'
+                        expected += '        </annotation>\n'
+                    expected += '      </annotations>\n'
+                if tag.find('description') is not None:
+                    expected += '      <description>%s</description>\n' % (tag.find('description').text, )
+                expected += '    </tag>\n'
+            expected += '  </tags>\n'
+
+        expected += '<docblock>'
+
+    return expected
+
+
+def create_tests(tests_dir, tests_file):
+    tests_name = os.path.relpath(tests_file[:-4], tests_dir)
+    tests_name = tests_name.replace('/', '.').replace('\\', '.')
+
+    tests_tree = etree.parse(tests_file).getroot()
+
+    fix_cdata_elements = tests_tree.findall('test/commentblock')
+    fix_cdata_elements += tests_tree.findall('.//description')
+
+    for element in fix_cdata_elements:
+        if element.text:
+            element.text = element.text.replace('{{?', '<!')
+            element.text = element.text.replace('}}', '>')
+
+    for counter, test in enumerate(tests_tree.findall('test')):
+        test_name = 'test_%s.%03d' % (tests_name, counter + 1)
+        test_method = TestCommentBlock.__create_test__(test)
+        setattr(TestCommentBlock, test_name, test_method)
+
+
+class TestCommentBlock(unittest.TestCase):
+    @classmethod
+    def __create_test__(cls, testcase):
+        def do_test(self):
+            # Parse GTK-Doc comment block
+            commentblock = testcase.find('commentblock').text
+            parsed_docblock = AnnotationParser().parse_comment_block((commentblock, 'test.c', 1))
+            parsed_tree = parsed2tree(parsed_docblock).split('\n')
+
+            # Get expected output
+            expected_docblock = testcase.find('docblock')
+            expected_tree = expected2tree(expected_docblock).split('\n')
+
+            # Construct a meaningful message
+            msg = 'Parsed DocBlock object tree does not match expected output:\n\n'
+            msg += '%s\n\n' % (commentblock, )
+
+            diff = difflib.unified_diff(expected_tree, parsed_tree,
+                                        'Expected DocBlock', 'Parsed DocBlock',
+                                        n=max(len(expected_tree), len(parsed_tree)),
+                                        lineterm='')
+            for line in diff:
+                msg += '%s\n' % (line, )
+
+            # Compare parsed with expected DocBlock tree
+            self.assertEqual(parsed_tree, expected_tree, msg)
+
+        return do_test
+
+
+if __name__ == '__main__':
+    # Initialize message logger
+    # TODO: at some point it might be a good idea to test warnings emitted
+    # by annotationparser here, instead of having them in tests/warn/annotationparser.h?
+    namespace = Namespace('Test', '1.0')
+    logger = MessageLogger.get(namespace=namespace)
+    logger.enable_warnings(False)
+
+    # Load test cases from disc
+    tests_dir = os.path.dirname(os.path.abspath(__file__))
+
+    for dirpath, dirnames, filenames in os.walk(tests_dir):
+        for filename in filenames:
+            tests_file = os.path.join(dirpath, filename)
+            if os.path.basename(tests_file).endswith('.xml'):
+                create_tests(tests_dir, tests_file)
+
+    # Run test suite
+    unittest.main()



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