[gobject-introspection] scanner: Don't mark as constructors things that are more obviously methods



commit 5140ec172415192af4f406b1fd5ff4615caf1386
Author: Colin Walters <walters verbum org>
Date:   Wed Sep 8 12:18:51 2010 -0400

    scanner: Don't mark as constructors things that are more obviously methods
    
    If the first parameter matches the origin, don't scan as a constructor.
    Happened in practice with meta_screen_append_new_workspace from mutter.

 giscanner/maintransformer.py       |   13 +++++++++--
 tests/scanner/Foo-1.0-expected.gir |   25 ++++++++++++++++++++++++
 tests/scanner/foo.c                |   37 ++++++++++++++++++++++++++++++++++++
 tests/scanner/foo.h                |   10 +++++++++
 4 files changed, 82 insertions(+), 3 deletions(-)
---
diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py
index ae05195..a9f43a3 100644
--- a/giscanner/maintransformer.py
+++ b/giscanner/maintransformer.py
@@ -819,9 +819,7 @@ method or constructor of some type."""
         target = self._transformer.lookup_typenode(func.retval.type)
         if not isinstance(target, (ast.Class, glibast.GLibBoxed)):
             return False
-        new_idx = func.symbol.rfind('_new')
-        assert (new_idx >= 0)
-        prefix = func.symbol[:new_idx]
+
         split = self._split_uscored_by_type(subsymbol)
         if split is None:
             # TODO - need a e.g. (method) annotation
@@ -829,10 +827,19 @@ method or constructor of some type."""
                 "Can't find matching type for constructor; symbol=%r" % (func.symbol, ))
             return False
         (origin_node, funcname) = split
+
+        # Some sanity checks; only objects and boxeds can have ctors
         if not isinstance(origin_node, (ast.Class, glibast.GLibBoxed)):
             return False
+        # Verify the namespace - don't want to append to foreign namespaces!
         if origin_node.namespace != self._namespace:
             return False
+        # If it takes the object as a first arg, it's not a constructor
+        if len(func.parameters) > 0:
+            first_arg = self._transformer.lookup_typenode(func.parameters[0].type)
+            if (first_arg is not None) and first_arg.gi_name == origin_node.gi_name:
+                return False
+
         if isinstance(target, ast.Class):
             parent = origin_node
             while parent and (not parent.gi_name == 'GObject.Object'):
diff --git a/tests/scanner/Foo-1.0-expected.gir b/tests/scanner/Foo-1.0-expected.gir
index 0c4c2b6..36bec03 100644
--- a/tests/scanner/Foo-1.0-expected.gir
+++ b/tests/scanner/Foo-1.0-expected.gir
@@ -368,6 +368,18 @@ uses a C sugar return type.</doc>
           </parameter>
         </parameters>
       </virtual-method>
+      <method name="append_new_stack_layer"
+              c:identifier="foo_object_append_new_stack_layer">
+        <doc xml:whitespace="preserve">This shouldn't be scanned as a constructor.</doc>
+        <return-value transfer-ownership="none">
+          <type name="OtherObject" c:type="FooOtherObject*"/>
+        </return-value>
+        <parameters>
+          <parameter name="x" transfer-ownership="none">
+            <type name="gint" c:type="int"/>
+          </parameter>
+        </parameters>
+      </method>
       <method name="dup_name" c:identifier="foo_object_dup_name">
         <return-value transfer-ownership="full">
           <type name="utf8" c:type="char*"/>
@@ -560,6 +572,19 @@ uses a C sugar return type.</doc>
         </array>
       </field>
     </record>
+    <class name="OtherObject"
+           c:symbol-prefix="other_object"
+           c:type="FooOtherObject"
+           parent="GObject.Object"
+           glib:type-name="FooOtherObject"
+           glib:get-type="foo_other_object_get_type"
+           glib:type-struct="OtherObjectClass">
+    </class>
+    <record name="OtherObjectClass"
+            c:type="FooOtherObjectClass"
+            disguised="1"
+            glib:is-gtype-struct-for="OtherObject">
+    </record>
     <constant name="PIE_IS_TASTY" value="3.141590">
       <type name="gdouble" c:type="gdouble"/>
     </constant>
