[gobject-introspection/ebassi/signal-emitter: 1/2] scanner: Add (emitter) annotation for signals




commit 897f22390f99cc8719af0afef0e9102bbab5fa0d
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Jun 23 19:12:18 2021 +0100

    scanner: Add (emitter) annotation for signals
    
    Signals that have an emitter function should have an annotation to allow
    consumers of the introspection XML to effectively pair signals to their
    corresponding emitter functions that share the same prototype.

 docs/gir-1.2.rnc                           |  2 ++
 docs/website/annotations/giannotations.rst |  4 ++++
 giscanner/annotationparser.py              | 16 +++++++++++++++-
 giscanner/ast.py                           |  1 +
 giscanner/girparser.py                     |  1 +
 giscanner/girwriter.py                     |  2 ++
 giscanner/maintransformer.py               | 11 ++++++++---
 7 files changed, 33 insertions(+), 4 deletions(-)
---
diff --git a/docs/gir-1.2.rnc b/docs/gir-1.2.rnc
index 8f53c18e..5dbb58c9 100644
--- a/docs/gir-1.2.rnc
+++ b/docs/gir-1.2.rnc
@@ -369,6 +369,8 @@ grammar {
       attribute no-hooks { "0" | "1" }?,
       ## Binary attribute, true if signals emitted for an object while currently being in emission for this 
very object will not be emitted recursively, but instead cause the first emission to be restarted 
(https://developer.gnome.org/gobject/unstable/gobject-Signals.html#GSignalFlags)
       attribute no-recurse { "0" | "1" }?,
+      ## The emitter method for the signal
+      attribute emitter { xsd:string }?,
 
       # Other elements a property can contain
       (Info.elements
diff --git a/docs/website/annotations/giannotations.rst b/docs/website/annotations/giannotations.rst
index cacc20de..cd98362b 100644
--- a/docs/website/annotations/giannotations.rst
+++ b/docs/website/annotations/giannotations.rst
@@ -97,6 +97,10 @@ Support for GObject objects
     - This function is the invoker for a virtual method.
     - :commit:`v0.6.3 <fdbe3cc3>`
       :bzbug:`557383`
+  * - ``(emitter METHOD)``
+    - identifier
+    - This signal is emitted by the given method
+    -
 
 
 Support for GObject closures
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index 267542f9..1676e38a 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -195,6 +195,7 @@ ANN_CLOSURE = 'closure'
 ANN_CONSTRUCTOR = 'constructor'
 ANN_DESTROY = 'destroy'
 ANN_ELEMENT_TYPE = 'element-type'
+ANN_EMITTER = 'emitter'
 ANN_FOREIGN = 'foreign'
 ANN_GET_VALUE_FUNC = 'get-value-func'
 ANN_IN = 'in'
@@ -225,6 +226,7 @@ GI_ANNS = [ANN_ALLOW_NONE,
            ANN_CONSTRUCTOR,
            ANN_DESTROY,
            ANN_ELEMENT_TYPE,
+           ANN_EMITTER,
            ANN_FOREIGN,
            ANN_GET_VALUE_FUNC,
            ANN_IN,
@@ -800,6 +802,18 @@ class GtkDocAnnotatable(object):
 
         self._validate_annotation(position, ann_name, options, min_n_options=1, max_n_options=2)
 
+    def _do_validate_emitter(self, position, ann_name, options):
+        '''
+        Validate the ``(emitter)`` annotation.
+
+        :param position: :class:`giscanner.message.Position` of the line in the source file
+                         containing the annotation to be validated
+        :param ann_name: name of the annotation holding the options to validate
+        :param options: annotation options to validate
+        '''
+
+        self._validate_annotation(position, ann_name, options, exact_n_options=1)
+
     def _do_validate_foreign(self, position, ann_name, options):
         '''
         Validate the ``(foreign)`` annotation.
@@ -1092,7 +1106,7 @@ class GtkDocCommentBlock(GtkDocAnnotatable):
                  'name', 'params', 'description', 'tags')
 
     #: Valid annotation names for the GTK-Doc comment block identifier part.
-    valid_annotations = (ANN_ATTRIBUTES, ANN_CONSTRUCTOR, ANN_FOREIGN, ANN_GET_VALUE_FUNC,
+    valid_annotations = (ANN_ATTRIBUTES, ANN_CONSTRUCTOR, ANN_EMITTER, ANN_FOREIGN, ANN_GET_VALUE_FUNC,
                          ANN_METHOD, ANN_REF_FUNC, ANN_RENAME_TO, ANN_SET_VALUE_FUNC,
                          ANN_SKIP, ANN_TRANSFER, ANN_TYPE, ANN_UNREF_FUNC, ANN_VALUE, ANN_VFUNC)
 
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 9a0d95c7..2c9ff3db 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -1179,6 +1179,7 @@ class Signal(Callable):
         self.detailed = detailed
         self.action = action
         self.no_hooks = no_hooks
+        self.emitter = None
 
 
 class Class(Node, Registered):
diff --git a/giscanner/girparser.py b/giscanner/girparser.py
index da200a65..1570d931 100644
--- a/giscanner/girparser.py
+++ b/giscanner/girparser.py
@@ -376,6 +376,7 @@ class GIRParser(object):
                          detailed=node.attrib.get('detailed', '0') == '1',
                          action=node.attrib.get('action', '0') == '1',
                          no_hooks=node.attrib.get('no-hooks', '0') == '1')
+            func.emitter = node.attrib.get('emitter')
         else:
             assert False
 
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 54c957c0..d06eab45 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -664,6 +664,8 @@ class GIRWriter(XMLWriter):
             attrs.append(('action', '1'))
         if signal.no_hooks:
             attrs.append(('no-hooks', '1'))
+        if signal.emitter:
+            attrs.append(('emitter', signal.emitter))
 
         self._append_version(signal, attrs)
         self._append_node_generic(signal, attrs)
diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py
index 9077a1d0..c097cfe4 100644
--- a/giscanner/maintransformer.py
+++ b/giscanner/maintransformer.py
@@ -23,9 +23,9 @@ from . import ast
 from . import message
 from .annotationparser import (TAG_DEPRECATED, TAG_SINCE, TAG_STABILITY, TAG_RETURNS)
 from .annotationparser import (ANN_ALLOW_NONE, ANN_ARRAY, ANN_ATTRIBUTES, ANN_CLOSURE,
-                               ANN_CONSTRUCTOR, ANN_DESTROY, ANN_ELEMENT_TYPE, ANN_FOREIGN,
-                               ANN_GET_VALUE_FUNC, ANN_IN, ANN_INOUT, ANN_METHOD, ANN_OUT,
-                               ANN_REF_FUNC, ANN_RENAME_TO, ANN_SCOPE, ANN_SET_VALUE_FUNC,
+                               ANN_CONSTRUCTOR, ANN_DESTROY, ANN_ELEMENT_TYPE, ANN_EMITTER,
+                               ANN_FOREIGN, ANN_GET_VALUE_FUNC, ANN_IN, ANN_INOUT, ANN_METHOD,
+                               ANN_OUT, ANN_REF_FUNC, ANN_RENAME_TO, ANN_SCOPE, ANN_SET_VALUE_FUNC,
                                ANN_SKIP, ANN_TRANSFER, ANN_TYPE, ANN_UNREF_FUNC, ANN_VALUE,
                                ANN_VFUNC, ANN_NULLABLE, ANN_OPTIONAL, ANN_NOT)
 from .annotationparser import (OPT_ARRAY_FIXED_SIZE, OPT_ARRAY_LENGTH, OPT_ARRAY_ZERO_TERMINATED,
@@ -922,6 +922,11 @@ class MainTransformer(object):
 
         if block:
             self._apply_annotations_annotated(signal, block)
+
+            emitter = block.annotations.get(ANN_EMITTER)
+            if emitter:
+                signal.emitter = emitter[0]
+
             # We're only attempting to name the signal parameters if
             # the number of parameters (@foo) is the same or greater
             # than the number of signal parameters


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