[gobject-introspection] scanner: Don't parse constructors on non-registered, warn for return values



commit f7f93038881b1fe4be7356dc0ce2b1af0776fac4
Author: Colin Walters <walters verbum org>
Date:   Wed Sep 1 14:25:46 2010 -0400

    scanner: Don't parse constructors on non-registered, warn for return values
    
    First, we can't support constructors on unregistered types.
    
    Second, warn if we see a return value of an unregistered.

 giscanner/introspectablepass.py    |   57 +++++++++++++++++++++++++++--------
 giscanner/maintransformer.py       |    2 +-
 tests/scanner/Foo-1.0-expected.gir |   30 ++++++++++---------
 tests/scanner/foo.c                |   17 +++++++++++
 4 files changed, 78 insertions(+), 28 deletions(-)
---
diff --git a/giscanner/introspectablepass.py b/giscanner/introspectablepass.py
index 61604b1..4d19ab3 100644
--- a/giscanner/introspectablepass.py
+++ b/giscanner/introspectablepass.py
@@ -54,30 +54,61 @@ class IntrospectablePass(object):
         self._transformer.log_node_warning(parent, prefix + context + text, *args)
 
     def _introspectable_param_analysis(self, parent, node):
+        is_return = isinstance(node, ast.Return)
+        is_parameter = isinstance(node, ast.Parameter)
+        assert is_return or is_parameter
+
+        if node.type.target_giname is not None:
+            target = self._transformer.lookup_typenode(node.type)
+        else:
+            target = None
+
         if not node.type.resolved:
             self._parameter_warning(parent, node, "Unresolved ctype: %r" % (node.type.ctype, ))
             parent.introspectable = False
-        elif isinstance(node.type, ast.Varargs):
+            return
+
+        if isinstance(node.type, ast.Varargs):
             parent.introspectable = False
-        elif not isinstance(node.type, ast.List) and \
+            return
+
+        if not isinstance(node.type, ast.List) and \
                 (node.type.target_giname == 'GLib.List'):
             self._parameter_warning(parent, node, "Missing (element-type) annotation")
             parent.introspectable = False
-        elif node.transfer is None:
-            self._parameter_warning(parent, node, "Missing (transfer) annotation")
-            parent.introspectable = False
+            return
 
-        if isinstance(node, ast.Parameter) and node.type.target_giname:
-            target = self._transformer.lookup_typenode(node.type)
-            if (isinstance(target, ast.Callback)
-                and not target.create_type().target_giname in ('GLib.DestroyNotify',
-                                                               'Gio.AsyncReadyCallback')
-                and node.scope is None):
+        if (is_parameter
+            and isinstance(target, ast.Callback)
+            and not node.type.target_giname in ('GLib.DestroyNotify',
+                                                'Gio.AsyncReadyCallback')
+            and node.scope is None):
                 self._parameter_warning(parent, node,
                     ("Missing (scope) annotation for callback" +
                      " without GDestroyNotify (valid: %s, %s)")
                      % (ast.PARAM_SCOPE_CALL, ast.PARAM_SCOPE_ASYNC))
                 parent.introspectable = False
+                return
+
+        if is_return and isinstance(target, ast.Callback):
+            self._parameter_warning(parent, node, "Callbacks cannot be return values; use (skip)")
+            parent.introspectable = False
+            return
+
+        if (is_return
+            and isinstance(target, (ast.Record, ast.Union))
+            and not target.foreign
+            and not isinstance(target, glibast.GLibBoxed)):
+            if node.transfer != ast.PARAM_TRANSFER_NONE:
+                self._parameter_warning(parent, node,
+"Invalid non-constant return of bare structure or union; register as boxed type or (skip)")
+                parent.introspectable = False
+            return
+
+        if node.transfer is None:
+            self._parameter_warning(parent, node, "Missing (transfer) annotation")
+            parent.introspectable = False
+            return
 
     def _type_is_introspectable(self, typeval, warn=False):
         if not typeval.resolved:
