diff options
author | Colin Walters <walters@verbum.org> | 2009-02-25 23:43:14 (GMT) |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2009-02-26 19:07:21 (GMT) |
commit | 4470a24e8cf3827efaddcfe240c3271cf1a0d6c0 (patch) | |
tree | 4bbcd76c1c325c403ec0408a81489ab97c5465f0 | |
parent | 251de52b083d3e0e42f25cb164a46865c2c2b9a9 (diff) |
Bug 557383 - Virtual function support
In order to determine whether a method is virtual, by default we look
at the class table to find a callback field. This should be fairly reliable,
but we may also later need annotations to more finely control this
in the case of a name clash with a signal.
-rw-r--r-- | giscanner/ast.py | 6 | ||||
-rw-r--r-- | giscanner/girwriter.py | 6 | ||||
-rw-r--r-- | giscanner/glibtransformer.py | 21 | ||||
-rw-r--r-- | tests/scanner/foo-1.0-expected.gir | 35 | ||||
-rw-r--r-- | tests/scanner/foo-1.0-expected.tgir | 27 | ||||
-rw-r--r-- | tests/scanner/foo.c | 10 | ||||
-rw-r--r-- | tests/scanner/foo.h | 6 |
7 files changed, 76 insertions, 35 deletions
diff --git a/giscanner/ast.py b/giscanner/ast.py index e708258..4bd674d 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -205,6 +205,7 @@ class Function(Node): self.symbol = symbol self.throws = not not throws self.is_method = False + self.is_virtual = False self.doc = None def get_parameter_index(self, name): @@ -222,11 +223,6 @@ class Function(Node): self.name, self.retval, self.parameters) - -class VFunction(Function): - pass - - class Type(Node): def __init__(self, name, ctype=None): diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index df52709..9a08aaa 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -167,7 +167,11 @@ and/or use gtk-doc annotations. ''') self._write_parameters(func.parameters) def _write_method(self, method): - self._write_function(method, tag_name='method') + if method.is_virtual: + tag_name = 'vfunc' + else: + tag_name = 'method' + self._write_function(method, tag_name) def _write_static_method(self, method): self._write_function(method, tag_name='function') diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py index 5a7a96d..fc7f17c 100644 --- a/giscanner/glibtransformer.py +++ b/giscanner/glibtransformer.py @@ -159,6 +159,10 @@ class GLibTransformer(object): except KeyError, e: print "WARNING: DELETING node %s: %s" % (node.name, e) self._remove_attribute(node.name) + # Another pass, since we need to have the methods parsed + # in order to correctly modify them after class/record + # pairing + for (ns, node) in nodes: # associate GtkButtonClass with GtkButton if isinstance(node, Record): self._pair_class_record(node) @@ -573,10 +577,19 @@ class GLibTransformer(object): for field in maybe_class.fields: if isinstance(field, Field): field.writable = False - # TODO: remove this, we should be computing vfuncs instead - if isinstance(pair_class, GLibInterface): - for field in maybe_class.fields[1:]: - pair_class.fields.append(field) + + # Pair up virtual methods by finding a slot in + # the class with the same name + for field in maybe_class.fields: + if not isinstance(field, Callback): + continue + matched = False + for method in pair_class.methods: + if (method.name == field.name and + len(method.parameters)+1 == len(field.parameters)): + method.is_virtual = True + break + gclass_struct = GLibRecord.from_record(class_struct) self._remove_attribute(class_struct.name) self._add_attribute(gclass_struct, True) diff --git a/tests/scanner/foo-1.0-expected.gir b/tests/scanner/foo-1.0-expected.gir index 0f6b1f1..38bde58 100644 --- a/tests/scanner/foo-1.0-expected.gir +++ b/tests/scanner/foo-1.0-expected.gir @@ -232,16 +232,16 @@ and/or use gtk-doc annotations. --> glib:type-name="FooInterface" glib:get-type="foo_interface_get_type" glib:type-struct="InterfaceIface"> - <callback name="do_foo" c:type="do_foo"> + <vfunc name="do_foo" c:identifier="foo_interface_do_foo"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> </return-value> <parameters> - <parameter name="self" transfer-ownership="none"> - <type name="Interface" c:type="FooInterface*"/> + <parameter name="x" transfer-ownership="none"> + <type name="int" c:type="int"/> </parameter> </parameters> - </callback> + </vfunc> </interface> <record name="InterfaceIface" c:type="FooInterfaceIface" @@ -257,6 +257,9 @@ and/or use gtk-doc annotations. --> <parameter name="self" transfer-ownership="none"> <type name="Interface" c:type="FooInterface*"/> </parameter> + <parameter name="x" transfer-ownership="none"> + <type name="int" c:type="int"/> + </parameter> </parameters> </callback> </record> @@ -359,6 +362,16 @@ and/or use gtk-doc annotations. --> </parameter> </parameters> </method> + <vfunc name="virtual_method" c:identifier="foo_object_virtual_method"> + <return-value transfer-ownership="none"> + <type name="none" c:type="void"/> + </return-value> + <parameters> + <parameter name="first_param" transfer-ownership="none"> + <type name="int" c:type="int"/> + </parameter> + </parameters> + </vfunc> <property name="string" writable="1" construct="1"> <type name="utf8" c:type="gchararray"/> </property> @@ -467,21 +480,11 @@ and/or use gtk-doc annotations. --> glib:get-type="foo_sub_interface_get_type" glib:type-struct="SubInterfaceIface"> <prerequisite name="Interface"/> - <method name="do_bar" c:identifier="foo_sub_interface_do_bar"> - <return-value transfer-ownership="none"> - <type name="none" c:type="void"/> - </return-value> - </method> - <callback name="do_bar" c:type="do_bar"> + <vfunc name="do_bar" c:identifier="foo_sub_interface_do_bar"> <return-value transfer-ownership="none"> <type name="none" c:type="void"/> </return-value> - <parameters> - <parameter name="self" transfer-ownership="none"> - <type name="SubInterface" c:type="FooSubInterface*"/> - </parameter> - </parameters> - </callback> + </vfunc> </interface> <record name="SubInterfaceIface" c:type="FooSubInterfaceIface" diff --git a/tests/scanner/foo-1.0-expected.tgir b/tests/scanner/foo-1.0-expected.tgir index f8e1ee5..e2a02b1 100644 --- a/tests/scanner/foo-1.0-expected.tgir +++ b/tests/scanner/foo-1.0-expected.tgir @@ -161,7 +161,18 @@ <member name="second" value="2"/> <member name="third" value="4"/> </bitfield> - <interface name="Interface" glib:type-name="FooInterface" glib:get-type="foo_interface_get_type" glib:type-struct="InterfaceIface"/> + <interface name="Interface" glib:type-name="FooInterface" glib:get-type="foo_interface_get_type" glib:type-struct="InterfaceIface"> + <vfunc name="do_foo" offset="0"> + <return-value transfer-ownership="none"> + <type name="none"/> + </return-value> + <parameters> + <parameter name="x" transfer-ownership="none"> + <type name="int"/> + </parameter> + </parameters> + </vfunc> + </interface> <record name="InterfaceIface" glib:is-gtype-struct="1"> <field name="parent_iface"> <type name="GObject.TypeInterface"/> @@ -271,6 +282,16 @@ </parameter> </parameters> </glib:signal> + <vfunc name="virtual_method" offset="0"> + <return-value transfer-ownership="none"> + <type name="none"/> + </return-value> + <parameters> + <parameter name="first_param" transfer-ownership="none"> + <type name="int"/> + </parameter> + </parameters> + </vfunc> </class> <record name="ObjectClass" glib:is-gtype-struct="1"> <field name="parent_class"> @@ -337,11 +358,11 @@ <record name="StructPrivate"/> <interface name="SubInterface" glib:type-name="FooSubInterface" glib:get-type="foo_sub_interface_get_type" glib:type-struct="SubInterfaceIface"> <prerequisite name="Interface"/> - <method name="do_bar" c:identifier="foo_sub_interface_do_bar"> + <vfunc name="do_bar" offset="0"> <return-value transfer-ownership="none"> <type name="none"/> </return-value> - </method> + </vfunc> </interface> <record name="SubInterfaceIface" glib:is-gtype-struct="1"> <field name="parent_iface"> diff --git a/tests/scanner/foo.c b/tests/scanner/foo.c index 0488260..98d2f4b 100644 --- a/tests/scanner/foo.c +++ b/tests/scanner/foo.c @@ -8,8 +8,8 @@ int foo_init_argv (int argc, char **argv); int foo_init_argv_address (int *argc, char ***argv); void foo_private_function (FooObject *foo); void foo_test_unsigned (unsigned int uint); -void foo_interface_do_foo (FooInterface *self); -void foo_do_foo (FooInterface *self); +void foo_interface_do_foo (FooInterface *self, int x); +void foo_do_foo (FooInterface *self, int x); int foo_enum_method (FooEnumType foo_enum); FooHidden * foo_hidden_copy (const FooHidden *boxed); void foo_hidden_free (FooHidden *boxed); @@ -47,9 +47,9 @@ foo_interface_get_type (void) return object_type; } -void foo_interface_do_foo (FooInterface *self) +void foo_interface_do_foo (FooInterface *self, int x) { - FOO_INTERFACE_GET_INTERFACE(self)->do_foo (self); + FOO_INTERFACE_GET_INTERFACE(self)->do_foo (self, x); } enum { @@ -191,7 +191,7 @@ foo_object_take_all (FooObject *object, int x, ...) } void -foo_do_foo (FooInterface *self) +foo_do_foo (FooInterface *self, int x) { diff --git a/tests/scanner/foo.h b/tests/scanner/foo.h index da30df3..2eeed6d 100644 --- a/tests/scanner/foo.h +++ b/tests/scanner/foo.h @@ -48,11 +48,13 @@ struct _FooInterfaceIface { GTypeInterface parent_iface; - void (*do_foo) (FooInterface *self); + void (*do_foo) (FooInterface *self, int x); }; GType foo_interface_get_type (void) G_GNUC_CONST; +void foo_interface_do_foo (FooInterface *iface, int x); + struct _FooSubInterfaceIface { GTypeInterface parent_iface; @@ -105,6 +107,8 @@ char * foo_object_dup_name (FooObject *object); void foo_object_handle_glyph (FooObject *object, UtilityGlyph glyph); +void foo_object_virtual_method (FooObject *object, int first_param); + int foo_object_static_meth (); struct _FooSubobject |