From cf7621f31c6b3eaf29e1da82631a9404f8b1c036 Mon Sep 17 00:00:00 2001 From: Andreas Rottmann Date: Mon, 23 Mar 2009 22:19:24 +0000 Subject: Bug 574284 - Add support for a 'closure' and 'destroy' annotations This allows to annotate cases where the heuristics don't work. TODO: According to Juerbi, there are cases where two callbacks refer to the same user_data, which is prohibited by the current implementation. Signed-off-by: Andreas Rottmann --- 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. --> + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + @@ -384,6 +394,22 @@ + + + + + + + + + + + + + + + + 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); -- cgit v0.9.1