[gobject-introspection/wip/transformer] A few bugfixes



commit a379bc54117dd637cfe762400e350dbe1345a715
Author: Colin Walters <walters verbum org>
Date:   Wed Jul 28 16:51:39 2010 -0400

    A few bugfixes
    
    * Walk through multiple matching namespaces when trying type
      resolution; we need to handle GLib, GObject, Gio which all
      have a G prefix.
    * Handle traversing to None for parent
    * Handle unresolved types better when traversing introspectability

 giscanner/finaltransformer.py   |   22 ++++++++++++++++------
 giscanner/primarytransformer.py |    8 ++++++--
 giscanner/transformer.py        |   16 +++++++++++-----
 3 files changed, 33 insertions(+), 13 deletions(-)
---
diff --git a/giscanner/finaltransformer.py b/giscanner/finaltransformer.py
index cf19b55..07db3ba 100644
--- a/giscanner/finaltransformer.py
+++ b/giscanner/finaltransformer.py
@@ -82,6 +82,14 @@ class FinalTransformer(object):
             self._parameter_warning(parent, node, "Missing (transfer) annotation")
             parent.introspectable = False
 
+    def _type_is_introspectable(self, typeval, warn=False):
+        if not typeval.resolved:
+            return False
+        target = self._transformer.lookup_typenode(typeval)
+        if not target:
+            return False
+        return target.introspectable
+
     def _analyze_node(self, obj, stack):
         if obj.skip:
             return False
@@ -92,6 +100,11 @@ class FinalTransformer(object):
             for param in obj.parameters:
                 self._introspectable_param_analysis(obj, param)
             self._introspectable_param_analysis(obj, obj.retval)
+        if isinstance(obj, (Class, Interface, Record, Union)):
+            for field in obj.fields:
+                if field.type:
+                    if not self._type_is_introspectable(field.type):
+                        field.introspectable = False
         return True
 
     def _introspectable_callable_analysis(self, obj, stack):
@@ -100,12 +113,10 @@ class FinalTransformer(object):
         # Propagate introspectability of parameters to entire functions
         if isinstance(obj, Callable):
             for param in obj.parameters:
-                target = self._transformer.lookup_typenode(param.type)
-                if target and not target.introspectable:
+                if not self._type_is_introspectable(param.type):
                     obj.introspectable = False
                     return True
-            target = self._transformer.lookup_typenode(obj.retval.type)
-            if target and not target.introspectable:
+            if not self._type_is_introspectable(obj.retval.type):
                 obj.introspectable = False
                 return True
 
@@ -119,7 +130,6 @@ class FinalTransformer(object):
                     if not field.anonymous_node.introspectable:
                         field.introspectable = False
                 else:
-                    target = self._transformer.lookup_typenode(field.type)
-                    if target and not target.introspectable:
+                    if not self._type_is_introspectable(field.type):
                         field.introspectable = False
         return True
diff --git a/giscanner/primarytransformer.py b/giscanner/primarytransformer.py
index 71799b9..86d0d44 100644
--- a/giscanner/primarytransformer.py
+++ b/giscanner/primarytransformer.py
@@ -566,7 +566,8 @@ class PrimaryTransformer(object):
             short = node.symbol[:-len('_quark')]
             if short == "g_io_error":
                 # Special case; GIOError was already taken forcing GIOErrorEnum
-                enum = self._names.type_names["GIOErrorEnum"][1]
+                assert self._namespace.name == 'Gio'
+                enum = self._namespace.get('IOErrorEnum')
             else:
                 enum = self._uscore_type_names.get(short)
                 if enum is None:
@@ -667,7 +668,10 @@ method or constructor of some type."""
             while parent:
                 if parent == target:
                     break
-                parent = self._transformer.lookup_typenode(parent.parent)
+                if parent.parent:
+                    parent = self._transformer.lookup_typenode(parent.parent)
+                else:
+                    parent = None
                 if parent is None:
                     self._transformer.log_node_warning(func,
                                                        "Return value is not superclass for constructor; symbol=%r constructed=%r return=%r" % (func.symbol, str(origin_node.create_type()), str(func.retval.type)))
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index a79ed3a..4322bda 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -236,16 +236,17 @@ currently-scanned namespace is first."""
         for ns in self._includes.itervalues():
             yield ns
 
-    def split_ctype(self, ident):
+    def split_ctype_namespaces(self, ident):
         """Given a StudlyCaps string identifier like FooBar, return a
-pair of (namespace, stripped_identifier) or raise ValueError."""
+list of (namespace, stripped_identifier) sorted by namespace length,
+or raise ValueError."""
         matches = []
         for ns in self._iter_namespaces():
             if ns.contains_ident(ident):
                 matches.append((ns, ident[len(ns.c_prefix):]))
         if matches:
             matches.sort(lambda x,y : cmp(len(x[0].c_prefix), len(y[0].c_prefix)))
-            return matches[0]
+            return matches
         raise ValueError("Unknown namespace for identifier %r" % (ident, ))
 
     def split_csymbol(self, symbol):
@@ -663,10 +664,15 @@ pair of (namespace, stripped_identifier) or raise ValueError."""
         elif not typeval.resolved and typeval.ctype:
             pointer_stripped = typeval.ctype.replace('*', '')
             try:
-                (ns, name) = self.split_ctype(pointer_stripped)
+                matches = self.split_ctype_namespaces(pointer_stripped)
             except ValueError, e:
                 raise TypeResolutionException(e)
-            typeval.target_giname = '%s.%s' % (ns.name, name)
+            target_giname=None
+            for namespace,name in matches:
+                target = namespace.get(name)
+                if target:
+                    typeval.target_giname='%s.%s' % (namespace.name, target.name)
+                    return
         
     def _typepair_to_str(self, item):
         nsname, item = item



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