[gobject-introspection/action-syntax] Support the gtk-doc action syntax



commit c776cb173054c58367c0f9a2de86cb3e8d493c87
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Apr 8 14:00:51 2020 +0100

    Support the gtk-doc action syntax
    
    GTK4 allows adding widget-related actions to the documentation with the
    newly defined syntax:
    
      <class_name> '|' <action_name> ':'
    
    This means g-ir-scanner needs to detect this new format, to avoid
    emitting unnecessary warnings.
    
    Currently, we don't do anything with the actions; in the future we might
    want to add them to the documentation in the GIR, but for that we'd need
    a new element.
    
    See also: GNOME/gtk-doc!30

 giscanner/annotationparser.py                   |  42 ++++++-
 tests/scanner/annotationparser/test_patterns.py | 154 +++++++++++++++++++++++-
 2 files changed, 189 insertions(+), 7 deletions(-)
---
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index 9ab629b3..16a66f33 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -440,6 +440,27 @@ SIGNAL_RE = re.compile(
     ''',
     re.UNICODE | re.VERBOSE)
 
+# Pattern matching action identifiers.
+ACTION_RE = re.compile(
+    r'''
+    ^                                                    # start
+    \s*                                                  # 0 or more whitespace characters
+    (?P<class_name>[\w]+)                                # class name
+    \s*                                                  # 0 or more whitespace characters
+    \|{1}                                                # 1 required vertical bar
+    \s*                                                  # 0 or more whitespace characters
+    (?P<action_name>[\w-]+\.[\w-]+)                      # action name
+    \s*                                                  # 0 or more whitespace characters
+    (?P<delimiter>:?)                                    # delimiter
+    \s*                                                  # 0 or more whitespace characters
+    (?P<fields>.*?)                                      # annotations + description
+    \s*                                                  # 0 or more whitespace characters
+    :?                                                   # invalid delimiter
+    \s*                                                  # 0 or more whitespace characters
+    $                                                    # end
+    ''',
+    re.UNICODE | re.VERBOSE)
+
 # Pattern matching parameters.
 PARAMETER_RE = re.compile(
     r'''
@@ -1338,13 +1359,22 @@ class GtkDocCommentBlockParser(object):
                             identifier_fields = result.group('fields')
                             identifier_fields_start = result.start('fields')
                         else:
-                            result = SYMBOL_RE.match(line)
+                            result = ACTION_RE.match(line)
 
                             if result:
-                                identifier_name = '%s' % (result.group('symbol_name'), )
-                                identifier_delimiter = result.group('delimiter')
-                                identifier_fields = result.group('fields')
-                                identifier_fields_start = result.start('fields')
+                                identifier_name = 'ACTION:%s:%s' % (result.group('class_name'),
+                                                                        result.group('action_name'))
+                                identifier_delimiter = None
+                                identifier_fields = None
+                                identifier_fields_start = None
+                            else:
+                                result = SYMBOL_RE.match(line)
+
+                                if result:
+                                    identifier_name = '%s' % (result.group('symbol_name'), )
+                                    identifier_delimiter = result.group('delimiter')
+                                    identifier_fields = result.group('fields')
+                                    identifier_fields_start = result.start('fields')
 
                 if result:
                     in_part = PART_IDENTIFIER
@@ -2117,7 +2147,7 @@ class GtkDocCommentBlockWriter(object):
             lines = []
 
             # Identifier part
-            if block.name.startswith('SECTION'):
+            if block.name.startswith('SECTION') or block.name.startswith('ACTION'):
                 lines.append(block.name)
             else:
                 if block.annotations:
diff --git a/tests/scanner/annotationparser/test_patterns.py b/tests/scanner/annotationparser/test_patterns.py
index 131d6282..68db9870 100644
--- a/tests/scanner/annotationparser/test_patterns.py
+++ b/tests/scanner/annotationparser/test_patterns.py
@@ -33,7 +33,7 @@ import unittest
 
 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,
+                                        SECTION_RE, SYMBOL_RE, PROPERTY_RE, ACTION_RE,
                                         SIGNAL_RE, PARAMETER_RE, TAG_RE,
                                         TAG_VALUE_VERSION_RE, TAG_VALUE_STABILITY_RE)
 
