From 3490687771781b70391456d1828911cf79bcfd69 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 23 Jun 2021 19:12:18 +0100 Subject: 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 | 15 ++++++++ giscanner/ast.py | 1 + giscanner/girparser.py | 1 + giscanner/girwriter.py | 2 ++ giscanner/maintransformer.py | 58 ++++++++++++++++++++++++------ 7 files changed, 73 insertions(+), 10 deletions(-) diff --git a/docs/gir-1.2.rnc b/docs/gir-1.2.rnc index 4244532e..ef7f038b 100644 --- a/docs/gir-1.2.rnc +++ b/docs/gir-1.2.rnc @@ -375,6 +375,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-old.gnome.org/gobject/stable/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 b37262fc..c4b2b6a4 100644 --- a/docs/website/annotations/giannotations.rst +++ b/docs/website/annotations/giannotations.rst @@ -125,6 +125,10 @@ Support for GObject objects called by the ``GObjectClass.get_property`` implementation in a class. - :issue:`13` + * - ``(emitter METHOD)`` + - identifier (only applies to methods) + - This signal is emitted by the given method + - Support for GObject closures diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py index 3307327e..bc7b2127 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_PROPERTY = 'get-property' ANN_GET_VALUE_FUNC = 'get-value-func' @@ -229,6 +230,7 @@ GI_ANNS = [ANN_ALLOW_NONE, ANN_CONSTRUCTOR, ANN_DESTROY, ANN_ELEMENT_TYPE, + ANN_EMITTER, ANN_FOREIGN, ANN_GET_PROPERTY, ANN_GET_VALUE_FUNC, @@ -808,6 +810,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. @@ -1151,6 +1165,7 @@ class GtkDocCommentBlock(GtkDocAnnotatable): valid_annotations = ( ANN_ATTRIBUTES, ANN_CONSTRUCTOR, + ANN_EMITTER, ANN_FOREIGN, ANN_GET_PROPERTY, ANN_GET_VALUE_FUNC, diff --git a/giscanner/ast.py b/giscanner/ast.py index c94ee768..c668c3f9 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -1181,6 +1181,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 d9cda8d2..edaaa992 100644 --- a/giscanner/girparser.py +++ b/giscanner/girparser.py @@ -379,6 +379,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 9a315145..9ff10d31 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -674,6 +674,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 3da86797..027b5235 100644 --- a/giscanner/maintransformer.py +++ b/giscanner/maintransformer.py @@ -22,16 +22,49 @@ import re 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_PROPERTY, ANN_GET_VALUE_FUNC, ANN_GETTER, ANN_IN, ANN_INOUT, - ANN_METHOD, ANN_OUT, ANN_REF_FUNC, ANN_RENAME_TO, ANN_SCOPE, - ANN_SET_PROPERTY, ANN_SET_VALUE_FUNC, ANN_SETTER, 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, - OPT_OUT_CALLEE_ALLOCATES, OPT_OUT_CALLER_ALLOCATES, - OPT_TRANSFER_CONTAINER, OPT_TRANSFER_FLOATING, OPT_TRANSFER_NONE) +from .annotationparser import ( + ANN_ALLOW_NONE, + ANN_ARRAY, + ANN_ATTRIBUTES, + ANN_CLOSURE, + ANN_CONSTRUCTOR, + ANN_DESTROY, + ANN_ELEMENT_TYPE, + ANN_EMITTER, + ANN_FOREIGN, + ANN_GET_PROPERTY, + ANN_GET_VALUE_FUNC, + ANN_GETTER, + ANN_IN, + ANN_INOUT, + ANN_METHOD, + ANN_OUT, + ANN_REF_FUNC, + ANN_RENAME_TO, + ANN_SCOPE, + ANN_SET_PROPERTY, + ANN_SET_VALUE_FUNC, + ANN_SETTER, + 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, + OPT_OUT_CALLEE_ALLOCATES, + OPT_OUT_CALLER_ALLOCATES, + OPT_TRANSFER_CONTAINER, + OPT_TRANSFER_FLOATING, + OPT_TRANSFER_NONE, +) from .utils import to_underscores_noprefix @@ -938,6 +971,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 -- cgit v1.2.1