summaryrefslogtreecommitdiff
path: root/giscanner
diff options
context:
space:
mode:
authorAndreas Rottmann <a.rottmann@gmx.at>2009-01-03 13:44:42 +0000
committerJürg Billeter <juergbi@src.gnome.org>2009-01-03 13:44:42 +0000
commitbc88ef7bcda59b15988d27517a4f4f7e0672e33b (patch)
tree7e3af8b1d130ca9e4b5e78fb7314340d02b11eca /giscanner
parent00b0ae6bca603adc2c424c9a9384c60c4e4b1ccb (diff)
downloadgobject-introspection-bc88ef7bcda59b15988d27517a4f4f7e0672e33b.tar.gz
Bug 556489 – callback annotations
2008-01-03 Andreas Rottmann <a.rottmann@gmx.at> Bug 556489 – callback annotations * giscanner/transformer.py * tools/generate.c (write_callable_info): Write out the new scope, closure and destroy attributes. * giscanner/transformer.py (Transformer._type_is_callback): New method, checking if a given type is a callback. (Transformer._augment_callback_params): New method; adds information (closure, destroy) to callback parameters. (Transformer._handle_closure, Transformer._handle_destroy): New methods, auxiliary to _augment_callback_params. (Transformer._create_function): Call _augment_callback_params(). (Transformer._create_parameter): Handle scope option. (Transformer._create_typedef_callback): New method, creates a callback, and registers it in the typedef namespace (Transformer._create_typedef): Use _create_typedef_callback() instead of the plain _create_callback(). * giscanner/ast.py (Parameter): Added callback-related fields. * giscanner/girwriter.py: Write out new Parameter fields. * girepository/girnode.h (GIrNodeParam): Added fields scope, closure and destroy. * girepository/gtypelib.h (ArgBlob): Ditto. * girepository/girparser.c (start_parameter): Handle new fields. * girepository/girmodule.c (g_ir_module_build_typelib): Adjust arg_blob_size, bump major version due to this change. * girepository/girnode.c (g_ir_node_get_full_size_internal) (g_ir_node_build_typelib) * girepository/gtypelib.c (g_typelib_check_sanity): ArgBlob size adjustments. (g_ir_node_build_typelib): Fill in new ArgBlob flags from param. * girepository/girepository.h (GIScope): New enumeration, listing the different possible scopes for callbacks. * girepository/ginfo.c (g_arg_info_get_scope) (g_arg_info_get_closure, g_arg_info_get_destroy): Accessors for callback-related argument indices (callback scope, closure for a callback, destroy notification for a callback). * tests/scanner/: Added testcases for new features. svn path=/trunk/; revision=998
Diffstat (limited to 'giscanner')
-rw-r--r--giscanner/ast.py5
-rw-r--r--giscanner/girwriter.py6
-rw-r--r--giscanner/transformer.py56
3 files changed, 65 insertions, 2 deletions
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 7df1bf69..6bd858b2 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -289,7 +289,7 @@ class TypeContainer(Node):
class Parameter(TypeContainer):
def __init__(self, name, typenode, direction=PARAM_DIRECTION_IN,
- transfer=None, allow_none=False):
+ transfer=None, allow_none=False, scope=None):
TypeContainer.__init__(self, name, typenode, transfer)
if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
PARAM_DIRECTION_INOUT]:
@@ -298,6 +298,9 @@ class Parameter(TypeContainer):
self.direction = PARAM_DIRECTION_IN
self.allow_none = not not allow_none
+ self.scope = scope
+ self.closure_index = -1
+ self.destroy_index = -1
def __repr__(self):
return 'Parameter(%r, %r)' % (self.name, self.type)
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 4468e25b..f82a73e5 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -162,6 +162,12 @@ class GIRWriter(XMLWriter):
parameter.transfer))
if parameter.allow_none:
attrs.append(('allow-none', '1'))
+ if parameter.scope:
+ attrs.append(('scope', parameter.scope))
+ if parameter.closure_index >= 0:
+ attrs.append(('closure', '%d' % parameter.closure_index))
+ if parameter.destroy_index >= 0:
+ attrs.append(('destroy', '%d' % parameter.destroy_index))
with self.tagcontext('parameter', attrs):
self._write_type(parameter.type)
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index e7c7214a..0ed7ca00 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -269,6 +269,52 @@ class Transformer(object):
if isinstance(return_.type, Array):
self._pair_array(params, return_)
+ def _type_is_callback(self, type):
+ if (isinstance(type, Callback) or
+ isinstance(self._typedefs_ns.get(type.name), Callback)):
+ return True
+ return False
+
+ def _handle_closure(self, param, closure_idx, closure_param):
+ if (closure_param.type.name == 'any' and
+ closure_param.name == 'user_data'):
+ param.closure_name = closure_param.name
+ param.closure_index = closure_idx
+ return True
+ return False
+
+ def _handle_destroy(self, param, destroy_idx, destroy_param):
+ if ((self._namespace.name == 'GLib' and
+ destroy_param.type.name == 'DestroyNotify') or
+ destroy_param.type.name == 'GLib.DestroyNotify'):
+ param.destroy_name = destroy_param.name
+ param.destroy_index = destroy_idx
+ return True
+ return False
+
+ def _augment_callback_params(self, params):
+ for i, param in enumerate(params):
+ if self._type_is_callback(param.type):
+ # j is the index where we look for closure/destroy to
+ # group with the callback param
+ j = i + 1
+ if j == len(params):
+ continue # no more args -> nothing to group look
+ # at the param directly following for either a closure
+ # or a destroy; only one of these will fire
+ had_closure = self._handle_closure(param, j, params[j])
+ had_destroy = self._handle_destroy(param, j, params[j])
+ j += 1
+ # are we out of params, or did we find neither?
+ if j == len(params) or (not had_closure and not had_destroy):
+ continue
+ # we found either a closure or a destroy; check the
+ # parameter following for the other
+ if not had_closure:
+ self._handle_closure(param, j, params[j])
+ if not had_destroy:
+ self._handle_destroy(param, j, params[j])
+
# We take the annotations from the parser as strings; here we
# want to split them into components, so:
# (transfer full) -> {'transfer' : [ 'full' ]}
@@ -286,6 +332,7 @@ class Transformer(object):
symbol.base_type, directives))
return_ = self._create_return(symbol.base_type.base_type,
directives.get('return', {}))
+ self._augment_callback_params(parameters)
self._pair_annotations(parameters, return_)
name = self._strip_namespace_func(symbol.ident)
func = Function(name, return_, parameters, symbol.ident)
@@ -357,7 +404,7 @@ class Transformer(object):
ctype = symbol.base_type.type
if (ctype == CTYPE_POINTER and
symbol.base_type.base_type.type == CTYPE_FUNCTION):
- node = self._create_callback(symbol)
+ node = self._create_typedef_callback(symbol)
elif (ctype == CTYPE_POINTER and
symbol.base_type.base_type.type == CTYPE_STRUCT):
node = self._create_typedef_struct(symbol, disguised=True)
@@ -586,6 +633,8 @@ class Transformer(object):
pass
elif option in ('transfer', 'transfer-inferred'):
pass
+ elif option == 'scope':
+ param.scope = data[0]
else:
print 'Unhandled parameter annotation option: %r' % (
option, )
@@ -642,6 +691,11 @@ class Transformer(object):
self._create_union(symbol)
return union
+ def _create_typedef_callback(self, symbol):
+ callback = self._create_callback(symbol)
+ self._typedefs_ns[callback.name] = callback
+ return callback
+
def _create_struct(self, symbol):
directives = symbol.directives()
struct = self._typedefs_ns.get(symbol.ident, None)