giscanner: update annotationparser to most recent gtkdoc-mkdb bug fixes.
authorDieter Verfaillie <dieterv@optionexplicit.be>
Tue, 17 Jul 2012 15:19:14 +0000 (17:19 +0200)
committerDieter Verfaillie <dieterv@optionexplicit.be>
Wed, 28 Nov 2012 20:31:23 +0000 (21:31 +0100)
This patch adds a test for and implements a more generic solution to
GTK-Doc commit 47abcd53b8489ebceec9e394676512a181c1f1f6

https://bugzilla.gnome.org/show_bug.cgi?id=688897

giscanner/annotationparser.py
tests/scanner/annotationparser/gi/syntax_nested_tags.xml [new file with mode: 0644]
tests/scanner/annotationparser/gtkdoc/gobject/gtypes.h.xml

index f1fbfda..8c48d0a 100644 (file)
@@ -178,6 +178,19 @@ COMMENT_ASTERISK_RE = re.compile(r'''
     ''',
     re.VERBOSE)
 
+# Program matching the indentation at the beginning of every
+# line (stripped from the ' * ') inside a comment block.
+#
+# Results in 1 symbolic group:
+#   - group 1 = indentation
+COMMENT_INDENTATION_RE = re.compile(r'''
+    ^
+    (?P<indentation>[^\S\n\r]*)              # 0 or more whitespace characters
+    .*
+    $
+    ''',
+    re.VERBOSE)
+
 # Program matching an empty line.
 #
 # Results in 0 symbolic groups.
@@ -726,13 +739,13 @@ class AnnotationParser(object):
 
     .. NOTE:: :class:`AnnotationParser` functionality is heavily based on gtkdoc-mkdb's
         `ScanSourceFile()`_ function and is currently in sync with GTK-Doc
-        commit `b41641b`_.
+        commit `47abcd5`_.
 
     .. _GTK-Doc's documentation:
             http://developer.gnome.org/gtk-doc-manual/1.18/documenting.html.en
     .. _ScanSourceFile():
             http://git.gnome.org/browse/gtk-doc/tree/gtkdoc-mkdb.in#n3722
-    .. _b41641b: b41641bd75f870afff7561ceed8a08456da57565
+    .. _47abcd5: 47abcd53b8489ebceec9e394676512a181c1f1f6
     """
 
     def parse(self, comments):
@@ -821,6 +834,8 @@ class AnnotationParser(object):
                 http://git.gnome.org/browse/gtk-doc/tree/gtkdoc-mkdb.in#n3722
         """
         comment_block = None
+        part_indent = None
+        line_indent = None
         in_part = None
         identifier = None
         current_param = None
@@ -841,6 +856,10 @@ class AnnotationParser(object):
                 column_offset = result.end(0)
                 line = line[result.end(0):]
 
+            # Store indentation level of the line.
+            result = COMMENT_INDENTATION_RE.match(line)
+            line_indent = len(result.group('indentation').replace('\t', '  '))
+
             ####################################################################
             # Check for GTK-Doc comment block identifier.
             ####################################################################
@@ -877,6 +896,7 @@ class AnnotationParser(object):
 
                 if identifier:
                     in_part = PART_IDENTIFIER
+                    part_indent = line_indent
 
                     comment_block = DocBlock(identifier_name)
                     comment_block.position = position
@@ -923,6 +943,8 @@ class AnnotationParser(object):
                 if in_part == PART_IDENTIFIER:
                     in_part = PART_PARAMETERS
 
+                part_indent = line_indent
+
                 if in_part != PART_PARAMETERS:
                     column = result.start('parameter_name') + column_offset
                     marker = ' '*column + '^'
@@ -970,13 +992,14 @@ class AnnotationParser(object):
             if (EMPTY_LINE_RE.match(line)
             and in_part in [PART_IDENTIFIER, PART_PARAMETERS]):
                 in_part = PART_DESCRIPTION
+                part_indent = line_indent
                 continue
 
             ####################################################################
             # Check for GTK-Doc comment block tags.
             ####################################################################
             result = TAG_RE.match(line)
-            if result:
+            if result and line_indent <= part_indent:
                 tag_name = result.group('tag_name')
                 tag_annotations = result.group('annotations')
                 tag_description = result.group('description')
@@ -990,6 +1013,7 @@ class AnnotationParser(object):
                                  position)
 
                     in_part = PART_DESCRIPTION
+                    part_indent = line_indent
 
                     if not comment_block.comment:
                         comment_block.comment = tag_description
@@ -1001,6 +1025,8 @@ class AnnotationParser(object):
                 if in_part == PART_DESCRIPTION:
                     in_part = PART_TAGS
 
+                part_indent = line_indent
+
                 if in_part != PART_TAGS:
                     column = result.start('tag_name') + column_offset
                     marker = ' '*column + '^'
diff --git a/tests/scanner/annotationparser/gi/syntax_nested_tags.xml b/tests/scanner/annotationparser/gi/syntax_nested_tags.xml
new file mode 100644 (file)
index 0000000..d07b6f1
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<tests>
+
+<test>
+  <!--
+  Well, not really nested tags as the Since: 2.30 is considered to be part of the
+  description of the @G_APPLICATION_NON_UNIQUE parameter.
+  -->
+  <commentblock>/**
+ * GApplicationFlags:
+ * @G_APPLICATION_NON_UNIQUE: Make no attempts to do any of the typical
+ *     single-instance application negotiation, even if the application
+ *     ID is given.  The application neither attempts to become the
+ *     owner of the application ID nor does it check if an existing
+ *     owner already exists.  Everything occurs in the local process.
+ *     Since: 2.30.
+ *
+ * Flags used to define the behaviour of a #GApplication.
+ *
+ * Since: 2.28
+ **/</commentblock>
+  <docblock>
+    <identifier>
+      <name>GApplicationFlags</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>G_APPLICATION_NON_UNIQUE</name>
+        <description>Make no attempts to do any of the typical single-instance application negotiation, even if the application ID is given.  The application neither attempts to become the owner of the application ID nor does it check if an existing owner already exists.  Everything occurs in the local process. Since: 2.30.</description>
+      </parameter>
+    </parameters>
+    <description>Flags used to define the behaviour of a #GApplication.</description>
+    <tags>
+      <tag>
+        <name>since</name>
+        <description>2.28</description>
+      </tag>
+    </tags>
+  </docblock>
+</test>
+
+</tests>
index f4e76e5..1d18827 100644 (file)
@@ -4,6 +4,33 @@
 
 <test>
   <commentblock>/**
+ * GtkdocEnum:
+ * @GTKDOC_ENUM_V1: first
+ * @GTKDOC_ENUM_V2: second
+ *    Since: 0.10
+ *
+ * Enum values for the #GtkdocEnum type.
+ */</commentblock>
+  <docblock>
+    <identifier>
+      <name>GtkdocEnum</name>
+    </identifier>
+    <parameters>
+      <parameter>
+        <name>GTKDOC_ENUM_V1</name>
+        <description>first</description>
+      </parameter>
+      <parameter>
+        <name>GTKDOC_ENUM_V2</name>
+        <description>second Since: 0.10</description>
+      </parameter>
+    </parameters>
+    <description>Enum values for the #GtkdocEnum type.</description>
+  </docblock>
+</test>
+
+<test>
+  <commentblock>/**
  * GtkdocPlainOldData:
  * @n: Some integer member.
  * @x: Some floating point member.