@@ -663,6 +663,157 @@ identifier_signal_tests = [
           'delimiter': ':',
           'fields': '(type GLib.List(GLib.List(utf8))) (transfer full)'})]
 
+identifier_action_tests = [
+    (ACTION_RE, 'GtkWidget|group.action (skip)',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.action',
+          'delimiter': '',
+          'fields': '(skip)'}),
+    (ACTION_RE, 'GtkWidget|group.action',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.action',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, ' GtkWidget |group.action',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.action',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, 'GtkWidget| group.action ',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.action',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, '  GtkWidget  |  group.action  ',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.action',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, 'GtkWidget|group.action:',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.action',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, 'GtkWidget|group.action:  ',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.action',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, '  GtkWidget|group.action:',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.action',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, 'Something|group.action:',
+         {'class_name': 'Something',
+          'action_name': 'group.action',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, 'Something|group.action:  ',
+         {'class_name': 'Something',
+          'action_name': 'group.action',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, '  Something|group.action:',
+         {'class_name': 'Something',
+          'action_name': 'group.action',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, 'Weird-thing|name:',
+         None),
+    (ACTION_RE, 'really-weird_thing|name:',
+         None),
+    (ACTION_RE, 'GWin32InputStream|group.action:',
+         {'class_name': 'GWin32InputStream',
+          'action_name': 'group.action',
+          'delimiter': ':',
+          'fields': ''}),
+    # properties: action name that contains a dash
+    (ACTION_RE, 'GtkWidget|group.double-buffered (skip)',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.double-buffered',
+          'delimiter': '',
+          'fields': '(skip)'}),
+    (ACTION_RE, 'GtkWidget|group.double-buffered',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.double-buffered',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, ' GtkWidget |group.double-buffered',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.double-buffered',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, 'GtkWidget| group.double-buffered ',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.double-buffered',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, '  GtkWidget  |  group.double-buffered  ',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.double-buffered',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, 'GtkWidget|group.double-buffered:',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.double-buffered',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, 'GtkWidget|group.double-buffered:  ',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.double-buffered',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, '  GtkWidget|group.double-buffered:',
+         {'class_name': 'GtkWidget',
+          'action_name': 'group.double-buffered',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, 'Something|group.double-buffered:',
+         {'class_name': 'Something',
+          'action_name': 'group.double-buffered',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, 'Something|group.double-buffered:  ',
+         {'class_name': 'Something',
+          'action_name': 'group.double-buffered',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, '  Something|group.double-buffered:',
+         {'class_name': 'Something',
+          'action_name': 'group.double-buffered',
+          'delimiter': ':',
+          'fields': ''}),
+    (ACTION_RE, 'Weird-thing|double-buffered:',
+         None),
+    (ACTION_RE, 'really-weird_thing|double-buffered:',
+         None),
+    (ACTION_RE, ' GMemoryOutputStream|group.realloc-function: (skip)',
+         {'class_name': 'GMemoryOutputStream',
+          'action_name': 'group.realloc-function',
+          'delimiter': ':',
+          'fields': '(skip)'}),
+    (ACTION_RE, 'Something|group-double.double-buffered',
+         {'class_name': 'Something',
+          'action_name': 'group-double.double-buffered',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, 'Something| group-double.double-buffered',
+         {'class_name': 'Something',
+          'action_name': 'group-double.double-buffered',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, 'Something |group-double.double-buffered',
+         {'class_name': 'Something',
+          'action_name': 'group-double.double-buffered',
+          'delimiter': '',
+          'fields': ''}),
+    (ACTION_RE, 'Something | group-double.double-buffered',
+         {'class_name': 'Something',
+          'action_name': 'group-double.double-buffered',
+          'delimiter': '',
+          'fields': ''})]
+
 parameter_tests = [
     (PARAMETER_RE, '@Short_description: Base class for all widgets  ',
          {'parameter_name': 'Short_description',
@@ -908,6 +1059,7 @@ def create_test_cases():
                             ('TestIdentifierSymbol', identifier_symbol_tests),
                             ('TestIdentifierProperty', identifier_property_tests),
                             ('TestIdentifierSignal', identifier_signal_tests),
+                            ('TestIdentifierAction', identifier_action_tests),
                             ('TestParameter', parameter_tests),
                             ('TestTag', tag_tests),
                             ('TestTagValueVersion', tag_value_version_tests),


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