[gtk-doc] mkdb: extract helper function in sctruct output generation



commit 9b85fb55b6a2f0dcf5552753b5fd58ac3c368d72
Author: Stefan Sauer <ensonic users sf net>
Date:   Sun Jul 28 10:44:13 2019 +0200

    mkdb: extract helper function in sctruct output generation
    
    Add some tests for it too.
    See #95

 gtkdoc/mkdb.py | 90 ++++++++++++++++++++++++++++++++--------------------------
 tests/mkdb.py  | 47 ++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+), 40 deletions(-)
---
diff --git a/gtkdoc/mkdb.py b/gtkdoc/mkdb.py
index 5658449..009e99e 100644
--- a/gtkdoc/mkdb.py
+++ b/gtkdoc/mkdb.py
@@ -1209,6 +1209,55 @@ def uri_escape(text):
     return re.sub(r"([^A-Za-z0-9\-_.!~*'()]", do_escape, text)
 
 
+def extract_struct_body(symbol, decl, has_typedef, public):
+    """Returns a normalized struct body.
+
+    Normalizes whitespace and newlines and supresses non public members.
+
+    Returns:
+      str: the nomalized struct declaration
+    """
+    decl_out = ''
+
+    m = re.search(
+        r'^\s*(typedef\s+)?struct\s*\w*\s*(?:\/\*.*\*\/)?\s*{(.*)}\s*\w*\s*;\s*$', decl, flags=re.DOTALL)
+    if m:
+        new_boby = ''
+        for line in m.group(2).splitlines():
+            logging.info("Struct line: %s", line)
+            m2 = re.search(r'/\*\s*<\s*public\s*>\s*\*/', line)
+            m3 = re.search(r'/\*\s*<\s*(private|protected)\s*>\s*\*/', line)
+            if m2:
+                public = True
+            elif m3:
+                public = False
+            elif public:
+                new_boby += line + "\n"
+
+        if new_boby:
+            # Strip any blank lines off the ends.
+            new_boby = re.sub(r'^\s*\n', '', new_boby)
+            new_boby = re.sub(r'\n\s*$', r'\n', new_boby)
+
+            if has_typedef:
+                decl_out = "typedef struct {\n%s} %s;\n" % (new_boby, symbol)
+            else:
+                decl_out = "struct %s {\n%s};\n" % (symbol, new_boby)
+    else:
+        common.LogWarning(*GetSymbolSourceLocation(symbol),
+                          "Couldn't parse struct:\n%s" % decl)
+
+    if decl_out == '':
+        # If we couldn't parse the struct or it was all private, output an
+        # empty struct declaration.
+        if has_typedef:
+            decl_out = "typedef struct _%s %s;" % (symbol, symbol)
+        else:
+            decl_out = "struct %s;" % symbol
+
+    return decl_out
+
+
 def OutputSymbolExtraLinks(symbol):
     """Returns extralinks for the symbol (if enabled).
 
@@ -1404,46 +1453,7 @@ def OutputStruct(symbol, declaration):
         logging.info("Found opaque struct: %s", symbol)
         decl_out = "struct %s;" % symbol
     else:
-        m = re.search(
-            r'^\s*(typedef\s+)?struct\s*\w*\s*(?:\/\*.*\*\/)?\s*{(.*)}\s*\w*\s*;\s*$', declaration, 
flags=re.S)
-        if m:
-            struct_contents = m.group(2)
-
-            public = default_to_public
-            new_declaration = ''
-
-            for decl_line in struct_contents.splitlines():
-                logging.info("Struct line: %s", decl_line)
-                m2 = re.search(r'/\*\s*<\s*public\s*>\s*\*/', decl_line)
-                m3 = re.search(r'/\*\s*<\s*(private|protected)\s*>\s*\*/', decl_line)
-                if m2:
-                    public = True
-                elif m3:
-                    public = False
-                elif public:
-                    new_declaration += decl_line + "\n"
-
-            if new_declaration:
-                # Strip any blank lines off the ends.
-                new_declaration = re.sub(r'^\s*\n', '', new_declaration)
-                new_declaration = re.sub(r'\n\s*$', r'\n', new_declaration)
-
-                if has_typedef:
-                    decl_out = "typedef struct {\n%s} %s;\n" % (new_declaration, symbol)
-                else:
-                    decl_out = "struct %s {\n%s};\n" % (symbol, new_declaration)
-
-        else:
-            common.LogWarning(*GetSymbolSourceLocation(symbol),
-                              "Couldn't parse struct:\n%s" % declaration)
-
-        # If we couldn't parse the struct or it was all private, output an
-        # empty struct declaration.
-        if decl_out == '':
-            if has_typedef:
-                decl_out = "typedef struct _%s %s;" % (symbol, symbol)
-            else:
-                decl_out = "struct %s;" % symbol
+        decl_out = extract_struct_body(symbol, declaration, has_typedef, default_to_public)
 
     decl_out = CreateValidSGML(decl_out)
     desc += "<programlisting language=\"C\">%s</programlisting>\n" % decl_out
diff --git a/tests/mkdb.py b/tests/mkdb.py
index 9d58c77..d41bd8c 100755
--- a/tests/mkdb.py
+++ b/tests/mkdb.py
@@ -203,5 +203,52 @@ class ScanSourceContentAnnotations(ScanSourceContentTestCase):
     # multiple annotations, multiline annotations, symbol-level ...
 
 
+class OutputStruct(unittest.TestCase):
+
+    def test_SimpleStructGetNormalized(self):
+        res = mkdb.extract_struct_body('data', textwrap.dedent("""\
+            struct data
+            {
+                int i;
+                char *c;
+            };
+            """), False, True)
+        self.assertEqual(textwrap.dedent("""\
+            struct data {
+                int i;
+                char *c;
+            };
+            """), res)
+
+    def test_SimpleTypedefStructGetNormalized(self):
+        res = mkdb.extract_struct_body('data', textwrap.dedent("""\
+            typedef struct _data
+            {
+                int i;
+                char *c;
+            } data;
+            """), True, True)
+        self.assertEqual(textwrap.dedent("""\
+            typedef struct {
+                int i;
+                char *c;
+            } data;
+            """), res)
+
+    def test_InternalStructNameIsNormalized(self):
+        res = mkdb.extract_struct_body('data', textwrap.dedent("""\
+            struct _data {
+                int i;
+                char *c;
+            };
+            """), False, True)
+        self.assertEqual(textwrap.dedent("""\
+            struct data {
+                int i;
+                char *c;
+            };
+            """), res)
+
+
 if __name__ == '__main__':
     unittest.main()


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