diff options
-rw-r--r-- | giscanner/annotationparser.py | 27 | ||||
-rw-r--r-- | giscanner/ast.py | 10 | ||||
-rw-r--r-- | tests/scanner/annotation-1.0-expected.gir | 39 | ||||
-rw-r--r-- | tests/scanner/annotation-1.0-expected.tgir | 26 | ||||
-rw-r--r-- | tests/scanner/annotation.c | 15 | ||||
-rw-r--r-- | tests/scanner/annotation.h | 12 |
6 files changed, 128 insertions, 1 deletions
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py index fae839f..30b0eed 100644 --- a/giscanner/annotationparser.py +++ b/giscanner/annotationparser.py @@ -60,6 +60,8 @@ OPT_OUT = 'out' OPT_SCOPE = 'scope' OPT_TRANSFER = 'transfer' OPT_TYPE = 'type' +OPT_CLOSURE = 'closure' +OPT_DESTROY = 'destroy' # Specific option values OPT_VAL_BITFIELD = 'bitfield' @@ -476,14 +478,37 @@ class AnnotationApplier(object): self._parse_param_ret_common(parent, return_, tag) def _parse_param(self, parent, param, tag): + options = getattr(tag, 'options', {}) if isinstance(parent, Function): - options = getattr(tag, 'options', {}) scope = options.get(OPT_SCOPE) if scope: param.scope = scope.one() param.transfer = PARAM_TRANSFER_NONE + destroy = options.get(OPT_DESTROY) + if destroy: + param.destroy_index = parent.get_parameter_index(destroy.one()) + self._fixup_param_destroy(parent, param) + closure = options.get(OPT_CLOSURE) + if closure: + param.closure_index = parent.get_parameter_index(closure.one()) + self._fixup_param_closure(parent, param) + if isinstance(parent, Callback): + if OPT_CLOSURE in options: + param.closure_index = parent.get_parameter_index(param.name) + self._fixup_param_closure(parent, param) + self._parse_param_ret_common(parent, param, tag) + def _fixup_param_destroy(self, parent, param): + for p in parent.parameters: + if p is not param and p.destroy_index == param.destroy_index: + p.destroy_index = None + + def _fixup_param_closure(self, parent, param): + for p in parent.parameters: + if p is not param and p.closure_index == param.closure_index: + p.closure_index = None + def _parse_param_ret_common(self, parent, node, tag): options = getattr(tag, 'options', {}) node.direction = self._extract_direction(node, options) diff --git a/giscanner/ast.py b/giscanner/ast.py index 0d3f0bb..b0db6e2 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -521,6 +521,16 @@ class Callback(Node): self.throws = False self.doc = None + def get_parameter_index(self, name): + for i, parameter in enumerate(self.parameters): + if parameter.name == name: + return i + + def get_parameter(self, name): + for parameter in self.parameters: + if parameter.name == name: + return parameter + def __repr__(self): return 'Callback(%r, %r, %r)' % ( self.name, self.retval, self.parameters) diff --git a/tests/scanner/annotation-1.0-expected.gir b/tests/scanner/annotation-1.0-expected.gir index e82201e..c4e0fa0 100644 --- a/tests/scanner/annotation-1.0-expected.gir +++ b/tests/scanner/annotation-1.0-expected.gir @@ -58,6 +58,22 @@ and/or use gtk-doc annotations. --> </parameter> </parameters> </callback> + <callback name="NotifyFunc" + c:type="AnnotationNotifyFunc" + doc="This is a callback with a 'closure' argument that is not named +'user_data' and hence has to be annotated."> + <return-value transfer-ownership="none"> + <type name="none" c:type="void"/> + </return-value> + <parameters> + <parameter name="data" + transfer-ownership="none" + closure="0" + doc="The user data"> + <type name="any" c:type="gpointer"/> + </parameter> + </parameters> + </callback> <class name="Object" c:type="AnnotationObject" doc="This is an object used to test annotations." @@ -517,6 +533,29 @@ known by GObject as it's only marked as G_TYPE_POINTER"> </array> </field> </record> + <function name="custom_destroy" + c:identifier="annotation_custom_destroy" + doc="Test messing up the heuristic of closure/destroy-notification +detection, and fixing it via annotations."> + <return-value transfer-ownership="none"> + <type name="none" c:type="void"/> + </return-value> + <parameters> + <parameter name="callback" + transfer-ownership="none" + closure="2" + destroy="1" + doc="Destroy notification"> + <type name="Callback" c:type="AnnotationCallback"/> + </parameter> + <parameter name="destroy" transfer-ownership="none"> + <type name="NotifyFunc" c:type="AnnotationNotifyFunc"/> + </parameter> + <parameter name="data" transfer-ownership="none"> + <type name="any" c:type="gpointer"/> + </parameter> + </parameters> + </function> <function name="get_source_file" c:identifier="annotation_get_source_file"> <return-value transfer-ownership="full" doc="Source file"> <type name="filename" c:type="char*"/> diff --git a/tests/scanner/annotation-1.0-expected.tgir b/tests/scanner/annotation-1.0-expected.tgir index 0d88c47..46af2ec 100644 --- a/tests/scanner/annotation-1.0-expected.tgir +++ b/tests/scanner/annotation-1.0-expected.tgir @@ -47,6 +47,16 @@ </parameter> </parameters> </callback> + <callback name="NotifyFunc"> + <return-value transfer-ownership="none"> + <type name="none"/> + </return-value> + <parameters> + <parameter name="data" transfer-ownership="none" closure="0"> + <type name="any"/> + </parameter> + </parameters> + </callback> <class name="Object" parent="GObject.Object" glib:type-struct="ObjectClass" glib:type-name="AnnotationObject" glib:get-type="annotation_object_get_type"> <attribute name="org.example.Test" value="cows"/> <field name="parent_instance"> @@ -384,6 +394,22 @@ </array> </field> </record> + <function name="custom_destroy" c:identifier="annotation_custom_destroy"> + <return-value transfer-ownership="none"> + <type name="none"/> + </return-value> + <parameters> + <parameter name="callback" transfer-ownership="none" closure="2" destroy="1"> + <type name="Callback"/> + </parameter> + <parameter name="destroy" transfer-ownership="none"> + <type name="NotifyFunc"/> + </parameter> + <parameter name="data" transfer-ownership="none"> + <type name="any"/> + </parameter> + </parameters> + </function> <function name="get_source_file" c:identifier="annotation_get_source_file"> <return-value transfer-ownership="full"> <type name="filename"/> diff --git a/tests/scanner/annotation.c b/tests/scanner/annotation.c index cbc9244..5c5d46d 100644 --- a/tests/scanner/annotation.c +++ b/tests/scanner/annotation.c @@ -611,6 +611,21 @@ annotation_object_extra_annos (AnnotationObject *object) } /** + * annotation_custom_destroy: + * + * @callback: (destroy destroy) (closure data): Destroy notification + * + * Test messing up the heuristic of closure/destroy-notification + * detection, and fixing it via annotations. + */ +void +annotation_custom_destroy (AnnotationCallback callback, + AnnotationNotifyFunc destroy, + gpointer data) +{ +} + +/** * annotation_get_source_file: * * Return value: (type filename): Source file diff --git a/tests/scanner/annotation.h b/tests/scanner/annotation.h index e43e7ba..745a94b 100644 --- a/tests/scanner/annotation.h +++ b/tests/scanner/annotation.h @@ -22,6 +22,15 @@ typedef const gint* (*AnnotationCallback) (const gint *in); typedef GList* (*AnnotationListCallback) (GList *in); /** + * AnnotationNotifyFunc: + * @data: (closure): The user data + * + * This is a callback with a 'closure' argument that is not named + * 'user_data' and hence has to be annotated. + */ +typedef void (*AnnotationNotifyFunc) (gpointer data); + +/** * AnnotationObject: * * This is an object used to test annotations. @@ -122,6 +131,9 @@ void annotation_string_zero_terminated_out (char ***out); void annotation_object_extra_annos (AnnotationObject *object); +void annotation_custom_destroy (AnnotationCallback callback, + AnnotationNotifyFunc destroy, + gpointer data); char * annotation_get_source_file (void); void annotation_set_source_file (const char *fname); |