diff --git a/tests/scanner/foo.c b/tests/scanner/foo.c
index d84c58a..9e3a38d 100644
--- a/tests/scanner/foo.c
+++ b/tests/scanner/foo.c
@@ -667,6 +667,31 @@ foo_buffer_some_method (FooBuffer *buffer)
 {
 }
 
+struct _FooOtherObject
+{
+  GObject parent_instance;
+};
+
+struct _FooOtherObjectClass
+{
+  GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE(FooOtherObject, foo_other_object, G_TYPE_OBJECT);
+
+static void
+foo_other_object_class_init (FooOtherObjectClass *klass)
+{
+
+}
+
+static void
+foo_other_object_init (FooOtherObject *object)
+{
+
+}
+
+
 #define FOO_DEFINE_SHOULD_NOT_BE_EXPOSED "should not be exposed"
 
 /**
@@ -714,3 +739,15 @@ foo_test_varargs_callback3 (FooVarargsCallback callback,
 {
 }
 
+/**
+ * foo_object_append_new_stack_layer:
+ *
+ * This shouldn't be scanned as a constructor.
+ *
+ * Returns: (transfer none):
+ */
+FooOtherObject *
+foo_object_append_new_stack_layer (FooObject *obj, int x)
+{
+  return NULL;
+}
diff --git a/tests/scanner/foo.h b/tests/scanner/foo.h
index 5a67e65..110c313 100644
--- a/tests/scanner/foo.h
+++ b/tests/scanner/foo.h
@@ -34,6 +34,10 @@
 #define FOO_BUFFER(object)     (G_TYPE_CHECK_INSTANCE_CAST ((object), FOO_TYPE_BUFFER, FooBuffer))
 #define FOO_IS_BUFFER(object)  (G_TYPE_CHECK_INSTANCE_TYPE ((object), FOO_TYPE_BUFFER))
 
+#define FOO_TYPE_OTHER_OBJECT  (foo_other_object_get_type ())
+#define FOO_OTHER_OBJECT(object)     (G_TYPE_CHECK_INSTANCE_CAST ((object), FOO_TYPE_OTHER_OBJECT, FooOtherObject))
+#define FOO_IS_OTHER_OBJECT(object)  (G_TYPE_CHECK_INSTANCE_TYPE ((object), FOO_TYPE_OTHER_OBJECT))
+
 typedef struct _FooInterface       FooInterface;
 typedef struct _FooInterfaceIface  FooInterfaceIface;
 typedef struct _FooSubInterface       FooSubInterface;
@@ -44,6 +48,8 @@ typedef struct _FooSubobject       FooSubobject;
 typedef struct _FooSubobjectClass  FooSubobjectClass;
 typedef struct _FooBuffer          FooBuffer;
 typedef struct _FooBufferClass     FooBufferClass;
+typedef struct _FooOtherObject          FooOtherObject;
+typedef struct _FooOtherObjectClass     FooOtherObjectClass;
 
 struct _FooInterfaceIface
 {
@@ -151,6 +157,8 @@ GType                 foo_buffer_get_type          (void);
 
 void                  foo_buffer_some_method       (FooBuffer *buffer);
 
+GType                 foo_other_object_get_type    (void) G_GNUC_CONST;
+
 typedef enum
 {
   FOO_ENUM_ALPHA,
@@ -420,4 +428,6 @@ struct _FooForeignStruct
  */
 void foo_object_a_global_method (UtilityObject *obj);
 
+FooOtherObject * foo_object_append_new_stack_layer (FooObject *obj, int x);
+
 #endif /* __FOO_OBJECT_H__ */



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