summaryrefslogtreecommitdiff
path: root/tests/scanner/annotationparser
diff options
context:
space:
mode:
Diffstat (limited to 'tests/scanner/annotationparser')
-rw-r--r--tests/scanner/annotationparser/Makefile.am68
-rw-r--r--tests/scanner/annotationparser/README52
-rw-r--r--tests/scanner/annotationparser/gi/annotation_allow_none.xml63
-rw-r--r--tests/scanner/annotationparser/gi/annotation_array.xml483
-rw-r--r--tests/scanner/annotationparser/gi/annotation_attributes.xml477
-rw-r--r--tests/scanner/annotationparser/gi/annotation_closure.xml147
-rw-r--r--tests/scanner/annotationparser/gi/annotation_constructor.xml26
-rw-r--r--tests/scanner/annotationparser/gi/annotation_destroy.xml110
-rw-r--r--tests/scanner/annotationparser/gi/annotation_element_type.xml272
-rw-r--r--tests/scanner/annotationparser/gi/annotation_foreign.xml27
-rw-r--r--tests/scanner/annotationparser/gi/annotation_get_value_func.xml154
-rw-r--r--tests/scanner/annotationparser/gi/annotation_in.xml63
-rw-r--r--tests/scanner/annotationparser/gi/annotation_in_out.xml71
-rw-r--r--tests/scanner/annotationparser/gi/annotation_method.xml34
-rw-r--r--tests/scanner/annotationparser/gi/annotation_out.xml192
-rw-r--r--tests/scanner/annotationparser/gi/annotation_ref_func.xml154
-rw-r--r--tests/scanner/annotationparser/gi/annotation_rename_to.xml232
-rw-r--r--tests/scanner/annotationparser/gi/annotation_scope.xml131
-rw-r--r--tests/scanner/annotationparser/gi/annotation_set_value_func.xml118
-rw-r--r--tests/scanner/annotationparser/gi/annotation_skip.xml91
-rw-r--r--tests/scanner/annotationparser/gi/annotation_transfer.xml285
-rw-r--r--tests/scanner/annotationparser/gi/annotation_type.xml263
-rw-r--r--tests/scanner/annotationparser/gi/annotation_unref_func.xml118
-rw-r--r--tests/scanner/annotationparser/gi/annotation_value.xml118
-rw-r--r--tests/scanner/annotationparser/gi/annotation_virtual.xml158
-rw-r--r--tests/scanner/annotationparser/gi/annotations.xml637
-rw-r--r--tests/scanner/annotationparser/gi/identifier.xml122
-rw-r--r--tests/scanner/annotationparser/gi/identifier_section.xml332
-rw-r--r--tests/scanner/annotationparser/gi/identifier_symbol.xml435
-rw-r--r--tests/scanner/annotationparser/gi/parameter.xml375
-rw-r--r--tests/scanner/annotationparser/gi/parameter_varargs.xml298
-rw-r--r--tests/scanner/annotationparser/gi/syntax.xml467
-rw-r--r--tests/scanner/annotationparser/gi/syntax_indentation.xml89
-rw-r--r--tests/scanner/annotationparser/gi/syntax_multiline_annotations.xml81
-rw-r--r--tests/scanner/annotationparser/gi/syntax_nested_tags.xml230
-rw-r--r--tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml359
-rw-r--r--tests/scanner/annotationparser/gi/syntax_whitespace.xml124
-rw-r--r--tests/scanner/annotationparser/gi/tag.xml401
-rw-r--r--tests/scanner/annotationparser/gi/tag_deprecated.xml127
-rw-r--r--tests/scanner/annotationparser/gi/tag_description.xml132
-rw-r--r--tests/scanner/annotationparser/gi/tag_returns.xml595
-rw-r--r--tests/scanner/annotationparser/gi/tag_since.xml187
-rw-r--r--tests/scanner/annotationparser/gi/tag_stability.xml211
-rw-r--r--tests/scanner/annotationparser/gtkdoc/annotations/tester.c.xml482
-rw-r--r--tests/scanner/annotationparser/gtkdoc/annotations/tester.h.xml39
-rw-r--r--tests/scanner/annotationparser/gtkdoc/bugs/tester.c.xml1108
-rw-r--r--tests/scanner/annotationparser/gtkdoc/bugs/tester.h.xml925
-rw-r--r--tests/scanner/annotationparser/gtkdoc/empty/tester.c.xml72
-rw-r--r--tests/scanner/annotationparser/gtkdoc/fail/tester.c.xml216
-rw-r--r--tests/scanner/annotationparser/gtkdoc/fail/tester.h.xml281
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/giface.c.xml197
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/giface.h.xml162
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/gobject.c.xml616
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/gobject.h.xml213
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/gtypes.c.xml46
-rw-r--r--tests/scanner/annotationparser/gtkdoc/gobject/gtypes.h.xml113
-rw-r--r--tests/scanner/annotationparser/test_parser.py461
-rw-r--r--tests/scanner/annotationparser/test_patterns.py943
-rw-r--r--tests/scanner/annotationparser/tests.xsd171
59 files changed, 15154 insertions, 0 deletions
diff --git a/tests/scanner/annotationparser/Makefile.am b/tests/scanner/annotationparser/Makefile.am
new file mode 100644
index 00000000..3003df85
--- /dev/null
+++ b/tests/scanner/annotationparser/Makefile.am
@@ -0,0 +1,68 @@
+include $(top_srcdir)/common.mk
+
+TESTS = \
+ test_parser.py \
+ test_patterns.py
+
+TESTS_ENVIRONMENT = builddir=$(builddir) top_builddir=$(top_builddir) srcdir=$(srcdir) top_srcdir=$(top_srcdir) \
+ PYTHON=$(PYTHON) UNINSTALLED_INTROSPECTION_SRCDIR=$(top_srcdir)
+LOG_COMPILER = $(top_srcdir)/tests/gi-tester
+
+EXTRA_DIST = \
+ $(TESTS) \
+ README \
+ tests.xsd \
+ gi/annotation_allow_none.xml \
+ gi/annotation_array.xml \
+ gi/annotation_attributes.xml \
+ gi/annotation_closure.xml \
+ gi/annotation_constructor.xml \
+ gi/annotation_destroy.xml \
+ gi/annotation_element_type.xml \
+ gi/annotation_foreign.xml \
+ gi/annotation_get_value_func.xml \
+ gi/annotation_in.xml \
+ gi/annotation_in_out.xml \
+ gi/annotation_method.xml \
+ gi/annotation_out.xml \
+ gi/annotation_ref_func.xml \
+ gi/annotation_rename_to.xml \
+ gi/annotation_scope.xml \
+ gi/annotation_set_value_func.xml \
+ gi/annotation_skip.xml \
+ gi/annotation_transfer.xml \
+ gi/annotation_type.xml \
+ gi/annotation_unref_func.xml \
+ gi/annotation_value.xml \
+ gi/annotation_virtual.xml \
+ gi/annotations.xml \
+ gi/identifier.xml \
+ gi/identifier_section.xml \
+ gi/identifier_symbol.xml \
+ gi/parameter.xml \
+ gi/parameter_varargs.xml \
+ gi/syntax.xml \
+ gi/syntax_indentation.xml \
+ gi/syntax_multiline_annotations.xml \
+ gi/syntax_nested_tags.xml \
+ gi/syntax_paragraph_breaks.xml \
+ gi/syntax_whitespace.xml \
+ gi/tag.xml \
+ gi/tag_deprecated.xml \
+ gi/tag_description.xml \
+ gi/tag_returns.xml \
+ gi/tag_since.xml \
+ gi/tag_stability.xml \
+ gtkdoc/gobject/gtypes.h.xml \
+ gtkdoc/gobject/gtypes.c.xml \
+ gtkdoc/gobject/giface.h.xml \
+ gtkdoc/gobject/giface.c.xml \
+ gtkdoc/fail/tester.h.xml \
+ gtkdoc/fail/tester.c.xml \
+ gtkdoc/empty/tester.c.xml \
+ gtkdoc/bugs/tester.h.xml \
+ gtkdoc/bugs/tester.c.xml \
+ gtkdoc/annotations/tester.h.xml \
+ gtkdoc/annotations/tester.c.xml \
+ gtkdoc/gobject/gobject.h.xml \
+ gtkdoc/gobject/gobject.c.xml
diff --git a/tests/scanner/annotationparser/README b/tests/scanner/annotationparser/README
new file mode 100644
index 00000000..1dbc64e1
--- /dev/null
+++ b/tests/scanner/annotationparser/README
@@ -0,0 +1,52 @@
+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 the 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 (DocBook) 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 (DocBook) 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 trailing whitespace characters in test .xml files are not there by accident.
+ So whatever your text editor of choice or scm du jour might claim, trailing whitespace
+ is required!
+
+
+Test files
+----------
+
+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
+ GtkDocCommentBlockParser 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
+ and should be updated regularly to reflect changes in the GTK-Doc project.
+ - updated 2013/07/30 to 1846fc7e904f6f56b74c366d205d6bb946eac17e
+
+gobject-introspection/*.xml:
+ GTK-Doc comment blocks specifically designed to ensure GtkDocCommentBlockParser 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..ae6b3b37
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_allow_none.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_object_inout:
+ * @object: a #GObject
+ * @inoutarg: (inout) (allow-none): This is an argument test
+ *
+ * This is a test for out arguments
+ *
+ * Return value: (allow-none): an int
+ */</input>
+ <parser>
+ <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>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>an int</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_object_inout:
+ * @object: a #GObject
+ * @inoutarg: (inout) (allow-none): This is an argument test
+ *
+ * This is a test for out arguments
+ *
+ * Returns: (allow-none): an int
+ */</output>
+</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..3a7cbc0b
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_array.xml
@@ -0,0 +1,483 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_object_compute_sum:
+ * @nums: (array): Sequence of numbers
+ *
+ * Test taking a zero-terminated array
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_object_compute_sum:
+ * @nums: (array): Sequence of numbers
+ *
+ * Test taking a zero-terminated array
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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.
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_string_zero_terminated:
+ * @data: (array fixed-size=2): a third value
+ *
+ * Return value: (transfer full) (array zero-terminated=1): The return value
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_string_zero_terminated:
+ * @data: (array fixed-size=2): a third value
+ *
+ * Returns: (transfer full) (array zero-terminated=1): The return value
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_string_zero_terminated:
+ * @data: (array invalid fixed-size=2): a third value
+ *
+ * Return value: (transfer full) (array zero-terminated=1): The return value
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_string_zero_terminated</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>data</name>
+ <annotations>
+ <annotation>
+ <name>array</name>
+ <options>
+ <option>
+ <name>invalid</name>
+ </option>
+ <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>
+ <messages>
+ <message>3: Warning: Test: invalid "array" annotation option: "invalid"</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_string_zero_terminated:
+ * @data: (array invalid fixed-size=2): a third value
+ *
+ * Returns: (transfer full) (array zero-terminated=1): The return value
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * g_app_launch_context_get_environment:
+ * @arg1: (array zero-terminated): ...
+ * @arg2: (array length): ...
+ *
+ * Returns: (array zero-terminated=yes): the child's environment
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>g_app_launch_context_get_environment</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>arg1</name>
+ <annotations>
+ <annotation>
+ <name>array</name>
+ <options>
+ <option>
+ <name>zero-terminated</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>...</description>
+ </parameter>
+ <parameter>
+ <name>arg2</name>
+ <annotations>
+ <annotation>
+ <name>array</name>
+ <options>
+ <option>
+ <name>length</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>...</description>
+ </parameter>
+ </parameters>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>array</name>
+ <options>
+ <option>
+ <name>zero-terminated</name>
+ <value>yes</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>the child's environment</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>3: Warning: Test: "array" annotation option "zero-terminated" needs a value</message>
+ <message>4: Warning: Test: "array" annotation option "length" needs a value</message>
+ <message>6: Warning: Test: invalid "array" annotation option "zero-terminated" value "yes", must be an integer</message>
+ </messages>
+ </parser>
+ <output>/**
+ * g_app_launch_context_get_environment:
+ * @arg1: (array zero-terminated): ...
+ * @arg2: (array length): ...
+ *
+ * Returns: (array zero-terminated=yes): the child's environment
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotation_attributes.xml b/tests/scanner/annotationparser/gi/annotation_attributes.xml
new file mode 100644
index 00000000..e9d9b429
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_attributes.xml
@@ -0,0 +1,477 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * AnnotationObject: (attributes org.example.test1=horses org.example.test2 org.example.test3=cows)
+ *
+ * This is an object used to test annotations.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>org.example.test1</name>
+ <value>horses</value>
+ </option>
+ <option>
+ <name>org.example.test2</name>
+ </option>
+ <option>
+ <name>org.example.test3</name>
+ <value>cows</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is an object used to test annotations.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * AnnotationObject: (attributes org.example.test1=horses org.example.test2 org.example.test3=cows)
+ *
+ * This is an object used to test annotations.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Attributes:" tag
+ -->
+ <input>/**
+ * AnnotationObject:
+ *
+ * This is an object used to test annotations.
+ *
+ * Attributes: (org.example.test1 horses) (org.example.test2) (org.example.test3 cows)
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>org.example.test1</name>
+ <value>horses</value>
+ </option>
+ <option>
+ <name>org.example.test2</name>
+ </option>
+ <option>
+ <name>org.example.test3</name>
+ <value>cows</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is an object used to test annotations.</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Attributes" has been deprecated, please use annotations on the identifier instead:
+ * Attributes: (org.example.test1 horses) (org.example.test2) (org.example.test3 cows)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * AnnotationObject: (attributes org.example.test1=horses org.example.test2 org.example.test3=cows)
+ *
+ * This is an object used to test annotations.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Variation of "Attributes:" tag
+ -->
+ <input>/**
+ * AnnotationObject:
+ *
+ * This is an object used to test annotations.
+ *
+ * Attributes: (org.example.test1 horses))
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject</name>
+ </identifier>
+ <description>This is an object used to test annotations.</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Attributes" has been deprecated, please use annotations on the identifier instead:
+ * Attributes: (org.example.test1 horses))
+ ^</message>
+ <message>6: Error: Test: unbalanced parentheses, annotations will be ignored:
+Attributes: (org.example.test1 horses))
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * AnnotationObject:
+ *
+ * This is an object used to test annotations.
+ */</output>
+</test>
+
+<test>
+ <!--
+ (attributes) annotation on the identifier together with a
+ deprecated "Attributes:" tag.
+ -->
+ <input>/**
+ * AnnotationObject: (attributes org.example.test1=horses)
+ *
+ * This is an object used to test annotations.
+ *
+ * Attributes: (org.example.test1 horses) (org.example.test2 cows)
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>org.example.test1</name>
+ <value>horses</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is an object used to test annotations.</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Attributes" has been deprecated, please use annotations on the identifier instead:
+ * Attributes: (org.example.test1 horses) (org.example.test2 cows)
+ ^</message>
+ <message>6: Error: Test: Duplicate "Attributes:" annotation will be ignored:
+ * Attributes: (org.example.test1 horses) (org.example.test2 cows)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * AnnotationObject: (attributes org.example.test1=horses)
+ *
+ * This is an object used to test annotations.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Attributes:" tag in the wrong location
+ -->
+ <input>/**
+ * AnnotationObject:
+ *
+ * Attributes: (org.example.Test horses) (org.example.test2 cows)
+ *
+ * This is an object used to test annotations.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>org.example.Test</name>
+ <value>horses</value>
+ </option>
+ <option>
+ <name>org.example.test2</name>
+ <value>cows</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is an object used to test annotations.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Attributes" has been deprecated, please use annotations on the identifier instead:
+ * Attributes: (org.example.Test horses) (org.example.test2 cows)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * AnnotationObject: (attributes org.example.Test=horses org.example.test2=cows)
+ *
+ * This is an object used to test annotations.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * AnnotationObject:
+ *
+ * Attributes: (org.example.Test horses cows)
+ *
+ * This is an object used to test annotations.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject</name>
+ </identifier>
+ <description>This is an object used to test annotations.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Attributes" has been deprecated, please use annotations on the identifier instead:
+ * Attributes: (org.example.Test horses cows)
+ ^</message>
+ <message>4: Error: Test: malformed "Attributes:" tag will be ignored:
+ * Attributes: (org.example.Test horses cows)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * AnnotationObject:
+ *
+ * This is an object used to test annotations.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * AnnotationObject::attribute-signal:
+ * @annotation: the annotation object
+ * @arg1: (attributes some.annotation.foo1=val1): a value
+ * @arg2: (attributes some.annotation.foo2=val2): another value
+ * @arg3: (array fixed-size=2): a third value
+ *
+ * This signal tests a signal with attributes.
+ *
+ * Returns: (attributes some.annotation.foo3=val3): the return value
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject::attribute-signal</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>annotation</name>
+ <description>the annotation object</description>
+ </parameter>
+ <parameter>
+ <name>arg1</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>some.annotation.foo1</name>
+ <value>val1</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>a value</description>
+ </parameter>
+ <parameter>
+ <name>arg2</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>some.annotation.foo2</name>
+ <value>val2</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>another value</description>
+ </parameter>
+ <parameter>
+ <name>arg3</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>
+ <description>This signal tests a signal with attributes.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>some.annotation.foo3</name>
+ <value>val3</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>the return value</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * AnnotationObject::attribute-signal:
+ * @annotation: the annotation object
+ * @arg1: (attributes some.annotation.foo1=val1): a value
+ * @arg2: (attributes some.annotation.foo2=val2): another value
+ * @arg3: (array fixed-size=2): a third value
+ *
+ * This signal tests a signal with attributes.
+ *
+ * Returns: (attributes some.annotation.foo3=val3): the return value
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated (attribute) annotation.
+ -->
+ <input>/**
+ * AnnotationObject::attribute-signal:
+ * @annotation: the annotation object
+ * @arg1: (attribute some.annotation.foo1): a value
+ * @arg2: (attribute some.annotation.foo2 val2): another value
+ * @arg3: (attribute x y z): something special
+ * @arg4: (array fixed-size=2): a third value
+ *
+ * This signal tests a signal with attributes.
+ *
+ * Returns: (attribute some.annotation.foo3 val3): the return value
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject::attribute-signal</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>annotation</name>
+ <description>the annotation object</description>
+ </parameter>
+ <parameter>
+ <name>arg1</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>some.annotation.foo1</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>a value</description>
+ </parameter>
+ <parameter>
+ <name>arg2</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>some.annotation.foo2</name>
+ <value>val2</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>another value</description>
+ </parameter>
+ <parameter>
+ <name>arg3</name>
+ <description>something special</description>
+ </parameter>
+ <parameter>
+ <name>arg4</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>
+ <description>This signal tests a signal with attributes.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>some.annotation.foo3</name>
+ <value>val3</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>the return value</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: "attribute" annotation has been deprecated, please use "attributes" instead:
+ * @arg1: (attribute some.annotation.foo1): a value
+ ^</message>
+ <message>5: Warning: Test: "attribute" annotation has been deprecated, please use "attributes" instead:
+ * @arg2: (attribute some.annotation.foo2 val2): another value
+ ^</message>
+ <message>6: Warning: Test: "attribute" annotation has been deprecated, please use "attributes" instead:
+ * @arg3: (attribute x y z): something special
+ ^</message>
+ <message>6: Error: Test: malformed "(attribute)" annotation will be ignored:
+ * @arg3: (attribute x y z): something special
+ ^</message>
+ <message>11: Warning: Test: "attribute" annotation has been deprecated, please use "attributes" instead:
+ * Returns: (attribute some.annotation.foo3 val3): the return value
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * AnnotationObject::attribute-signal:
+ * @annotation: the annotation object
+ * @arg1: (attributes some.annotation.foo1): a value
+ * @arg2: (attributes some.annotation.foo2=val2): another value
+ * @arg3: something special
+ * @arg4: (array fixed-size=2): a third value
+ *
+ * This signal tests a signal with attributes.
+ *
+ * Returns: (attributes some.annotation.foo3=val3): the return value
+ */</output>
+</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..f67862c5
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_closure.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_custom_destroy:
+ * @callback: (destroy destroy) (closure data=invalid): Destroy notification
+ *
+ * Test messing up the heuristic of closure/destroy-notification
+ * detection, and fixing it via annotations.
+ */</input>
+ <parser>
+ <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=invalid</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>
+ <messages>
+ <message>3: Warning: Test: invalid annotation options: expected a "list" but received "key=value pairs":
+ * @callback: (destroy destroy) (closure data=invalid): Destroy notification
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_custom_destroy:
+ * @callback: (destroy destroy) (closure data=invalid): Destroy notification
+ *
+ * Test messing up the heuristic of closure/destroy-notification
+ * detection, and fixing it via annotations.
+ */</output>
+</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..8c0aeb28
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_constructor.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * regress_constructor: (constructor)
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>regress_constructor</name>
+ <annotations>
+ <annotation>
+ <name>constructor</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ </docblock>
+ </parser>
+ <output>/**
+ * regress_constructor: (constructor)
+ */</output>
+</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..e504a962
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_destroy.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_custom_destroy:
+ * @callback: (destroy destroy=invalid) (closure data): Destroy notification
+ *
+ * Test messing up the heuristic of closure/destroy-notification
+ * detection, and fixing it via annotations.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_custom_destroy</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>callback</name>
+ <annotations>
+ <annotation>
+ <name>destroy</name>
+ <options>
+ <option>
+ <name>destroy=invalid</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>
+ <messages>
+ <message>3: Warning: Test: invalid annotation options: expected a "list" but received "key=value pairs":
+ * @callback: (destroy destroy=invalid) (closure data): Destroy notification
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_custom_destroy:
+ * @callback: (destroy destroy=invalid) (closure data): Destroy notification
+ *
+ * Test messing up the heuristic of closure/destroy-notification
+ * detection, and fixing it via annotations.
+ */</output>
+</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..65b3dd09
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_element_type.xml
@@ -0,0 +1,272 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * foo_test_array:
+ * @a: (element-type):
+ * @b: (element-type x y z):
+ *
+ * Returns: (element-type utf8) (transfer container): returns %NULL.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>foo_test_array</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>a</name>
+ <annotations>
+ <annotation>
+ <name>element-type</name>
+ </annotation>
+ </annotations>
+ </parameter>
+ <parameter>
+ <name>b</name>
+ <annotations>
+ <annotation>
+ <name>element-type</name>
+ <options>
+ <option>
+ <name>x</name>
+ </option>
+ <option>
+ <name>y</name>
+ </option>
+ <option>
+ <name>z</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </parameter>
+ </parameters>
+ <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>
+ <messages>
+ <message>3: Warning: Test: "element-type" annotation takes at least one option, none given</message>
+ <message>4: Warning: Test: "element-type" annotation takes at most 2 options, 3 given</message>
+ </messages>
+ </parser>
+ <output>/**
+ * foo_test_array:
+ * @a: (element-type):
+ * @b: (element-type x y z):
+ *
+ * Returns: (element-type utf8) (transfer container): returns %NULL.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * RegressTestObj::sig-with-hash-prop:
+ * @self: an object
+ * @hash: (element-type utf8 GObject.Value):
+ *
+ * This test signal is like TelepathyGlib's
+ * TpAccount::status-changed
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * RegressTestObj::sig-with-hash-prop:
+ * @self: an object
+ * @hash: (element-type utf8 GObject.Value):
+ *
+ * This test signal is like TelepathyGlib's
+ * TpAccount::status-changed
+ */</output>
+</test>
+
+<test>
+ <input><![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):
+ */]]></input>
+ <parser>
+ <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>GLib.HashTable(utf8,utf8)</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>full</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * regress_test_ghash_nested_everything_return2:
+ *
+ * Another way of specifying nested parameterized types: using the
+ * element-type annotation.
+ *
+ * Returns: (element-type utf8 GLib.HashTable(utf8,utf8)) (transfer full):
+ */</output>
+</test>
+
+<test>
+ <input> /**
+ * foo_test_array:
+ *
+ * Returns: (element-type invalid utf8=invalid GLib.HashTable(utf8,utf8)): returns %NULL.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>foo_test_array</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>element-type</name>
+ <options>
+ <option>
+ <name>invalid utf8=invalid GLib.HashTable(utf8,utf8)</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>returns %NULL.</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: invalid annotation options: expected a "list" but received "key=value pairs":
+ * Returns: (element-type invalid utf8=invalid GLib.HashTable(utf8,utf8)): returns %NULL.
+ ^</message>
+ </messages>
+ </parser>
+ <output> /**
+ * foo_test_array:
+ *
+ * Returns: (element-type invalid utf8=invalid GLib.HashTable(utf8,utf8)): returns %NULL.
+ */</output>
+</test>
+
+<test>
+ <input> /**
+ * foo_test_array:
+ *
+ * Returns: (element-type utf8=invalid GLib.HashTable(utf8,utf8) invalid): returns %NULL.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>foo_test_array</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>element-type</name>
+ <options>
+ <option>
+ <name>utf8=invalid GLib.HashTable(utf8,utf8) invalid</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>returns %NULL.</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: invalid annotation options: expected a "list" but received "key=value pairs":
+ * Returns: (element-type utf8=invalid GLib.HashTable(utf8,utf8) invalid): returns %NULL.
+ ^</message>
+ </messages>
+ </parser>
+ <output> /**
+ * foo_test_array:
+ *
+ * Returns: (element-type utf8=invalid GLib.HashTable(utf8,utf8) invalid): returns %NULL.
+ */</output>
+</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..e65e9747
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_foreign.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * FooForeignStruct: (foreign)
+ *
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>FooForeignStruct</name>
+ <annotations>
+ <annotation>
+ <name>foreign</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ </docblock>
+ </parser>
+ <output>/**
+ * FooForeignStruct: (foreign)
+ */</output>
+</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..3e96f837
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_get_value_func.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * RegressTestFundamentalObject: (get-value-func regress_test_value_get_fundamental_object)
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>get-value-func</name>
+ <options>
+ <option>
+ <name>regress_test_value_get_fundamental_object</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (get-value-func regress_test_value_get_fundamental_object)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Get value func:" tag syntax
+ -->
+ <input>/**
+ * RegressTestFundamentalObject:
+ *
+ * This object tests regressions...
+ *
+ * Get value func: regress_test_value_get_fundamental_object
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>get-value-func</name>
+ <options>
+ <option>
+ <name>regress_test_value_get_fundamental_object</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Get value func" has been deprecated, please use annotations on the identifier instead:
+ * Get value func: regress_test_value_get_fundamental_object
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (get-value-func regress_test_value_get_fundamental_object)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Get value func:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * RegressTestFundamentalObject:
+ *
+ * Get value func: regress_test_value_get_fundamental_object
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>get-value-func</name>
+ <options>
+ <option>
+ <name>regress_test_value_get_fundamental_object</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Get value func" has been deprecated, please use annotations on the identifier instead:
+ * Get value func: regress_test_value_get_fundamental_object
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (get-value-func regress_test_value_get_fundamental_object)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * RegressTestFundamentalObject: (get-value-func regress_test_value_get_fundamental_object=invalid)
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>get-value-func</name>
+ <options>
+ <option>
+ <name>regress_test_value_get_fundamental_object=invalid</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: invalid annotation options: expected a "list" but received "key=value pairs":
+ * RegressTestFundamentalObject: (get-value-func regress_test_value_get_fundamental_object=invalid)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (get-value-func regress_test_value_get_fundamental_object=invalid)
+ *
+ * This object tests regressions...
+ */</output>
+</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..26daf5a6
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_in.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_object_in:
+ * @object: a #GObject
+ * @inarg: (in) (transfer none): This is an argument test
+ *
+ * This is a test for in arguments
+ *
+ * Returns: an int
+ */</output>
+</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..1900229e
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_in_out.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>inout</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>
+ <messages>
+ <message>5: Warning: Test: "in-out" annotation has been deprecated, please use "inout" instead:
+ * @inoutarg2: (in-out): This is an argument test
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_object_inout:
+ * @object: a #GObject
+ * @inoutarg: (inout): This is an argument test
+ * @inoutarg2: (inout): This is an argument test
+ *
+ * This is a test for inout arguments
+ *
+ * Returns: an int
+ */</output>
+</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..3b9f1b87
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_method.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * regress_forced_method: (method)
+ * @obj: A #RegressTestObj
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * regress_forced_method: (method)
+ * @obj: A #RegressTestObj
+ */</output>
+</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..7bfc8638
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_out.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_object_out:
+ * @object: a #GObject
+ * @outarg: (out): This is an argument test
+ *
+ * This is a test for out arguments
+ *
+ * Return value: an int
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_object_out:
+ * @object: a #GObject
+ * @outarg: (out): This is an argument test
+ *
+ * This is a test for out arguments
+ *
+ * Returns: an int
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * regress_test_struct_a_clone:
+ * @a: the structure
+ * @a_out: (out caller-allocates): the cloned structure
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * regress_test_struct_a_clone:
+ * @a: the structure
+ * @a_out: (out caller-allocates): the cloned structure
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * regress_test_struct_a_clone:
+ * @a: the structure
+ * @a_out: (out callee-allocates): the cloned structure
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * regress_test_struct_a_clone:
+ * @a: the structure
+ * @a_out: (out callee-allocates): the cloned structure
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * regress_test_struct_a_clone:
+ * @a: (out invalid): the structure
+ * @a_out: (out callee-allocates=invalid): the cloned structure
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>regress_test_struct_a_clone</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>a</name>
+ <annotations>
+ <annotation>
+ <name>out</name>
+ <options>
+ <option>
+ <name>invalid</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>the structure</description>
+ </parameter>
+ <parameter>
+ <name>a_out</name>
+ <annotations>
+ <annotation>
+ <name>out</name>
+ <options>
+ <option>
+ <name>callee-allocates=invalid</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>the cloned structure</description>
+ </parameter>
+ </parameters>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: invalid annotation options: expected a "list" but received "key=value pairs":
+ * @a_out: (out callee-allocates=invalid): the cloned structure
+ ^</message>
+ <message>3: Warning: Test: invalid "out" annotation option: "invalid"</message>
+ <message>4: Warning: Test: invalid "out" annotation option: "callee-allocates=invalid"</message>
+ </messages>
+ </parser>
+ <output>/**
+ * regress_test_struct_a_clone:
+ * @a: (out invalid): the structure
+ * @a_out: (out callee-allocates=invalid): the cloned structure
+ */</output>
+</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..a967102a
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_ref_func.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * RegressTestFundamentalObject: (ref-func regress_test_fundamental_object_ref)
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>ref-func</name>
+ <options>
+ <option>
+ <name>regress_test_fundamental_object_ref</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (ref-func regress_test_fundamental_object_ref)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Ref func:" tag syntax
+ -->
+ <input>/**
+ * RegressTestFundamentalObject:
+ *
+ * This object tests regressions...
+ *
+ * Ref func: regress_test_fundamental_object_ref
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>ref-func</name>
+ <options>
+ <option>
+ <name>regress_test_fundamental_object_ref</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Ref func" has been deprecated, please use annotations on the identifier instead:
+ * Ref func: regress_test_fundamental_object_ref
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (ref-func regress_test_fundamental_object_ref)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Ref func:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * RegressTestFundamentalObject:
+ *
+ * Ref func: regress_test_fundamental_object_ref
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>ref-func</name>
+ <options>
+ <option>
+ <name>regress_test_fundamental_object_ref</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Ref func" has been deprecated, please use annotations on the identifier instead:
+ * Ref func: regress_test_fundamental_object_ref
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (ref-func regress_test_fundamental_object_ref)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * RegressTestFundamentalObject: (ref-func regress_test_fundamental_object_ref=invalid)
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>ref-func</name>
+ <options>
+ <option>
+ <name>regress_test_fundamental_object_ref=invalid</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: invalid annotation options: expected a "list" but received "key=value pairs":
+ * RegressTestFundamentalObject: (ref-func regress_test_fundamental_object_ref=invalid)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (ref-func regress_test_fundamental_object_ref=invalid)
+ *
+ * This object tests regressions...
+ */</output>
+</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..2987d889
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_rename_to.xml
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_object_watch_full: (rename-to annotation_object_watch)
+ * @object: A #AnnotationObject
+ * @func: The callback
+ * @user_data: The callback data
+ * @destroy: Destroy notification
+ *
+ * Test overriding via the "Rename To" annotation.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_watch_full</name>
+ <annotations>
+ <annotation>
+ <name>rename-to</name>
+ <options>
+ <option>
+ <name>annotation_object_watch</name>
+ </option>
+ </options>
+ </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>
+ <parameter>
+ <name>destroy</name>
+ <description>Destroy notification</description>
+ </parameter>
+ </parameters>
+ <description>Test overriding via the "Rename To" annotation.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_object_watch_full: (rename-to annotation_object_watch)
+ * @object: A #AnnotationObject
+ * @func: The callback
+ * @user_data: The callback data
+ * @destroy: Destroy notification
+ *
+ * Test overriding via the "Rename To" annotation.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Rename to:" tag syntax
+ -->
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_watch_full</name>
+ <annotations>
+ <annotation>
+ <name>rename-to</name>
+ <options>
+ <option>
+ <name>annotation_object_watch</name>
+ </option>
+ </options>
+ </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>
+ <parameter>
+ <name>destroy</name>
+ <description>Destroy notification</description>
+ </parameter>
+ </parameters>
+ <description>Test overriding via the "Rename To" annotation.</description>
+ </docblock>
+ <messages>
+ <message>10: Warning: Test: GObject-Introspection specific GTK-Doc tag "Rename to" has been deprecated, please use annotations on the identifier instead:
+ * Rename to: annotation_object_watch
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_object_watch_full: (rename-to annotation_object_watch)
+ * @object: A #AnnotationObject
+ * @func: The callback
+ * @user_data: The callback data
+ * @destroy: Destroy notification
+ *
+ * Test overriding via the "Rename To" annotation.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Rename to:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * annotation_object_watch_full:
+ *
+ * Rename to: annotation_object_watch
+ *
+ * Test overriding via the "Rename To" annotation.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_watch_full</name>
+ <annotations>
+ <annotation>
+ <name>rename-to</name>
+ <options>
+ <option>
+ <name>annotation_object_watch</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test overriding via the "Rename To" annotation.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Rename to" has been deprecated, please use annotations on the identifier instead:
+ * Rename to: annotation_object_watch
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_object_watch_full: (rename-to annotation_object_watch)
+ *
+ * Test overriding via the "Rename To" annotation.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_object_watch_full: (rename-to annotation_object_watch=invalid)
+ * @object: A #AnnotationObject
+ * @func: The callback
+ * @user_data: The callback data
+ * @destroy: Destroy notification
+ *
+ * Test overriding via the "Rename To" annotation.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_watch_full</name>
+ <annotations>
+ <annotation>
+ <name>rename-to</name>
+ <options>
+ <option>
+ <name>annotation_object_watch=invalid</name>
+ </option>
+ </options>
+ </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>
+ <parameter>
+ <name>destroy</name>
+ <description>Destroy notification</description>
+ </parameter>
+ </parameters>
+ <description>Test overriding via the "Rename To" annotation.</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: invalid annotation options: expected a "list" but received "key=value pairs":
+ * annotation_object_watch_full: (rename-to annotation_object_watch=invalid)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_object_watch_full: (rename-to annotation_object_watch=invalid)
+ * @object: A #AnnotationObject
+ * @func: The callback
+ * @user_data: The callback data
+ * @destroy: Destroy notification
+ *
+ * Test overriding via the "Rename To" annotation.
+ */</output>
+</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..3a22274a
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_scope.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_object_foreach:
+ * @object: a #AnnotationObject
+ * @func: (scope call): Callback to invoke
+ * @user_data: Callback user data
+ *
+ * Test taking a call-scoped callback
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_object_foreach:
+ * @object: a #AnnotationObject
+ * @func: (scope call): Callback to invoke
+ * @user_data: Callback user data
+ *
+ * Test taking a call-scoped callback
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * regress_test_callback_destroy_notify:
+ * @callback: (scope notified):
+ *
+ * Notified - callback persists until a DestroyNotify delegate
+ * is invoked.
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * regress_test_callback_destroy_notify:
+ * @callback: (scope notified):
+ *
+ * Notified - callback persists until a DestroyNotify delegate
+ * is invoked.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * regress_test_callback_async:
+ * @callback: (scope async):
+ *
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * regress_test_callback_async:
+ * @callback: (scope async):
+ */</output>
+</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..f98944b5
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_set_value_func.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * RegressTestFundamentalObject: (set-value-func regress_test_value_set_fundamental_object)
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>set-value-func</name>
+ <options>
+ <option>
+ <name>regress_test_value_set_fundamental_object</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (set-value-func regress_test_value_set_fundamental_object)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Set value func:" tag syntax
+ -->
+ <input>/**
+ * RegressTestFundamentalObject:
+ *
+ * This object tests regressions...
+ *
+ * Set value func: regress_test_value_set_fundamental_object
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>set-value-func</name>
+ <options>
+ <option>
+ <name>regress_test_value_set_fundamental_object</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Set value func" has been deprecated, please use annotations on the identifier instead:
+ * Set value func: regress_test_value_set_fundamental_object
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (set-value-func regress_test_value_set_fundamental_object)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Set value func:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * RegressTestFundamentalObject:
+ *
+ * Set value func: regress_test_value_set_fundamental_object
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>set-value-func</name>
+ <options>
+ <option>
+ <name>regress_test_value_set_fundamental_object</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Set value func" has been deprecated, please use annotations on the identifier instead:
+ * Set value func: regress_test_value_set_fundamental_object
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (set-value-func regress_test_value_set_fundamental_object)
+ *
+ * This object tests regressions...
+ */</output>
+</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..e0352e03
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_skip.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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().
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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().
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_object_watch: (skip yes)
+ *
+ * This is here just for the sake of being overriden by its
+ * annotation_object_watch_full().
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_watch</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ <options>
+ <option>
+ <name>yes</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is here just for the sake of being overriden by its
+annotation_object_watch_full().</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: "skip" annotation needs no options, 1 given</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_object_watch: (skip yes)
+ *
+ * This is here just for the sake of being overriden by its
+ * annotation_object_watch_full().
+ */</output>
+</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..9b4ded1a
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_transfer.xml
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_object_in:
+ * @object: a #GObject
+ * @inarg: (in) (transfer none): This is an argument test
+ *
+ * This is a test for in arguments
+ *
+ * Returns: an int
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_transfer_floating:
+ *
+ * Returns: (transfer floating): A floating object
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_transfer_floating:
+ *
+ * Returns: (transfer floating): A floating object
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * FsSession:codecs-without-config: (transfer full)
+ *
+ * This is the same list of codecs as #FsSession:codecs
+ * without....
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>FsSession:codecs-without-config</name>
+ <annotations>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>full</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is the same list of codecs as #FsSession:codecs
+without....</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * FsSession:codecs-without-config: (transfer full)
+ *
+ * This is the same list of codecs as #FsSession:codecs
+ * without....
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Transfer:" tag syntax
+ -->
+ <input>/**
+ * FsSession:codecs-without-config:
+ *
+ * This is the same list of codecs as #FsSession:codecs
+ * without....
+ *
+ * Transfer: full
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>FsSession:codecs-without-config</name>
+ <annotations>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>full</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is the same list of codecs as #FsSession:codecs
+without....</description>
+ </docblock>
+ <messages>
+ <message>7: Warning: Test: GObject-Introspection specific GTK-Doc tag "Transfer" has been deprecated, please use annotations on the identifier instead:
+ * Transfer: full
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * FsSession:codecs-without-config: (transfer full)
+ *
+ * This is the same list of codecs as #FsSession:codecs
+ * without....
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Transfer:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * FsSession:codecs-without-config:
+ *
+ * Transfer: full
+ *
+ * This is the same list of codecs as #FsSession:codecs
+ * without....
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>FsSession:codecs-without-config</name>
+ <annotations>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>full</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is the same list of codecs as #FsSession:codecs
+without....</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Transfer" has been deprecated, please use annotations on the identifier instead:
+ * Transfer: full
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * FsSession:codecs-without-config: (transfer full)
+ *
+ * This is the same list of codecs as #FsSession:codecs
+ * without....
+ */</output>
+</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..c3d6351d
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_type.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * AnnotationObject:hash-table: (type GLib.HashTable(utf8,gint8)) (transfer container)
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject:hash-table</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.HashTable(utf8,gint8)</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>container</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ </docblock>
+ </parser>
+ <output>/**
+ * AnnotationObject:hash-table: (type GLib.HashTable(utf8,gint8)) (transfer container)
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated inequality sign/angled brackets notation.
+ -->
+ <input><![CDATA[/**
+ * AnnotationObject:hash-table: (type GLib.HashTable<utf8,gint8>) (transfer container)
+ */]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>AnnotationObject:hash-table</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.HashTable(utf8,gint8)</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>container</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ </docblock>
+ </parser>
+ <output>/**
+ * AnnotationObject:hash-table: (type GLib.HashTable(utf8,gint8)) (transfer container)
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Type:" tag syntax
+ -->
+ <input>/**
+ * RegressTestObj:hash-table:
+ *
+ * Test.
+ *
+ * Type: GLib.HashTable(utf8,gint8)
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestObj:hash-table</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.HashTable(utf8,gint8)</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test.</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Type" has been deprecated, please use annotations on the identifier instead:
+ * Type: GLib.HashTable(utf8,gint8)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestObj:hash-table: (type GLib.HashTable(utf8,gint8))
+ *
+ * Test.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Type:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * RegressTestObj:hash-table:
+ *
+ * Type: GLib.HashTable(utf8,gint8)
+ *
+ * Test.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestObj:hash-table</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.HashTable(utf8,gint8)</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Type" has been deprecated, please use annotations on the identifier instead:
+ * Type: GLib.HashTable(utf8,gint8)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestObj:hash-table: (type GLib.HashTable(utf8,gint8))
+ *
+ * Test.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated angled brackets in deprecated "Type:" tag syntax
+ -->
+ <input><![CDATA[/**
+ * RegressTestObj:hash-table:
+ *
+ * Test.
+ *
+ * Type: GLib.HashTable<utf8,gint8>
+ */]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestObj:hash-table</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.HashTable(utf8,gint8)</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test.</description>
+ </docblock>
+ <messages>
+ <message><![CDATA[6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Type" has been deprecated, please use annotations on the identifier instead:
+ * Type: GLib.HashTable<utf8,gint8>
+ ^]]></message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestObj:hash-table: (type GLib.HashTable(utf8,gint8))
+ *
+ * Test.
+ */</output>
+</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..59f3f8d4
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_unref_func.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * RegressTestFundamentalObject: (unref-func regress_test_fundamental_object_unref)
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>unref-func</name>
+ <options>
+ <option>
+ <name>regress_test_fundamental_object_unref</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (unref-func regress_test_fundamental_object_unref)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Unref func:" tag syntax
+ -->
+ <input>/**
+ * RegressTestFundamentalObject:
+ *
+ * This object tests regressions...
+ *
+ * Unref func: regress_test_fundamental_object_unref
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>unref-func</name>
+ <options>
+ <option>
+ <name>regress_test_fundamental_object_unref</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Unref func" has been deprecated, please use annotations on the identifier instead:
+ * Unref func: regress_test_fundamental_object_unref
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (unref-func regress_test_fundamental_object_unref)
+ *
+ * This object tests regressions...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Unref func:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * RegressTestFundamentalObject:
+ *
+ * Unref func: regress_test_fundamental_object_unref
+ *
+ * This object tests regressions...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>RegressTestFundamentalObject</name>
+ <annotations>
+ <annotation>
+ <name>unref-func</name>
+ <options>
+ <option>
+ <name>regress_test_fundamental_object_unref</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This object tests regressions...</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Unref func" has been deprecated, please use annotations on the identifier instead:
+ * Unref func: regress_test_fundamental_object_unref
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * RegressTestFundamentalObject: (unref-func regress_test_fundamental_object_unref)
+ *
+ * This object tests regressions...
+ */</output>
+</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..7d72ef71
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_value.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * ANNOTATION_CALCULATED_LARGE: (value 10000000000UL)
+ *
+ * Constant to define a calculated large value
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>ANNOTATION_CALCULATED_LARGE</name>
+ <annotations>
+ <annotation>
+ <name>value</name>
+ <options>
+ <option>
+ <name>10000000000UL</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Constant to define a calculated large value</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * ANNOTATION_CALCULATED_LARGE: (value 10000000000UL)
+ *
+ * Constant to define a calculated large value
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Value:" tag syntax
+ -->
+ <input>/**
+ * ANNOTATION_CALCULATED_LARGE:
+ *
+ * Constant to define a calculated large value
+ *
+ * Value: 10000000000UL
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>ANNOTATION_CALCULATED_LARGE</name>
+ <annotations>
+ <annotation>
+ <name>value</name>
+ <options>
+ <option>
+ <name>10000000000UL</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Constant to define a calculated large value</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GObject-Introspection specific GTK-Doc tag "Value" has been deprecated, please use annotations on the identifier instead:
+ * Value: 10000000000UL
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * ANNOTATION_CALCULATED_LARGE: (value 10000000000UL)
+ *
+ * Constant to define a calculated large value
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Value:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * ANNOTATION_CALCULATED_LARGE:
+ *
+ * Value: 10000000000UL
+ *
+ * Constant to define a calculated large value
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>ANNOTATION_CALCULATED_LARGE</name>
+ <annotations>
+ <annotation>
+ <name>value</name>
+ <options>
+ <option>
+ <name>10000000000UL</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Constant to define a calculated large value</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Value" has been deprecated, please use annotations on the identifier instead:
+ * Value: 10000000000UL
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * ANNOTATION_CALCULATED_LARGE: (value 10000000000UL)
+ *
+ * Constant to define a calculated large value
+ */</output>
+</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..3321eea0
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotation_virtual.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * foo_object_read: (virtual read_fn)
+ * @object: obj
+ * @offset: offset
+ * @length: length
+ *
+ * Read some stuff.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>foo_object_read</name>
+ <annotations>
+ <annotation>
+ <name>virtual</name>
+ <options>
+ <option>
+ <name>read_fn</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </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>
+ </docblock>
+ </parser>
+ <output>/**
+ * foo_object_read: (virtual read_fn)
+ * @object: obj
+ * @offset: offset
+ * @length: length
+ *
+ * Read some stuff.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Virtual:" tag syntax
+ -->
+ <input>/**
+ * foo_object_read:
+ * @object: obj
+ * @offset: offset
+ * @length: length
+ *
+ * Read some stuff.
+ *
+ * Virtual: read_fn
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>foo_object_read</name>
+ <annotations>
+ <annotation>
+ <name>virtual</name>
+ <options>
+ <option>
+ <name>read_fn</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </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>
+ </docblock>
+ <messages>
+ <message>9: Warning: Test: GObject-Introspection specific GTK-Doc tag "Virtual" has been deprecated, please use annotations on the identifier instead:
+ * Virtual: read_fn
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * foo_object_read: (virtual read_fn)
+ * @object: obj
+ * @offset: offset
+ * @length: length
+ *
+ * Read some stuff.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Virtual:" tag syntax in the wrong location
+ -->
+ <input>/**
+ * foo_object_read:
+ *
+ * Virtual: read_fn
+ *
+ * Read some stuff.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>foo_object_read</name>
+ <annotations>
+ <annotation>
+ <name>virtual</name>
+ <options>
+ <option>
+ <name>read_fn</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Read some stuff.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Virtual" has been deprecated, please use annotations on the identifier instead:
+ * Virtual: read_fn
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * foo_object_read: (virtual read_fn)
+ *
+ * Read some stuff.
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/annotations.xml b/tests/scanner/annotationparser/gi/annotations.xml
new file mode 100644
index 00000000..a7ca8e74
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/annotations.xml
@@ -0,0 +1,637 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_test: (skip) (skip)
+ *
+ * Oops.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Oops.</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: multiple "skip" annotations:
+ * annotation_test: (skip) (skip)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test: (skip)
+ *
+ * Oops.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (hello) (world)
+ * @param: (invalid-annotation-option): sizeof (x) == 1
+ *
+ * Test unknown annotations without options.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ <annotations>
+ <annotation>
+ <name>hello</name>
+ </annotation>
+ <annotation>
+ <name>world</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param</name>
+ <annotations>
+ <annotation>
+ <name>invalid-annotation-option</name>
+ </annotation>
+ </annotations>
+ <description>sizeof (x) == 1</description>
+ </parameter>
+ </parameters>
+ <description>Test unknown annotations without options.</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: unknown annotation: hello</message>
+ <message>2: Warning: Test: unknown annotation: world</message>
+ <message>3: Warning: Test: unknown annotation: invalid-annotation-option</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test: (hello) (world)
+ * @param: (invalid-annotation-option): sizeof (x) == 1
+ *
+ * Test unknown annotations without options.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: some data: (foo bar)
+ *
+ * Oops.
+ */</input>
+ <parser>
+ <messages>
+ <message>2: Error: Test: identifier not found on the first line:
+ * annotation_test: some data: (foo bar)
+ ^</message>
+ </messages>
+ </parser>
+</test>
+
+<test>
+ <input>/**
+ * annotationtest some data (foo bar)
+ * @object: some data (foo bar)
+ *
+ * Oops.
+ */</input>
+ <parser>
+ <messages>
+ <message>2: Error: Test: identifier not found on the first line:
+ * annotationtest some data (foo bar)
+ ^</message>
+ </messages>
+ </parser>
+</test>
+
+<test>
+ <input>/**
+ * annotationtest
+ * @object: some data (foo bar)
+ *
+ * Oops.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotationtest</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>object</name>
+ <description>some data (foo bar)</description>
+ </parameter>
+ </parameters>
+ <description>Oops.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotationtest:
+ * @object: some data (foo bar)
+ *
+ * Oops.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: )skip)
+ *
+ * Oops.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <description>Oops.</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: unbalanced parentheses, annotations will be ignored:
+ * annotation_test: )skip)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test:
+ *
+ * Oops.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (hello)(world)
+ *
+ * Test unknown annotations without options.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ <annotations>
+ <annotation>
+ <name>hello</name>
+ </annotation>
+ <annotation>
+ <name>world</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test unknown annotations without options.</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: unknown annotation: hello</message>
+ <message>2: Warning: Test: unknown annotation: world</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test: (hello) (world)
+ *
+ * Test unknown annotations without options.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (hello x=y z ) (world something else)
+ *
+ * Test unknown annotations with options.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ <annotations>
+ <annotation>
+ <name>hello</name>
+ <options>
+ <option>
+ <name>x=y z</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>world</name>
+ <options>
+ <option>
+ <name>something else</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test unknown annotations with options.</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: unknown annotation: hello</message>
+ <message>2: Warning: Test: unknown annotation: world</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test: (hello x=y z) (world something else)
+ *
+ * Test unknown annotations with options.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test:
+ * @test: (element-type gint gint) (transfer none)
+ *
+ * Test multiple identical option names.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>test</name>
+ <annotations>
+ <annotation>
+ <name>element-type</name>
+ <options>
+ <option>
+ <name>gint</name>
+ </option>
+ <option>
+ <name>gint</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>none</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </parameter>
+ </parameters>
+ <description>Test multiple identical option names.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_test:
+ * @test: (element-type gint gint) (transfer none):
+ *
+ * Test multiple identical option names.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (type GLib.HashTable(utf8,gint8)) (attributes x=1 y=2)
+ *
+ * Test nested parentheses.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.HashTable(utf8,gint8)</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>x</name>
+ <value>1</value>
+ </option>
+ <option>
+ <name>y</name>
+ <value>2</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test nested parentheses.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_test: (type GLib.HashTable(utf8,gint8)) (attributes x=1 y=2)
+ *
+ * Test nested parentheses.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (type GLib.HashTable(utf8,GLib.HashTable(utf8,gint8))) (attributes x=1 y=2)
+ *
+ * Test nested parentheses.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.HashTable(utf8,GLib.HashTable(utf8,gint8))</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>x</name>
+ <value>1</value>
+ </option>
+ <option>
+ <name>y</name>
+ <value>2</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test nested parentheses.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_test: (type GLib.HashTable(utf8,GLib.HashTable(utf8,gint8))) (attributes x=1 y=2)
+ *
+ * Test nested parentheses.
+ */</output>
+</test>
+
+<test>
+ <input><![CDATA[/**
+ * annotation_test: (type GLib.HashTable<utf8,GLib.HashTable<utf8,gint8>>) (attributes x=1 y=2)
+ *
+ * Test deprecated angled brackets.
+ */]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.HashTable(utf8,GLib.HashTable(utf8,gint8))</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>attributes</name>
+ <options>
+ <option>
+ <name>x</name>
+ <value>1</value>
+ </option>
+ <option>
+ <name>y</name>
+ <value>2</value>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Test deprecated angled brackets.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_test: (type GLib.HashTable(utf8,GLib.HashTable(utf8,gint8))) (attributes x=1 y=2)
+ *
+ * Test deprecated angled brackets.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: ((skip)
+ *
+ * Test too many '('.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <description>Test too many '('.</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: unexpected parentheses, annotations will be ignored:
+ * annotation_test: ((skip)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test:
+ *
+ * Test too many '('.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (skip) element-type (int))
+ *
+ * Test missing '('.
+ */</input>
+ <parser>
+ <messages>
+ <message>2: Error: Test: identifier not found on the first line:
+ * annotation_test: (skip) element-type (int))
+ ^</message>
+ </messages>
+ </parser>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: ()
+ *
+ * Closing should not follow an opening parentheses.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <description>Closing should not follow an opening parentheses.</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: unexpected parentheses, annotations will be ignored:
+ * annotation_test: ()
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test:
+ *
+ * Closing should not follow an opening parentheses.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (hello()) (world(())) (foo)
+ *
+ * Closing should not follow an opening parentheses.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <description>Closing should not follow an opening parentheses.</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: unexpected parentheses, annotations will be ignored:
+ * annotation_test: (hello()) (world(())) (foo)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test:
+ *
+ * Closing should not follow an opening parentheses.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (skip)) (type uint))
+ *
+ * Test too many ')'.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <description>Test too many ')'.</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: unbalanced parentheses, annotations will be ignored:
+ * annotation_test: (skip)) (type uint))
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test:
+ *
+ * Test too many ')'.
+ */</output>
+</test>
+
+<test>
+ <input><![CDATA[/**
+ * annotation_test:
+ * @test: (type GLib.HashTableutf8,gint8)) (element-type <int>)
+ *
+ * Test missing '('.
+ */]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>test</name>
+ </parameter>
+ </parameters>
+ <description>Test missing '('.</description>
+ </docblock>
+ <messages>
+ <message><![CDATA[3: Error: Test: unbalanced parentheses, annotations will be ignored:
+ * @test: (type GLib.HashTableutf8,gint8)) (element-type <int>)
+ ^]]></message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test:
+ * @test:
+ *
+ * Test missing '('.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_test: (skip (element-type (int))
+ *
+ * Test missing ')'.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <description>Test missing ')'.</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: unbalanced parentheses, annotations will be ignored:
+ * annotation_test: (skip (element-type (int))
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test:
+ *
+ * Test missing ')'.
+ */</output>
+</test>
+
+<test>
+ <input><![CDATA[/**
+ * annotation_test:
+ * @test: (type GLib.HashTable(utf8,gint8) (element-type <int>)
+ *
+ * Test missing ')'.
+ */]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_test</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>test</name>
+ </parameter>
+ </parameters>
+ <description>Test missing ')'.</description>
+ </docblock>
+ <messages>
+ <message><![CDATA[3: Error: Test: unbalanced parentheses, annotations will be ignored:
+ * @test: (type GLib.HashTable(utf8,gint8) (element-type <int>)
+ ^]]></message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_test:
+ * @test:
+ *
+ * Test missing ')'.
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/identifier.xml b/tests/scanner/annotationparser/gi/identifier.xml
new file mode 100644
index 00000000..eb090307
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/identifier.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <!--
+ Identifier part not on the first line.
+ -->
+ <input>/**
+ * This is not a valid section identifier
+ * SECTION:test_invalid_section_identifier
+ *
+ * Above identifier is not on the first line.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test_invalid_section_identifier</name>
+ </identifier>
+ <description>Above identifier is not on the first line.</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: identifier not found on the first line:
+ * This is not a valid section identifier
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * SECTION:test_invalid_section_identifier
+ *
+ * Above identifier is not on the first line.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Identifier part not on the first line.
+ -->
+ <input>/**
+
+
+
+* SECTION:meepapp
+*/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:meepapp</name>
+ </identifier>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: identifier not found on the first line:
+
+^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * SECTION:meepapp
+ */</output>
+</test>
+
+<test>
+ <!--
+ Multiple identifier parts
+ -->
+ <input>/**
+ * SECTION:meepapp
+ * SECTION:meepapp2
+ * @short_description: the application class
+ *
+ * The application class handles ...
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * SECTION:meepapp
+ * @short_description: the application class
+ *
+ * SECTION:meepapp2
+ * The application class handles ...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Invalid identifier
+ -->
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <messages>
+ <message>2: Error: Test: identifier not found on the first line:
+ * gnm_cell_set_expr_and_value: Stores (WITHOUT COPYING) the supplied value, and
+ ^</message>
+ </messages>
+ </parser>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/identifier_section.xml b/tests/scanner/annotationparser/gi/identifier_section.xml
new file mode 100644
index 00000000..fad2b2ed
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/identifier_section.xml
@@ -0,0 +1,332 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <!--
+ Section documentation including all optional metadata.
+ -->
+ <input>/**
+ * 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 ...
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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 ...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Broken comment block with empty line between identifier and parameters parts.
+ -->
+ <input>/**
+ * 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 ...
+ */</input>
+ <parser>
+ <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>
+ <messages>
+ <message>4: Warning: Test: "@short_description" parameter unexpected at this location:
+ * @short_description: the application class
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * 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 ...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Broken comment block with description part before parameters part, without empty line.
+ -->
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ <messages>
+ <message>5: Warning: Test: "@short_description" parameter unexpected at this location:
+ * @short_description: the application class
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * 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 ...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Broken comment block with description part before parameters part, with empty line.
+ -->
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ <messages>
+ <message>6: Warning: Test: "@short_description" parameter unexpected at this location:
+ * @short_description: the application class
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * 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 ...
+ */</output>
+</test>
+
+<test>
+ <!--
+ Old style implicit returns.
+ https://bugzilla.gnome.org/show_bug.cgi?id=457077
+ -->
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/identifier_symbol.xml b/tests/scanner/annotationparser/gi/identifier_symbol.xml
new file mode 100644
index 00000000..522f1fa8
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/identifier_symbol.xml
@@ -0,0 +1,435 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * test_symbol
+ *
+ * test_symbol does something nifty.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_symbol</name>
+ </identifier>
+ <description>test_symbol does something nifty.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_symbol:
+ *
+ * test_symbol does something nifty.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_symbol_unnecessary_colon:
+ *
+ * Unnecessary colon.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_symbol_unnecessary_colon</name>
+ </identifier>
+ <description>Unnecessary colon.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_symbol_unnecessary_colon:
+ *
+ * Unnecessary colon.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_annotated_symbol: (skip)
+ *
+ * test_annotated_symbol does something nifty.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_annotated_symbol</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>test_annotated_symbol does something nifty.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_annotated_symbol: (skip)
+ *
+ * test_annotated_symbol does something nifty.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_symbol_missing_colon (skip)
+ *
+ * Missing colon will result in a warning.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_symbol_missing_colon</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Missing colon will result in a warning.</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: missing ":" at column 30:
+ * test_symbol_missing_colon (skip)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_symbol_missing_colon: (skip)
+ *
+ * Missing colon will result in a warning.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_malformed_symbol: (skip):
+ *
+ * Malformed symbol identifier.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_malformed_symbol</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Malformed symbol identifier.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_malformed_symbol: (skip)
+ *
+ * Malformed symbol identifier.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget:test_property
+ *
+ * Some property.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget:test_property</name>
+ </identifier>
+ <description>Some property.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkWidget:test_property:
+ *
+ * Some property.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget:test_property_unnecessary_colon:
+ *
+ * Unnecessary colon.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget:test_property_unnecessary_colon</name>
+ </identifier>
+ <description>Unnecessary colon.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkWidget:test_property_unnecessary_colon:
+ *
+ * Unnecessary colon.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget:test_annotated_property: (skip)
+ *
+ * Some annotated property.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget:test_annotated_property</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Some annotated property.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkWidget:test_annotated_property: (skip)
+ *
+ * Some annotated property.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget:test_property_missing_colon (skip)
+ *
+ * Missing colon will result in a warning.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget:test_property_missing_colon</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Missing colon will result in a warning.</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: missing ":" at column 42:
+ * GtkWidget:test_property_missing_colon (skip)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * GtkWidget:test_property_missing_colon: (skip)
+ *
+ * Missing colon will result in a warning.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget:test_malformed_property: (skip):
+ *
+ * Malformed property identifier.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget:test_malformed_property</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Malformed property identifier.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkWidget:test_malformed_property: (skip)
+ *
+ * Malformed property identifier.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget::test_signal
+ *
+ * Some signal.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget::test_signal</name>
+ </identifier>
+ <description>Some signal.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkWidget::test_signal:
+ *
+ * Some signal.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget::test_signal_unnecessary_colon:
+ *
+ * Unnecessary colon.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget::test_signal_unnecessary_colon</name>
+ </identifier>
+ <description>Unnecessary colon.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkWidget::test_signal_unnecessary_colon:
+ *
+ * Unnecessary colon.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget::test_annotated_signal: (skip)
+ *
+ * Some annotated signal.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget::test_annotated_signal</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Some annotated signal.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkWidget::test_annotated_signal: (skip)
+ *
+ * Some annotated signal.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget::test_signal_missing_colon (skip)
+ *
+ * Missing colon will result in a warning.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget::test_signal_missing_colon</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Missing colon will result in a warning.</description>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: missing ":" at column 41:
+ * GtkWidget::test_signal_missing_colon (skip)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * GtkWidget::test_signal_missing_colon: (skip)
+ *
+ * Missing colon will result in a warning.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkWidget::test_malformed_signal: (skip):
+ *
+ * Malformed signal identifier.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkWidget::test_malformed_signal</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>Malformed signal identifier.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkWidget::test_malformed_signal: (skip)
+ *
+ * Malformed signal identifier.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_multiline_annotations_on_identifier: (skip)
+ * (foreign)
+ * @param1: (allow-none) (transfer full): first parameter
+ *
+ * Annotations spanning multiple lines are not valid
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiline_annotations_on_identifier</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param1</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>full</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>first parameter</description>
+ </parameter>
+ </parameters>
+ <description>(foreign)
+Annotations spanning multiple lines are not valid</description>
+ </docblock>
+ <messages>
+ <message>3: Error: Test: ignoring invalid multiline annotation continuation:
+ * (foreign)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiline_annotations_on_identifier: (skip)
+ * @param1: (allow-none) (transfer full): first parameter
+ *
+ * (foreign)
+ * Annotations spanning multiple lines are not valid
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/parameter.xml b/tests/scanner/annotationparser/gi/parameter.xml
new file mode 100644
index 00000000..43f97b3f
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/parameter.xml
@@ -0,0 +1,375 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * test_parameter_missing_colon:
+ * @param1: (allow-none) first parameter
+ *
+ * Forgotten colon above will result in a warning.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_parameter_missing_colon</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param1</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>first parameter</description>
+ </parameter>
+ </parameters>
+ <description>Forgotten colon above will result in a warning.</description>
+ </docblock>
+ <messages>
+ <message>3: Warning: Test: missing ":" at column 25:
+ * @param1: (allow-none) first parameter
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_parameter_missing_colon:
+ * @param1: (allow-none): first parameter
+ *
+ * Forgotten colon above will result in a warning.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_unexpected_parameter:
+ *
+ * Parameters should go before the comment block description.
+ *
+ * @param1: first parameter
+ * Returns: something
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_unexpected_parameter</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param1</name>
+ <description>first parameter</description>
+ </parameter>
+ </parameters>
+ <description>Parameters should go before the comment block description.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>something</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: "@param1" parameter unexpected at this location:
+ * @param1: first parameter
+ ^</message>
+ <message>7: Warning: Test: "Returns:" tag unexpected at this location:
+ * Returns: something
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_unexpected_parameter:
+ * @param1: first parameter
+ *
+ * Parameters should go before the comment block description.
+ *
+ * Returns: something
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_multiple_parameters:
+ * @param1: first parameter
+ * @param1: first parameter again
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiple_parameters</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param1</name>
+ <description>first parameter again</description>
+ </parameter>
+ </parameters>
+ </docblock>
+ <messages>
+ <message>4: Error: Test: multiple "@param1" parameters for identifier "test_multiple_parameters":
+ * @param1: first parameter again
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiple_parameters:
+ * @param1: first parameter again
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_multiline_annotations_on_parameter:
+ * @param1: (allow-none)
+ * (transfer full): first parameter
+ *
+ * Annotations spanning multiple lines are not valid
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiline_annotations_on_parameter</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param1</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>
+(transfer full): first parameter</description>
+ </parameter>
+ </parameters>
+ <description>Annotations spanning multiple lines are not valid</description>
+ </docblock>
+ <messages>
+ <message>4: Error: Test: ignoring invalid multiline annotation continuation:
+ * (transfer full): first parameter
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiline_annotations_on_parameter:
+ * @param1: (allow-none):
+ * (transfer full): first parameter
+ *
+ * Annotations spanning multiple lines are not valid
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_multiline_annotations_on_parameter:
+ * @param1: (allow-none): first parameter having a second line which looks
+ * (like an annotation), but isn't. This should not result in a warning.
+ *
+ * Annotations spanning multiple lines are not valid
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiline_annotations_on_parameter</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param1</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>first parameter having a second line which looks
+(like an annotation), but isn't. This should not result in a warning.</description>
+ </parameter>
+ </parameters>
+ <description>Annotations spanning multiple lines are not valid</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_multiline_annotations_on_parameter:
+ * @param1: (allow-none): first parameter having a second line which looks
+ * (like an annotation), but isn't. This should not result in a warning.
+ *
+ * Annotations spanning multiple lines are not valid
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * anjuta_async_notify_get_error:
+ *
+ * @self: An #AnjutaAsyncNotify object
+ * @error: Return location for the error set by the called interface to which
+ * this object was passed. If no error is set, @error is set to NULL.
+ *
+ * Gets the error set on @self.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>anjuta_async_notify_get_error</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>self</name>
+ <description>An #AnjutaAsyncNotify object</description>
+ </parameter>
+ <parameter>
+ <name>error</name>
+ <description>Return location for the error set by the called interface to which
+ this object was passed. If no error is set, @error is set to NULL.</description>
+ </parameter>
+ </parameters>
+ <description>Gets the error set on @self.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: "@self" parameter unexpected at this location:
+ * @self: An #AnjutaAsyncNotify object
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * anjuta_async_notify_get_error:
+ * @self: An #AnjutaAsyncNotify object
+ * @error: Return location for the error set by the called interface to which
+ * this object was passed. If no error is set, @error is set to NULL.
+ *
+ * Gets the error set on @self.
+ */</output>
+</test>
+
+<test>
+ <input> /**
+ * GtkPrintOperation::done
+ * @operation: the #GtkPrintOperation on which the signal was emitted
+ * @result: the result of the print operation
+ *
+ * Emitted when the print operation run has finished doing
+ * everything required for printing.
+ *
+ * @result gives you information about what happened during the run.
+ * If @result is %GTK_PRINT_OPERATION_RESULT_ERROR then you can call
+ * gtk_print_operation_get_error() for more information.
+ *
+ * If you enabled print status tracking then
+ * gtk_print_operation_is_finished() may still return %FALSE
+ * after #GtkPrintOperation::done was emitted.
+ *
+ * Since: 2.10
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkPrintOperation::done</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>operation</name>
+ <description>the #GtkPrintOperation on which the signal was emitted</description>
+ </parameter>
+ <parameter>
+ <name>result</name>
+ <description>the result of the print operation</description>
+ </parameter>
+ </parameters>
+ <description>Emitted when the print operation run has finished doing
+everything required for printing.
+
+@result gives you information about what happened during the run.
+If @result is %GTK_PRINT_OPERATION_RESULT_ERROR then you can call
+gtk_print_operation_get_error() for more information.
+
+If you enabled print status tracking then
+gtk_print_operation_is_finished() may still return %FALSE
+after #GtkPrintOperation::done was emitted.</description>
+ <tags>
+ <tag>
+ <name>since</name>
+ <value>2.10</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output> /**
+ * GtkPrintOperation::done:
+ * @operation: the #GtkPrintOperation on which the signal was emitted
+ * @result: the result of the print operation
+ *
+ * Emitted when the print operation run has finished doing
+ * everything required for printing.
+ *
+ * @result gives you information about what happened during the run.
+ * If @result is %GTK_PRINT_OPERATION_RESULT_ERROR then you can call
+ * gtk_print_operation_get_error() for more information.
+ *
+ * If you enabled print status tracking then
+ * gtk_print_operation_is_finished() may still return %FALSE
+ * after #GtkPrintOperation::done was emitted.
+ *
+ * Since: 2.10
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * TrackerDirectoryFlags:
+ * @TRACKER_DIRECTORY_FLAG_NONE: No flags.
+ * @TRACKER_DIRECTORY_FLAG_RECURSE: Should recurse in the directory.
+ * @TRACKER_DIRECTORY_FLAG_CHECK_MTIME: Should check mtimes of items in the directory.
+ * @TRACKER_DIRECTORY_FLAG_MONITOR: Should setup monitors in the items found in the directory.
+ * @TRACKER_DIRECTORY_FLAG_IGNORE: Should ignore the directory contents.
+ * @TRACKER_DIRECTORY_FLAG_PRESERVE: Should preserve items in the directory even if the directory gets removed.
+ *
+ * Flags used when adding a new directory to be indexed in the #TrackerIndexingTree.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>TrackerDirectoryFlags</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>TRACKER_DIRECTORY_FLAG_NONE</name>
+ <description>No flags.</description>
+ </parameter>
+ <parameter>
+ <name>TRACKER_DIRECTORY_FLAG_RECURSE</name>
+ <description>Should recurse in the directory.</description>
+ </parameter>
+ <parameter>
+ <name>TRACKER_DIRECTORY_FLAG_CHECK_MTIME</name>
+ <description>Should check mtimes of items in the directory.</description>
+ </parameter>
+ <parameter>
+ <name>TRACKER_DIRECTORY_FLAG_MONITOR</name>
+ <description>Should setup monitors in the items found in the directory.</description>
+ </parameter>
+ <parameter>
+ <name>TRACKER_DIRECTORY_FLAG_IGNORE</name>
+ <description>Should ignore the directory contents.</description>
+ </parameter>
+ <parameter>
+ <name>TRACKER_DIRECTORY_FLAG_PRESERVE</name>
+ <description>Should preserve items in the directory even if the directory gets removed.</description>
+ </parameter>
+ </parameters>
+ <description>Flags used when adding a new directory to be indexed in the #TrackerIndexingTree.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * TrackerDirectoryFlags:
+ * @TRACKER_DIRECTORY_FLAG_NONE: No flags.
+ * @TRACKER_DIRECTORY_FLAG_RECURSE: Should recurse in the directory.
+ * @TRACKER_DIRECTORY_FLAG_CHECK_MTIME: Should check mtimes of items in the directory.
+ * @TRACKER_DIRECTORY_FLAG_MONITOR: Should setup monitors in the items found in the directory.
+ * @TRACKER_DIRECTORY_FLAG_IGNORE: Should ignore the directory contents.
+ * @TRACKER_DIRECTORY_FLAG_PRESERVE: Should preserve items in the directory even if the directory gets removed.
+ *
+ * Flags used when adding a new directory to be indexed in the #TrackerIndexingTree.
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/parameter_varargs.xml b/tests/scanner/annotationparser/gi/parameter_varargs.xml
new file mode 100644
index 00000000..b22906de
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/parameter_varargs.xml
@@ -0,0 +1,298 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * function_name:
+ * @par1: description of parameter 1. These can extend over more than
+ * one line.
+ * @par2: description of parameter 2
+ * @...: a %NULL-terminated list of bars
+ *
+ * The function description goes here. You can use @par1 to refer to parameters
+ * so that they are highlighted in the output. You can also use %constant
+ * for constants, function_name2() for functions and #GtkWidget for links to
+ * other declarations (which may be documented elsewhere).
+ *
+ * Returns: an integer.
+ *
+ * Since: 2.2
+ * Deprecated: 2.18: Use other_function() instead.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>function_name</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>par1</name>
+ <description>description of parameter 1. These can extend over more than
+one line.</description>
+ </parameter>
+ <parameter>
+ <name>par2</name>
+ <description>description of parameter 2</description>
+ </parameter>
+ <parameter>
+ <name>...</name>
+ <description>a %NULL-terminated list of bars</description>
+ </parameter>
+ </parameters>
+ <description>The function description goes here. You can use @par1 to refer to parameters
+so that they are highlighted in the output. You can also use %constant
+for constants, function_name2() for functions and #GtkWidget for links to
+other declarations (which may be documented elsewhere).</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>an integer.</description>
+ </tag>
+ <tag>
+ <name>since</name>
+ <value>2.2</value>
+ </tag>
+ <tag>
+ <name>deprecated</name>
+ <value>2.18</value>
+ <description>Use other_function() instead.</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * function_name:
+ * @par1: description of parameter 1. These can extend over more than
+ * one line.
+ * @par2: description of parameter 2
+ * @...: a %NULL-terminated list of bars
+ *
+ * The function description goes here. You can use @par1 to refer to parameters
+ * so that they are highlighted in the output. You can also use %constant
+ * for constants, function_name2() for functions and #GtkWidget for links to
+ * other declarations (which may be documented elsewhere).
+ *
+ * Returns: an integer.
+ * Since: 2.2
+ * Deprecated: 2.18: Use other_function() instead.
+ */</output>
+</test>
+
+<test>
+ <!--
+ gtkdoc-mkdb has deprecated named __VA_ARGS__ parameter notation.
+ But there is a gcc CPP extension that, for macros, makes it possible to give a more descriptive
+ name for the variable argument than simply __VA_ARGS__. See
+ http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html for more information.
+ Encountered in the wild in for example:
+ http://git.kernel.org/?p=bluetooth/bluez.git;a=blob;f=src/log.h;h=3d34fa3774e5400c030d29a264824fe0584de2a8;hb=HEAD#l44
+ -->
+ <input>/**
+ * DBG:
+ * @fmt: format string
+ * @arg...: list of arguments
+ *
+ * Simple macro around btd_debug() which also include the function
+ * name it is called in.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>DBG</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>fmt</name>
+ <description>format string</description>
+ </parameter>
+ <parameter>
+ <name>...</name>
+ <description>list of arguments</description>
+ </parameter>
+ </parameters>
+ <description>Simple macro around btd_debug() which also include the function
+name it is called in.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: "@arg..." parameter is deprecated, please use "@..." instead:
+ * @arg...: list of arguments
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * DBG:
+ * @fmt: format string
+ * @...: list of arguments
+ *
+ * Simple macro around btd_debug() which also include the function
+ * name it is called in.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated @Vargargs parameter
+ -->
+ <input>/**
+ * function_name:
+ * @par1: description of parameter 1. These can extend over more than
+ * one line.
+ * @par2: description of parameter 2
+ * @Varargs: a %NULL-terminated list of bars
+ *
+ * The function description goes here. You can use @par1 to refer to parameters
+ * so that they are highlighted in the output. You can also use %constant
+ * for constants, function_name2() for functions and #GtkWidget for links to
+ * other declarations (which may be documented elsewhere).
+ *
+ * Returns: an integer.
+ *
+ * Since: 2.2
+ * Deprecated: 2.18: Use other_function() instead.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>function_name</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>par1</name>
+ <description>description of parameter 1. These can extend over more than
+one line.</description>
+ </parameter>
+ <parameter>
+ <name>par2</name>
+ <description>description of parameter 2</description>
+ </parameter>
+ <parameter>
+ <name>...</name>
+ <description>a %NULL-terminated list of bars</description>
+ </parameter>
+ </parameters>
+ <description>The function description goes here. You can use @par1 to refer to parameters
+so that they are highlighted in the output. You can also use %constant
+for constants, function_name2() for functions and #GtkWidget for links to
+other declarations (which may be documented elsewhere).</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>an integer.</description>
+ </tag>
+ <tag>
+ <name>since</name>
+ <value>2.2</value>
+ </tag>
+ <tag>
+ <name>deprecated</name>
+ <value>2.18</value>
+ <description>Use other_function() instead.</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: "@Varargs" parameter is deprecated, please use "@..." instead:
+ * @Varargs: a %NULL-terminated list of bars
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * function_name:
+ * @par1: description of parameter 1. These can extend over more than
+ * one line.
+ * @par2: description of parameter 2
+ * @...: a %NULL-terminated list of bars
+ *
+ * The function description goes here. You can use @par1 to refer to parameters
+ * so that they are highlighted in the output. You can also use %constant
+ * for constants, function_name2() for functions and #GtkWidget for links to
+ * other declarations (which may be documented elsewhere).
+ *
+ * Returns: an integer.
+ * Since: 2.2
+ * Deprecated: 2.18: Use other_function() instead.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Normal @vargargs parameter (usually seen for va_list)
+ -->
+ <input>/**
+ * function_name:
+ * @par1: description of parameter 1. These can extend over more than
+ * one line.
+ * @par2: description of parameter 2
+ * @varargs: a %NULL-terminated list of bars
+ *
+ * The function description goes here. You can use @par1 to refer to parameters
+ * so that they are highlighted in the output. You can also use %constant
+ * for constants, function_name2() for functions and #GtkWidget for links to
+ * other declarations (which may be documented elsewhere).
+ *
+ * Returns: an integer.
+ *
+ * Since: 2.2
+ * Deprecated: 2.18: Use other_function() instead.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>function_name</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>par1</name>
+ <description>description of parameter 1. These can extend over more than
+one line.</description>
+ </parameter>
+ <parameter>
+ <name>par2</name>
+ <description>description of parameter 2</description>
+ </parameter>
+ <parameter>
+ <name>varargs</name>
+ <description>a %NULL-terminated list of bars</description>
+ </parameter>
+ </parameters>
+ <description>The function description goes here. You can use @par1 to refer to parameters
+so that they are highlighted in the output. You can also use %constant
+for constants, function_name2() for functions and #GtkWidget for links to
+other declarations (which may be documented elsewhere).</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>an integer.</description>
+ </tag>
+ <tag>
+ <name>since</name>
+ <value>2.2</value>
+ </tag>
+ <tag>
+ <name>deprecated</name>
+ <value>2.18</value>
+ <description>Use other_function() instead.</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * function_name:
+ * @par1: description of parameter 1. These can extend over more than
+ * one line.
+ * @par2: description of parameter 2
+ * @varargs: a %NULL-terminated list of bars
+ *
+ * The function description goes here. You can use @par1 to refer to parameters
+ * so that they are highlighted in the output. You can also use %constant
+ * for constants, function_name2() for functions and #GtkWidget for links to
+ * other declarations (which may be documented elsewhere).
+ *
+ * Returns: an integer.
+ * Since: 2.2
+ * Deprecated: 2.18: Use other_function() instead.
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/syntax.xml b/tests/scanner/annotationparser/gi/syntax.xml
new file mode 100644
index 00000000..d1841a35
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax.xml
@@ -0,0 +1,467 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <!--
+ Not GTK-Doc
+ -->
+ <input>//Test</input>
+</test>
+
+<test>
+ <!--
+ Not GTK-Doc
+ -->
+ <input>// Test</input>
+</test>
+
+<test>
+ <!--
+ Not GTK-Doc
+ -->
+ <input>/**
+//</input>
+</test>
+
+<test>
+ <!--
+ Not GTK-Doc
+ -->
+ <input>/*Test*/</input>
+</test>
+
+<test>
+ <!--
+ Not GTK-Doc
+ -->
+ <input>/* Test */</input>
+</test>
+
+<test>
+ <!--
+ Not GTK-Doc
+ -->
+ <input>/* Test
+something */</input>
+</test>
+
+<test>
+ <!--
+ Not GTK-Doc
+ -->
+ <input>/*
+Test
+something */</input>
+</test>
+
+<test>
+ <!--
+ Not GTK-Doc
+ -->
+ <input>/**
+*/</input>
+</test>
+
+<test>
+ <input>/** Test **/</input>
+ <parser>
+ <messages>
+ <message>1: Error: Test: Skipping invalid GTK-Doc comment block:
+/** Test **/
+^</message>
+ </messages>
+ </parser>
+</test>
+
+<test>
+ <input>/**Test
+*/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>Test</name>
+ </identifier>
+ </docblock>
+ <messages>
+ <message>1: Warning: Test: GTK-Doc comment block start token "/**" should not be followed by comment text:
+/**Test
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * Test:
+ */</output>
+</test>
+
+<test>
+ <input>/**
+Test */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>Test</name>
+ </identifier>
+ </docblock>
+ <messages>
+ <message>2: Warning: Test: GTK-Doc comment block end token "*/" should not be preceded by comment text:
+Test */
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * Test:
+ */</output>
+</test>
+
+<test>
+ <input>/** Test
+something */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>Test</name>
+ </identifier>
+ <description>something</description>
+ </docblock>
+ <messages>
+ <message>1: Warning: Test: GTK-Doc comment block start token "/**" should not be followed by comment text:
+/** Test
+ ^</message>
+ <message>2: Warning: Test: GTK-Doc comment block end token "*/" should not be preceded by comment text:
+something */
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * Test:
+ *
+ * something
+ */</output>
+</test>
+
+<test>
+ <input>/**
+Test
+something */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>Test</name>
+ </identifier>
+ <description>something</description>
+ </docblock>
+ <messages>
+ <message>3: Warning: Test: GTK-Doc comment block end token "*/" should not be preceded by comment text:
+something */
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * Test:
+ *
+ * something
+ */</output>
+</test>
+
+<test>
+ <input>/**
+Test
+something **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>Test</name>
+ </identifier>
+ <description>something</description>
+ </docblock>
+ <messages>
+ <message>3: Warning: Test: GTK-Doc comment block end token "*/" should not be preceded by comment text:
+something **/
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * Test:
+ *
+ * something
+ */</output>
+</test>
+
+<test>
+ <input>code goes here /** Test
+something */ code goes here</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>Test</name>
+ </identifier>
+ <description>something</description>
+ </docblock>
+ <messages>
+ <message>1: Warning: Test: GTK-Doc comment block start token "/**" should not be preceded by code:
+code goes here /** Test
+ ^</message>
+ <message>1: Warning: Test: GTK-Doc comment block start token "/**" should not be followed by comment text:
+code goes here /** Test
+ ^</message>
+ <message>2: Warning: Test: GTK-Doc comment block end token "*/" should not be followed by code:
+something */ code goes here
+ ^</message>
+ <message>2: Warning: Test: GTK-Doc comment block end token "*/" should not be preceded by comment text:
+something */ code goes here
+ ^</message>
+ </messages>
+ </parser>
+ <output><![CDATA[code goes here
+/**
+ * Test:
+ *
+ * something
+ */
+ code goes here]]></output>
+</test>
+
+<test>
+ <!--
+ Malformed comment block, signal the start of the comment block description followed
+ by a parameter instead.
+ -->
+ <input>/**
+ * SECTION:meepapp
+ *
+ * @short_description: the application class
+ *
+ * The application class handles ...
+ */</input>
+ <parser>
+ <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>
+ <messages>
+ <message>4: Warning: Test: "@short_description" parameter unexpected at this location:
+ * @short_description: the application class
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * SECTION:meepapp
+ * @short_description: the application class
+ *
+ * The application class handles ...
+ */</output>
+</test>
+
+<test>
+ <!--
+ identifier not on the first line.
+ -->
+ <input>/**
+
+ *
+
+ * regress_test_invalid_comment:
+ * @foo: a param
+
+ * comment having lines without ' * '
+ * https://bugzilla.gnome.org/show_bug.cgi?id=673806
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>regress_test_invalid_comment</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>foo</name>
+ <description>a param</description>
+ </parameter>
+ </parameters>
+ <description>comment having lines without ' * '
+https://bugzilla.gnome.org/show_bug.cgi?id=673806</description>
+ </docblock>
+ <messages>
+ <message>2: Error: Test: identifier not found on the first line:
+
+^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * regress_test_invalid_comment:
+ * @foo: a param
+ *
+ * comment having lines without ' * '
+ * https://bugzilla.gnome.org/show_bug.cgi?id=673806
+ */</output>
+</test>
+
+<test>
+ <!-- Confusing but well formed mixing of lines starting with and without * -->
+ <input>/**
+ * atk_hyperlink_is_inline:
+ * @link_: an #AtkHyperlink
+ *
+ * Indicates whether the link currently displays some or all of its
+ * content inline. Ordinary HTML links will usually return
+ * %FALSE, but an inline &lt;src&gt; HTML element will return
+ * %TRUE.
+ a *
+ * Returns: whether or not this link displays its content inline.
+ *
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>atk_hyperlink_is_inline</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>link_</name>
+ <description>an #AtkHyperlink</description>
+ </parameter>
+ </parameters>
+ <description>Indicates whether the link currently displays some or all of its
+ content inline. Ordinary HTML links will usually return
+ %FALSE, but an inline &lt;src&gt; HTML element will return
+ %TRUE.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>whether or not this link displays its content inline.</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>9: Error: Test: invalid comment text:
+ a *
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * atk_hyperlink_is_inline:
+ * @link_: an #AtkHyperlink
+ *
+ * Indicates whether the link currently displays some or all of its
+ * content inline. Ordinary HTML links will usually return
+ * %FALSE, but an inline &lt;src&gt; HTML element will return
+ * %TRUE.
+ *
+ * Returns: whether or not this link displays its content inline.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * gtk_tooltip_set_custom:
+ *
+ * Replaces the widget packed into the tooltip with
+ * @custom_widget. @custom_widget does not get destroyed when the tooltip goes
+ * away.
+ * By default a box with a #GtkImage and #GtkLabel is embedded in
+ * the tooltip, which can be configured using gtk_tooltip_set_markup()
+ * and gtk_tooltip_set_icon().
+
+ *
+ * Since: 2.12
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>gtk_tooltip_set_custom</name>
+ </identifier>
+ <description>Replaces the widget packed into the tooltip with
+@custom_widget. @custom_widget does not get destroyed when the tooltip goes
+away.
+By default a box with a #GtkImage and #GtkLabel is embedded in
+the tooltip, which can be configured using gtk_tooltip_set_markup()
+and gtk_tooltip_set_icon().</description>
+ <tags>
+ <tag>
+ <name>since</name>
+ <value>2.12</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * gtk_tooltip_set_custom:
+ *
+ * Replaces the widget packed into the tooltip with
+ * @custom_widget. @custom_widget does not get destroyed when the tooltip goes
+ * away.
+ * By default a box with a #GtkImage and #GtkLabel is embedded in
+ * the tooltip, which can be configured using gtk_tooltip_set_markup()
+ * and gtk_tooltip_set_icon().
+ *
+ * Since: 2.12
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * clutter_text_coords_to_position:
+ * @self: a #ClutterText
+ * Return: the position of the character
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>clutter_text_coords_to_position</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>self</name>
+ <description>a #ClutterText</description>
+ </parameter>
+ </parameters>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>the position of the character</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * clutter_text_coords_to_position:
+ * @self: a #ClutterText
+ *
+ * Returns: the position of the character
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * clutter_text_coords_to_position:
+ * Return: the position of the character
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>clutter_text_coords_to_position</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>the position of the character</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * clutter_text_coords_to_position:
+ *
+ * Returns: the position of the character
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/syntax_indentation.xml b/tests/scanner/annotationparser/gi/syntax_indentation.xml
new file mode 100644
index 00000000..1b8c6324
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_indentation.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input> /**
+ * SECTION:test
+ *
+ * Describe section here
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test</name>
+ </identifier>
+ <description>Describe section here</description>
+ </docblock>
+ </parser>
+ <output> /**
+ * SECTION:test
+ *
+ * Describe section here
+ */</output>
+</test>
+
+<test>
+ <input> /**
+ * SECTION:test
+ *
+ * Describe section here
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test</name>
+ </identifier>
+ <description>Describe section here</description>
+ </docblock>
+ </parser>
+ <output> /**
+ * SECTION:test
+ *
+ * Describe section here
+ */</output>
+</test>
+
+<test>
+ <input> /**
+ * SECTION:test
+ *
+ * Describe section here
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test</name>
+ </identifier>
+ <description>Describe section here</description>
+ </docblock>
+ </parser>
+ <output> /**
+ * SECTION:test
+ *
+ * Describe section here
+ */</output>
+</test>
+
+<test>
+ <input> /**
+ * SECTION:test
+ *
+ * Describe section here
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test</name>
+ </identifier>
+ <description>Describe section here</description>
+ </docblock>
+ </parser>
+ <output indent="false">/**
+ * SECTION:test
+ *
+ * Describe section here
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/syntax_multiline_annotations.xml b/tests/scanner/annotationparser/gi/syntax_multiline_annotations.xml
new file mode 100644
index 00000000..4aa92e42
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_multiline_annotations.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * regress_forced_method: (skip)
+ * (method)
+ * @obj: A #RegressTestObj
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>regress_forced_method</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>obj</name>
+ <description>A #RegressTestObj</description>
+ </parameter>
+ </parameters>
+ <description>(method)</description>
+ </docblock>
+ <messages>
+ <message>3: Error: Test: ignoring invalid multiline annotation continuation:
+ * (method)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * regress_forced_method: (skip)
+ * @obj: A #RegressTestObj
+ *
+ * (method)
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * regress_forced_method: (skip)
+ * (method)
+ * @obj: A #RegressTestObj
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>regress_forced_method</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>obj</name>
+ <description>A #RegressTestObj</description>
+ </parameter>
+ </parameters>
+ <description>(method)</description>
+ </docblock>
+ <messages>
+ <message>3: Error: Test: ignoring invalid multiline annotation continuation:
+ * (method)
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * regress_forced_method: (skip)
+ * @obj: A #RegressTestObj
+ *
+ * (method)
+ */</output>
+</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..11b5a674
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_nested_tags.xml
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<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.
+ -->
+ <input>/**
+ * 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
+ **/</input>
+ <parser>
+ <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>
+ <value>2.28</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input><![CDATA[/**
+ * GSourceFuncs:
+ * @prepare: Called before all the file descriptors are polled. If the
+ * source can determine that it is ready here (without waiting for the
+ * results of the poll() call) it should return %TRUE. It can also return
+ * a @timeout_ value which should be the maximum timeout (in milliseconds)
+ * which should be passed to the poll() call. The actual timeout used will
+ * be -1 if all sources returned -1, or it will be the minimum of all the
+ * @timeout_ values returned which were >= 0. Since 2.36 this may
+ * be %NULL, in which case the effect is as if the function always
+ * returns %FALSE with a timeout of -1. If @prepare returns a
+ * timeout and the source also has a 'ready time' set then the
+ * nearer of the two will be used.
+ * @check: Called after all the file descriptors are polled. The source
+ * should return %TRUE if it is ready to be dispatched. Note that some
+ * time may have passed since the previous prepare function was called,
+ * so the source should be checked again here. Since 2.36 this may
+ * be %NULL, in which case the effect is as if the function always
+ * returns %FALSE.
+ * @dispatch: Called to dispatch the event source, after it has returned
+ * %TRUE in either its @prepare or its @check function. The @dispatch
+ * function is passed in a callback function and data. The callback
+ * function may be %NULL if the source was never connected to a callback
+ * using g_source_set_callback(). The @dispatch function should call the
+ * callback function with @user_data and whatever additional parameters
+ * are needed for this type of event source.
+ * @finalize: Called when the source is finalized.
+ *
+ * The <structname>GSourceFuncs</structname> struct contains a table of
+ * functions used to handle event sources in a generic manner.
+ *
+ * For idle sources, the prepare and check functions always return %TRUE
+ * to indicate that the source is always ready to be processed. The prepare
+ * function also returns a timeout value of 0 to ensure that the poll() call
+ * doesn't block (since that would be time wasted which could have been spent
+ * running the idle function).
+ *
+ * For timeout sources, the prepare and check functions both return %TRUE
+ * if the timeout interval has expired. The prepare function also returns
+ * a timeout value to ensure that the poll() call doesn't block too long
+ * and miss the next timeout.
+ *
+ * For file descriptor sources, the prepare function typically returns %FALSE,
+ * since it must wait until poll() has been called before it knows whether
+ * any events need to be processed. It sets the returned timeout to -1 to
+ * indicate that it doesn't mind how long the poll() call blocks. In the
+ * check function, it tests the results of the poll() call to see if the
+ * required condition has been met, and returns %TRUE if so.
+ */]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GSourceFuncs</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>prepare</name>
+ <description>Called before all the file descriptors are polled. If the
+ source can determine that it is ready here (without waiting for the
+ results of the poll() call) it should return %TRUE. It can also return
+ a @timeout_ value which should be the maximum timeout (in milliseconds)
+ which should be passed to the poll() call. The actual timeout used will
+ be -1 if all sources returned -1, or it will be the minimum of all the
+ @timeout_ values returned which were >= 0. Since 2.36 this may
+ be %NULL, in which case the effect is as if the function always
+ returns %FALSE with a timeout of -1. If @prepare returns a
+ timeout and the source also has a 'ready time' set then the
+ nearer of the two will be used.</description>
+ </parameter>
+ <parameter>
+ <name>check</name>
+ <description>Called after all the file descriptors are polled. The source
+ should return %TRUE if it is ready to be dispatched. Note that some
+ time may have passed since the previous prepare function was called,
+ so the source should be checked again here. Since 2.36 this may
+ be %NULL, in which case the effect is as if the function always
+ returns %FALSE.</description>
+ </parameter>
+ <parameter>
+ <name>dispatch</name>
+ <description>Called to dispatch the event source, after it has returned
+ %TRUE in either its @prepare or its @check function. The @dispatch
+ function is passed in a callback function and data. The callback
+ function may be %NULL if the source was never connected to a callback
+ using g_source_set_callback(). The @dispatch function should call the
+ callback function with @user_data and whatever additional parameters
+ are needed for this type of event source.</description>
+ </parameter>
+ <parameter>
+ <name>finalize</name>
+ <description>Called when the source is finalized.</description>
+ </parameter>
+ </parameters>
+ <description><![CDATA[The <structname>GSourceFuncs</structname> struct contains a table of
+functions used to handle event sources in a generic manner.
+
+For idle sources, the prepare and check functions always return %TRUE
+to indicate that the source is always ready to be processed. The prepare
+function also returns a timeout value of 0 to ensure that the poll() call
+doesn't block (since that would be time wasted which could have been spent
+running the idle function).
+
+For timeout sources, the prepare and check functions both return %TRUE
+if the timeout interval has expired. The prepare function also returns
+a timeout value to ensure that the poll() call doesn't block too long
+and miss the next timeout.
+
+For file descriptor sources, the prepare function typically returns %FALSE,
+since it must wait until poll() has been called before it knows whether
+any events need to be processed. It sets the returned timeout to -1 to
+indicate that it doesn't mind how long the poll() call blocks. In the
+check function, it tests the results of the poll() call to see if the
+required condition has been met, and returns %TRUE if so.]]></description>
+ </docblock>
+ </parser>
+ <output><![CDATA[/**
+ * GSourceFuncs:
+ * @prepare: Called before all the file descriptors are polled. If the
+ * source can determine that it is ready here (without waiting for the
+ * results of the poll() call) it should return %TRUE. It can also return
+ * a @timeout_ value which should be the maximum timeout (in milliseconds)
+ * which should be passed to the poll() call. The actual timeout used will
+ * be -1 if all sources returned -1, or it will be the minimum of all the
+ * @timeout_ values returned which were >= 0. Since 2.36 this may
+ * be %NULL, in which case the effect is as if the function always
+ * returns %FALSE with a timeout of -1. If @prepare returns a
+ * timeout and the source also has a 'ready time' set then the
+ * nearer of the two will be used.
+ * @check: Called after all the file descriptors are polled. The source
+ * should return %TRUE if it is ready to be dispatched. Note that some
+ * time may have passed since the previous prepare function was called,
+ * so the source should be checked again here. Since 2.36 this may
+ * be %NULL, in which case the effect is as if the function always
+ * returns %FALSE.
+ * @dispatch: Called to dispatch the event source, after it has returned
+ * %TRUE in either its @prepare or its @check function. The @dispatch
+ * function is passed in a callback function and data. The callback
+ * function may be %NULL if the source was never connected to a callback
+ * using g_source_set_callback(). The @dispatch function should call the
+ * callback function with @user_data and whatever additional parameters
+ * are needed for this type of event source.
+ * @finalize: Called when the source is finalized.
+ *
+ * The <structname>GSourceFuncs</structname> struct contains a table of
+ * functions used to handle event sources in a generic manner.
+ *
+ * For idle sources, the prepare and check functions always return %TRUE
+ * to indicate that the source is always ready to be processed. The prepare
+ * function also returns a timeout value of 0 to ensure that the poll() call
+ * doesn't block (since that would be time wasted which could have been spent
+ * running the idle function).
+ *
+ * For timeout sources, the prepare and check functions both return %TRUE
+ * if the timeout interval has expired. The prepare function also returns
+ * a timeout value to ensure that the poll() call doesn't block too long
+ * and miss the next timeout.
+ *
+ * For file descriptor sources, the prepare function typically returns %FALSE,
+ * since it must wait until poll() has been called before it knows whether
+ * any events need to be processed. It sets the returned timeout to -1 to
+ * indicate that it doesn't mind how long the poll() call blocks. In the
+ * check function, it tests the results of the poll() call to see if the
+ * required condition has been met, and returns %TRUE if so.
+ */]]></output>
+</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..77cabf0e
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_paragraph_breaks.xml
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <!--
+ All lines (outside program- listings and CDATA sections) just containing
+ a ' *' (blank-asterisk) are converted to paragraph breaks.
+ -->
+ <input>/**
+ * SECTION:test
+ *
+ * The following line is ' *' (blank-asterisk).
+ *
+ * So this is considered a new paragraph.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test</name>
+ </identifier>
+ <description>The following line is ' *' (blank-asterisk).
+
+So this is considered a new paragraph.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * SECTION:test
+ *
+ * The following line is ' *' (blank-asterisk).
+ *
+ * So this is considered a new paragraph.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Description: tag, all lines (outside program- listings and CDATA sections) just containing
+ a ' *' (blank-asterisk) are converted to paragraph breaks.
+ -->
+ <input>/**
+ * SECTION:test
+ *
+ * Description: The following line is ' *' (blank-asterisk).
+ *
+ * So this is considered a new paragraph.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test</name>
+ </identifier>
+ <description>The following line is ' *' (blank-asterisk).
+
+So this is considered a new paragraph.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: The following line is ' *' (blank-asterisk).
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * SECTION:test
+ *
+ * The following line is ' *' (blank-asterisk).
+ *
+ * So this is considered a new paragraph.
+ */</output>
+</test>
+
+<test>
+ <!--
+ ' * ' (blank-asterisk-blank) are also converted to paragraph breaks.
+ -->
+ <input>/**
+ * SECTION:test
+ *
+ * The following line is ' * ' (blank-asterisk-blank).
+ *
+ * So this is considered a new paragraph.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test</name>
+ </identifier>
+ <description>The following line is ' * ' (blank-asterisk-blank).
+
+So this is considered a new paragraph.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * SECTION:test
+ *
+ * The following line is ' * ' (blank-asterisk-blank).
+ *
+ * So this is considered a new paragraph.
+ */</output>
+</test>
+
+<test>
+ <!--
+ Description: tag, ' * ' (blank-asterisk-blank) are also converted to paragraph breaks.
+ -->
+ <input>/**
+ * SECTION:test
+ *
+ * Description: The following line is ' * ' (blank-asterisk-blank).
+ *
+ * So this is considered a new paragraph.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>SECTION:test</name>
+ </identifier>
+ <description>The following line is ' * ' (blank-asterisk-blank).
+
+So this is considered a new paragraph.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: The following line is ' * ' (blank-asterisk-blank).
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * SECTION:test
+ *
+ * The following line is ' * ' (blank-asterisk-blank).
+ *
+ * So this is considered a new paragraph.
+ */</output>
+</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.
+ -->
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</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.
+ -->
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ <messages>
+ <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: The following line is (blank-asterisk-blank-blank).
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</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.
+ -->
+ <input><![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>
+ */]]></input>
+ <parser>
+ <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>
+ </parser>
+ <output><![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>
+ */]]></output>
+</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.
+ -->
+ <input><![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>
+ */]]></input>
+ <parser>
+ <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>
+ <messages>
+ <message><![CDATA[4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: <example>
+ ^]]></message>
+ </messages>
+ </parser>
+ <output><![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>
+ */]]></output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/syntax_whitespace.xml b/tests/scanner/annotationparser/gi/syntax_whitespace.xml
new file mode 100644
index 00000000..3857ea64
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/syntax_whitespace.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * whitespace_test:
+ * @object: (skip):
+ *
+ * A #AnnotationObject
+ *
+ *
+ * @func: The callback
+ *
+ *
+ * Test overriding via the "Rename To" annotation.
+ *
+ *
+ * Returns: nothing
+ *
+ *
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>whitespace_test</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>object</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ </parameter>
+ <parameter>
+ <name>func</name>
+ <description>The callback</description>
+ </parameter>
+ </parameters>
+ <description>A #AnnotationObject
+
+
+
+Test overriding via the "Rename To" annotation.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>nothing</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>8: Warning: Test: "@func" parameter unexpected at this location:
+ * @func: The callback
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * whitespace_test:
+ * @object: (skip):
+ * @func: The callback
+ *
+ * A #AnnotationObject
+ *
+ *
+ *
+ * Test overriding via the "Rename To" annotation.
+ *
+ * Returns: nothing
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ *atk_text_get_default_attributes:
+ *@text: an #AtkText
+ *
+ *Creates ...
+ *
+ *Returns: (transfer full): an ...
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>atk_text_get_default_attributes</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>text</name>
+ <description>an #AtkText</description>
+ </parameter>
+ </parameters>
+ <description>Creates ...</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>full</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>an ...</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * atk_text_get_default_attributes:
+ * @text: an #AtkText
+ *
+ * Creates ...
+ *
+ * Returns: (transfer full): an ...
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/gi/tag.xml b/tests/scanner/annotationparser/gi/tag.xml
new file mode 100644
index 00000000..8480d4b4
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag.xml
@@ -0,0 +1,401 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * test_tag_missing_colon:
+ *
+ * Forgotten colon below will result in a warning.
+ *
+ * Returns: (allow-none) return value
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_tag_missing_colon</name>
+ </identifier>
+ <description>Forgotten colon below will result in a warning.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>return value</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: missing ":" at column 25:
+ * Returns: (allow-none) return value
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_tag_missing_colon:
+ *
+ * Forgotten colon below will result in a warning.
+ *
+ * Returns: (allow-none): return value
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_unexpected_tag:
+ *
+ * @param1: first parameter
+ * does something
+ * Returns: something
+ * returning something
+ *
+ * Probably intended as the comment block description part but in reality belongs to
+ * the "Returns:"" tag description field.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_unexpected_tag</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param1</name>
+ <description>first parameter
+does something</description>
+ </parameter>
+ </parameters>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>something
+returning something
+
+Probably intended as the comment block description part but in reality belongs to
+the "Returns:"" tag description field.</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: "@param1" parameter unexpected at this location:
+ * @param1: first parameter
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_unexpected_tag:
+ * @param1: first parameter
+ * does something
+ *
+ * Returns: something
+ * returning something
+ *
+ * Probably intended as the comment block description part but in reality belongs to
+ * the "Returns:"" tag description field.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_unknown_tag:
+ *
+ * Foo: something
+ *
+ * Returns: True
+ * Moo: anything
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_unknown_tag</name>
+ </identifier>
+ <description>Foo: something</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>True
+Moo: anything</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_unknown_tag:
+ *
+ * Foo: something
+ *
+ * Returns: True
+ * Moo: anything
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_multiline_tag:
+ *
+ * Returns:
+ * True
+ * Since:
+ * 1.0: yeah
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiline_tag</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>True</description>
+ </tag>
+ <tag>
+ <name>since</name>
+ <description>1.0: yeah</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_multiline_tag:
+ *
+ * Returns: True
+ * Since: 1.0: yeah
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_multiline_annotations_on_tag:
+ *
+ * Annotations spanning multiple lines are not valid
+ *
+ * Returns: (allow-none)
+ * (transfer full): something
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiline_annotations_on_tag</name>
+ </identifier>
+ <description>Annotations spanning multiple lines are not valid</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>
+(transfer full): something</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>7: Error: Test: ignoring invalid multiline annotation continuation:
+ * (transfer full): something
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiline_annotations_on_tag:
+ *
+ * Annotations spanning multiple lines are not valid
+ *
+ * Returns: (allow-none):
+ * (transfer full): something
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_multiline_annotations_on_tag:
+ *
+ * Annotations spanning multiple lines are not valid
+ *
+ * Returns: (allow-none): Returns tag having a second line which looks
+ * (like an annotation), but isn't. This should not result in a warning.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiline_annotations_on_tag</name>
+ </identifier>
+ <description>Annotations spanning multiple lines are not valid</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>Returns tag having a second line which looks
+(like an annotation), but isn't. This should not result in a warning.</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_multiline_annotations_on_tag:
+ *
+ * Annotations spanning multiple lines are not valid
+ *
+ * Returns: (allow-none): Returns tag having a second line which looks
+ * (like an annotation), but isn't. This should not result in a warning.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * gdk_device_list_axes:
+ * @device: a pointer #GdkDevice
+ *
+ * Returns a #GList of #GdkAtom<!-- -->s, containing the labels for
+ * the axes that @device currently has.
+ *
+ * Returns: (transfer container) (element-type GdkAtom):
+ * A #GList of #GdkAtom<!-- -->s, free
+ * with g_list_free().
+ *
+ * Since: 3.0
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>gdk_device_list_axes</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>device</name>
+ <description>a pointer #GdkDevice</description>
+ </parameter>
+ </parameters>
+ <description>Returns a #GList of #GdkAtom<!-- -->s, containing the labels for
+the axes that @device currently has.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>container</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>element-type</name>
+ <options>
+ <option>
+ <name>GdkAtom</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ <description>
+ A #GList of #GdkAtom<!-- -->s, free
+ with g_list_free().</description>
+ </tag>
+ <tag>
+ <name>since</name>
+ <value>3.0</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * gdk_device_list_axes:
+ * @device: a pointer #GdkDevice
+ *
+ * Returns a #GList of #GdkAtom<!-- -->s, containing the labels for
+ * the axes that @device currently has.
+ *
+ * Returns: (transfer container) (element-type GdkAtom):
+ * A #GList of #GdkAtom<!-- -->s, free
+ * with g_list_free().
+ * Since: 3.0
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * FsSession:codec-preferences:
+ *
+ * Type: GLib.List(FsCodec)
+ * Transfer: full
+ *
+ * This is the current preferences list for the local codecs. It is
+ * set by the user to specify the codec options and priorities. The user may
+ * change its value with fs_session_set_codec_preferences() at any time
+ * during a session. It is a #GList of #FsCodec.
+ * The user must free this codec list using fs_codec_list_destroy() when done.
+ *
+ * The payload type may be a valid dynamic PT (96-127), %FS_CODEC_ID_DISABLE
+ * or %FS_CODEC_ID_ANY. If the encoding name is "reserve-pt", then the
+ * payload type of the codec will be "reserved" and not be used by any
+ * dynamically assigned payload type.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>FsSession:codec-preferences</name>
+ <annotations>
+ <annotation>
+ <name>type</name>
+ <options>
+ <option>
+ <name>GLib.List(FsCodec)</name>
+ </option>
+ </options>
+ </annotation>
+ <annotation>
+ <name>transfer</name>
+ <options>
+ <option>
+ <name>full</name>
+ </option>
+ </options>
+ </annotation>
+ </annotations>
+ </identifier>
+ <description>This is the current preferences list for the local codecs. It is
+set by the user to specify the codec options and priorities. The user may
+change its value with fs_session_set_codec_preferences() at any time
+during a session. It is a #GList of #FsCodec.
+The user must free this codec list using fs_codec_list_destroy() when done.
+
+The payload type may be a valid dynamic PT (96-127), %FS_CODEC_ID_DISABLE
+or %FS_CODEC_ID_ANY. If the encoding name is "reserve-pt", then the
+payload type of the codec will be "reserved" and not be used by any
+dynamically assigned payload type.</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GObject-Introspection specific GTK-Doc tag "Type" has been deprecated, please use annotations on the identifier instead:
+ * Type: GLib.List(FsCodec)
+ ^</message>
+ <message>5: Warning: Test: GObject-Introspection specific GTK-Doc tag "Transfer" has been deprecated, please use annotations on the identifier instead:
+ * Transfer: full
+ ^</message>
+ </messages>
+ </parser>
+ <output> /**
+ * FsSession:codec-preferences: (type GLib.List(FsCodec)) (transfer full)
+ *
+ * This is the current preferences list for the local codecs. It is
+ * set by the user to specify the codec options and priorities. The user may
+ * change its value with fs_session_set_codec_preferences() at any time
+ * during a session. It is a #GList of #FsCodec.
+ * The user must free this codec list using fs_codec_list_destroy() when done.
+ *
+ * The payload type may be a valid dynamic PT (96-127), %FS_CODEC_ID_DISABLE
+ * or %FS_CODEC_ID_ANY. If the encoding name is "reserve-pt", then the
+ * payload type of the codec will be "reserved" and not be used by any
+ * dynamically assigned payload type.
+ */</output>
+</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..f1e8ca60
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_deprecated.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Deprecated: 0.6: Use something else instead
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_versioned</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>deprecated</name>
+ <value>0.6</value>
+ <description>Use something else instead</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Deprecated: 0.6: Use something else instead
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Deprecated: 0.6
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_versioned</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>deprecated</name>
+ <value>0.6</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Deprecated: 0.6
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_tag_not_annotatable:
+ *
+ * Tags (except Returns:) don't have annotations
+ *
+ * Deprecated: (allow-none): 2.24
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_tag_not_annotatable</name>
+ </identifier>
+ <description>Tags (except Returns:) don't have annotations</description>
+ <tags>
+ <tag>
+ <name>deprecated</name>
+ <value>2.24</value>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>6: Error: Test: annotations not supported for tag "Deprecated:".</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_tag_not_annotatable:
+ *
+ * Tags (except Returns:) don't have annotations
+ *
+ * Deprecated: 2.24
+ */</output>
+</test>
+
+<test>
+ <!--
+ Multiple "Deprecated:" tags
+ -->
+ <input>/**
+ * test_multiple_tags:
+ *
+ * Deprecated: 3.0
+ * Deprecated: 2.0
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiple_tags</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>deprecated</name>
+ <value>2.0</value>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>5: Error: Test: multiple "Deprecated:" tags for identifier "test_multiple_tags":
+ * Deprecated: 2.0
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiple_tags:
+ *
+ * Deprecated: 2.0
+ */</output>
+</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..3dff7f33
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_description.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * shiny_function:
+ *
+ * Description: This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ **/</input>
+ <parser>
+ <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>
+ <messages>
+ <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: This is a callback with a 'closure' argument that is not named
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * shiny_function:
+ *
+ * This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * shiny_function:
+ * Description: This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ **/</input>
+ <parser>
+ <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>
+ <messages>
+ <message>3: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: This is a callback with a 'closure' argument that is not named
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * shiny_function:
+ *
+ * This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * shiny_function:
+ *
+ * Some description here, but also below...
+ *
+ * Description: This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>shiny_function</name>
+ </identifier>
+ <description>Some description here, but also below...
+
+This is a callback with a 'closure' argument that is not named
+'user_data' and hence has to be annotated.</description>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: This is a callback with a 'closure' argument that is not named
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * shiny_function:
+ *
+ * Some description here, but also below...
+ *
+ * This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * shiny_function:
+ *
+ * Description: This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ *
+ * etc...
+ **/</input>
+ <parser>
+ <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.
+
+ etc...</description>
+ </docblock>
+ <messages>
+ <message>4: Warning: Test: GTK-Doc tag "Description:" has been deprecated:
+ * Description: This is a callback with a 'closure' argument that is not named
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * shiny_function:
+ *
+ * This is a callback with a 'closure' argument that is not named
+ * 'user_data' and hence has to be annotated.
+ *
+ * etc...
+ */</output>
+</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..8ccfaa63
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_returns.xml
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns: (allow-none): some boolean
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_string_out</name>
+ </identifier>
+ <description>Test returning a string as an out parameter</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>some boolean</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns: (allow-none): some boolean
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns: (allow-none)): some boolean
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_string_out</name>
+ </identifier>
+ <description>Test returning a string as an out parameter</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>6: Error: Test: unbalanced parentheses, annotations will be ignored:
+ * Returns: (allow-none)): some boolean
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns:
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_unexpected_tag:
+ * @param1: first parameter
+ * Returns: something
+ *
+ * Tags should go after the comment block description
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_unexpected_tag</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>param1</name>
+ <description>first parameter</description>
+ </parameter>
+ </parameters>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>something
+
+Tags should go after the comment block description</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_unexpected_tag:
+ * @param1: first parameter
+ *
+ * Returns: something
+ *
+ * Tags should go after the comment block description
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "Return value:" tag
+ -->
+ <input>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Return value: (allow-none): some boolean
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_string_out</name>
+ </identifier>
+ <description>Test returning a string as an out parameter</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>some boolean</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns: (allow-none): some boolean
+ */</output>
+</test>
+
+<test>
+ <!--
+ Deprecated "@returns" as a parameter
+ -->
+ <input>/**
+ * annotation_object_string_out:
+ * @returns: (allow-none): some boolean
+ *
+ * Test returning a string as an out parameter
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_string_out</name>
+ </identifier>
+ <description>Test returning a string as an out parameter</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>allow-none</name>
+ </annotation>
+ </annotations>
+ <description>some boolean</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns: (allow-none): some boolean
+ */</output>
+</test>
+
+<test>
+ <!--
+ Variation of "@returns" as a parameter
+ -->
+ <input>/**
+ * annotation_object_string_out:
+ * @returns: (allow-none)): some boolean
+ *
+ * Test returning a string as an out parameter
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_string_out</name>
+ </identifier>
+ <description>Test returning a string as an out parameter</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>3: Error: Test: unbalanced parentheses, annotations will be ignored:
+ * @returns: (allow-none)): some boolean
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns:
+ */</output>
+</test>
+
+<test>
+ <!--
+ Variation of "@returns" as a parameter
+ -->
+ <input>/**
+ * annotation_object_string_out:
+ * @returns:
+ *
+ * Test returning a string as an out parameter
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_string_out</name>
+ </identifier>
+ <description>Test returning a string as an out parameter</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns:
+ */</output>
+</test>
+
+<test>
+ <!--
+ Variation of multiple "Returns:" notations
+ -->
+ <input>/**
+ * test_multiple_returns_tag_and_parameter:
+ *
+ * Multiple return value warnings are checked for when a returns
+ * parameter is encountered.
+ *
+ * Return Value: something
+ * @returns: something else
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiple_returns_tag_and_parameter</name>
+ </identifier>
+ <description>Multiple return value warnings are checked for when a returns
+parameter is encountered.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>something else</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>8: Warning: Test: "@returns" parameter unexpected at this location:
+ * @returns: something else
+ ^</message>
+ <message>8: Error: Test: encountered multiple "Returns" parameters or tags for "test_multiple_returns_tag_and_parameter".</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiple_returns_tag_and_parameter:
+ *
+ * Multiple return value warnings are checked for when a returns
+ * parameter is encountered.
+ *
+ * Returns: something else
+ */</output>
+</test>
+
+<test>
+ <!--
+ Variation of multiple "Returns:" notations
+ -->
+ <input>/**
+ * test_multiple_returns_tag_and_parameter:
+ * @returns: something
+ *
+ * Multiple return value warnings are checked for when a returns
+ * parameter is encountered.
+ *
+ * Return Value: something else
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiple_returns_tag_and_parameter</name>
+ </identifier>
+ <description>Multiple return value warnings are checked for when a returns
+parameter is encountered.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>something else</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>8: Error: Test: encountered multiple return value parameters or tags for "test_multiple_returns_tag_and_parameter".</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiple_returns_tag_and_parameter:
+ *
+ * Multiple return value warnings are checked for when a returns
+ * parameter is encountered.
+ *
+ * Returns: something else
+ */</output>
+</test>
+
+<test>
+ <!--
+ Variation of multiple "Returns:" notations
+ -->
+ <input>/**
+ * test_multiple_returns_tag_and_parameter:
+ * @returns: something
+ *
+ * Multiple return value warnings are checked for when a returns
+ * parameter is encountered.
+ *
+ * Returns: something else
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiple_returns_tag_and_parameter</name>
+ </identifier>
+ <description>Multiple return value warnings are checked for when a returns
+parameter is encountered.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>something else</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>8: Error: Test: encountered multiple return value parameters or tags for "test_multiple_returns_tag_and_parameter".</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiple_returns_tag_and_parameter:
+ *
+ * Multiple return value warnings are checked for when a returns
+ * parameter is encountered.
+ *
+ * Returns: something else
+ */</output>
+</test>
+
+<test>
+ <input><![CDATA[/**
+ * gtk_rc_get_im_module_path:
+ * @returns: a newly-allocated string containing the path in which to
+ * look for IM modules.
+ *
+ * Obtains the path in which to look for IM modules. See the documentation
+ * of the <link linkend="im-module-path"><envar>GTK_PATH</envar></link>
+ * environment variable for more details about looking up modules. This
+ * function is useful solely for utilities supplied with GTK+ and should
+ * not be used by applications under normal circumstances.
+ */]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>gtk_rc_get_im_module_path</name>
+ </identifier>
+ <description><![CDATA[Obtains the path in which to look for IM modules. See the documentation
+of the <link linkend="im-module-path"><envar>GTK_PATH</envar></link>
+environment variable for more details about looking up modules. This
+function is useful solely for utilities supplied with GTK+ and should
+not be used by applications under normal circumstances.]]></description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>a newly-allocated string containing the path in which to
+ look for IM modules.</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output><![CDATA[/**
+ * gtk_rc_get_im_module_path:
+ *
+ * Obtains the path in which to look for IM modules. See the documentation
+ * of the <link linkend="im-module-path"><envar>GTK_PATH</envar></link>
+ * environment variable for more details about looking up modules. This
+ * function is useful solely for utilities supplied with GTK+ and should
+ * not be used by applications under normal circumstances.
+ *
+ * Returns: a newly-allocated string containing the path in which to
+ * look for IM modules.
+ */]]></output>
+</test>
+
+<test>
+ <!--
+ Technically not a valid Returns: tag, but we need to support this for backwards compatibility
+ with the old annotationparser.
+ -->
+ <input>/**
+ * clutter_text_coords_to_position:
+ * @self: a #ClutterText
+ * @x: the X coordinate, relative to the actor
+ * @y: the Y coordinate, relative to the actor
+ *
+ * Retrieves the position of the character at the given coordinates.
+ *
+ * Return: the position of the character
+ *
+ * Since: 1.10
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>clutter_text_coords_to_position</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>self</name>
+ <description>a #ClutterText</description>
+ </parameter>
+ <parameter>
+ <name>x</name>
+ <description>the X coordinate, relative to the actor</description>
+ </parameter>
+ <parameter>
+ <name>y</name>
+ <description>the Y coordinate, relative to the actor</description>
+ </parameter>
+ </parameters>
+ <description>Retrieves the position of the character at the given coordinates.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>the position of the character</description>
+ </tag>
+ <tag>
+ <name>since</name>
+ <value>1.10</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * clutter_text_coords_to_position:
+ * @self: a #ClutterText
+ * @x: the X coordinate, relative to the actor
+ * @y: the Y coordinate, relative to the actor
+ *
+ * Retrieves the position of the character at the given coordinates.
+ *
+ * Returns: the position of the character
+ * Since: 1.10
+ */</output>
+</test>
+
+<test>
+ <!--
+ Technically not a valid Returns: tag, but we need to support this for backwards compatibility
+ with the old annotationparser.
+ -->
+ <input>/**
+ * clutter_text_coords_to_position:
+ * @self: a #ClutterText
+ * @x: the X coordinate, relative to the actor
+ * @y: the Y coordinate, relative to the actor
+ *
+ * Retrieves the position of the character at the given coordinates.
+ *
+ * Returns value: the position of the character
+ *
+ * Since: 1.10
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>clutter_text_coords_to_position</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>self</name>
+ <description>a #ClutterText</description>
+ </parameter>
+ <parameter>
+ <name>x</name>
+ <description>the X coordinate, relative to the actor</description>
+ </parameter>
+ <parameter>
+ <name>y</name>
+ <description>the Y coordinate, relative to the actor</description>
+ </parameter>
+ </parameters>
+ <description>Retrieves the position of the character at the given coordinates.</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <description>the position of the character</description>
+ </tag>
+ <tag>
+ <name>since</name>
+ <value>1.10</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * clutter_text_coords_to_position:
+ * @self: a #ClutterText
+ * @x: the X coordinate, relative to the actor
+ * @y: the Y coordinate, relative to the actor
+ *
+ * Retrieves the position of the character at the given coordinates.
+ *
+ * Returns: the position of the character
+ * Since: 1.10
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns: (out): some boolean
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_object_string_out</name>
+ </identifier>
+ <description>Test returning a string as an out parameter</description>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>out</name>
+ </annotation>
+ </annotations>
+ <description>some boolean</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>6: Warning: Test: unexpected annotation: out</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_object_string_out:
+ *
+ * Test returning a string as an out parameter
+ *
+ * Returns: (out): some boolean
+ */</output>
+</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..06116aa1
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_since.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Since: 0.6
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_versioned</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>since</name>
+ <value>0.6</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Since: 0.6
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Since: (invalid)): 0.6
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_versioned</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>since</name>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>4: Error: Test: unbalanced parentheses, annotations will be ignored:
+ * Since: (invalid)): 0.6
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Since:
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Since: this function is available since version 0.6
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Since: this function is available since version 0.6
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Since: 0.6: this function is available since version 0.6
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_versioned</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>since</name>
+ <value>0.6</value>
+ <description>this function is available since version 0.6</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Since: 0.6: this function is available since version 0.6
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_tag_not_annotatable:
+ *
+ * Tags (except Returns:) don't have annotations
+ *
+ * Since: (allow-none): 2.24
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_tag_not_annotatable</name>
+ </identifier>
+ <description>Tags (except Returns:) don't have annotations</description>
+ <tags>
+ <tag>
+ <name>since</name>
+ <value>2.24</value>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>6: Error: Test: annotations not supported for tag "Since:".</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_tag_not_annotatable:
+ *
+ * Tags (except Returns:) don't have annotations
+ *
+ * Since: 2.24
+ */</output>
+</test>
+
+<test>
+ <!--
+ Multiple "Since:" tags
+ -->
+ <input>/**
+ * test_multiple_tags:
+ *
+ * Since: 3.0
+ * Since: 2.0: one of these "Since:"
+ * tags is wrong...
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiple_tags</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>since</name>
+ <value>2.0</value>
+ <description>one of these "Since:"
+tags is wrong...</description>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>5: Error: Test: multiple "Since:" tags for identifier "test_multiple_tags":
+ * Since: 2.0: one of these "Since:"
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiple_tags:
+ *
+ * Since: 2.0: one of these "Since:"
+ * tags is wrong...
+ */</output>
+</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..25c907ff
--- /dev/null
+++ b/tests/scanner/annotationparser/gi/tag_stability.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Stability: Stable
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_versioned</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>stability</name>
+ <value>Stable</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Stability: Stable
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Stability: Unstable
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_versioned</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>stability</name>
+ <value>Unstable</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Stability: Unstable
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Stability: Private
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_versioned</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>stability</name>
+ <value>Private</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Stability: Private
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_versioned:
+ *
+ * Stability: behavior tends to vary depending on the phase of the moon.
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_versioned:
+ *
+ * Stability: behavior tends to vary depending on the phase of the moon.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * test_tag_not_annotatable:
+ *
+ * Tags (except Returns:) don't have annotations
+ *
+ * Stability: (allow-none): Private
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_tag_not_annotatable</name>
+ </identifier>
+ <description>Tags (except Returns:) don't have annotations</description>
+ <tags>
+ <tag>
+ <name>stability</name>
+ <value>Private</value>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>6: Error: Test: annotations not supported for tag "Stability:".</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_tag_not_annotatable:
+ *
+ * Tags (except Returns:) don't have annotations
+ *
+ * Stability: Private
+ */</output>
+</test>
+
+<test>
+ <!--
+ Multiple "Stability:" tags
+ -->
+ <input>/**
+ * test_multiple_tags:
+ *
+ * Stability: Public
+ * Stability: Private
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_multiple_tags</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>stability</name>
+ <value>Private</value>
+ </tag>
+ </tags>
+ </docblock>
+ <messages>
+ <message>5: Error: Test: multiple "Stability:" tags for identifier "test_multiple_tags":
+ * Stability: Private
+ ^</message>
+ </messages>
+ </parser>
+ <output>/**
+ * test_multiple_tags:
+ *
+ * Stability: Private
+ */</output>
+</test>
+
+<test>
+ <!--
+ "Stability:" description
+ -->
+ <input>/**
+ * test_stability_description:
+ *
+ * Stability: Unstable: maybe one day this will work
+ * correctly...
+ **/</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test_stability_description</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>stability</name>
+ <value>Unstable</value>
+ <description>maybe one day this will work
+ correctly...</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * test_stability_description:
+ *
+ * Stability: Unstable: maybe one day this will work
+ * correctly...
+ */</output>
+</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..d28d5d9b
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/annotations/tester.c.xml
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * SECTION:tester
+ * @short_description: module for gtk-doc unit test
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * SECTION:tester
+ * @short_description: module for gtk-doc unit test
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_elementtype:
+ * @list: (element-type GObject): list of #GObject instances to search
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_elementtype:
+ * @list: (element-type GObject): list of #GObject instances to search
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_elementtype_transfer:
+ * @list: (element-type utf8) (transfer full): list of #GObject instances to search
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_elementtype_transfer:
+ * @list: (element-type utf8) (transfer full): list of #GObject instances to search
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_elementtype_returns:
+ *
+ * Document optional parameters.
+ *
+ * Returns: (element-type GObject): A list of #GObject instances.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_elementtype_returns:
+ *
+ * Document optional parameters.
+ *
+ * Returns: (element-type GObject): A list of #GObject instances.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_outparams:
+ * @list: (out) (transfer none): a pointer to take a list
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_outparams:
+ * @list: (out) (transfer none): a pointer to take a list
+ *
+ * Document optional parameters.
+ *
+ * Returns: %TRUE for success
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_skip: (skip)
+ * @list: a pointer to take a list
+ *
+ * Documentation for this function.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_skip: (skip)
+ * @list: a pointer to take a list
+ *
+ * Documentation for this function.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_skip_return: (skip)
+ * @list: a pointer to take a list
+ *
+ * Documentation for this function.
+ *
+ * Returns: (skip): %TRUE for success
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>annotation_skip_return</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>
+ <tags>
+ <tag>
+ <name>returns</name>
+ <annotations>
+ <annotation>
+ <name>skip</name>
+ </annotation>
+ </annotations>
+ <description>%TRUE for success</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * annotation_skip_return: (skip)
+ * @list: a pointer to take a list
+ *
+ * Documentation for this function.
+ *
+ * Returns: (skip): %TRUE for success
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * annotation_scope:
+ * @callback: (scope async): a callback
+ * @user_data: data to pass to callback
+ *
+ * Documentation for this function.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * annotation_scope:
+ * @callback: (scope async): a callback
+ * @user_data: data to pass to callback
+ *
+ * Documentation for this function.
+ */</output>
+</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..0917cd95
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/annotations/tester.h.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * GtkdocAnnotation:
+ * @that: (allow-none): eventualy points to something
+ *
+ * small struct
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * GtkdocAnnotation:
+ * @that: (allow-none): eventualy points to something
+ *
+ * small struct
+ */</output>
+</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..09ab9773
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/bugs/tester.c.xml
@@ -0,0 +1,1108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input><![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>
+ */]]></input>
+ <parser>
+ <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>
+ </parser>
+ <output><![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>
+ */]]></output>
+</test>
+
+<test>
+ <input>/**
+ * bug_141869_a:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=141869
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_141869_a:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=141869
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_141869_b:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=141869
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_141869_b:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=141869
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_379466:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=379466
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_379466:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=379466
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_380824:
+ * @arg: arg
+ *
+ * Returns a value.
+ * http://bugzilla.gnome.org/show_bug.cgi?id=380824
+ *
+ * Since: 0.1
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ <value>0.1</value>
+ </tag>
+ <tag>
+ <name>returns</name>
+ <description>result</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_380824:
+ * @arg: arg
+ *
+ * Returns a value.
+ * http://bugzilla.gnome.org/show_bug.cgi?id=380824
+ *
+ * Since: 0.1
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_411739:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=411739
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_411739:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=411739
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_419997:
+ * @const_values: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=419997
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_419997:
+ * @const_values: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=419997
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_445693:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=445693
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_445693:
+ * @pid: arg
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=445693
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_471014:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=471014
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_471014:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=471014
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * Bug446648:
+ * @BUG_446648_FOO: foo
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=446648
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * Bug446648:
+ * @BUG_446648_FOO: foo
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=446648
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_552602:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=552602
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_552602:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=552602
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_574654a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=574654
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_574654a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=574654
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_574654b:
+ * @offset: skip this many items
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=574654
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_574654b:
+ * @offset: skip this many items
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=574654
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_580300a_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_580300a_get_type</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=580300</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_580300a_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_580300b_get_type:
+ * @a: value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_580300b_get_type:
+ * @a: value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_580300c_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_580300c_get_type</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=580300</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_580300c_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_580300d_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_580300d_get_type:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=580300
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_597937:
+ * @function_arg: value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=597937
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_597937:
+ * @function_arg: value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=597937
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_602518a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_602518a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_602518b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_602518b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_602518c:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_602518c:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=602518
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_607445:
+ * @a: parameter
+ * @n: parameter
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=607445
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_607445:
+ * @a: parameter
+ * @n: parameter
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=607445
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_610257:
+ * @der: parameter
+ * @len: parameter
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=610257
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_610257:
+ * @der: parameter
+ * @len: parameter
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=610257
+ */</output>
+</test>
+
+<test>
+ <input><![CDATA[/**
+ * bug_623968a:
+ *
+ * <para>test</para>
+ * <refsect3>
+ * <title>subsect</title>
+ * <para>test</para>
+ * </refsect3>
+ **/]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_623968a</name>
+ </identifier>
+ <description><![CDATA[<para>test</para>
+<refsect3>
+ <title>subsect</title>
+ <para>test</para>
+</refsect3>]]></description>
+ </docblock>
+ </parser>
+ <output><![CDATA[/**
+ * bug_623968a:
+ *
+ * <para>test</para>
+ * <refsect3>
+ * <title>subsect</title>
+ * <para>test</para>
+ * </refsect3>
+ */]]></output>
+</test>
+
+<test>
+ <input><![CDATA[/**
+ * bug_623968b:
+ *
+ * test
+ *
+ * <refsect3>
+ * <title>subsect</title>
+ * <para>test</para>
+ * </refsect3>
+ **/]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_623968b</name>
+ </identifier>
+ <description><![CDATA[test
+
+<refsect3>
+ <title>subsect</title>
+ <para>test</para>
+</refsect3>]]></description>
+ </docblock>
+ </parser>
+ <output><![CDATA[/**
+ * bug_623968b:
+ *
+ * test
+ *
+ * <refsect3>
+ * <title>subsect</title>
+ * <para>test</para>
+ * </refsect3>
+ */]]></output>
+</test>
+
+<test>
+ <input><![CDATA[/**
+ * bug_623968c:
+ *
+ * <para>test</para>
+ **/]]></input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_623968c</name>
+ </identifier>
+ <description><![CDATA[<para>test</para>]]></description>
+ </docblock>
+ </parser>
+ <output><![CDATA[/**
+ * bug_623968c:
+ *
+ * <para>test</para>
+ */]]></output>
+</test>
+
+<test>
+ <input>/**
+ * bug_624200a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624200
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_624200a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624200
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_624200b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624200
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_624200b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624200
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_638330:
+ * @arg1: arg1
+ * @data: data
+ * @length: length
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=638330
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_638330:
+ * @arg1: arg1
+ * @data: data
+ * @length: length
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=638330
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_000000_va1:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_000000_va1:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_624001a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_624001a</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_624001a:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_624001b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_624001b</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_624001b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_624001c:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_624001c</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_624001c:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_624001d:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_624001d</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_624001d:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_624001e:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_624001e</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=624001</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_624001e:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=624001
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * deprecation_notice:
+ *
+ * Foo.
+ *
+ * Deprecated: 3.10: Use named icon "bar" instead.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>deprecation_notice</name>
+ </identifier>
+ <description>Foo.</description>
+ <tags>
+ <tag>
+ <name>deprecated</name>
+ <value>3.10</value>
+ <description>Use named icon "bar" instead.</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * deprecation_notice:
+ *
+ * Foo.
+ *
+ * Deprecated: 3.10: Use named icon "bar" instead.
+ */</output>
+</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..5dad3cb8
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/bugs/tester.h.xml
@@ -0,0 +1,925 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_481811:
+ * @x: argument
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=481811
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_481811:
+ * @x: argument
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=481811
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_501038:
+ * @a: value
+ * @b: deprecated value
+ * @_b: scrambled deprecated value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=501038
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_501038:
+ * @a: value
+ * @b: deprecated value
+ * @_b: scrambled deprecated value
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=501038
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_460127:
+ * @a: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=460127
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_460127:
+ * @a: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=460127
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_477532:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=477532
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_477532</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=477532</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_477532:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=477532
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * Bug446648:
+ * @BUG_446648_FOO: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=446648
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * Bug446648:
+ * @BUG_446648_FOO: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=446648
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * Bug512154:
+ * @index: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512154
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * Bug512154:
+ * @index: field
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512154
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_512155a_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_512155a_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_512155b_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_512155b_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_512155c_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_512155c_function_pointer_t:
+ * @arg1: param 1
+ * @arg2: param 1
+ * @arg3: param 1
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=512155
+ */</output>
+</test>
+
+<test>
+ <input><![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>
+ */]]></input>
+ <parser>
+ <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>
+ </parser>
+ <output><![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>
+ */]]></output>
+</test>
+
+<test>
+ <input>/**
+ * bug_532395a:
+ * @number: a number
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=532395
+ *
+ * Returns: number
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_532395a:
+ * @number: a number
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=532395
+ *
+ * Returns: number
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_532395b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=532395
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>bug_532395b</name>
+ </identifier>
+ <description>http://bugzilla.gnome.org/show_bug.cgi?id=532395</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * bug_532395b:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=532395
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_544172:
+ * @self: object pointer.
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=544172
+ *
+ * Returns: result or %NULL.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_544172:
+ * @self: object pointer.
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=544172
+ *
+ * Returns: result or %NULL.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_554833:
+ * @i: value;
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=554833
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_554833:
+ * @i: value;
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=554833
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * bug_554833_new:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=554833
+ *
+ * Returns: result
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * bug_554833_new:
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=554833
+ *
+ * Returns: result
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * Bug165425a:
+ * @i: data as int
+ * @f: data as float
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=165425
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * Bug165425a:
+ * @i: data as int
+ * @f: data as float
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=165425
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * Bug165425b:
+ * @i: data as int
+ * @f: data as float
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=165425
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * Bug165425b:
+ * @i: data as int
+ * @f: data as float
+ *
+ * http://bugzilla.gnome.org/show_bug.cgi?id=165425
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * BUG_000000_VA2:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * BUG_000000_VA2:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * BUG_000000_VA3:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * BUG_000000_VA3:
+ * @name: a name
+ * @...: A printf-style message to output
+ *
+ * Outputs a message.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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";
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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";
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * gst_play_marshal_BUFFER__BOXED:
+ * @closure: test
+ * @return_value: test
+ * @marshal_data: test
+ *
+ * test.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * gst_play_marshal_BUFFER__BOXED:
+ * @closure: test
+ * @return_value: test
+ * @marshal_data: test
+ *
+ * test.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * BUG_656773a:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>BUG_656773a</name>
+ </identifier>
+ <description>https://bugzilla.gnome.org/show_bug.cgi?id=656773</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * BUG_656773a:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * BUG_656773b:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>BUG_656773b</name>
+ </identifier>
+ <description>https://bugzilla.gnome.org/show_bug.cgi?id=656773</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * BUG_656773b:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * BUG_656773c:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>BUG_656773c</name>
+ </identifier>
+ <description>https://bugzilla.gnome.org/show_bug.cgi?id=656773</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * BUG_656773c:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656773
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * BUG_656946:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656946
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>BUG_656946</name>
+ </identifier>
+ <description>https://bugzilla.gnome.org/show_bug.cgi?id=656946</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * BUG_656946:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=656946
+ */</output>
+</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..65bda61f
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/empty/tester.c.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input><![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.
+ */]]></input>
+ <parser>
+ <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>
+ </parser>
+ <output><![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.
+ */]]></output>
+</test>
+
+<test>
+ <input>/**
+ * test:
+ * @a: arg
+ *
+ * lonely function
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>test</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>a</name>
+ <description>arg</description>
+ </parameter>
+ </parameters>
+ <description>lonely function</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * test:
+ * @a: arg
+ *
+ * lonely function
+ */</output>
+</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..40fbbff5
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/fail/tester.c.xml
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/*
+ * 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.
+ */</input>
+</test>
+
+<test>
+ <input>/**
+ * SECTION:tester_nolongdesc
+ * @short_description: module for gtk-doc unit test
+ * @title: GtkdocTesterNoLongDesc
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * SECTION:tester_nolongdesc
+ * @short_description: module for gtk-doc unit test
+ * @title: GtkdocTesterNoLongDesc
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * SECTION:tester_noshortdesc
+ * @title: GtkdocTesterNoShortDesc
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * SECTION:tester_noshortdesc
+ * @title: GtkdocTesterNoShortDesc
+ *
+ * This file contains non-sense code for the sole purpose of testing the docs.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * func_no_docs:
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>func_no_docs</name>
+ </identifier>
+ </docblock>
+ </parser>
+ <output>/**
+ * func_no_docs:
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * func_no_item_docs:
+ *
+ * Here we document the function but not the parameters.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>func_no_item_docs</name>
+ </identifier>
+ <description>Here we document the function but not the parameters.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * func_no_item_docs:
+ *
+ * Here we document the function but not the parameters.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * func_incomplete_docs:
+ * @a: a value
+ *
+ * Here we document the function but not all the parameters.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * func_incomplete_docs:
+ * @a: a value
+ *
+ * Here we document the function but not all the parameters.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * func_unused_docs:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the function and more than the actual parameters.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * func_unused_docs:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the function and more than the actual parameters.
+ */</output>
+</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..069ae71a
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/fail/tester.h.xml
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+<input>/**
+ * MACRO_NO_ITEM_DOCS:
+ *
+ * Here we document the macro but not the parameters.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>MACRO_NO_ITEM_DOCS</name>
+ </identifier>
+ <description>Here we document the macro but not the parameters.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * MACRO_NO_ITEM_DOCS:
+ *
+ * Here we document the macro but not the parameters.
+ */</output>
+</test>
+
+<test>
+<input>/**
+ * MACRO_INCOMPLETE_DOCS:
+ * @a: a value
+ *
+ * Here we document the macro but not all the parameters.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * MACRO_INCOMPLETE_DOCS:
+ * @a: a value
+ *
+ * Here we document the macro but not all the parameters.
+ */</output>
+</test>
+
+<test>
+<input>/**
+ * MACRO_UNUSED_DOCS:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the macro and more than the actual parameters.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * MACRO_UNUSED_DOCS:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the macro and more than the actual parameters.
+ */</output>
+</test>
+
+<test>
+<input>/**
+ * EnumNoItemDocs:
+ *
+ * Here we document the enum but not the values.
+ * http://bugzilla.gnome.org/show_bug.cgi?id=568711
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * EnumNoItemDocs:
+ *
+ * Here we document the enum but not the values.
+ * http://bugzilla.gnome.org/show_bug.cgi?id=568711
+ */</output>
+</test>
+
+<test>
+<input>/**
+ * EnumIncompleteDocs:
+ * @ENUM_INCOMPLETE_DOCS_1: a value
+ *
+ * Here we document the enum but not all the values.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * EnumIncompleteDocs:
+ * @ENUM_INCOMPLETE_DOCS_1: a value
+ *
+ * Here we document the enum but not all the values.
+ */</output>
+</test>
+
+<test>
+<input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+<test>
+<input>/**
+ * StructNoItemDocs:
+ *
+ * Here we document the struct but not the values.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>StructNoItemDocs</name>
+ </identifier>
+ <description>Here we document the struct but not the values.</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * StructNoItemDocs:
+ *
+ * Here we document the struct but not the values.
+ */</output>
+</test>
+
+<test>
+<input>/**
+ * StructIncompleteDocs:
+ * @a: a value
+ *
+ * Here we document the struct but not all the values.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * StructIncompleteDocs:
+ * @a: a value
+ *
+ * Here we document the struct but not all the values.
+ */</output>
+</test>
+
+<test>
+<input>/**
+ * StructUnusedDocs:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the struct and more than the actual values.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * StructUnusedDocs:
+ * @a: a value
+ * @b: a value
+ * @c: an unexisting value
+ *
+ * Here we document the struct and more than the actual values.
+ */</output>
+</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..c295edbc
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/giface.c.xml
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input><![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 \@.
+ */]]></input>
+ <parser>
+ <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>
+ </parser>
+ <output><![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 \@.
+ */]]></output>
+</test>
+
+<test>
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * gtkdoc_iface_configure:
+ * @config: settings
+ *
+ * Configure a new instance
+ *
+ * Returns: %TRUE for sucess or %FALSE in case of an error
+ * Since: 0.1
+ */</input>
+ <parser>
+ <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>
+ <value>0.1</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * gtkdoc_iface_configure:
+ * @config: settings
+ *
+ * Configure a new instance
+ *
+ * Returns: %TRUE for sucess or %FALSE in case of an error
+ * Since: 0.1
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocIface::itest:
+ * @self: myself
+ *
+ * The event has been triggered.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output> /**
+ * GtkdocIface::itest:
+ * @self: myself
+ *
+ * The event has been triggered.
+ */</output>
+</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..e3ed09ca
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/giface.h.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * GtkdocIface:
+ *
+ * opaque instance of gtk-doc unit test interface
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocIface</name>
+ </identifier>
+ <description>opaque instance of gtk-doc unit test interface</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkdocIface:
+ *
+ * opaque instance of gtk-doc unit test interface
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocIface2:
+ *
+ * opaque instance of gtk-doc unit test interface
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocIface2</name>
+ </identifier>
+ <description>opaque instance of gtk-doc unit test interface</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkdocIface2:
+ *
+ * opaque instance of gtk-doc unit test interface
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocIfaceInterface:
+ * @parent: this is a bug :/
+ * @test: overideable method
+ *
+ * class data of gtk-doc unit test interface
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * GtkdocIfaceInterface:
+ * @parent: this is a bug :/
+ * @test: overideable method
+ *
+ * class data of gtk-doc unit test interface
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GTKDOC_IFACE_MACRO_DUMMY:
+ * @parameter_1: first arg
+ * @parameter_2: second arg
+ *
+ * This macro does nothing.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * GTKDOC_IFACE_MACRO_DUMMY:
+ * @parameter_1: first arg
+ * @parameter_2: second arg
+ *
+ * This macro does nothing.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</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..b54a1a74
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gobject.c.xml
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input><![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.
+ */]]></input>
+ <parser>
+ <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>
+ </parser>
+ <output><![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.
+ */]]></output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input><![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
+ */]]></input>
+ <parser>
+ <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>
+ <value>0.1</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output><![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
+ */]]></output>
+</test>
+
+<test>
+ <input><![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. This is a long paragraph.
+ *
+ * Oh, btw. setting the property directly saves us one method.
+ *
+ * Deprecated: Use g_object_set(obj,&quot;otest&quot;,value,NULL); instead.
+ * Since: 0.5
+ */]]></input>
+ <parser>
+ <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. This is a long paragraph.
+
+Oh, btw. setting the property directly saves us one method.</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>
+ <value>0.5</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output><![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. This is a long paragraph.
+ *
+ * Oh, btw. setting the property directly saves us one method.
+ *
+ * Deprecated: Use g_object_set(obj,&quot;otest&quot;,value,NULL); instead.
+ * Since: 0.5
+ */]]></output>
+</test>
+
+<test>
+ <input><![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
+ */]]></input>
+ <parser>
+ <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>
+ <value>0.5</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output><![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
+ */]]></output>
+</test>
+
+<test>
+ <input>/**
+ * gtkdoc_object_fooify:
+ * @self: the object
+ * @...: a NULL terminated list of arguments
+ *
+ * Fooify the content of @self.
+ *
+ * Returns: %TRUE for success
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * gtkdoc_object_fooify:
+ * @self: the object
+ * @...: a NULL terminated list of arguments
+ *
+ * Fooify the content of @self.
+ *
+ * Returns: %TRUE for success
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocObject::otest:
+ * @self: myself
+ *
+ * The event has been triggered.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output> /**
+ * GtkdocObject::otest:
+ * @self: myself
+ *
+ * The event has been triggered.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocObject::dep-otest:
+ * @self: myself
+ *
+ * Here's an example signal handler.
+ * |[
+ * static gchar*
+ * otest_callback (GObject *o,
+ * gpointer user_data)
+ * {
+ * gdouble value;
+ *
+ * value = abs (o->value);
+ *
+ * return value;
+ * }
+ * ]|
+ *
+ * Deprecated: Use the #GtkdocObject::otest signal instead.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocObject::dep-otest</name>
+ </identifier>
+ <parameters>
+ <parameter>
+ <name>self</name>
+ <description>myself</description>
+ </parameter>
+ </parameters>
+ <description>Here's an example signal handler.
+|[
+static gchar*
+otest_callback (GObject *o,
+ gpointer user_data)
+{
+ gdouble value;
+
+ value = abs (o->value);
+
+ return value;
+}
+]|</description>
+ <tags>
+ <tag>
+ <name>deprecated</name>
+ <description>Use the #GtkdocObject::otest signal instead.</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output> /**
+ * GtkdocObject::dep-otest:
+ * @self: myself
+ *
+ * Here's an example signal handler.
+ * |[
+ * static gchar*
+ * otest_callback (GObject *o,
+ * gpointer user_data)
+ * {
+ * gdouble value;
+ *
+ * value = abs (o->value);
+ *
+ * return value;
+ * }
+ * ]|
+ *
+ * Deprecated: Use the #GtkdocObject::otest signal instead.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocObject::strings-changed:
+ *
+ * Something has happened.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocObject::strings-changed</name>
+ </identifier>
+ <description>Something has happened.</description>
+ </docblock>
+ </parser>
+ <output> /**
+ * GtkdocObject::strings-changed:
+ *
+ * Something has happened.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocObject::variant-changed:
+ *
+ * Something has happened.
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocObject::variant-changed</name>
+ </identifier>
+ <description>Something has happened.</description>
+ </docblock>
+ </parser>
+ <output> /**
+ * GtkdocObject::variant-changed:
+ *
+ * Something has happened.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocObject:otest:
+ *
+ * Since: 0.1
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocObject:otest</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>since</name>
+ <value>0.1</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output> /**
+ * GtkdocObject:otest:
+ *
+ * Since: 0.1
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocObject:dep-otest:
+ *
+ * Deprecated: use #GtkdocObject:otest property
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocObject:dep-otest</name>
+ </identifier>
+ <tags>
+ <tag>
+ <name>deprecated</name>
+ <description>use #GtkdocObject:otest property</description>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output> /**
+ * GtkdocObject:dep-otest:
+ *
+ * Deprecated: use #GtkdocObject:otest property
+ */</output>
+</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..ec68a7f0
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gobject.h.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * GtkdocObject:
+ *
+ * instance data of gtk-doc unit test class
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocObject</name>
+ </identifier>
+ <description>instance data of gtk-doc unit test class</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkdocObject:
+ *
+ * instance data of gtk-doc unit test class
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocObject2:
+ *
+ * instance data of gtk-doc unit test class
+ */</input>
+ <parser>
+ <docblock>
+ <identifier>
+ <name>GtkdocObject2</name>
+ </identifier>
+ <description>instance data of gtk-doc unit test class</description>
+ </docblock>
+ </parser>
+ <output>/**
+ * GtkdocObject2:
+ *
+ * instance data of gtk-doc unit test class
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocObject2Class:
+ * @parent: this is a bug :/
+ *
+ * class data of gtk-doc unit test class
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * GtkdocObject2Class:
+ * @parent: this is a bug :/
+ *
+ * class data of gtk-doc unit test class
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GTKDOC_OBJECT_MACRO_DUMMY:
+ * @parameter_1: first arg
+ * @parameter_2: second arg
+ *
+ * This macro does nothing.
+ *
+ * Since: 0.1
+ */</input>
+ <parser>
+ <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>
+ <value>0.1</value>
+ </tag>
+ </tags>
+ </docblock>
+ </parser>
+ <output>/**
+ * GTKDOC_OBJECT_MACRO_DUMMY:
+ * @parameter_1: first arg
+ * @parameter_2: second arg
+ *
+ * This macro does nothing.
+ *
+ * Since: 0.1
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * 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
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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
+ */</output>
+</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..17d23562
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.c.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * 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.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * 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.
+ */</output>
+</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..7331a556
--- /dev/null
+++ b/tests/scanner/annotationparser/gtkdoc/gobject/gtypes.h.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests xmlns="http://schemas.gnome.org/gobject-introspection/2013/test">
+
+<test>
+ <input>/**
+ * GtkdocEnum:
+ * @GTKDOC_ENUM_V1: first
+ * @GTKDOC_ENUM_V2: second
+ * Since: 0.10
+ *
+ * Enum values for the #GtkdocEnum type.
+ */</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * GtkdocEnum:
+ * @GTKDOC_ENUM_V1: first
+ * @GTKDOC_ENUM_V2: second
+ * Since: 0.10
+ *
+ * Enum values for the #GtkdocEnum type.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocPlainOldData:
+ * @n: Some integer member.
+ * @x: Some floating point member.
+ *
+ * Unboxed plain old data that should default to public members.
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * GtkdocPlainOldData:
+ * @n: Some integer member.
+ * @x: Some floating point member.
+ *
+ * Unboxed plain old data that should default to public members.
+ */</output>
+</test>
+
+<test>
+ <input>/**
+ * GtkdocBoxedPlainOldData:
+ * @n: Some integer member.
+ * @x: Some floating point member.
+ *
+ * Boxed plain old data that should default to public members.
+ **/</input>
+ <parser>
+ <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>
+ </parser>
+ <output>/**
+ * GtkdocBoxedPlainOldData:
+ * @n: Some integer member.
+ * @x: Some floating point member.
+ *
+ * Boxed plain old data that should default to public members.
+ */</output>
+</test>
+
+</tests>
diff --git a/tests/scanner/annotationparser/test_parser.py b/tests/scanner/annotationparser/test_parser.py
new file mode 100644
index 00000000..79cc8622
--- /dev/null
+++ b/tests/scanner/annotationparser/test_parser.py
@@ -0,0 +1,461 @@
+# -*- 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 annotationparser.py continues to function correctly.
+'''
+
+
+import difflib
+import os
+import subprocess
+import unittest
+import xml.etree.ElementTree as etree
+
+from giscanner.annotationparser import GtkDocCommentBlockParser, GtkDocCommentBlockWriter
+from giscanner.ast import Namespace
+from giscanner.message import MessageLogger, WARNING, ERROR, FATAL
+
+
+XML_NS = 'http://schemas.gnome.org/gobject-introspection/2013/test'
+XML_SCHEMA = os.path.abspath(os.path.join(os.path.dirname(__file__), 'tests.xsd'))
+XML_LINT = None
+
+
+class ChunkedIO(object):
+ def __init__(self):
+ self.buffer = []
+
+ def write(self, s):
+ self.buffer.append(s)
+
+ def getvalue(self):
+ return self.buffer
+
+
+def ns(x):
+ return x.replace('{}', '{%s}' % (XML_NS, ))
+
+
+def validate(tests_file):
+ global XML_LINT
+
+ try:
+ cmd = ['xmllint', '--noout', '--nonet', '--schema', XML_SCHEMA, tests_file]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ stdout, stderr = p.communicate()
+ except OSError:
+ if XML_LINT is None:
+ XML_LINT = False
+ print('warning: xmllint not found, validation of test definition files will be skipped')
+ else:
+ if p.returncode != 0:
+ raise SystemExit(stdout)
+
+
+class TestCommentBlock(unittest.TestCase):
+ @classmethod
+ def __create_test__(cls, logger, testcase):
+ def do_test(self):
+ output = ChunkedIO()
+ logger._output = output
+
+ # Parse GTK-Doc comment block
+ commentblock = testcase.find(ns('{}input')).text
+ parsed_docblock = GtkDocCommentBlockParser().parse_comment_block(commentblock, 'test.c', 1)
+ parsed_tree = self.parsed2tree(parsed_docblock).split('\n')
+ emitted_messages = [w[w.find(':') + 1:].strip() for w in output.getvalue()]
+
+ # Get expected parser output
+ expected_docblock = testcase.find(ns('{}parser/{}docblock'))
+ expected_tree = self.expected2tree(expected_docblock).split('\n')
+
+ expected_messages = []
+ for w in testcase.findall(ns('{}parser/{}messages/{}message')):
+ expected_messages.append(w.text.strip())
+
+ # Compare parsed with expected GtkDocCommentBlock
+ msg = 'Parsed GtkDocCommentBlock object tree does not match expected output:\n\n'
+ msg += '%s\n\n' % (commentblock, )
+
+ diff = difflib.unified_diff(expected_tree, parsed_tree,
+ 'Expected GtkDocCommentBlock', 'Parsed GtkDocCommentBlock',
+ n=max(len(expected_tree), len(parsed_tree)),
+ lineterm='')
+ for line in diff:
+ msg += '%s\n' % (line, )
+
+ self.assertTrue(parsed_tree == expected_tree, msg)
+
+ # Compare emitted with expected messages
+ msg = 'Emitted messages do not match expected messages:\n\n'
+ msg += '%s\n\n' % (commentblock, )
+ msg += self._diff_messages(expected_messages, emitted_messages)
+ self.assertTrue(len(expected_messages) == len(emitted_messages), msg)
+
+ for emitted_message, expected_message in zip(emitted_messages, expected_messages):
+ msg = 'Emitted message does not match expected message:\n\n'
+ msg += '%s\n\n' % (commentblock, )
+ msg += self._diff_messages([expected_message], [emitted_message])
+ self.assertTrue(expected_message == emitted_message, msg)
+
+ # Compare serialized with expected comment block
+ expected_serialized = testcase.find(ns('{}output'))
+ indent = True
+
+ if expected_serialized is None:
+ expected_serialized = ''
+ else:
+ if 'indent' in expected_serialized.attrib:
+ indent = expected_serialized.attrib['indent']
+ if indent.lower() in ('false', '0'):
+ indent = False
+ elif indent.lower() in ('true', '1'):
+ indent = True
+ else:
+ self.assert_(False, 'Unknown value for "indent" attribute: %s' % (indent))
+
+ expected_serialized = expected_serialized.text + '\n' or None
+
+ commentblockwriter = GtkDocCommentBlockWriter(indent=indent)
+ serialized = commentblockwriter.write(parsed_docblock)
+
+ msg = 'Serialized comment block does not match expected output:\n\n'
+ msg += self._diff_messages(expected_serialized.split('\n'), serialized.split('\n'))
+ self.assertTrue(expected_serialized == serialized, msg)
+
+ return do_test
+
+ def parsed2tree(self, docblock):
+ parsed = ''
+
+ if docblock is not None:
+ parsed += '<docblock>\n'
+
+ parsed += ' <identifier>\n'
+ parsed += ' <name>%s</name>\n' % (docblock.name, )
+ if docblock.annotations:
+ parsed += ' <annotations>\n'
+ for ann_name, ann_options in docblock.annotations.items():
+ parsed += ' <annotation>\n'
+ parsed += ' <name>%s</name>\n' % (ann_name, )
+ if ann_options:
+ parsed += ' <options>\n'
+ if isinstance(ann_options, list):
+ for option in ann_options:
+ parsed += ' <option>\n'
+ parsed += ' <name>%s</name>\n' % (option, )
+ parsed += ' </option>\n'
+ else:
+ for (option, value) in ann_options.items():
+ parsed += ' <option>\n'
+ parsed += ' <name>%s</name>\n' % (option, )
+ if value:
+ parsed += ' <value>%s</value>\n' % (value, )
+ 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.annotations:
+ parsed += ' <annotations>\n'
+ for ann_name, ann_options in param.annotations.items():
+ parsed += ' <annotation>\n'
+ parsed += ' <name>%s</name>\n' % (ann_name, )
+ if ann_options:
+ parsed += ' <options>\n'
+ if isinstance(ann_options, list):
+ for option in ann_options:
+ parsed += ' <option>\n'
+ parsed += ' <name>%s</name>\n' % (option, )
+ parsed += ' </option>\n'
+ else:
+ for (option, value) in ann_options.items():
+ parsed += ' <option>\n'
+ parsed += ' <name>%s</name>\n' % (option, )
+ if value:
+ parsed += ' <value>%s</value>\n' % (value, )
+ parsed += ' </option>\n'
+ parsed += ' </options>\n'
+ parsed += ' </annotation>\n'
+ parsed += ' </annotations>\n'
+ if param.description:
+ parsed += ' <description>%s</description>\n' % (param.description, )
+ parsed += ' </parameter>\n'
+ parsed += ' </parameters>\n'
+
+ if docblock.description:
+ parsed += ' <description>%s</description>\n' % (docblock.description, )
+
+ 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.annotations:
+ parsed += ' <annotations>\n'
+ for ann_name, ann_options in tag.annotations.items():
+ parsed += ' <annotation>\n'
+ parsed += ' <name>%s</name>\n' % (ann_name, )
+ if ann_options:
+ parsed += ' <options>\n'
+ if isinstance(ann_options, list):
+ for option in ann_options:
+ parsed += ' <option>\n'
+ parsed += ' <name>%s</name>\n' % (option, )
+ parsed += ' </option>\n'
+ else:
+ for (option, value) in ann_options.items():
+ parsed += ' <option>\n'
+ parsed += ' <name>%s</name>\n' % (option, )
+ if value:
+ parsed += ' <value>%s</value>\n' % (value, )
+ parsed += ' </option>\n'
+ parsed += ' </options>\n'
+ parsed += ' </annotation>\n'
+ parsed += ' </annotations>\n'
+ if tag.value:
+ parsed += ' <value>%s</value>\n' % (tag.value, )
+ if tag.description:
+ parsed += ' <description>%s</description>\n' % (tag.description, )
+ parsed += ' </tag>\n'
+ parsed += ' </tags>\n'
+
+ parsed += '</docblock>'
+
+ return parsed
+
+ def expected2tree(self, docblock):
+ expected = ''
+
+ if docblock is not None:
+ expected += '<docblock>\n'
+
+ if docblock.find(ns('{}identifier')) is not None:
+ expected += ' <identifier>\n'
+ expected += ' <name>%s</name>\n' % (docblock.find(ns('{}identifier/{}name')).text, )
+ annotations = docblock.find(ns('{}identifier/{}annotations'))
+ if annotations is not None:
+ expected += ' <annotations>\n'
+ for annotation in annotations.findall(ns('{}annotation')):
+ expected += ' <annotation>\n'
+ expected += ' <name>%s</name>\n' % (annotation.find(ns('{}name')).text, )
+ if annotation.find(ns('{}options')) is not None:
+ expected += ' <options>\n'
+ for option in annotation.findall(ns('{}options/{}option')):
+ expected += ' <option>\n'
+ if option.find(ns('{}name')) is not None:
+ expected += ' <name>%s</name>\n' % (option.find(ns('{}name')).text, )
+ if option.find(ns('{}value')) is not None:
+ expected += ' <value>%s</value>\n' % (option.find(ns('{}value')).text, )
+ expected += ' </option>\n'
+ expected += ' </options>\n'
+ expected += ' </annotation>\n'
+ expected += ' </annotations>\n'
+ expected += ' </identifier>\n'
+
+ parameters = docblock.find(ns('{}parameters'))
+ if parameters is not None:
+ expected += ' <parameters>\n'
+ for parameter in parameters.findall(ns('{}parameter')):
+ expected += ' <parameter>\n'
+ expected += ' <name>%s</name>\n' % (parameter.find(ns('{}name')).text, )
+ annotations = parameter.find(ns('{}annotations'))
+ if annotations is not None:
+ expected += ' <annotations>\n'
+ for annotation in parameter.findall(ns('{}annotations/{}annotation')):
+ expected += ' <annotation>\n'
+ expected += ' <name>%s</name>\n' % (annotation.find(ns('{}name')).text, )
+ if annotation.find(ns('{}options')) is not None:
+ expected += ' <options>\n'
+ for option in annotation.findall(ns('{}options/{}option')):
+ expected += ' <option>\n'
+ if option.find(ns('{}name')) is not None:
+ expected += ' <name>%s</name>\n' % (option.find(ns('{}name')).text, )
+ if option.find(ns('{}value')) is not None:
+ expected += ' <value>%s</value>\n' % (option.find(ns('{}value')).text, )
+ expected += ' </option>\n'
+ expected += ' </options>\n'
+ expected += ' </annotation>\n'
+ expected += ' </annotations>\n'
+ if parameter.find(ns('{}description')) is not None:
+ expected += ' <description>%s</description>\n' % (parameter.find(ns('{}description')).text, )
+ expected += ' </parameter>\n'
+ expected += ' </parameters>\n'
+
+ description = docblock.find(ns('{}description'))
+ if description is not None:
+ expected += ' <description>%s</description>\n' % (description.text, )
+
+ tags = docblock.find(ns('{}tags'))
+ if tags is not None:
+ expected += ' <tags>\n'
+ for tag in tags.findall(ns('{}tag')):
+ expected += ' <tag>\n'
+ expected += ' <name>%s</name>\n' % (tag.find(ns('{}name')).text, )
+ annotations = tag.find(ns('{}annotations'))
+ if annotations is not None:
+ expected += ' <annotations>\n'
+ for annotation in tag.findall(ns('{}annotations/{}annotation')):
+ expected += ' <annotation>\n'
+ expected += ' <name>%s</name>\n' % (annotation.find(ns('{}name')).text, )
+ if annotation.find(ns('{}options')) is not None:
+ expected += ' <options>\n'
+ for option in annotation.findall(ns('{}options/{}option')):
+ expected += ' <option>\n'
+ if option.find(ns('{}name')) is not None:
+ expected += ' <name>%s</name>\n' % (option.find(ns('{}name')).text, )
+ if option.find(ns('{}value')) is not None:
+ expected += ' <value>%s</value>\n' % (option.find(ns('{}value')).text, )
+ expected += ' </option>\n'
+ expected += ' </options>\n'
+ expected += ' </annotation>\n'
+ expected += ' </annotations>\n'
+ if tag.find(ns('{}value')) is not None:
+ expected += ' <value>%s</value>\n' % (tag.find(ns('{}value')).text, )
+ if tag.find(ns('{}description')) is not None:
+ expected += ' <description>%s</description>\n' % (tag.find(ns('{}description')).text, )
+ expected += ' </tag>\n'
+ expected += ' </tags>\n'
+
+ expected += '</docblock>'
+
+ return expected
+
+ def _diff_messages(self, a, b):
+ retval = ''
+ started = False
+
+ for group in difflib.SequenceMatcher(None, a, b).get_grouped_opcodes(3):
+ if not started:
+ started = True
+ retval += '--- expected\n'
+ retval += '+++ emitted\n'
+
+ for tag, i1, i2, j1, j2 in group:
+ if tag == 'equal':
+ for line in a[i1:i2]:
+ for l in line.split('\n'):
+ retval += ' ' + l + '\n'
+ continue
+
+ if tag in ('replace', 'delete'):
+ for line in a[i1:i2]:
+ for l in line.split('\n'):
+ retval += '-' + l + '\n'
+
+ if tag in ('replace', 'insert'):
+ for line in b[j1:j2]:
+ for l in line.split('\n'):
+ retval += '+' + l + '\n'
+
+ return retval
+
+
+def create_test_case(logger, tests_dir, tests_file):
+ tests_tree = etree.parse(tests_file).getroot()
+
+ fix_cdata_elements = tests_tree.findall(ns('{}test/{}input'))
+ fix_cdata_elements += tests_tree.findall(ns('.//{}description'))
+ fix_cdata_elements += tests_tree.findall(ns('{}test/{}output'))
+
+ for element in fix_cdata_elements:
+ if element.text:
+ element.text = element.text.replace('{{?', '<!')
+ element.text = element.text.replace('}}', '>')
+
+ test_methods = {}
+ for counter, test in enumerate(tests_tree.findall(ns('{}test'))):
+ test_name = 'test_%03d' % (counter + 1)
+ test_method = TestCommentBlock.__create_test__(logger, test)
+ test_method.__name__ = test_name
+ test_methods[test_name] = test_method
+
+ # Dynamically generate a new subclass of TestCommentBlock in TitleCase
+ # with generated test methods.
+ test_class_name = os.path.relpath(tests_file[:-4], tests_dir)
+ test_class_name = test_class_name.replace('/', ' ').replace('\\', ' ').replace('.', ' ')
+ test_class_name = 'Test' + test_class_name.title().replace(' ', '')
+ return type(test_class_name, (TestCommentBlock,), test_methods)
+
+
+def create_test_cases():
+ # Initialize message logger
+ namespace = Namespace('Test', '1.0')
+ logger = MessageLogger.get(namespace=namespace)
+ logger.enable_warnings((WARNING, ERROR, FATAL))
+ test_cases = {}
+
+ # 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'):
+ validate(tests_file)
+ test_case = create_test_case(logger, tests_dir, tests_file)
+ test_cases[test_case.__name__] = test_case
+
+ return test_cases
+
+
+# We currently need to push all the new test cases into the modules globals
+# in order for parameterized tests to work. Ideally all that should be needed
+# is the "load_tests" hook, but this does not work in the case were the tests
+# are run in parameterized mode, e.g: python -m unittest test_parser.Test...
+_all_tests = create_test_cases()
+globals().update(_all_tests)
+
+
+# Hook function for Python test loader.
+def load_tests(loader, tests, pattern):
+ suite = unittest.TestSuite()
+ # add standard tests from module
+ suite.addTests(tests)
+
+ # Initialize message logger
+ namespace = Namespace('Test', '1.0')
+ logger = MessageLogger.get(namespace=namespace)
+ logger.enable_warnings((WARNING, ERROR, FATAL))
+
+ # Load test cases from disc
+ tests_dir = os.path.dirname(os.path.abspath(__file__))
+
+ for name, test_case in _all_tests.iteritems():
+ tests = loader.loadTestsFromTestCase(test_case)
+ suite.addTests(tests)
+ return suite
+
+
+if __name__ == '__main__':
+ # 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..774d674c
--- /dev/null
+++ b/tests/scanner/annotationparser/test_patterns.py
@@ -0,0 +1,943 @@
+# -*- 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 (COMMENT_BLOCK_START_RE, COMMENT_BLOCK_END_RE,
+ COMMENT_ASTERISK_RE, INDENTATION_RE, EMPTY_LINE_RE,
+ SECTION_RE, SYMBOL_RE, PROPERTY_RE,
+ SIGNAL_RE, PARAMETER_RE, TAG_RE,
+ TAG_VALUE_VERSION_RE, TAG_VALUE_STABILITY_RE)
+import unittest
+
+
+comment_start_tests = [
+ (COMMENT_BLOCK_START_RE, '/**',
+ {'code': '',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, ' /**',
+ {'code': '',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, ' /** ',
+ {'code': '',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, 'xyz /** ',
+ {'code': 'xyz',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, ' xyz /** ',
+ {'code': ' xyz',
+ 'token': '/**',
+ 'comment': ''}),
+ (COMMENT_BLOCK_START_RE, '/** xyz',
+ {'code': '',
+ 'token': '/**',
+ 'comment': 'xyz'}),
+ (COMMENT_BLOCK_START_RE, ' /**xyz',
+ {'code': '',
+ 'token': '/**',
+ 'comment': 'xyz'}),
+ (COMMENT_BLOCK_START_RE, ' /** xyz',
+ {'code': '',
+ 'token': '/**',
+ 'comment': 'xyz'}),
+ (COMMENT_BLOCK_START_RE, '/***',
+ None),
+ (COMMENT_BLOCK_START_RE, ' /***',
+ None),
+ (COMMENT_BLOCK_START_RE, ' /*** ',
+ None),
+ (COMMENT_BLOCK_START_RE, '/*** xyz',
+ None),
+ (COMMENT_BLOCK_START_RE, '/***** xyz',
+ None),
+ (COMMENT_BLOCK_START_RE, ' /*****xyz',
+ None),
+ (COMMENT_BLOCK_START_RE, ' /**/',
+ None),
+]
+
+
+comment_end_tests = [
+ (COMMENT_BLOCK_END_RE, '*/',
+ {'comment': '',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' */',
+ {'comment': '',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' */ ',
+ {'comment': '',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, '*/xyz',
+ {'comment': '',
+ 'token': '*/',
+ 'code': 'xyz'}),
+ (COMMENT_BLOCK_END_RE, ' */xyz',
+ {'comment': '',
+ 'token': '*/',
+ 'code': 'xyz'}),
+ (COMMENT_BLOCK_END_RE, ' */ xyz',
+ {'comment': '',
+ 'token': '*/',
+ 'code': ' xyz'}),
+ (COMMENT_BLOCK_END_RE, '**/',
+ {'comment': '',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' **/',
+ {'comment': '',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' **/ ',
+ {'comment': '',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, 'test */',
+ {'comment': 'test',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' test*/',
+ {'comment': 'test',
+ 'token': '*/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, 'test */ xyz',
+ {'comment': 'test',
+ 'token': '*/',
+ 'code': ' xyz'}),
+ (COMMENT_BLOCK_END_RE, ' test*/ xyz ',
+ {'comment': 'test',
+ 'token': '*/',
+ 'code': ' xyz'}),
+ (COMMENT_BLOCK_END_RE, 'test **/',
+ {'comment': 'test',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' test**/',
+ {'comment': 'test',
+ 'token': '**/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, 'test *****/',
+ {'comment': 'test',
+ 'token': '*****/',
+ 'code': ''}),
+ (COMMENT_BLOCK_END_RE, ' test*****/',
+ {'comment': 'test',
+ 'token': '*****/',
+ 'code': ''})]
+
+
+comment_asterisk_tests = [
+ (COMMENT_ASTERISK_RE, '*',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, '* ',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, ' *',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, ' * ',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, ' * ',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, ' * test',
+ {'comment': ''}),
+ (COMMENT_ASTERISK_RE, 'test * ',
+ {'comment': 'test'})]
+
+
+indentaton_tests = [
+ (INDENTATION_RE, '',
+ {'indentation': ''}),
+ (INDENTATION_RE, ' ',
+ {'indentation': ' '}),
+ (INDENTATION_RE, ' ',
+ {'indentation': ' '}),
+ (INDENTATION_RE, ' x',
+ {'indentation': ' '}),
+ (INDENTATION_RE, ' *',
+ {'indentation': ' '})]
+
+
+empty_line_tests = [
+ (EMPTY_LINE_RE, '',
+ {}),
+ (EMPTY_LINE_RE, ' ',
+ {}),
+ (EMPTY_LINE_RE, ' .',
+ None)]
+
+
+identifier_section_tests = [
+ (SECTION_RE, 'TSIEOCN',
+ None),
+ (SECTION_RE, 'section',
+ None),
+ (SECTION_RE, 'section:',
+ None),
+ (SECTION_RE, 'section:test',
+ None),
+ (SECTION_RE, 'SECTION',
+ None),
+ (SECTION_RE, 'SECTION \t ',
+ None),
+ (SECTION_RE, ' \t SECTION \t ',
+ None),
+ (SECTION_RE, 'SECTION: \t ',
+ None),
+ (SECTION_RE, 'SECTION : ',
+ None),
+ (SECTION_RE, ' SECTION : ',
+ None),
+ (SECTION_RE, 'SECTION:gtkwidget',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION:gtkwidget ',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, ' SECTION:gtkwidget',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, ' SECTION:gtkwidget\t ',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION: gtkwidget ',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION : gtkwidget',
+ {'delimiter': ':',
+ 'section_name': 'gtkwidget'}),
+ (SECTION_RE, 'SECTION gtkwidget \f ',
+ {'delimiter': '',
+ 'section_name': 'gtkwidget'})]
+
+identifier_symbol_tests = [
+ (SYMBOL_RE, 'GBaseFinalizeFunc:',
+ {'delimiter': ':',
+ 'symbol_name': 'GBaseFinalizeFunc',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show ',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show ',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show:',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show :',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show: ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show : ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show:',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show :',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show: ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, ' gtk_widget_show : ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': ''}),
+ (SYMBOL_RE, 'gtk_widget_show:(skip):',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show (skip)',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) \t ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) \t ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)'}),
+ (SYMBOL_RE, 'gtk_widget_show:(skip)(test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)(test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show (skip)(test1)',
+ {'delimiter': '',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip)(test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip) (test1)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show: (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, 'gtk_widget_show : (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show:(skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show :(skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show: (skip) (test1) (test-2)',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) (test-2) ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ (SYMBOL_RE, ' gtk_widget_show : (skip) (test1) (test-2) ',
+ {'delimiter': ':',
+ 'symbol_name': 'gtk_widget_show',
+ 'fields': '(skip) (test1) (test-2)'}),
+ # constants
+ (SYMBOL_RE, 'MY_CONSTANT:',
+ {'delimiter': ':',
+ 'symbol_name': 'MY_CONSTANT',
+ 'fields': ''}),
+ # structs
+ (SYMBOL_RE, 'FooWidget:',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': ''}),
+ # enums
+ (SYMBOL_RE, 'Something:',
+ {'delimiter': ':',
+ 'symbol_name': 'Something',
+ 'fields': ''}),
+ # annotations with multiple closing parentheses
+ (SYMBOL_RE, 'FooWidget: (transfer full) (type GLib.List(utf8))',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(transfer full) (type GLib.List(utf8))'}),
+ (SYMBOL_RE, 'FooWidget: (transfer full) (type GLib.List((utf8)))',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(transfer full) (type GLib.List((utf8)))'}),
+ (SYMBOL_RE, 'FooWidget: (transfer full) (type GLib.List(GLib.List(utf8)))',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(transfer full) (type GLib.List(GLib.List(utf8)))'}),
+ (SYMBOL_RE, 'FooWidget: (type GLib.List(GLib.List(utf8))) (transfer full)',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(type GLib.List(GLib.List(utf8))) (transfer full)'}),
+ (SYMBOL_RE, 'FooWidget: (type GLib.List(GLib.List(utf8)))(transfer full)(type GLib.List(GLib.List(utf8)))',
+ {'delimiter': ':',
+ 'symbol_name': 'FooWidget',
+ 'fields': '(type GLib.List(GLib.List(utf8)))(transfer full)(type GLib.List(GLib.List(utf8)))'})]
+
+identifier_property_tests = [
+ # simple property name
+ (PROPERTY_RE, 'GtkWidget:name (skip)',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': '(skip)'}),
+ (PROPERTY_RE, 'GtkWidget:name',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget :name',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget: name ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget : name ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget:name:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget:name: ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget:name:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Something:name:',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Something:name: ',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, ' Something:name:',
+ {'class_name': 'Something',
+ 'property_name': 'name',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Weird-thing:name:',
+ None),
+ (PROPERTY_RE, 'really-weird_thing:name:',
+ None),
+ (PROPERTY_RE, 'GWin32InputStream:handle:',
+ {'class_name': 'GWin32InputStream',
+ 'property_name': 'handle',
+ 'delimiter': ':',
+ 'fields': ''}),
+ # properties: property name that contains a dash
+ (PROPERTY_RE, 'GtkWidget:double-buffered (skip)',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': '(skip)'}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget :double-buffered',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget: double-buffered ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget : double-buffered ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': '',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'GtkWidget:double-buffered: ',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, ' GtkWidget:double-buffered:',
+ {'class_name': 'GtkWidget',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Something:double-buffered:',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, 'Something:double-buffered: ',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (PROPERTY_RE, ' Something:double-buffered:',
+ {'class_name': 'Something',
+ 'property_name': 'double-buffered',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (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',
+ 'delimiter': ':',
+ 'fields': '(skip)'}),
+ # properties: data with multiple closing parentheses
+ (PROPERTY_RE, 'GMemoryOutputStream:realloc-function: (transfer full) (type GLib.List(utf8))',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List(utf8))'}),
+ (PROPERTY_RE, 'GMemoryOutputStream:realloc-function: (transfer full) (type GLib.List((utf8)))',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List((utf8)))'}),
+ (PROPERTY_RE, 'GMemoryOutputStream:realloc-function: (transfer full) (type GLib.List(GLib.List(utf8)))',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List(GLib.List(utf8)))'}),
+ (PROPERTY_RE, 'GMemoryOutputStream:realloc-function: (type GLib.List(GLib.List(utf8))) (transfer full)',
+ {'class_name': 'GMemoryOutputStream',
+ 'property_name': 'realloc-function',
+ 'delimiter': ':',
+ 'fields': '(type GLib.List(GLib.List(utf8))) (transfer full)'})]
+
+identifier_signal_tests = [
+ # simple signal name
+ (SIGNAL_RE, 'GtkWidget::changed: (skip)',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'changed',
+ 'delimiter': ':',
+ 'fields': '(skip)'}),
+ (SIGNAL_RE, 'GtkWidget::changed:',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'changed',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (SIGNAL_RE, 'Something::changed:',
+ {'class_name': 'Something',
+ 'signal_name': 'changed',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (SIGNAL_RE, 'Weird-thing::changed:',
+ None),
+ (SIGNAL_RE, 'really-weird_thing::changed:',
+ None),
+ # signals: signal name that contains a dash
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (skip)',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(skip)'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed:',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (SIGNAL_RE, 'Something::hierarchy-changed:',
+ {'class_name': 'Something',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': ''}),
+ (SIGNAL_RE, 'Weird-thing::hierarchy-changed:',
+ None),
+ (SIGNAL_RE, 'really-weird_thing::hierarchy-changed:',
+ None),
+ # signals: data with multiple closing parentheses
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (transfer full) (type GLib.List(utf8))',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List(utf8))'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (transfer full) (type GLib.List((utf8)))',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List((utf8)))'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (transfer full) (type GLib.List(GLib.List(utf8)))',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(transfer full) (type GLib.List(GLib.List(utf8)))'}),
+ (SIGNAL_RE, 'GtkWidget::hierarchy-changed: (type GLib.List(GLib.List(utf8))) (transfer full)',
+ {'class_name': 'GtkWidget',
+ 'signal_name': 'hierarchy-changed',
+ 'delimiter': ':',
+ 'fields': '(type GLib.List(GLib.List(utf8))) (transfer full)'})]
+
+parameter_tests = [
+ (PARAMETER_RE, '@Short_description: Base class for all widgets ',
+ {'parameter_name': 'Short_description',
+ 'fields': 'Base class for all widgets'}),
+ (PARAMETER_RE, '@...: the value of the first property, followed optionally by more',
+ {'parameter_name': '...',
+ 'fields': 'the value of the first property, followed optionally by more'}),
+ (PARAMETER_RE, '@args...: list of arguments',
+ {'parameter_name': 'args...',
+ 'fields': 'list of arguments'}),
+ (PARAMETER_RE, '@widget: a #GtkWidget',
+ {'parameter_name': 'widget',
+ 'fields': 'a #GtkWidget'}),
+ (PARAMETER_RE, '@widget_pointer: (inout) (transfer none): '
+ 'address of a variable that contains @widget',
+ {'parameter_name': 'widget_pointer',
+ 'fields': '(inout) (transfer none): 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',
+ 'fields': '(inout) (transfer none) (allow-none) (attribute) (destroy) '
+ '(foreign) (inout) (out) (transfer) (skip) (method): '
+ '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',
+ 'fields': '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',
+ 'fields': 'a #GSequenceIter'}),
+ (PARAMETER_RE, '@keys: (array length=n_keys) (element-type GQuark) (allow-none):',
+ {'parameter_name': 'keys',
+ 'fields': '(array length=n_keys) (element-type GQuark) (allow-none):'}),
+ # parentheses in description
+ (PARAMETER_RE, '@foo: This is a foo (be careful using it)',
+ {'parameter_name': 'foo',
+ 'fields': 'This is a foo (be careful using it)'}),
+ (PARAMETER_RE, '@foo: This is a foo (be careful using it) and see also: bar',
+ {'parameter_name': 'foo',
+ 'fields': 'This is a foo (be careful using it) and see also: bar'}),
+ (PARAMETER_RE, '@foo: This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': 'This is a foo (be careful using it) and see also: bar and baz'}),
+ # annotations with multiple closing parentheses, combined with parentheses in description
+ (PARAMETER_RE, '@foo: (transfer full) (element-type guint8): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(transfer full) (element-type guint8): This is a foo (be careful using it) and see also: bar and baz'}),
+ (PARAMETER_RE, '@foo: (transfer full) (element-type GLib.List(utf8)): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(transfer full) (element-type GLib.List(utf8)): This is a foo (be careful using it) and see also: bar and baz'}),
+ (PARAMETER_RE, '@foo: (transfer full) (element-type GLib.List((utf8))): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(transfer full) (element-type GLib.List((utf8))): This is a foo (be careful using it) and see also: bar and baz'}),
+ (PARAMETER_RE, '@foo: (transfer full) (element-type GLib.List(GLib.List(utf8))): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(transfer full) (element-type GLib.List(GLib.List(utf8))): This is a foo (be careful using it) and see also: bar and baz'}),
+ (PARAMETER_RE, '@foo: (element-type GLib.List(GLib.List(utf8))) (transfer full): This is a foo (be careful using it) and see also: bar and baz',
+ {'parameter_name': 'foo',
+ 'fields': '(element-type GLib.List(GLib.List(utf8))) (transfer full): This is a foo (be careful using it) and see also: bar and baz'})]
+
+tag_tests = [
+ (TAG_RE, 'Since 3.0',
+ None),
+ (TAG_RE, 'Since: 3.0',
+ {'tag_name': 'Since',
+ 'fields': '3.0'}),
+ (TAG_RE, 'Attributes: (inout) (transfer none): some note about attributes',
+ {'tag_name': 'Attributes',
+ 'fields': '(inout) (transfer none): some note about attributes'}),
+ (TAG_RE, 'Rename to: something_else',
+ {'tag_name': 'Rename to',
+ 'fields': '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',
+ 'fields': 'a #GtkWidget'}),
+ (TAG_RE, 'Return value: (transfer none): The binary data that @text responds. '
+ 'This pointer',
+ {'tag_name': 'Return value',
+ 'fields': '(transfer none): 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',
+ 'fields': '(transfer full) (array length=out_len) (element-type guint8):'}),
+ (TAG_RE, 'Returns: A boolean value, but let me tell you a bit about this boolean. It',
+ {'tag_name': 'Returns',
+ 'fields': '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',
+ 'fields': '(transfer container) (element-type GObject.ParamSpec): a'}),
+ (TAG_RE, 'Return value: (type GLib.HashTable<utf8,GLib.HashTable<utf8,utf8>>) '
+ '(transfer full):',
+ {'tag_name': 'Return value',
+ 'fields': '(type GLib.HashTable<utf8,GLib.HashTable<utf8,utf8>>) (transfer full):'}),
+ # parentheses in description
+ (TAG_RE, 'Returns: Returns a foo (be careful using it)',
+ {'tag_name': 'Returns',
+ 'fields': 'Returns a foo (be careful using it)'}),
+ (TAG_RE, 'Returns: Returns a foo (be careful using it) and see also: bar',
+ {'tag_name': 'Returns',
+ 'fields': 'Returns a foo (be careful using it) and see also: bar'}),
+ (TAG_RE, 'Returns: Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': 'Returns a foo (be careful using it) and see also: bar and baz'}),
+ # annotations with multiple closing parentheses, combined with parentheses in description
+ (TAG_RE, 'Returns: (transfer full) (element-type guint8): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer full) (element-type guint8): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (transfer full) (element-type GLib.List(utf8)): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer full) (element-type GLib.List(utf8)): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (transfer full) (element-type GLib.List((utf8))): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer full) (element-type GLib.List((utf8))): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (transfer full) (element-type GLib.List(GLib.List(utf8))): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(transfer full) (element-type GLib.List(GLib.List(utf8))): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (element-type GLib.List(GLib.List(utf8))) (transfer full): Returns a foo (be careful using it) and see also: bar and baz',
+ {'tag_name': 'Returns',
+ 'fields': '(element-type GLib.List(GLib.List(utf8))) (transfer full): Returns a foo (be careful using it) and see also: bar and baz'}),
+ (TAG_RE, 'Returns: (element-type utf8=invalid GLib.HashTable(utf8,utf8) invalid): returns %NULL.',
+ {'tag_name': 'Returns',
+ 'fields': '(element-type utf8=invalid GLib.HashTable(utf8,utf8) invalid): returns %NULL.'})]
+
+
+tag_value_version_tests = [
+ (TAG_VALUE_VERSION_RE, ' abc',
+ {'value': '',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_VERSION_RE, '5 abc',
+ {'value': '5',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_VERSION_RE, '5:abc',
+ {'value': '5',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_VERSION_RE, ' 0.1: abc',
+ {'value': '0.1',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_VERSION_RE, ' 12.10.3698: abc',
+ {'value': '12.10.3698',
+ 'delimiter': ':',
+ 'description': 'abc'})]
+
+
+tag_value_stability_tests = [
+ (TAG_VALUE_STABILITY_RE, ' abc',
+ {'value': '',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'stable abc',
+ {'value': 'stable',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'unstable abc',
+ {'value': 'unstable',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'private abc',
+ {'value': 'private',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'internal abc',
+ {'value': 'internal',
+ 'delimiter': '',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'StAbLe: abc',
+ {'value': 'StAbLe',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'uNsTaBlE: abc',
+ {'value': 'uNsTaBlE',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'PRIVATE: abc',
+ {'value': 'PRIVATE',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, ' internal : abc',
+ {'value': 'internal',
+ 'delimiter': ':',
+ 'description': 'abc'}),
+ (TAG_VALUE_STABILITY_RE, 'xyz: abc',
+ {'value': '',
+ 'delimiter': '',
+ 'description': 'xyz: abc'})]
+
+
+def create_test_method(testcase):
+ def do_test(self):
+ (program, text, expected) = testcase
+
+ match = program.match(text)
+
+ if match is not None:
+ msg = 'Test matched pattern but specifies no expected named groups.'
+ self.assertTrue(isinstance(expected, dict), msg)
+
+ for group in match.groupdict().keys():
+ msg = 'Test case is missing expected results for named group "%s".' % (group)
+ self.assertTrue(group in expected.keys(), msg)
+
+ 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
+
+
+def create_test_case(tests_class_name, testcases):
+ test_methods = {}
+ for (index, testcase) in enumerate(testcases):
+ test_method_name = 'test_%03d' % index
+
+ test_method = create_test_method(testcase)
+ test_method.__name__ = test_method_name
+ test_methods[test_method_name] = test_method
+
+ return type(tests_class_name, (unittest.TestCase,), test_methods)
+
+
+def create_test_cases():
+ test_cases = {}
+ for name, test_data in (('TestCommentStart', comment_start_tests),
+ ('TestCommentEnd', comment_end_tests),
+ ('TestCommentAsterisk', comment_asterisk_tests),
+ ('TestIndentaton', indentaton_tests),
+ ('TestEmptyLine', empty_line_tests),
+ ('TestIdentifierSection', identifier_section_tests),
+ ('TestIdentifierSymbol', identifier_symbol_tests),
+ ('TestIdentifierProperty', identifier_property_tests),
+ ('TestIdentifierSignal', identifier_signal_tests),
+ ('TestParameter', parameter_tests),
+ ('TestTag', tag_tests),
+ ('TestTagValueVersion', tag_value_version_tests),
+ ('TestTagValueStability', tag_value_stability_tests)):
+ test_cases[name] = create_test_case(name, test_data)
+
+ return test_cases
+
+
+# We currently need to push all the new test cases into the modules globals
+# in order for parameterized tests to work. Ideally all that should be needed
+# is the "load_tests" hook, but this does not work in the case were the tests
+# are run in parameterized mode, e.g: python -m unittest test_parser.Test...
+_all_tests = create_test_cases()
+globals().update(_all_tests)
+
+
+# Hook function for Python test loader.
+def load_tests(loader, tests, pattern):
+ suite = unittest.TestSuite()
+ # add standard tests from module
+ suite.addTests(tests)
+
+ for name, test_case in _all_tests.iteritems():
+ tests = loader.loadTestsFromTestCase(test_case)
+ suite.addTests(tests)
+ return suite
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scanner/annotationparser/tests.xsd b/tests/scanner/annotationparser/tests.xsd
new file mode 100644
index 00000000..ca47cfe7
--- /dev/null
+++ b/tests/scanner/annotationparser/tests.xsd
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:t="http://schemas.gnome.org/gobject-introspection/2013/test"
+ targetNamespace="http://schemas.gnome.org/gobject-introspection/2013/test"
+ elementFormDefault="qualified"
+ version="1.0.0">
+
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+ GObject-Introspection - a framework for introspecting GObject libraries
+ Copyright © 2013 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.]]>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:simpleType name="PreservedStringtype">
+ <xs:restriction base="xs:string">
+ <xs:whiteSpace value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="OutputType">
+ <xs:simpleContent>
+ <xs:extension base="t:PreservedStringtype">
+ <xs:attribute name="indent" type="xs:boolean" default="true" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:element name="tests">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="t:test" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="test">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="input" type="t:PreservedStringtype" />
+ <xs:element ref="t:parser" minOccurs="0" />
+ <xs:element name="output" minOccurs="0" type="t:OutputType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="parser">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="t:docblock" minOccurs="0" />
+ <xs:element ref="t:messages" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="docblock">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="t:identifier" />
+ <xs:element ref="t:parameters" minOccurs="0" />
+ <xs:element name="description" type="t:PreservedStringtype" minOccurs="0" />
+ <xs:element ref="t:tags" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="identifier">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="name" type="xs:string" />
+ <xs:element ref="t:annotations" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="tags">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="t:tag" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="tag">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="name" />
+ <xs:element ref="t:annotations" minOccurs="0" />
+ <xs:element name="value" minOccurs="0" />
+ <xs:element name="description" type="t:PreservedStringtype" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="parameters">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="t:parameter" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="parameter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="name" />
+ <xs:element ref="t:annotations" minOccurs="0" />
+ <xs:element name="description" type="t:PreservedStringtype" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="annotations">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="t:annotation" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="annotation">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="name" />
+ <xs:element ref="t:options" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="options">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="t:option" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="option">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="name" />
+ <xs:element name="value" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="messages">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="message" type="t:PreservedStringtype" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>