[gobject-introspection/wip/transformer] lots more hacking
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gobject-introspection/wip/transformer] lots more hacking
- Date: Tue, 20 Jul 2010 15:39:42 +0000 (UTC)
commit 859da02b3e2e96990ece0ba6df586f917a5b5e06
Author: Colin Walters <walters verbum org>
Date: Wed Jul 14 18:48:37 2010 -0400
lots more hacking
giscanner/ast.py | 13 +++++-
giscanner/glibast.py | 2 +-
giscanner/glibtransformer.py | 84 ++++++++++++-----------------------------
giscanner/transformer.py | 19 +++++++--
4 files changed, 51 insertions(+), 67 deletions(-)
---
diff --git a/giscanner/ast.py b/giscanner/ast.py
index d6fe47f..8af0198 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -273,9 +273,7 @@ identifier string."""
previous = self._names.get(node.name)
if previous is not None:
if not replace:
- raise SystemExit(
- "transformer: conflict: ns=%r orig=%r new=%r" %
- (self.name, previous, node))
+ raise ValueError("Namespace conflict")
self.remove(previous)
# A layering violation...but oh well.
from .glibast import GLibBoxed
@@ -365,6 +363,11 @@ GIName. It's possible for nodes to contain or point to other nodes."""
self.foreign = False
self.file_positions = set()
+ def create_type(self):
+ """Create a Type object referencing this node."""
+ assert self.namespace is not None
+ return Type(target_giname=('%s.%s' % (self.namespace.name, self.name)))
+
def __cmp__(self, other):
nscmp = cmp(self.namespace, other.namespace)
if nscmp != 0:
@@ -599,6 +602,10 @@ class Class(Node):
Node.__init__(self, name)
self.ctype = name
self.parent = parent
+ # When we're in the scanner, we keep around a list
+ # of parents so that we can transparently fall back
+ # if there are 'hidden' parents
+ self.parent_chain = None
self.glib_type_struct = None
self.is_abstract = is_abstract
self.methods = []
diff --git a/giscanner/glibast.py b/giscanner/glibast.py
index dd6079d..c2b2600 100644
--- a/giscanner/glibast.py
+++ b/giscanner/glibast.py
@@ -27,7 +27,7 @@ class GLibRecord(Record):
@classmethod
def from_record(cls, record):
- obj = cls(record.namespace, record.name, record.symbol)
+ obj = cls(record.name, record.symbol)
obj.fields = record.fields
obj.constructors = record.constructors
obj.disguised = record.disguised
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 0fcec82..05ba2f1 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -29,7 +29,7 @@ from .ast import (Alias, Bitfield, Callable, Callback, Class, Constant, Enum,
Function, Interface, Member, Namespace, Node, Parameter,
Property, Record, Return, Type, TypeContainer, Union,
Field, VFunction, default_array_types,
- TYPE_ANY, TYPE_UINT8, PARAM_TRANSFER_FULL, Array, List,
+ TYPE_ANY, TYPE_GTYPE, TYPE_UINT8, PARAM_TRANSFER_FULL, Array, List,
Map, Varargs, type_names)
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
@@ -48,18 +48,6 @@ G_PARAM_STATIC_NAME = 1 << 5
G_PARAM_STATIC_NICK = 1 << 6
G_PARAM_STATIC_BLURB = 1 << 7
-GET_TYPE_OVERRIDES = {
- # this is a special case, from glibtransforer.py:create_gobject
- 'intern': 'g_object_get_type',
- # this is presumably a typo, should be fixed upstream
- 'g_gstring_get_type': 'g_string_get_type',
- # this is historical cruft: there's a deprecated
- # #define gdk_window_get_type gdk_window_get_window_type
- # upstream; this method can be renamed properly upstream once
- # that deprecated alias is removed (in some future release)
- 'gdk_window_object_get_type': 'gdk_window_get_type',
-}
-
class IntrospectionBinary(object):
@@ -172,20 +160,6 @@ class GLibTransformer(object):
prefix = type_name[:-len(suffix)]
return (prefix + '_' + to_underscores(suffix)).lower()
- def _register_internal_type(self, type_name, node):
- self._names.type_names[type_name] = (None, node)
- uscored = to_underscores(type_name).lower()
- # prefer the prefix of the get_type method, if there is one
- if hasattr(node, 'get_type'):
- uscored = GET_TYPE_OVERRIDES.get(node.get_type, node.get_type)
- uscored = uscored[:-len('_get_type')]
- self._uscore_type_names[uscored] = node
-
- no_uscore_prefixed = self._get_no_uscore_prefixed_name(type_name)
- # since this is a guess, don't overwrite any 'real' prefix
- if no_uscore_prefixed not in self._uscore_type_names:
- self._uscore_type_names[no_uscore_prefixed] = node
-
def _pass_type_resolution(self, node, chain):
if isinstance(node, Alias):
self._transformer.resolve_type(node.target)
@@ -302,9 +276,8 @@ blob containing data gleaned from GObject's primitive introspection."""
# what we do here is copy all of the GObject fields into
# GInitiallyUnowned so that struct offset computation
# works correctly.
- gnode.fields = self._names.names['Object'][1].fields
+ gnode.fields = self._namespace.get('Object').fields
self._namespace.append(gnode, replace=True)
- self._register_internal_type(type_name, gnode)
# Parser
@@ -322,21 +295,19 @@ blob containing data gleaned from GObject's primitive introspection."""
# No GObjects in GLib
return False
if (self._namespace.name == 'GObject' and
- symbol in ('g_object_get_type', 'g_initially_unowned_get_type')):
+ func.symbol in ('g_object_get_type', 'g_initially_unowned_get_type')):
# We handle these internally, see _create_gobject
return True
if func.parameters:
return False
# GType *_get_type(void)
- if func.retval.type.name not in ['Type',
- 'GType',
- 'GObject.Type',
- 'Gtk.Type']:
- self._transformer.log_("Warning: *_get_type function returns '%r'"
- ", not GObject.Type") % (func.retval.type.name, )
+ rettype = func.retval.type
+ if not (rettype.is_equiv(TYPE_GTYPE)
+ or rettype.target_giname == 'Gtk.Type'):
+ self._transformer.log_warning("function returns '%r', not a GType") % (func.retval.type, )
return False
- self._get_type_functions.append(symbol)
+ self._get_type_functions.append(func.symbol)
return True
def _initparse_error_quark_function(self, func):
@@ -350,7 +321,7 @@ blob containing data gleaned from GObject's primitive introspection."""
def _name_is_internal_gtype(self, giname):
try:
- node = self._get_attribute(giname)
+ node = self._namespace.get(giname)
return isinstance(node, (GLibObject, GLibInterface,
GLibBoxed, GLibEnum, GLibFlags))
except KeyError, e:
@@ -422,9 +393,6 @@ blob containing data gleaned from GObject's primitive introspection."""
new_idx = func.symbol.find('_new')
if new_idx < 0:
return None
- # Constructors don't return basic types
- derefed = self._transformer.follow_aliases(target_arg.type.name,
- self._names)
if derefed in type_names:
#print "NOTE: Rejecting constructor returning basic: %r" \
# % (func.symbol, )
@@ -448,7 +416,7 @@ blob containing data gleaned from GObject's primitive introspection."""
remove_prefix = klass.type_name
name = self._transformer.remove_prefix(remove_prefix)
- klass = self._get_attribute(name)
+ klass = self._namespace.get(name)
if klass is None:
return
@@ -484,7 +452,7 @@ blob containing data gleaned from GObject's primitive introspection."""
self._create_gobject(record)
return
if record.name == 'InitiallyUnownedClass':
- record.fields = self._names.names['ObjectClass'][1].fields
+ record.fields = self._namespace.get('ObjectClass').fields
self._namespace.append(record, replace=True)
def _strip_class_suffix(self, name):
@@ -515,7 +483,7 @@ blob containing data gleaned from GObject's primitive introspection."""
del self._names.names[class_struct.name]
return
- pair_class = self._get_attribute(name)
+ pair_class = self._namespace.get(name)
if (not pair_class or
not isinstance(pair_class, (GLibObject, GLibInterface))):
return
@@ -567,7 +535,7 @@ blob containing data gleaned from GObject's primitive introspection."""
self._namespace.append(gclass_struct, replace=True)
pair_class.glib_type_struct = gclass_struct
pair_class.inherit_file_positions(class_struct)
- gclass_struct.is_gtype_struct_for = name
+ gclass_struct.is_gtype_struct_for = maybe_class.create_type()
# Introspection over the data we get from the dynamic
# GObject/GType system out of the binary
@@ -635,7 +603,7 @@ blob containing data gleaned from GObject's primitive introspection."""
self._introspect_signals(node, xmlnode)
for child in xmlnode.findall('prerequisite'):
name = child.attrib['name']
- prereq = self._resolve_gtypename(name)
+ prereq = self._transformer.create_type(name)
node.prerequisites.append(prereq)
# GtkFileChooserEmbed is an example of a private interface, we
# just filter them out
@@ -650,12 +618,11 @@ blob containing data gleaned from GObject's primitive introspection."""
# the struct or union
node = GLibBoxed(type_name, xmlnode.attrib['get-type'])
self._boxed_types[node.type_name] = node
- self._register_internal_type(type_name, node)
def _introspect_implemented_interfaces(self, node, xmlnode):
gt_interfaces = []
for interface in xmlnode.findall('implements'):
- gitype = self._resolve_gtypename(interface.attrib['name'])
+ gitype = self._transformer.create_type(interface.attrib['name'])
gt_interfaces.append(gitype)
node.interfaces = sorted(gt_interfaces)
@@ -669,7 +636,7 @@ blob containing data gleaned from GObject's primitive introspection."""
construct_only = (flags & G_PARAM_CONSTRUCT_ONLY) != 0
node.properties.append(Property(
pspec.attrib['name'],
- self._transformer._create_type(ctype),
+ self._transformer.create_type(ctype),
readable, writable, construct, construct_only,
ctype,
))
@@ -704,29 +671,28 @@ blob containing data gleaned from GObject's primitive introspection."""
type_name = xmlnode.attrib['name']
- # Get a list of parents here; some of them may be hidden, and what
- # we really want to do is use the most-derived one that we know of.
if 'parents' in xmlnode.attrib:
- parent_type_names = xmlnode.attrib['parents'].split(',')
- parent_gitype = self._resolve_gtypename_chain(parent_type_names)
+ parent_types = map(lambda s: self._transformer.create_type(s),
+ xmlnode.attrib['parents'].split(','))
else:
- parent_gitype = None
+ parent_types = []
+ parent_type = parent_types[0] if parent_types else None
is_abstract = bool(xmlnode.attrib.get('abstract', False))
node = GLibObject(
self._transformer.remove_prefix(type_name),
- parent_gitype,
+ parent_type,
type_name,
xmlnode.attrib['get-type'], is_abstract)
+ node.parent_types = parent_types
node.fundamental = True
self._introspect_implemented_interfaces(node, xmlnode)
self._add_record_fields(node)
- self._add_attribute(node, replace=True)
- self._register_internal_type(type_name, node)
+ self._namespace.append(node, replace=True)
def _add_record_fields(self, node):
# add record fields
- record = self._get_attribute(node.name)
+ record = self._namespace.get(node.name)
if record is None:
return
node.fields = record.fields
@@ -738,7 +704,7 @@ blob containing data gleaned from GObject's primitive introspection."""
def _pair_boxed_type(self, boxed):
name = self._transformer.remove_prefix(boxed.type_name)
- pair_node = self._get_attribute(name)
+ pair_node = self._namespace.get(name)
if not pair_node:
boxed_item = GLibBoxedOther(name, boxed.type_name,
boxed.get_type)
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index f23bf3c..1e4a28d 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -83,7 +83,15 @@ class Transformer(object):
continue
node = self._traverse_one(symbol)
if node:
- self._namespace.append(node)
+ try:
+ self._namespace.append(node)
+ except ValueError, e:
+ original = self._namespace.get(node.name)
+ positions = set()
+ positions.update(original.file_positions)
+ positions.update(node.file_positions)
+ self.log_warning("Namespace conflict for '%s'" % (node.name, ),
+ positions, fatal=True)
def set_include_paths(self, paths):
self._includepaths = list(paths)
@@ -120,7 +128,8 @@ None."""
# Private
- def log_warning(self, text, file_positions=None, prefix=None):
+ def log_warning(self, text, file_positions=None, prefix=None,
+ fatal=False):
"""Log a warning, using optional file positioning information.
If the warning is related to a Node type, see log_node_warning()."""
if not self._enable_warnings:
@@ -148,6 +157,8 @@ If the warning is related to a Node type, see log_node_warning()."""
else:
print >>sys.stderr, \
'''%s: warning: ns=%r: %s''' % (position, self._namespace.name, text)
+ if fatal:
+ sys.exit(1)
def log_symbol_warning(self, symbol, text):
"""Log a warning in the context of the given symbol."""
@@ -155,7 +166,7 @@ If the warning is related to a Node type, see log_node_warning()."""
prefix = "symbol=%r" % (symbol.ident, )
self.log_warning(text, file_positions, prefix=prefix)
- def log_node_warning(self, node, text, context=None):
+ def log_node_warning(self, node, text, context=None, fatal=False):
"""Log a warning, using information about file positions from
the given node. The optional context argument, if given, should be
another Node type which will also be displayed. If no file position
@@ -170,7 +181,7 @@ context will be used."""
if context:
text = "context=%r %s" % (context.name, text)
- self.log_warning(text, file_positions)
+ self.log_warning(text, file_positions, fatal=fatal)
def _find_include(self, include):
searchdirs = self._includepaths[:]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]