summaryrefslogtreecommitdiff
path: root/tests/scanner/annotationparser
diff options
context:
space:
mode:
authorLars Wirzenius <lars.wirzenius@codethink.co.uk>2013-09-04 16:13:21 +0000
committerLars Wirzenius <lars.wirzenius@codethink.co.uk>2013-09-04 16:13:21 +0000
commita194122be492fbddd8748fe323a648434a866c36 (patch)
treef39293588b7922faa40f0c6b985a031f8f5cf0ae /tests/scanner/annotationparser
parent8a2a9f9db169eaaf2a7eede18e0ceba0af44345f (diff)
parent85d02d59f101f9eb37829b16a81890ef9801824a (diff)
downloadgobject-introspection-a194122be492fbddd8748fe323a648434a866c36.tar.gz
merge with GOBJECT_INTROSPECTION_1_37_6baserock/jonathan/fix-giscanner
Diffstat (limited to 'tests/scanner/annotationparser')
-rw-r--r--tests/scanner/annotationparser/README51
-rw-r--r--tests/scanner/annotationparser/gi/annotation_allow_none.xml47
-rw-r--r--tests/scanner/annotationparser/gi/annotation_array.xml277
-rw-r--r--tests/scanner/annotationparser/gi/annotation_closure.xml74
-rw-r--r--tests/scanner/annotationparser/gi/annotation_constructor.xml21
-rw-r--r--tests/scanner/annotationparser/gi/annotation_destroy.xml46
-rw-r--r--tests/scanner/annotationparser/gi/annotation_element_type.xml126
-rw-r--r--tests/scanner/annotationparser/gi/annotation_foreign.xml22
-rw-r--r--tests/scanner/annotationparser/gi/annotation_get_value_func.xml30
-rw-r--r--tests/scanner/annotationparser/gi/annotation_in.xml52
-rw-r--r--tests/scanner/annotationparser/gi/annotation_in_out.xml54
-rw-r--r--tests/scanner/annotationparser/gi/annotation_method.xml28
-rw-r--r--tests/scanner/annotationparser/gi/annotation_out.xml110
-rw-r--r--tests/scanner/annotationparser/gi/annotation_ref_func.xml30
-rw-r--r--tests/scanner/annotationparser/gi/annotation_rename_to.xml52
-rw-r--r--tests/scanner/annotationparser/gi/annotation_scope.xml106
-rw-r--r--tests/scanner/annotationparser/gi/annotation_set_value_func.xml30
-rw-r--r--tests/scanner/annotationparser/gi/annotation_skip.xml43
-rw-r--r--tests/scanner/annotationparser/gi/annotation_transfer.xml162
-rw-r--r--tests/scanner/annotationparser/gi/annotation_type.xml84
-rw-r--r--tests/scanner/annotationparser/gi/annotation_unref_func.xml30
-rw-r--r--tests/scanner/annotationparser/gi/annotation_value.xml30
-rw-r--r--tests/scanner/annotationparser/gi/annotation_virtual.xml47
-rw-r--r--tests/scanner/annotationparser/gi/syntax.xml136
-rw-r--r--tests/scanner/annotationparser/gi/syntax_identifier.xml304
-rw-r--r--tests/scanner/annotationparser/gi/syntax_nested_tags.xml43
-rw-r--r--tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml239
-rw-r--r--tests/scanner/annotationparser/gi/tag_deprecated.xml43
-rw-r--r--tests/scanner/annotationparser/gi/tag_description.xml21
-rw-r--r--tests/scanner/annotationparser/gi/tag_returns.xml76
-rw-r--r--tests/scanner/annotationparser/gi/tag_since.xml43
-rw-r--r--tests/scanner/annotationparser/gi/tag_stability.xml81
-rw-r--r--tests/scanner/annotationparser/gtkdoc/annotations/tester.c.xml344
-rw-r--r--tests/scanner/annotationparser/gtkdoc/annotations/tester.h.xml31
-rw-r--r--tests/scanner/annotationparser/gtkdoc/bugs/tester.c.xml765
-rw-r--r--tests/scanner/annotationparser/gtkdoc/bugs/tester.h.xml677
-rw-r--r--tests/scanner/annotationparser/gtkdoc/empty/tester.c.xml53
-rw-r--r--tests/scanner/annotationparser/gtkdoc/fail/tester.c.xml162
-rw-r--r--tests/scanner/annotationparser/gtkdoc/fail/tester.h.xml205
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/giface.c.xml147
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/giface.h.xml119
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/gobject.c.xml416
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/gobject.h.xml158
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/gtypes.c.xml36
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/gtypes.h.xml84
-rw-r--r--tests/scanner/annotationparser/test_parser.py298
-rw-r--r--tests/scanner/annotationparser/test_patterns.py618
47 files changed, 6651 insertions, 0 deletions
diff --git a/tests/scanner/annotationparser/README b/tests/scanner/annotationparser/README
new file mode 100644
index 00000000..03cdf59d
--- /dev/null
+++ b/tests/scanner/annotationparser/README
@@ -0,0 +1,51 @@
+test_patterns.py
+================
+
+Notes
+-----
+
+The tests included within test_patterns.py are designed to torture the regular
+expression programs used to match different parts of GTK-Doc comment blocks
+by giscanner/annotationparser.py
+
+
+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 00000000..02db79a9
--- /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 00000000..26bb1104
--- /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 00000000..8211dc7b
--- /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 00000000..4bf3b038
--- /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 00000000..449dd8e1
--- /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 00000000..d03c4268
--- /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 00000000..11e589c5
--- /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 00000000..bc779943
--- /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 00000000..517f1a3f
--- /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 00000000..c8d36f45
--- /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 00000000..e4d44389
--- /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 00000000..cca5e12e
--- /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 00000000..7850fc3f
--- /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 00000000..390f4878
--- /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 00000000..7f05a4c6
--- /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 00000000..1f3a44d3
--- /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 00000000..030b0c42
--- /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 00000000..49df32fd
--- /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 00000000..d357423a
--- /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 00000000..98ac0a3e
--- /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 00000000..4a1a0785
--- /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 00000000..f2b6b23a
--- /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 00000000..f07e4fbd
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax.xml
@@ -0,0 +1,136 @@
+<?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>
+ <!--
+ Not GTK-Doc
+ -->
+ <commentblock>/**
+*/</commentblock>
+</test>
+
+<test>
+ <!--
+ Technically not GTK-Doc, but we need to support this for backwards compatibility
+ -->
+ <commentblock>/**
+Test
+something */</commentblock>
+ <docblock>
+ <identifier>
+ <name>Test</name>
+ </identifier>
+ <description>something</description>
+ </docblock>
+</test>
+
+<test>
+ <!--
+ Technically not GTK-Doc, but we need to support this for backwards compatibility
+ -->
+ <commentblock>/**
+Test
+something **/</commentblock>
+ <docblock>
+ <identifier>
+ <name>Test</name>
+ </identifier>
+ <description>something</description>
+ </docblock>
+</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 00000000..69dcf328
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_identifier.xml
@@ -0,0 +1,304 @@
+<?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>
+
+<test>
+ <!--
+ Invalid identifier
+ -->
+ <commentblock>/**
+ * gnm_cell_set_expr_and_value: Stores (WITHOUT COPYING) the supplied value, and
+ * references the supplied expression and links it into the expression
+ * list. It marks the sheet as dirty. It is intended for use by import
+ * routines or operations that do bulk assignment.
+ *
+ * WARNING : This is an internal routine that does not queue redraws,
+ * does not auto-resize, does not calculate spans, and does
+ * not render the value.
+ *
+ * NOTE : This DOES check for array partitioning.
+ */</commentblock>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/syntax_nested_tags.xml b/tests/scanner/annotationparser/gi/syntax_nested_tags.xml
new file mode 100644
index 00000000..d07b6f12
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_nested_tags.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+ <!--
+ Well, not really nested tags as the Since: 2.30 is considered to be part of the
+ description of the @G_APPLICATION_NON_UNIQUE parameter.
+ -->
+ <commentblock>/**
+ * GApplicationFlags:
+ * @G_APPLICATION_NON_UNIQUE: Make no attempts to do any of the typical
+ * single-instance application negotiation, even if the application
+ * ID is given. The application neither attempts to become the
+ * owner of the application ID nor does it check if an existing
+ * owner already exists. Everything occurs in the local process.
+ * Since: 2.30.
+ *
+ * Flags used to define the behaviour of a #GApplication.
+ *
+ * Since: 2.28
+ **/</commentblock>
+ <docblock>
+ <identifier>
+ <name>GApplicationFlags</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>G_APPLICATION_NON_UNIQUE</name>
+ <description>Make no attempts to do any of the typical single-instance application negotiation, even if the application ID is given. The application neither attempts to become the owner of the application ID nor does it check if an existing owner already exists. Everything occurs in the local process. Since: 2.30.</description>
+ </parameter>
+ </parameters>
+ <description>Flags used to define the behaviour of a #GApplication.</description>
+ <tags>
+ <tag>
+ <name>since</name>
+ <description>2.28</description>
+ </tag>
+ </tags>
+ </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 00000000..4ae1e036
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml
@@ -0,0 +1,239 @@
+<?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>
+ <!--
+ Description: tag, all lines (outside program- listings and CDATA sections) just containing
+ a ' *' (blank-asterisk) are converted to paragraph breaks.
+ -->
+ <commentblock>/**
+ * SECTION:test
+ *
+ * Description: 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>
+ <!--
+ Description: tag, ' * ' (blank-asterisk-blank) are also converted to paragraph breaks.
+ -->
+ <commentblock>/**
+ * SECTION:test
+ *
+ * Description: 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>
+ <!--
+ Description: tag, 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
+ *
+ * Description: 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>
+
+<test>
+ <!--
+ Description: tag, 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
+ *
+ * Description: <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 00000000..6374bf81
--- /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 00000000..75860f60
--- /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 00000000..302d8cf6
--- /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 00000000..2bd8c5c2
--- /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 00000000..154b8385
--- /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 00000000..9be3db76
--- /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 00000000..b79e1bcd
--- /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 00000000..f0a2b225
--- /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 00000000..da7c7919
--- /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 00000000..c18e29fd
--- /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 00000000..7ebf440b
--- /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 00000000..3e51b761
--- /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 00000000..ea09d126
--- /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 00000000..7185ad0b
--- /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 00000000..e6ac5f97
--- /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 00000000..42fcc664
--- /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 00000000..72dcdf90
--- /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 00000000..1d188271
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.h.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+ <commentblock>/**
+ * GtkdocEnum:
+ * @GTKDOC_ENUM_V1: first
+ * @GTKDOC_ENUM_V2: second
+ * Since: 0.10
+ *
+ * Enum values for the #GtkdocEnum type.
+ */</commentblock>
+ <docblock>
+ <identifier>
+ <name>GtkdocEnum</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>GTKDOC_ENUM_V1</name>
+ <description>first</description>
+ </parameter>
+ <parameter>
+ <name>GTKDOC_ENUM_V2</name>
+ <description>second Since: 0.10</description>
+ </parameter>
+ </parameters>
+ <description>Enum values for the #GtkdocEnum type.</description>
+ </docblock>
+</test>
+
+<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 00000000..ce3ccd22
--- /dev/null
+++ b/tests/scanner/annotationparser/test_parser.py
@@ -0,0 +1,298 @@
+# -*- 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.findall('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.findall('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.findall('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.findall('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.findall('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.findall('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.findall('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.findall('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()
diff --git a/tests/scanner/annotationparser/test_patterns.py b/tests/scanner/annotationparser/test_patterns.py
new file mode 100644
index 00000000..6db99c3f
--- /dev/null
+++ b/tests/scanner/annotationparser/test_patterns.py
@@ -0,0 +1,618 @@
+# -*- 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_patterns.py
+
+Tests ensuring the regular expression programs used
+in annotationparser.py continue to function correctly.
+Each regular expression program is tested on input that
+should not match and input that should match. When input
+should match, resulting symbolic groups are verified
+against the expected output.
+'''
+
+
+from giscanner.annotationparser import (SECTION_RE, SYMBOL_RE, PROPERTY_RE,
+ SIGNAL_RE, PARAMETER_RE, TAG_RE,
+ COMMENT_END_RE)
+from unittest import (TestCase, main)
+
+
+identifier_section_tests = [
+ (SECTION_RE, 'TSIEOCN',
+ None),
+ (SECTION_RE, 'section',
+ None),
+ (SECTION_RE, 'section:',
+ None),
+ (SECTION_RE, 'section:test',
+ None),
+ (SECTION_RE, 'SECTION',
+ {'colon': '',
+ 'section_name': None}),
+ (SECTION_RE, 'SECTION \t ',
+ {'colon': '',
+ 'section_name': None}),
+ (SECTION_RE, ' \t SECTION \t ',
+ {'colon': '',
+ 'section_name': None}),
+ (SECTION_RE, 'SECTION: \t ',
+ {'colon': ':',
+ 'section_name': None}),
+ (SECTION_RE, 'SECTION : ',
+ {'colon': ':',
+ 'section_name': None}),
+ (SECTION_RE, ' SECTION : ',
+ {'colon': ':',
+ 'section_name': None}),
+ (SECTION_RE, 'SECTION:gtkwidget',
+ {'colon': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION:gtkwidget ',
+ {'colon': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, ' SECTION:gtkwidget',
+ {'colon': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, ' SECTION:gtkwidget\t ',
+ {'colon': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION: gtkwidget ',
+ {'colon': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION : gtkwidget',
+ {'colon': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION gtkwidget \f ',
+ {'colon': '',
+ 'section_name': 'gtkwidget'})]
+
+identifier_symbol_tests = [
+ (SYMBOL_RE, 'GBaseFinalizeFunc:',
+ {'colon': ':',
+ 'symbol_name': 'GBaseFinalizeFunc',
+ 'annotations': ''}),
+ (SYMBOL_RE, 'gtk_widget_show ',
+ {'colon': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, ' gtk_widget_show',
+ {'colon': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, ' gtk_widget_show ',
+ {'colon': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, 'gtk_widget_show:',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, 'gtk_widget_show :',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, 'gtk_widget_show: ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, 'gtk_widget_show : ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, ' gtk_widget_show:',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, ' gtk_widget_show :',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, ' gtk_widget_show: ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, ' gtk_widget_show : ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': ''}),
+ (SYMBOL_RE, 'gtk_widget_show (skip)',
+ {'colon': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) \t ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) \t '}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) \t ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) \t '}),
+ (SYMBOL_RE, 'gtk_widget_show:(skip)(test1)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)(test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show (skip)(test1)',
+ {'colon': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip)(test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip) (test1)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip) (test1)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip) (test1)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) '}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1) (test-2)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1) (test-2)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1) (test-2)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1) (test-2)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip) (test1) (test-2)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip) (test1) (test-2)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip) (test1) (test-2)',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) (test-2) ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2) '}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) (test-2) ',
+ {'colon': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'annotations': '(skip) (test1) (test-2) '}),
+ # constants
+ (SYMBOL_RE, 'MY_CONSTANT:',
+ {'colon': ':',
+ 'symbol_name': 'MY_CONSTANT',
+ 'annotations': ''}),
+ # structs
+ (SYMBOL_RE, 'FooWidget:',
+ {'colon': ':',
+ 'symbol_name': 'FooWidget',
+ 'annotations': ''}),
+ # enums
+ (SYMBOL_RE, 'Something:',
+ {'colon': ':',
+ 'symbol_name': 'Something',
+ 'annotations': ''})]
+
+identifier_property_tests = [
+ # simple property name
+ (PROPERTY_RE, 'GtkWidget:name (skip)',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'colon': '',
+ 'annotations': '(skip)'}),
+ (PROPERTY_RE, 'GtkWidget:name',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'colon': '',
+ 'annotations': ''}),
+ (PROPERTY_RE, ' GtkWidget :name',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'colon': '',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'GtkWidget: name ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'colon': '',
+ 'annotations': ''}),
+ (PROPERTY_RE, ' GtkWidget : name ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'colon': '',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'GtkWidget:name:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'GtkWidget:name: ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, ' GtkWidget:name:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'Something:name:',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'Something:name: ',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, ' Something:name:',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'Weird-thing:name:',
+ None),
+ (PROPERTY_RE, 'really-weird_thing:name:',
+ None),
+ (PROPERTY_RE, 'GWin32InputStream:handle:',
+ {'class_name': 'GWin32InputStream',
+ 'property_name': 'handle',
+ 'colon': ':',
+ 'annotations': ''}),
+ # property name that contains a dash
+ (PROPERTY_RE, 'GtkWidget:double-buffered (skip)',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'colon': '',
+ 'annotations': '(skip)'}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'colon': '',
+ 'annotations': ''}),
+ (PROPERTY_RE, ' GtkWidget :double-buffered',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'colon': '',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'GtkWidget: double-buffered ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'colon': '',
+ 'annotations': ''}),
+ (PROPERTY_RE, ' GtkWidget : double-buffered ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'colon': '',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered: ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, ' GtkWidget:double-buffered:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'Something:double-buffered:',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'Something:double-buffered: ',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, ' Something:double-buffered:',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'colon': ':',
+ 'annotations': ''}),
+ (PROPERTY_RE, 'Weird-thing:double-buffered:',
+ None),
+ (PROPERTY_RE, 'really-weird_thing:double-buffered:',
+ None),
+ (PROPERTY_RE, ' GMemoryOutputStream:realloc-function: (skip)',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'colon': ':',
+ 'annotations': '(skip)'})]
+
+identifier_signal_tests = [
+ # simple property name
+ (SIGNAL_RE, 'GtkWidget::changed: (skip)',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'changed',
+ 'colon': ':',
+ 'annotations': '(skip)'}),
+ (SIGNAL_RE, 'GtkWidget::changed:',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'changed',
+ 'colon': ':',
+ 'annotations': ''}),
+ (SIGNAL_RE, 'Something::changed:',
+ {'class_name': 'Something',
+ 'signal_name': 'changed',
+ 'colon': ':',
+ 'annotations': ''}),
+ (SIGNAL_RE, 'Weird-thing::changed:',
+ None),
+ (SIGNAL_RE, 'really-weird_thing::changed:',
+ None),
+ # signal name that contains a dash
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (skip)',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'colon': ':',
+ 'annotations': '(skip)'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed:',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'colon': ':',
+ 'annotations': ''}),
+ (SIGNAL_RE, 'Something::hierarchy-changed:',
+ {'class_name': 'Something',
+ 'signal_name': 'hierarchy-changed',
+ 'colon': ':',
+ 'annotations': ''}),
+ (SIGNAL_RE, 'Weird-thing::hierarchy-changed:',
+ None),
+ (SIGNAL_RE, 'really-weird_thing::hierarchy-changed:',
+ None)]
+
+parameter_tests = [
+ (PARAMETER_RE, '@Short_description: Base class for all widgets ',
+ {'parameter_name': 'Short_description',
+ 'annotations': '',
+ 'colon': '',
+ 'description': 'Base class for all widgets'}),
+ (PARAMETER_RE, '@...: the value of the first property, followed optionally by more',
+ {'parameter_name': '...',
+ 'annotations': '',
+ 'colon': '',
+ 'description': 'the value of the first property, followed optionally by more'}),
+ (PARAMETER_RE, '@widget: a #GtkWidget',
+ {'parameter_name': 'widget',
+ 'annotations': '',
+ 'colon': '',
+ 'description': 'a #GtkWidget'}),
+ (PARAMETER_RE, '@widget_pointer: (inout) (transfer none): '
+ 'address of a variable that contains @widget',
+ {'parameter_name': 'widget_pointer',
+ 'annotations': '(inout) (transfer none)',
+ 'colon': ':',
+ 'description': 'address of a variable that contains @widget'}),
+ (PARAMETER_RE, '@weird_thing: (inout) (transfer none) (allow-none) (attribute) (destroy) '
+ '(foreign) (inout) (out) (transfer) (skip) (method): some weird @thing',
+ {'parameter_name': 'weird_thing',
+ 'annotations': '(inout) (transfer none) (allow-none) (attribute) (destroy) '
+ '(foreign) (inout) (out) (transfer) (skip) (method)',
+ 'colon': ':',
+ 'description': 'some weird @thing'}),
+ (PARAMETER_RE, '@data: a pointer to the element data. The data may be moved as elements '
+ 'are added to the #GByteArray.',
+ {'parameter_name': 'data',
+ 'annotations': '',
+ 'colon': '',
+ 'description': 'a pointer to the element data. The data may be moved as elements '
+ 'are added to the #GByteArray.'}),
+ (PARAMETER_RE, '@a: a #GSequenceIter',
+ {'parameter_name': 'a',
+ 'annotations': '',
+ 'colon': '',
+ 'description': 'a #GSequenceIter'}),
+ (PARAMETER_RE, '@keys: (array length=n_keys) (element-type GQuark) (allow-none):',
+ {'parameter_name': 'keys',
+ 'annotations': '(array length=n_keys) (element-type GQuark) (allow-none)',
+ 'colon': ':',
+ 'description': ''})]
+
+tag_tests = [
+ (TAG_RE, 'Since 3.0',
+ None),
+ (TAG_RE, 'Since: 3.0',
+ {'tag_name': 'Since',
+ 'annotations': '',
+ 'colon': '',
+ 'description': '3.0'}),
+ (TAG_RE, 'Attributes: (inout) (transfer none): some note about attributes',
+ {'tag_name': 'Attributes',
+ 'annotations': '(inout) (transfer none)',
+ 'colon': ':',
+ 'description': 'some note about attributes'}),
+ (TAG_RE, 'Rename to: something_else',
+ {'tag_name': 'Rename to',
+ 'annotations': '',
+ 'colon': '',
+ 'description': 'something_else'}),
+ (TAG_RE, '@Deprecated: Since 2.8, reference counting is done atomically',
+ None),
+ (TAG_RE, 'Returns %TRUE and does weird things',
+ None),
+ (TAG_RE, 'Returns: a #GtkWidget',
+ {'tag_name': 'Returns',
+ 'annotations': '',
+ 'colon': '',
+ 'description': 'a #GtkWidget'}),
+ (TAG_RE, 'Return value: (transfer none): The binary data that @text responds. '
+ 'This pointer',
+ {'tag_name': 'Return value',
+ 'annotations': '(transfer none)',
+ 'colon': ':',
+ 'description': 'The binary data that @text responds. This pointer'}),
+ (TAG_RE, 'Return value: (transfer full) (array length=out_len) (element-type guint8):',
+ {'tag_name': 'Return value',
+ 'annotations': '(transfer full) (array length=out_len) (element-type guint8)',
+ 'colon': ':',
+ 'description': ''}),
+ (TAG_RE, 'Returns: A boolean value, but let me tell you a bit about this boolean. It',
+ {'tag_name': 'Returns',
+ 'annotations': '',
+ 'colon': '',
+ 'description': 'A boolean value, but let me tell you a bit about this boolean. '
+ 'It'}),
+ (TAG_RE, 'Returns: (transfer container) (element-type GObject.ParamSpec): a',
+ {'tag_name': 'Returns',
+ 'annotations': '(transfer container) (element-type GObject.ParamSpec)',
+ 'colon': ':',
+ 'description': 'a'}),
+ (TAG_RE, 'Return value: (type GLib.HashTable<utf8,GLib.HashTable<utf8,utf8>>) '
+ '(transfer full):',
+ {'tag_name': 'Return value',
+ 'annotations': '(type GLib.HashTable<utf8,GLib.HashTable<utf8,utf8>>) '
+ '(transfer full)',
+ 'colon': ':',
+ 'description': ''})]
+
+comment_end_tests = [
+ (COMMENT_END_RE, '*/',
+ {'description': ''}),
+ (COMMENT_END_RE, ' */',
+ {'description': ''}),
+ (COMMENT_END_RE, ' */ ',
+ {'description': ''}),
+ (COMMENT_END_RE, '**/',
+ {'description': ''}),
+ (COMMENT_END_RE, ' **/',
+ {'description': ''}),
+ (COMMENT_END_RE, ' **/ ',
+ {'description': ''}),
+ (COMMENT_END_RE, 'test */',
+ {'description': 'test'}),
+ (COMMENT_END_RE, ' test*/',
+ {'description': 'test'}),
+ (COMMENT_END_RE, 'test **/',
+ {'description': 'test'}),
+ (COMMENT_END_RE, ' test**/',
+ {'description': 'test'}),
+ (COMMENT_END_RE, 'test *****/',
+ {'description': 'test'}),
+ (COMMENT_END_RE, ' test*****/',
+ {'description': 'test'})]
+
+
+def create_tests(tests_name, testcases):
+ for (index, testcase) in enumerate(testcases):
+ real_test_name = '%s_%03d' % (tests_name, index)
+
+ test_method = TestProgram.__create_test__(testcase)
+ test_method.__name__ = real_test_name
+ setattr(TestProgram, real_test_name, test_method)
+
+
+class TestProgram(TestCase):
+ @classmethod
+ def __create_test__(cls, testcase):
+ def do_test(self):
+ (program, text, expected) = testcase
+
+ match = program.match(text)
+
+ if expected is None:
+ msg = 'Program matched text but shouldn\'t:\n"%s"'
+ self.assertTrue(match is None, msg % (text, ))
+ else:
+ msg = 'Program should match text but didn\'t:\n"%s"'
+ self.assertTrue(match is not None, msg % (text, ))
+
+ for key, value in expected.items():
+ msg = 'expected "%s" for "%s" but match returned "%s"'
+ msg = msg % (value, key, match.group(key))
+ self.assertEqual(match.group(key), value, msg)
+
+ return do_test
+
+
+if __name__ == '__main__':
+ # Create tests from data
+ create_tests('test_identifier_section', identifier_section_tests)
+ create_tests('test_identifier_symbol', identifier_symbol_tests)
+ create_tests('test_identifier_property', identifier_property_tests)
+ create_tests('test_identifier_signal', identifier_signal_tests)
+ create_tests('test_parameter', parameter_tests)
+ create_tests('test_tag', tag_tests)
+ create_tests('test_comment_end', comment_end_tests)
+
+ # Run test suite
+ main()