@@ -127,7 +158,7 @@ class IntrospectablePass(object):
 
     def _introspectable_callable_analysis(self, obj, stack):
         if obj.skip:
-            return True
+            return False
         # Propagate introspectability of parameters to entire functions
         if isinstance(obj, ast.Callable):
             for param in obj.parameters:
@@ -141,7 +172,7 @@ class IntrospectablePass(object):
 
     def _introspectable_pass3(self, obj, stack):
         if obj.skip:
-            return True
+            return False
         # Propagate introspectability for fields
         if isinstance(obj, (ast.Class, ast.Interface, ast.Record, ast.Union)):
             for field in obj.fields:
diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py
index 460f8b3..5463744 100644
--- a/giscanner/maintransformer.py
+++ b/giscanner/maintransformer.py
@@ -794,7 +794,7 @@ method or constructor of some type."""
         if not (func.symbol.find('_new_') >= 0 or func.symbol.endswith('_new')):
             return False
         target = self._transformer.lookup_typenode(func.retval.type)
-        if not isinstance(target, (ast.Class, ast.Record, ast.Union, glibast.GLibBoxedOther)):
+        if not isinstance(target, (ast.Class, glibast.GLibBoxed)):
             return False
         new_idx = func.symbol.rfind('_new')
         assert (new_idx >= 0)
diff --git a/tests/scanner/Foo-1.0-expected.gir b/tests/scanner/Foo-1.0-expected.gir
index c52a923..73c0310 100644
--- a/tests/scanner/Foo-1.0-expected.gir
+++ b/tests/scanner/Foo-1.0-expected.gir
@@ -565,8 +565,21 @@ uses a C sugar return type.</doc>
       <field name="height" writable="1">
         <type name="gint" c:type="gint"/>
       </field>
-      <constructor name="new" c:identifier="foo_rectangle_new">
-        <return-value transfer-ownership="full">
+      <method name="add" c:identifier="foo_rectangle_add">
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <parameter name="r2" transfer-ownership="none">
+            <doc xml:whitespace="preserve">source rectangle</doc>
+            <type name="Rectangle" c:type="FooRectangle*"/>
+          </parameter>
+        </parameters>
+      </method>
+      <function name="new" c:identifier="foo_rectangle_new" introspectable="0">
+        <doc xml:whitespace="preserve">This is a C convenience constructor; we have to (skip)
+it because it's not a boxed type.</doc>
+        <return-value>
           <type name="Rectangle" c:type="FooRectangle*"/>
         </return-value>
         <parameters>
@@ -583,18 +596,7 @@ uses a C sugar return type.</doc>
             <type name="gint" c:type="int"/>
           </parameter>
         </parameters>
-      </constructor>
-      <method name="add" c:identifier="foo_rectangle_add">
-        <return-value transfer-ownership="none">
-          <type name="none" c:type="void"/>
-        </return-value>
-        <parameters>
-          <parameter name="r2" transfer-ownership="none">
-            <doc xml:whitespace="preserve">source rectangle</doc>
-            <type name="Rectangle" c:type="FooRectangle*"/>
-          </parameter>
-        </parameters>
-      </method>
+      </function>
     </record>
     <constant name="SUCCESS_INT" value="4408">
       <type name="gint" c:type="gint"/>
diff --git a/tests/scanner/foo.c b/tests/scanner/foo.c
index d66817f..db578ec 100644
--- a/tests/scanner/foo.c
+++ b/tests/scanner/foo.c
@@ -497,6 +497,23 @@ foo_test_array (void)
 }
 
 /**
+ * foo_rectangle_new: (skip)
+ *
+ * This is a C convenience constructor; we have to (skip)
+ * it because it's not a boxed type.
+ */
+FooRectangle *
+foo_rectangle_new (int x, int y, int width, int height)
+{
+  FooRectangle *r = g_slice_new (FooRectangle);
+  r->x = x;
+  r->y = y;
+  r->width = width;
+  r->height = height;
+  return r;
+}
+
+/**
  * foo_rectangle_add:
  * @r1: (inout): add to this rect
  * @r2: source rectangle



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]