Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/giscanner/annotationparser.py
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2009-02-28 00:02:48 (GMT)
committer Colin Walters <walters@verbum.org>2009-03-05 20:52:12 (GMT)
commitfdbe3cc3e1cfaa546648a76b1dca72beead0b65b (patch)
tree01156e22ec59d29c642d59ce7ad75f383d77466a /giscanner/annotationparser.py
parentb8e3172424ba956a0d18eae8deb305310b2cab74 (diff)
Bug 557383 - Virtual method support
Broadly speaking, this change adds the concept of <vfunc> to the .gir. The typelib already had most of the infrastructure for virtual functions, though there is one API addition. The scanner assumes that any class callback slot that doesn't match a signal name is a virtual. In the .gir, we write out *both* the <method> wrapper and a <vfunc>. If we can determine an association between them (based on the names matching, or a new Virtual: annotation), then we notate that in the .gir. The typelib gains an association from the vfunc to the function, if it exists. This will be useful for bindings since they already know how to consume FunctionInfo.
Diffstat (limited to 'giscanner/annotationparser.py')
-rw-r--r--giscanner/annotationparser.py57
1 files changed, 43 insertions, 14 deletions
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index 35300b0..f32486c 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -41,6 +41,7 @@ from .glibast import GLibBoxed
_COMMENT_HEADER = '*\n '
# Tags - annotations applyed to comment blocks
+TAG_VFUNC = 'virtual'
TAG_SINCE = 'since'
TAG_DEPRECATED = 'deprecated'
TAG_RETURNS = 'returns'
@@ -298,8 +299,9 @@ class AnnotationApplier(object):
block = self._blocks.get(class_.type_name)
self._parse_node_common(class_, block)
self._parse_constructors(class_.constructors)
- self._parse_methods(class_.methods)
- self._parse_methods(class_.static_methods)
+ self._parse_methods(class_, class_.methods)
+ self._parse_vfuncs(class_, class_.virtual_methods)
+ self._parse_methods(class_, class_.static_methods)
self._parse_properties(class_, class_.properties)
self._parse_signals(class_, class_.signals)
self._parse_fields(class_, class_.fields)
@@ -309,7 +311,8 @@ class AnnotationApplier(object):
def _parse_interface(self, interface):
block = self._blocks.get(interface.type_name)
self._parse_node_common(interface, block)
- self._parse_methods(interface.methods)
+ self._parse_methods(interface, interface.methods)
+ self._parse_vfuncs(interface, interface.virtual_methods)
self._parse_properties(interface, interface.properties)
self._parse_signals(interface, interface.signals)
self._parse_fields(interface, interface.fields)
@@ -320,7 +323,7 @@ class AnnotationApplier(object):
block = self._blocks.get(record.symbol)
self._parse_node_common(record, block)
self._parse_constructors(record.constructors)
- self._parse_methods(record.methods)
+ self._parse_methods(record, record.methods)
self._parse_fields(record, record.fields)
if block:
record.doc = block.comment
@@ -329,7 +332,7 @@ class AnnotationApplier(object):
block = self._blocks.get(boxed.name)
self._parse_node_common(boxed, block)
self._parse_constructors(boxed.constructors)
- self._parse_methods(boxed.methods)
+ self._parse_methods(boxed, boxed.methods)
if block:
boxed.doc = block.comment
@@ -338,7 +341,7 @@ class AnnotationApplier(object):
self._parse_node_common(union, block)
self._parse_fields(union, union.fields)
self._parse_constructors(union.constructors)
- self._parse_methods(union.methods)
+ self._parse_methods(union, union.methods)
if block:
union.doc = block.comment
@@ -370,9 +373,13 @@ class AnnotationApplier(object):
for prop in properties:
self._parse_property(parent, prop)
- def _parse_methods(self, methods):
+ def _parse_methods(self, parent, methods):
for method in methods:
- self._parse_function(method)
+ self._parse_method(parent, method)
+
+ def _parse_vfuncs(self, parent, vfuncs):
+ for vfunc in vfuncs:
+ self._parse_vfunc(parent, vfunc)
def _parse_signals(self, parent, signals):
for signal in signals:
@@ -392,18 +399,20 @@ class AnnotationApplier(object):
if block:
callback.doc = block.comment
+ def _parse_callable(self, callable, block):
+ self._parse_node_common(callable, block)
+ self._parse_params(callable, callable.parameters, block)
+ self._parse_return(callable, callable.retval, block)
+ if block:
+ callable.doc = block.comment
+
def _parse_function(self, func):
block = self._blocks.get(func.symbol)
- self._parse_node_common(func, block)
- self._parse_params(func, func.parameters, block)
- self._parse_return(func, func.retval, block)
- if block:
- func.doc = block.comment
+ self._parse_callable(func, block)
def _parse_signal(self, parent, signal):
block = self._blocks.get('%s::%s' % (parent.type_name, signal.name))
self._parse_node_common(signal, block)
- self._parse_deprecated(signal, block)
# We're only attempting to name the signal parameters if
# the number of parameter tags (@foo) is the same or greater
# than the number of signal parameters
@@ -426,6 +435,26 @@ class AnnotationApplier(object):
if block:
signal.doc = block.comment
+ def _parse_method(self, parent, meth):
+ block = self._blocks.get(meth.symbol)
+ self._parse_function(meth)
+ virtual = self._get_tag(block, TAG_VFUNC)
+ if virtual:
+ invoker_name = virtual.value
+ matched = False
+ for vfunc in parent.virtual_methods:
+ if vfunc.name == invoker_name:
+ matched = True
+ vfunc.invoker = meth.name
+ break
+ if not matched:
+ print "warning: unmatched virtual invoker %r for method %r" % \
+ (invoker_name, meth.symbol)
+
+ def _parse_vfunc(self, parent, vfunc):
+ key = '%s::%s' % (parent.type_name, vfunc.name)
+ self._parse_callable(vfunc, self._blocks.get(key))
+
def _parse_field(self, parent, field):
if isinstance(field, Callback):
self._parse_callback(field)