[gobject-introspection] scanner: handle static methods on all types



commit c47a10f867da52695a5c5b5bf7e0a22dddc0b085
Author: Torsten SchÃnfeld <kaffeetisch gmx de>
Date:   Sat Aug 13 12:00:00 2011 +0200

    scanner: handle static methods on all types
    
    Instead of just handling static methods for classes, handle them for:
    
      - Records and boxed
      - Unions
      - Interfaces
    
    Based on a patch by Owen Taylor.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=572408

 giscanner/ast.py                       |    9 ++++++
 giscanner/maintransformer.py           |   38 ++++++++++++++++++++--------
 tests/scanner/Foo-1.0-expected.gir     |   43 ++++++++++++++++++++++++++++++++
 tests/scanner/Regress-1.0-expected.gir |    6 ++++
 tests/scanner/foo.c                    |    4 +++
 tests/scanner/foo.h                    |    2 +
 6 files changed, 91 insertions(+), 11 deletions(-)
---
diff --git a/giscanner/ast.py b/giscanner/ast.py
index bd56aef..8ca3a4d 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -19,6 +19,8 @@
 # Boston, MA 02111-1307, USA.
 #
 
+import copy
+
 from .message import Position
 from .odict import odict
 from .utils import to_underscores
@@ -568,6 +570,13 @@ class Function(Callable):
         self.shadowed_by = None # C symbol string
         self.shadows = None # C symbol string
 
+    def clone(self):
+        clone = copy.copy(self)
+        # copy the parameters array so a change to self.parameters does not
+        # influence clone.parameters.
+        clone.parameters = self.parameters[:]
+        return clone
+
 
 class ErrorQuarkFunction(Function):
 
diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py
index d2d1f2d..40dda29 100644
--- a/giscanner/maintransformer.py
+++ b/giscanner/maintransformer.py
@@ -993,19 +993,35 @@ method or constructor of some type."""
         if split is None:
             return False
         (node, funcname) = split
-
-        # We actually should treat static methods on a wider class of objects:
-        #  ast.Class, ast.Interface, ast.Record, ast.Union, ast.Boxed
-        # But we stick to ast.Class for now for compatibility with existing code.
-        #
-        # See https://bugzilla.gnome.org/show_bug.cgi?id=572408
-        #
-        if not isinstance(node, ast.Class):
+        if funcname == '':
             return False
 
-        self._namespace.float(func)
-        func.name = funcname
-        node.static_methods.append(func)
+        if isinstance(node, ast.Class):
+            self._namespace.float(func)
+            func.name = funcname
+            node.static_methods.append(func)
+            return True
+        elif isinstance(node, (ast.Interface, ast.Record, ast.Union,
+                               ast.Boxed)):
+            # prior to the introduction of this part of the code, only
+            # ast.Class could have static methods.  so for backwards
+            # compatibility, instead of removing the func from the namespace,
+            # leave it there and get a copy instead.  modify the copy and push
+            # it onto static_methods.  we need to copy the parameters list
+            # separately, because in the third pass functions are flagged as
+            # 'throws' depending on the presence of a GError parameter which is
+            # then removed from the parameters list.  without the explicit
+            # copy, only one of the two functions would thus get flagged as
+            # 'throws'.  clone() does this for us.
+            new_func = func.clone()
+            new_func.name = funcname
+            node.static_methods.append(new_func)
+            # TODO: flag func as a backwards-comptability kludge (and maybe
+            # prune it in the introspectable pass if we would have
+            # introspectable=0 anyway).
+            return True
+
+        return False
 
     def _set_up_constructor(self, func, subsymbol):
         self._namespace.float(func)
diff --git a/tests/scanner/Foo-1.0-expected.gir b/tests/scanner/Foo-1.0-expected.gir
index cc4c8d7..950648d 100644
--- a/tests/scanner/Foo-1.0-expected.gir
+++ b/tests/scanner/Foo-1.0-expected.gir
@@ -272,6 +272,17 @@ and/or use gtk-doc annotations.  -->
                glib:type-name="FooInterface"
                glib:get-type="foo_interface_get_type"
                glib:type-struct="InterfaceIface">
+      <function name="static_method"
+                c:identifier="foo_interface_static_method">
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <parameter name="x" transfer-ownership="none">
+            <type name="gint" c:type="int"/>
+          </parameter>
+        </parameters>
+      </function>
       <virtual-method name="do_foo" invoker="do_foo">
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -622,6 +633,27 @@ uses a C sugar return type.</doc>
           </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>
+          <parameter name="x" transfer-ownership="none">
+            <type name="gint" c:type="int"/>
+          </parameter>
+          <parameter name="y" transfer-ownership="none">
+            <type name="gint" c:type="int"/>
+          </parameter>
+          <parameter name="width" transfer-ownership="none">
+            <type name="gint" c:type="int"/>
+          </parameter>
+          <parameter name="height" transfer-ownership="none">
+            <type name="gint" c:type="int"/>
+          </parameter>
+        </parameters>
+      </function>
     </record>
     <constant name="SUCCESS_INT" value="4408">
       <type name="gint" c:type="gint"/>
@@ -952,6 +984,17 @@ exposed to language bindings.</doc>
         <type name="gint" c:type="gint"/>
       </return-value>
     </function>
+    <function name="interface_static_method"
+              c:identifier="foo_interface_static_method">
+      <return-value transfer-ownership="none">
+        <type name="none" c:type="void"/>
+      </return-value>
+      <parameters>
+        <parameter name="x" transfer-ownership="none">
+          <type name="gint" c:type="int"/>
+        </parameter>
+      </parameters>
+    </function>
     <function name="method_external_references"
               c:identifier="foo_method_external_references">
       <return-value transfer-ownership="none">
diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir
index 7e0b2e5..9b4ae8f 100644
--- a/tests/scanner/Regress-1.0-expected.gir
+++ b/tests/scanner/Regress-1.0-expected.gir
@@ -1014,6 +1014,12 @@ TpAccount::status-changed</doc>
           </parameter>
         </parameters>
       </method>
+      <function name="const_return"
+                c:identifier="regress_test_simple_boxed_a_const_return">
+        <return-value transfer-ownership="none">
+          <type name="TestSimpleBoxedA" c:type="RegressTestSimpleBoxedA*"/>
+        </return-value>
+      </function>
     </record>
     <record name="TestSimpleBoxedB"
             c:type="RegressTestSimpleBoxedB"
diff --git a/tests/scanner/foo.c b/tests/scanner/foo.c
index 8b8b40d..5456640 100644
--- a/tests/scanner/foo.c
+++ b/tests/scanner/foo.c
@@ -53,6 +53,10 @@ void foo_interface_do_foo (FooInterface *self, int x)
   FOO_INTERFACE_GET_INTERFACE(self)->do_foo (self, x);
 }
 
+void foo_interface_static_method (int x)
+{
+}
+
 enum {
   PROP_0,
   PROP_STRING,
diff --git a/tests/scanner/foo.h b/tests/scanner/foo.h
index e648e60..bd50221 100644
--- a/tests/scanner/foo.h
+++ b/tests/scanner/foo.h
@@ -62,6 +62,8 @@ GType                 foo_interface_get_type       (void) G_GNUC_CONST;
 
 void foo_interface_do_foo (FooInterface *iface, int x);
 
+void foo_interface_static_method (int x);
+
 struct _FooSubInterfaceIface
 {
   GTypeInterface parent_iface;



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