[gobject-introspection] scanner: support virtual functions with a typedef-ed callback



commit b6568a4c8007f574f8b9c6a048d04f80dd291f37
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sun Feb 2 00:57:24 2014 +0100

    scanner: support virtual functions with a typedef-ed callback
    
    The field of a callback need not be anonymous, it could be a
    typedef, with a proper Type node.
    
    Fixes TelepathyGlib.BaseClient having no virtual functions
    (and probably others)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=723439

 giscanner/ast.py                                   |    4 +-
 giscanner/maintransformer.py                       |   14 ++++-
 .../Regress.TestExternallyDefinedCallback.page     |   33 ++++++++++++
 .../Regress.TestFundamentalObject-copy.page        |   28 ++++++++++
 .../Regress.TestFundamentalObject-finalize.page    |   28 ++++++++++
 .../Regress.TestObj-complex_vfunc.page             |   33 ++++++++++++
 .../Regress.TestObjClass-complex_vfunc.page        |   14 +++++
 .../Regress.TestExternallyDefinedCallback.page     |   29 +++++++++++
 .../Regress.TestObj-complex_vfunc.page             |   25 +++++++++
 .../Regress.TestExternallyDefinedCallback.page     |   30 +++++++++++
 .../Regress.TestFundamentalObject-copy.page        |   30 +++++++++++
 .../Regress.TestFundamentalObject-finalize.page    |   26 +++++++++
 .../Regress.TestObj-complex_vfunc.page             |   30 +++++++++++
 tests/scanner/Regress-1.0-expected.gir             |   54 ++++++++++++++++++++
 tests/scanner/regress.h                            |    4 ++
 15 files changed, 377 insertions(+), 5 deletions(-)
---
diff --git a/giscanner/ast.py b/giscanner/ast.py
index b992c11..130f50c 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -681,8 +681,8 @@ class VFunction(Callable):
         self.invoker = None
 
     @classmethod
