scanner: Always explicitely set the scope of callbacks
[gnome.gobject-introspection] / giscanner / annotationparser.py
index 1cedfb9..aa04ef4 100644 (file)
@@ -73,6 +73,9 @@ OPT_ARRAY_FIXED_SIZE = 'fixed-size'
 OPT_ARRAY_LENGTH = 'length'
 OPT_ARRAY_ZERO_TERMINATED = 'zero-terminated'
 
+OPT_SCOPE_ASYNC = 'async'
+OPT_SCOPE_CALL = 'call'
+OPT_SCOPE_NOTIFIED = 'notified'
 
 class InvalidAnnotationError(Exception):
     pass
@@ -206,8 +209,9 @@ class AnnotationParser(object):
             tag_name, value = self._split_tag_namevalue(line)
             canon_name = tag_name.lower()
             if canon_name in block.tags:
-                print >>sys.stderr, "Multiple definition of tag %r" \
-                    % (canon_name, )
+                print >> sys.stderr, (
+                    "Symbol %s has multiple definition of tag %r" % (
+                    block_name, canon_name, ))
             block.tags[canon_name] = self._create_tag(canon_name, value)
         block.comment = '\n'.join(comment_lines)
         self._blocks[block.name] = block
@@ -218,6 +222,8 @@ class AnnotationParser(object):
         if len(parts) == 1:
             tag_name = parts[0]
             value = ''
+            if tag_name.endswith(':'):
+                tag_name = tag_name[:-1]
         else:
             tag_name, value = parts
         return (tag_name, value)
@@ -410,6 +416,17 @@ class AnnotationApplier(object):
 
     def _parse_callable(self, callable, block):
         self._parse_node_common(callable, block)
+        for i, param in enumerate(callable.parameters):
+            if (param.type.ctype != 'GDestroyNotify' and
+                param.type.name != 'GLib.DestroyNotify'):
+                continue
+            if i < 2:
+                break
+            callback_param = callable.parameters[i-2]
+            if callback_param.closure_index != -1:
+                callback_param.scope = OPT_SCOPE_NOTIFIED
+                callback_param.transfer = PARAM_TRANSFER_NONE
+
         self._parse_params(callable, callable.parameters, block)
         self._parse_return(callable, callable.retval, block)
         if block:
@@ -495,6 +512,11 @@ class AnnotationApplier(object):
             if scope:
                 param.scope = scope.one()
                 param.transfer = PARAM_TRANSFER_NONE
+            elif (param.type.ctype == 'GAsyncReadyCallback' or
+                  param.type.name == 'Gio.AsyncReadyCallback'):
+                param.scope = OPT_SCOPE_ASYNC
+                param.transfer = PARAM_TRANSFER_NONE
+
             destroy = options.get(OPT_DESTROY)
             if destroy:
                 param.destroy_index = parent.get_parameter_index(destroy.one())
@@ -640,9 +662,11 @@ class AnnotationApplier(object):
         def combiner(base, *rest):
             if not rest:
                 return base
-            if base.name in ['GLib.List', 'GLib.SList'] and len(rest)==1:
+            if (base.name in ['GLib.List', 'GLib.SList'] or
+                base.ctype in ['GList*', 'GSList*']) and len(rest)==1:
                 return List(base.name, base.ctype, *rest)
-            if base.name in ['GLib.HashTable'] and len(rest)==2:
+            if (base.name in ['GLib.HashTable'] or
+                base.ctype in ['GHashTable*']) and len(rest)==2:
                 return Map(base.name, base.ctype, *rest)
             print "WARNING: throwing away type parameters:", type_str
             return base
@@ -661,13 +685,15 @@ class AnnotationApplier(object):
     def _parse_element_type(self, parent, node, options):
         element_type_opt = options.get(OPT_ELEMENT_TYPE)
         element_type = element_type_opt.flat()
-        if node.type.name in ['GLib.List', 'GLib.SList']:
+        if (node.type.name in ['GLib.List', 'GLib.SList'] or
+            node.type.ctype in ['GList*', 'GSList*']):
             assert len(element_type) == 1
             container_type = List(
                 node.type.name,
                 node.type.ctype,
                 self._resolve(element_type[0]))
-        elif node.type.name in ['GLib.HashTable']:
+        elif (node.type.name in ['GLib.HashTable'] or
+              node.type.ctype in ['GHashTable*']):
             assert len(element_type) == 2
             container_type = Map(
                 node.type.name,