[gobject-introspection/wip/transformer] Fix class pairing, handle '_' prefix correctly
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gobject-introspection/wip/transformer] Fix class pairing, handle '_' prefix correctly
- Date: Fri, 23 Jul 2010 10:36:18 +0000 (UTC)
commit 7c8e06d49437d46f910a105a031b0ddb0912d116
Author: Colin Walters <walters verbum org>
Date: Fri Jul 23 03:19:56 2010 -0400
Fix class pairing, handle '_' prefix correctly
giscanner/ast.py | 23 ++++--
giscanner/glibtransformer.py | 170 +++++++++++++++++++++++-------------------
giscanner/transformer.py | 20 +++--
3 files changed, 119 insertions(+), 94 deletions(-)
---
diff --git a/giscanner/ast.py b/giscanner/ast.py
index d37af5a..464c794 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -67,6 +67,15 @@ In this case, the ctype must be specified.
assert self.target_giname is not None
return self.target_giname.split('.')[1]
+ def __cmp__(self, other):
+ if self.target_fundamental:
+ return cmp(self.target_fundamental, other.target_fundamental)
+ if self.target_giname:
+ return cmp(self.target_giname, other.target_giname)
+ if self.target_foreign:
+ return cmp(self.target_foreign, other.target_foreign)
+ return cmp(self.ctype, other.ctype)
+
def is_equiv(self, typeval):
"""Return True if the specified types are compatible at
an introspection level, disregarding their C types.
@@ -78,14 +87,7 @@ In this case, the ctype must be specified.
if self.is_equiv(val):
return True
return False
- if not (self.resolved and typeval.resolved):
- return False
- if self.target_fundamental:
- return typeval.target_fundamental == self.target_fundamental
- elif self.target_giname:
- return typeval.target_giname == self.target_giname
- elif self.target_foreign:
- return typeval.target_foreign == self.target_foreign
+ return self == typeval
def clone(self):
return Type(target_fundamental=self.target_fundamental,
@@ -152,6 +154,9 @@ GIR_TYPES.extend([TYPE_STRING, TYPE_FILENAME])
type_names = {}
for typeval in GIR_TYPES:
type_names[typeval.target_fundamental] = typeval
+basic_type_names = {}
+for typeval in BASIC_GIR_TYPES:
+ basic_type_names[typeval.target_fundamental] = typeval
# C builtin
type_names['char'] = TYPE_CHAR
@@ -269,7 +274,7 @@ create a Type object referncing it. If name is already a
fully-qualified GIName like 'Foo.Bar', returns a Type targeting it .
Otherwise a Type targeting name qualififed with the namespace name is
returned."""
- if name in GIR_TYPES:
+ if name in type_names:
return Type(target_fundamental=name, ctype=ctype)
if '.' in name:
target = name
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 8405177..10fa187 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -145,13 +145,13 @@ class GLibTransformer(object):
self._uscore_type_names[uscored] = node
for node in list(self._namespace.itervalues()):
- # Discover which functions are actually methods
+ # Discover which toplevel functions are actually methods
if isinstance(node, Function):
self._pair_function(node)
- self._namespace.walk(self._pass3_callable)
+ self._namespace.walk(self._pass3)
- # Third pass
+ # TODO - merge into pass3
for node in self._namespace.itervalues():
self._resolve_quarks()
@@ -381,7 +381,7 @@ _split_uscored_by_type(text_buffer_try_new) -> (Class(TextBuffer), 'try_new')"""
def _pair_function(self, func):
"""Check to see whether a toplevel function should be a
method or constructor of some type."""
- if func.symbol.endswith('_get_type'):
+ if func.symbol.endswith('_get_type') or func.symbol.startswith('_'):
return
(ns, subsymbol) = self._transformer.split_csymbol(func.symbol)
assert ns == self._namespace
@@ -472,76 +472,6 @@ method or constructor of some type."""
record.fields = self._namespace.get('ObjectClass').fields
self._namespace.append(record, replace=True)
- def _strip_class_suffix(self, name):
- if (name.endswith('Class') or
- name.endswith('Iface')):
- return name[:-5]
- elif name.endswith('Interface'):
- return name[:-9]
- else:
- return name
-
- def _pair_class_record(self, maybe_class):
- name = self._strip_class_suffix(maybe_class.name)
- if name == maybe_class.name:
- return
-
- class_struct = maybe_class
- pair_class = self._namespace.get(name)
- if not pair_class:
- return
- if not isinstance(pair_class, (GLibObject, GLibInterface)):
- return
-
- # Object class fields are assumed to be read-only
- # (see also _introspect_object and transformer.py)
- for field in maybe_class.fields:
- if isinstance(field, Field):
- field.writable = False
-
- # Loop through fields to determine which are virtual
- # functions and which are signal slots by
- # assuming everything that doesn't share a name
- # with a known signal is a virtual slot.
- for field in maybe_class.fields:
- if not isinstance(field, Callback):
- continue
- # Check the first parameter is the object
- if len(field.parameters) == 0:
- continue
- firstparam_type = field.parameters[0].type
- if firstparam_type != pair_class:
- continue
- # Also double check we don't have a signal with this
- # name.
- matched_signal = False
- for signal in pair_class.signals:
- if signal.name.replace('-', '_') == field.name:
- matched_signal = True
- break
- if matched_signal:
- continue
- vfunc = VFunction.from_callback(field)
- vfunc.inherit_file_positions(field)
- pair_class.virtual_methods.append(vfunc)
-
- # Take the set of virtual methods we found, and try
- # to pair up with any matching methods using the
- # name+signature.
- for vfunc in pair_class.virtual_methods:
- for method in pair_class.methods:
- if (method.name != vfunc.name or
- method.retval != vfunc.retval or
- method.parameters != vfunc.parameters):
- continue
- vfunc.invoker = method
-
- gclass_struct = GLibRecord.from_record(class_struct)
- self._namespace.append(gclass_struct, replace=True)
- pair_class.glib_type_struct = gclass_struct.create_type()
- pair_class.inherit_file_positions(class_struct)
- gclass_struct.is_gtype_struct_for = pair_class.create_type()
-
# Introspection over the data we get from the dynamic
# GObject/GType system out of the binary
@@ -741,11 +671,95 @@ method or constructor of some type."""
return True
return False
- def _pass3_callable(self, node, chain):
- if not isinstance(node, Callable):
+ def _strip_class_suffix(self, name):
+ if (name.endswith('Class') or
+ name.endswith('Iface')):
+ return name[:-5]
+ elif name.endswith('Interface'):
+ return name[:-9]
+ else:
+ return name
+
+ def _pair_class_record(self, maybe_class):
+ name = self._strip_class_suffix(maybe_class.name)
+ if name == maybe_class.name:
return
- self._pass3_callable_callbacks(node)
- self._pass3_callable_throws(node)
+
+ class_struct = maybe_class
+ pair_class = self._namespace.get(name)
+ if not pair_class:
+ return
+ if not isinstance(pair_class, (GLibObject, GLibInterface)):
+ return
+
+ gclass_struct = GLibRecord.from_record(class_struct)
+ self._namespace.append(gclass_struct, replace=True)
+ pair_class.glib_type_struct = gclass_struct.create_type()
+ pair_class.inherit_file_positions(class_struct)
+ gclass_struct.is_gtype_struct_for = pair_class.create_type()
+
+ def _pass3_class(self, node):
+ """Look for virtual methods from the class structure."""
+ if not node.glib_type_struct:
+ self._transformer.log_node_warning(node,
+ "Failed to find class structure for %r" % (node.name, ))
+ return
+
+ node_type = node.create_type()
+ class_struct = self._transformer.lookup_typenode(node.glib_type_struct)
+
+ # Object class fields are assumed to be read-only
+ # (see also _introspect_object and transformer.py)
+ for field in class_struct.fields:
+ if isinstance(field, Field):
+ field.writable = False
+
+ # Loop through fields to determine which are virtual
+ # functions and which are signal slots by
+ # assuming everything that doesn't share a name
+ # with a known signal is a virtual slot.
+ for field in class_struct.fields:
+ if not isinstance(field.anonymous_node, Callback):
+ 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
+ # Also double check we don't have a signal with this
+ # name.
+ matched_signal = False
+ for signal in node.signals:
+ if signal.name.replace('-', '_') == callback.name:
+ matched_signal = True
+ break
+ if matched_signal:
+ continue
+ vfunc = VFunction.from_callback(callback)
+ vfunc.inherit_file_positions(callback)
+ node.virtual_methods.append(vfunc)
+
+ # Take the set of virtual methods we found, and try
+ # to pair up with any matching methods using the
+ # name+signature.
+ for vfunc in node.virtual_methods:
+ for method in node.methods:
+ if (method.name != vfunc.name or
+ method.retval != vfunc.retval or
+ method.parameters != vfunc.parameters):
+ continue
+ vfunc.invoker = method
+
+ def _pass3(self, node, chain):
+ """Pass 3 is after we've loaded GType data and performed type
+ closure."""
+ if isinstance(node, Callable):
+ self._pass3_callable_callbacks(node)
+ self._pass3_callable_throws(node)
+ elif isinstance(node, Class):
+ self._pass3_class(node)
def _pass3_callable_callbacks(self, node):
"""Check to see if we have anything that looks like a
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index 4ad2ef1..23657ed 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -24,8 +24,8 @@ import sys
from .ast import (Bitfield, Callback, Enum, Function, Namespace, Member,
Parameter, Return, Record, Field,
Type, Array, List, Map, Alias, Interface, Class, Node, Union,
- Varargs, Constant, type_names, default_array_types, TYPE_STRING, TYPE_ANY,
- BASIC_GIR_TYPES)
+ Varargs, Constant, type_names, basic_type_names,
+ default_array_types, TYPE_STRING, TYPE_ANY)
from .config import DATADIR, GIR_DIR, GIR_SUFFIX
from .girparser import GIRParser
from .odict import odict
@@ -252,15 +252,21 @@ pair of (namespace, stripped_identifier) or raise ValueError."""
return matches[0]
raise ValueError("Unknown namespace for symbol %r" % (symbol, ))
- def _strip_csymbol_or_warn(self, symbol):
+ def _strip_symbol_or_warn(self, symbol):
+ ident = symbol.ident
+ hidden = ident.startswith('_')
+ if hidden:
+ ident = ident[1:]
try:
- (ns, name) = self.split_csymbol(symbol.ident)
+ (ns, name) = self.split_csymbol(ident)
except ValueError, e:
self.log_symbol_warning(symbol, "Unknown namespace")
return None
if ns != self._namespace:
self.log_symbol_warning(symbol, "Skipping foreign symbol from namespace %s" % (ns.name, ))
return None
+ if hidden:
+ return '_' + name
return name
def remove_prefix(self, name, isfunction=False):
@@ -358,7 +364,7 @@ pair of (namespace, stripped_identifier) or raise ValueError."""
def _create_function(self, symbol):
parameters = list(self._create_parameters(symbol.base_type))
return_ = self._create_return(symbol.base_type.base_type)
- name = self._strip_csymbol_or_warn(symbol)
+ name = self._strip_symbol_or_warn(symbol)
if not name:
return None
func = Function(name, return_, parameters, False, symbol.ident)
@@ -486,7 +492,7 @@ pair of (namespace, stripped_identifier) or raise ValueError."""
# Preserve "pointerness" of struct/union members
if (is_member and canonical.endswith('*') and
- derefed_typename in BASIC_GIR_TYPES):
+ derefed_typename in basic_type_names):
return 'gpointer'
else:
return derefed_typename
@@ -534,7 +540,7 @@ pair of (namespace, stripped_identifier) or raise ValueError."""
if (symbol.source_filename is None or
not symbol.source_filename.endswith('.h')):
return None
- name = self._strip_csymbol_or_warn(symbol)
+ name = self._strip_symbol_or_warn(symbol)
if not name:
return None
if symbol.const_string is not None:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]