-    def from_callback(cls, cb):
-        obj = cls(cb.name, cb.retval, cb.parameters[1:],
+    def from_callback(cls, name, cb):
+        obj = cls(name, cb.retval, cb.parameters[1:],
                   cb.throws)
         return obj
 
diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py
index c107bee..e6f0468 100644
--- a/giscanner/maintransformer.py
+++ b/giscanner/maintransformer.py
@@ -1225,16 +1225,24 @@ method or constructor of some type."""
                 field.writable = False
 
         for field in class_struct.fields:
-            if not isinstance(field.anonymous_node, ast.Callback):
+            callback = None
+
+            if isinstance(field.anonymous_node, ast.Callback):
+                callback = field.anonymous_node
+            elif field.type is not None:
+                callback = self._transformer.lookup_typenode(field.type)
+                if not isinstance(callback, ast.Callback):
+                    continue
+            else:
                 continue
-            callback = field.anonymous_node
+
             # Check the first parameter is the object
             if len(callback.parameters) == 0:
                 continue
             firstparam_type = callback.parameters[0].type
             if firstparam_type != node_type:
                 continue
-            vfunc = ast.VFunction.from_callback(callback)
+            vfunc = ast.VFunction.from_callback(field.name, callback)
             vfunc.instance_parameter = callback.parameters[0]
             vfunc.inherit_file_positions(callback)
 
diff --git a/tests/scanner/Regress-1.0-C-expected/Regress.TestExternallyDefinedCallback.page 
b/tests/scanner/Regress-1.0-C-expected/Regress.TestExternallyDefinedCallback.page
new file mode 100644
index 0000000..6514a35
--- /dev/null
+++ b/tests/scanner/Regress-1.0-C-expected/Regress.TestExternallyDefinedCallback.page
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<page id="Regress.TestExternallyDefinedCallback"
+      type="topic"
+      style="callback"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="index" group="callback" type="guide"/>
+    </info>
+  <title>Regress.TestExternallyDefinedCallback</title>
+  <synopsis><code mime="text/x-csrc">
+void TestExternallyDefinedCallback (RegressTestObj* obj,
+                                    int someint);
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+<item>
+<title><code>someint</code></title>
+
+</item>
+<item>
+<title><code>Returns</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-C-expected/Regress.TestFundamentalObject-copy.page 
b/tests/scanner/Regress-1.0-C-expected/Regress.TestFundamentalObject-copy.page
new file mode 100644
index 0000000..d4435c6
--- /dev/null
+++ b/tests/scanner/Regress-1.0-C-expected/Regress.TestFundamentalObject-copy.page
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<page id="Regress.TestFundamentalObject-copy"
+      type="topic"
+      style="vfunc"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="Regress.TestFundamentalObject" group="vfunc" type="guide"/>
+  </info>
+  <title>Regress.TestFundamentalObject::copy</title>
+  <synopsis><code mime="text/x-csrc">
+RegressTestFundamentalObject* copy (const RegressTestFundamentalObject* obj);
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+<item>
+<title><code>Returns</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-C-expected/Regress.TestFundamentalObject-finalize.page 
b/tests/scanner/Regress-1.0-C-expected/Regress.TestFundamentalObject-finalize.page
new file mode 100644
index 0000000..060684a
--- /dev/null
+++ b/tests/scanner/Regress-1.0-C-expected/Regress.TestFundamentalObject-finalize.page
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<page id="Regress.TestFundamentalObject-finalize"
+      type="topic"
+      style="vfunc"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="Regress.TestFundamentalObject" group="vfunc" type="guide"/>
+  </info>
+  <title>Regress.TestFundamentalObject::finalize</title>
+  <synopsis><code mime="text/x-csrc">
+void finalize (RegressTestFundamentalObject* obj);
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+<item>
+<title><code>Returns</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-C-expected/Regress.TestObj-complex_vfunc.page 
b/tests/scanner/Regress-1.0-C-expected/Regress.TestObj-complex_vfunc.page
new file mode 100644
index 0000000..50b9b0f
--- /dev/null
+++ b/tests/scanner/Regress-1.0-C-expected/Regress.TestObj-complex_vfunc.page
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<page id="Regress.TestObj-complex_vfunc"
+      type="topic"
+      style="vfunc"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="Regress.TestObj" group="vfunc" type="guide"/>
+  </info>
+  <title>Regress.TestObj::complex_vfunc</title>
+  <synopsis><code mime="text/x-csrc">
+void complex_vfunc (RegressTestObj* obj,
+                    int someint);
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+<item>
+<title><code>someint</code></title>
+
+</item>
+<item>
+<title><code>Returns</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-C-expected/Regress.TestObjClass-complex_vfunc.page 
b/tests/scanner/Regress-1.0-C-expected/Regress.TestObjClass-complex_vfunc.page
new file mode 100644
index 0000000..d658928
--- /dev/null
+++ b/tests/scanner/Regress-1.0-C-expected/Regress.TestObjClass-complex_vfunc.page
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<page id="Regress.TestObjClass-complex_vfunc"
+      type="topic"
+      style="field"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="Regress.TestObjClass" group="field" type="guide"/>
+  </info>
+  <title>Regress.TestObjClass->complex_vfunc</title>
+
+
+</page>
diff --git a/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestExternallyDefinedCallback.page 
b/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestExternallyDefinedCallback.page
new file mode 100644
index 0000000..f9d241c
--- /dev/null
+++ b/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestExternallyDefinedCallback.page
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<page id="Regress.TestExternallyDefinedCallback"
+      type="topic"
+      style="callback"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="index" group="callback" type="guide"/>
+  </info>
+  <title>Regress.TestExternallyDefinedCallback</title>
+  <synopsis><code mime="text/x-gjs">
+function onTestExternallyDefinedCallback(obj: <link xref="Regress.TestObj">Regress.TestObj</link>, someint: 
Number(gint)): void {
+}
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+<item>
+<title><code>someint</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj-complex_vfunc.page 
b/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj-complex_vfunc.page
new file mode 100644
index 0000000..682d7f3
--- /dev/null
+++ b/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj-complex_vfunc.page
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<page id="Regress.TestObj-complex_vfunc"
+      type="topic"
+      style="vfunc"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="Regress.TestObj" group="vfunc" type="guide"/>
+  </info>
+  <title>Regress.TestObj::complex_vfunc</title>
+  <synopsis><code mime="text/x-gjs">
+function vfunc_complex_vfunc(someint: Number(gint)): void {
+}
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>someint</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-Python-expected/Regress.TestExternallyDefinedCallback.page 
b/tests/scanner/Regress-1.0-Python-expected/Regress.TestExternallyDefinedCallback.page
new file mode 100644
index 0000000..f53f37e
--- /dev/null
+++ b/tests/scanner/Regress-1.0-Python-expected/Regress.TestExternallyDefinedCallback.page
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<page id="Regress.TestExternallyDefinedCallback"
+      type="topic"
+      style="callback"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="index" group="callback" type="guide"/>
+  </info>
+  <title>Regress.TestExternallyDefinedCallback</title>
+  <synopsis><code mime="text/x-python">
+ accepts(Regress.TestObj, int)
+ returns(none)
+def on_TestExternallyDefinedCallback(obj, someint):
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+<item>
+<title><code>someint</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-Python-expected/Regress.TestFundamentalObject-copy.page 
b/tests/scanner/Regress-1.0-Python-expected/Regress.TestFundamentalObject-copy.page
new file mode 100644
index 0000000..d80c40b
--- /dev/null
+++ b/tests/scanner/Regress-1.0-Python-expected/Regress.TestFundamentalObject-copy.page
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<page id="Regress.TestFundamentalObject-copy"
+      type="topic"
+      style="vfunc"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="Regress.TestFundamentalObject" group="vfunc" type="guide"/>
+  </info>
+  <title>Regress.TestFundamentalObject::copy</title>
+  <synopsis><code mime="text/x-python">
+ accepts(Regress.TestFundamentalObject)
+ returns(Regress.TestFundamentalObject)
+def do_copy(obj):
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+<item>
+<title><code>Returns</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-Python-expected/Regress.TestFundamentalObject-finalize.page 
b/tests/scanner/Regress-1.0-Python-expected/Regress.TestFundamentalObject-finalize.page
new file mode 100644
index 0000000..5ff38ee
--- /dev/null
+++ b/tests/scanner/Regress-1.0-Python-expected/Regress.TestFundamentalObject-finalize.page
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<page id="Regress.TestFundamentalObject-finalize"
+      type="topic"
+      style="vfunc"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="Regress.TestFundamentalObject" group="vfunc" type="guide"/>
+  </info>
+  <title>Regress.TestFundamentalObject::finalize</title>
+  <synopsis><code mime="text/x-python">
+ accepts(Regress.TestFundamentalObject)
+ returns(none)
+def do_finalize(obj):
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj-complex_vfunc.page 
b/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj-complex_vfunc.page
new file mode 100644
index 0000000..c4d02b1
--- /dev/null
+++ b/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj-complex_vfunc.page
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<page id="Regress.TestObj-complex_vfunc"
+      type="topic"
+      style="vfunc"
+      xmlns="http://projectmallard.org/1.0/";
+      xmlns:api="http://projectmallard.org/experimental/api/";
+      xmlns:ui="http://projectmallard.org/1.0/ui/";>
+  <info>
+    <link xref="Regress.TestObj" group="vfunc" type="guide"/>
+  </info>
+  <title>Regress.TestObj::complex_vfunc</title>
+  <synopsis><code mime="text/x-python">
+ accepts(Regress.TestObj, int)
+ returns(none)
+def do_complex_vfunc(obj, someint):
+  </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>obj</code></title>
+
+</item>
+<item>
+<title><code>someint</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir
index a565113..5ba2be8 100644
--- a/tests/scanner/Regress-1.0-expected.gir
+++ b/tests/scanner/Regress-1.0-expected.gir
@@ -2466,6 +2466,20 @@ use it should be.</doc>
         </return-value>
       </function>
     </enumeration>
+    <callback name="TestExternallyDefinedCallback"
+              c:type="RegressTestExternallyDefinedCallback">
+      <return-value transfer-ownership="none">
+        <type name="none" c:type="void"/>
+      </return-value>
+      <parameters>
+        <parameter name="obj" transfer-ownership="none">
+          <type name="TestObj" c:type="RegressTestObj*"/>
+        </parameter>
+        <parameter name="someint" transfer-ownership="none">
+          <type name="gint" c:type="int"/>
+        </parameter>
+      </parameters>
+    </callback>
     <bitfield name="TestFlags"
               glib:type-name="RegressTestFlags"
               glib:get-type="regress_test_flags_get_type"
@@ -2523,6 +2537,29 @@ use it should be.</doc>
            glib:unref-func="regress_test_fundamental_object_unref"
            glib:set-value-func="regress_test_value_set_fundamental_object"
            glib:get-value-func="regress_test_value_get_fundamental_object">
+      <virtual-method name="copy">
+        <return-value transfer-ownership="full">
+          <type name="TestFundamentalObject"
+                c:type="RegressTestFundamentalObject*"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="obj" transfer-ownership="none">
+            <type name="TestFundamentalObject"
+                  c:type="const RegressTestFundamentalObject*"/>
+          </instance-parameter>
+        </parameters>
+      </virtual-method>
+      <virtual-method name="finalize">
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="obj" transfer-ownership="none">
+            <type name="TestFundamentalObject"
+                  c:type="RegressTestFundamentalObject*"/>
+          </instance-parameter>
+        </parameters>
+      </virtual-method>
       <method name="ref" c:identifier="regress_test_fundamental_object_ref">
         <return-value transfer-ownership="full">
           <doc xml:space="preserve">A new #RegressTestFundamentalObject</doc>
@@ -2866,6 +2903,19 @@ use it should be.</doc>
           </parameter>
         </parameters>
       </virtual-method>
+      <virtual-method name="complex_vfunc">
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="obj" transfer-ownership="none">
+            <type name="TestObj" c:type="RegressTestObj*"/>
+          </instance-parameter>
+          <parameter name="someint" transfer-ownership="none">
+            <type name="gint" c:type="int"/>
+          </parameter>
+        </parameters>
+      </virtual-method>
       <virtual-method name="matrix" invoker="do_matrix">
         <doc xml:space="preserve">This method is virtual.  Notably its name differs from the virtual
 slot name, which makes it useful for testing bindings handle this
@@ -3597,6 +3647,10 @@ the introspection client langage.</doc>
       <field name="test_signal_with_static_scope_arg">
         <type name="guint" c:type="guint"/>
       </field>
+      <field name="complex_vfunc">
+        <type name="TestExternallyDefinedCallback"
+              c:type="RegressTestExternallyDefinedCallback"/>
+      </field>
       <field name="_regress_reserved1" introspectable="0">
         <callback name="_regress_reserved1">
           <return-value transfer-ownership="none">
diff --git a/tests/scanner/regress.h b/tests/scanner/regress.h
index 3f917e6..e6ae1c2 100644
--- a/tests/scanner/regress.h
+++ b/tests/scanner/regress.h
@@ -487,6 +487,8 @@ struct _RegressTestObj
   GType gtype;
 };
 
+typedef void (*RegressTestExternallyDefinedCallback) (RegressTestObj *obj, int someint);
+
 struct _RegressTestObjClass
 {
   GObjectClass parent_class;
@@ -502,6 +504,8 @@ struct _RegressTestObjClass
   guint test_signal;
   guint test_signal_with_static_scope_arg;
 
+  RegressTestExternallyDefinedCallback complex_vfunc;
+
   /* Should be replaced with simple "gpointer" and not be callback */
   void (*_regress_reserved1) (void);
   void (*_regress_reserved2) (void);


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