Add a --include argument to include types from other idls. Add a
authorJohan Dahlin <johan@gnome.org>
Tue, 22 Apr 2008 00:53:40 +0000 (00:53 +0000)
committerJohan Dahlin <johan@src.gnome.org>
Tue, 22 Apr 2008 00:53:40 +0000 (00:53 +0000)
2008-04-21  Johan Dahlin  <johan@gnome.org>

* giscanner/gidlparser.py:
* giscanner/gidlwriter.py:
* giscanner/gobjecttreebuilder.py:
* tools/g-ir-scanner:
Add a --include argument to include types from other idls.
Add a minimalistic GIDL parser (just objects for now)
Implement resolving of external type references and use it to
resolve parent types, argument types and return types.

svn path=/trunk/; revision=206

ChangeLog
giscanner/gidlparser.py [new file with mode: 0644]
giscanner/gidlwriter.py
giscanner/gobjecttreebuilder.py
tools/g-ir-scanner

index c4cf839..5e8e987 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2008-04-21  Johan Dahlin  <johan@gnome.org>
 
+       * giscanner/gidlparser.py:
+       * giscanner/gidlwriter.py:
+       * giscanner/gobjecttreebuilder.py:
+       * tools/g-ir-scanner:
+       Add a --include argument to include types from other idls.
+       Add a minimalistic GIDL parser (just objects for now)
+       Implement resolving of external type references and use it to
+       resolve parent types, argument types and return types.
+
+2008-04-21  Johan Dahlin  <johan@gnome.org>
+
        * giscanner/gidlwriter.py:
        * giscanner/gobjecttreebuilder.py:
        * giscanner/treebuilder.py:
diff --git a/giscanner/gidlparser.py b/giscanner/gidlparser.py
new file mode 100644 (file)
index 0000000..77a2f29
--- /dev/null
@@ -0,0 +1,35 @@
+from xml.etree.ElementTree import parse
+
+from .gobjecttreebuilder import GLibObject
+
+
+class GIDLParser(object):
+    def __init__(self, filename):
+        self._nodes = []
+        self._namespace_name = None
+
+        tree = parse(filename)
+        self._parse_api(tree.getroot())
+
+    def _parse_api(self, root):
+        assert root.tag == 'api'
+        ns = root.find('namespace')
+        self._namespace_name = ns.attrib['name']
+        for child in ns.getchildren():
+            if child.tag == 'object':
+                self._parse_object(child)
+            else:
+                print 'PARSER: Unhandled %s' % (child.tag,)
+
+    def _parse_object(self, node):
+        gobj = GLibObject(node.attrib['name'],
+                          node.attrib.get('parent'),
+                          node.attrib['type-name'],
+                          node.attrib['get-type'])
+        self._nodes.append(gobj)
+
+    def get_namespace_name(self):
+        return self._namespace_name
+
+    def get_nodes(self):
+        return self._nodes
index 3ef3497..8d637d9 100644 (file)
@@ -65,7 +65,8 @@ class GIDLWriter(XMLWriter):
         attrs = [('name', enum.name)]
         tag_name = 'enum'
         if isinstance(enum, GLibEnum):
-            attrs.append(('get-type', enum.get_type))
+            attrs.extend([('type-name', enum.type_name),
+                          ('get-type', enum.get_type)])
             if isinstance(enum, GLibFlags):
                 tag_name = 'flags'
 
@@ -84,10 +85,12 @@ class GIDLWriter(XMLWriter):
         attrs = [('name', node.name)]
         if isinstance(node, Class):
             tag_name = 'object'
-            attrs.append(('parent', node.parent))
+            if node.parent is not None:
+                attrs.append(('parent', node.parent))
         else:
             tag_name = 'interface'
         if isinstance(node, (GLibObject, GLibInterface)):
+            attrs.append(('type-name', node.type_name))
             attrs.append(('get-type', node.get_type))
         with self.tagcontext(tag_name, attrs):
             if isinstance(node, Class):
@@ -99,9 +102,10 @@ class GIDLWriter(XMLWriter):
                 self._write_property(prop)
 
     def _write_boxed(self, boxed):
-        attrs = [('name', boxed.name)]
-        if isinstance(boxed, GLibBoxed):
-            attrs.append(('get-type', boxed.get_type))
+        attrs = [('name', boxed.name),
+                 ('type-name', boxed.type_name),
+                 ('get-type', boxed.get_type)]
+
         with self.tagcontext('boxed', attrs):
             for method in boxed.constructors:
                 self._write_constructor(method)
index 188f160..7b8004a 100644 (file)
@@ -3,10 +3,9 @@ import re
 import os
 
 from . import cgobject
+from .odict import odict
 from .treebuilder import (Class, Enum, Function, Interface, Member, Property,
                           Struct)
-from .odict import odict
-
 
 # Copied from h2defs.py
 _upperstr_pat1 = re.compile(r'([^A-Z])([A-Z])')
@@ -33,8 +32,9 @@ def resolve_libtool(libname):
 
 
 class GLibEnum(Enum):
-    def __init__(self, name, members, get_type):
+    def __init__(self, name, members, type_name, get_type):
         Enum.__init__(self, name, members)
+        self.type_name = type_name
         self.get_type = get_type
 
     def __repr__(self):
@@ -56,22 +56,25 @@ class GLibEnumMember(Member):
 
 
 class GLibObject(Class):
-    def __init__(self, name, parent, get_type):
+    def __init__(self, name, parent, type_name, get_type):
         Class.__init__(self, name, parent)
+        self.type_name = type_name
         self.get_type = get_type
 
 
 class GLibBoxed(Struct):
-    def __init__(self, name, get_type):
+    def __init__(self, name, type_name, get_type):
         Struct.__init__(self, name)
         self.constructors = []
         self.methods = []
+        self.type_name = type_name
         self.get_type = get_type
 
 
 class GLibInterface(Interface):
-    def __init__(self, name, get_type):
+    def __init__(self, name, type_name, get_type):
         Interface.__init__(self, name)
+        self.type_name = type_name
         self.get_type = get_type
 
 
@@ -84,6 +87,7 @@ class GObjectTreeBuilder(object):
         self._namespace_name = namespace_name
         self._output_ns = odict()
         self._library = None
+        self._type_names = {}
 
     # Public API
 
@@ -99,6 +103,13 @@ class GObjectTreeBuilder(object):
         for node in nodes:
             self._parse_node(node)
 
+    def register_include(self, filename):
+        from .gidlparser import GIDLParser
+        parser = GIDLParser(filename)
+        nsname = parser.get_namespace_name()
+        for node in parser.get_nodes():
+            self._type_names[node.type_name] = (nsname, node)
+
     # Private
 
     def _add_attribute(self, node, replace=False):
@@ -113,6 +124,9 @@ class GObjectTreeBuilder(object):
     def _get_attribute(self, name):
         return self._output_ns.get(name)
 
+    def _register_internal_type(self, type_name, node):
+        self._type_names[type_name] = (None, node)
+
     def _strip_namespace(self, node):
         prefix = self._namespace_name.lower()
         if isinstance(node, Function):
@@ -131,6 +145,22 @@ class GObjectTreeBuilder(object):
             old = node.name
             node.name = node.name[len(prefix):]
 
+    def _resolve_type_name(self, type_name):
+        item = self._type_names.get(type_name)
+        if item is not None:
+            nsname, item = item
+            if nsname is None:
+                return item.name
+            return '%s.%s' % (nsname, item.name)
+        return type_name
+
+    def _resolve_param_type(self, ptype):
+        type_name = ptype.replace('*', '')
+        resolved_type_name = self._resolve_type_name(type_name)
+        if type_name != resolved_type_name:
+            return ptype.replace(type_name, resolved_type_name)
+        return ptype
+
     def _parse_node(self, node):
         if isinstance(node, Enum):
             self._parse_enum(node)
@@ -153,9 +183,16 @@ class GObjectTreeBuilder(object):
         elif self._parse_method(func):
             return
 
+        self._parse_parameters(func.parameters)
+        func.retval.type = self._resolve_param_type(func.retval.type)
+
         self._strip_namespace(func)
         self._add_attribute(func)
 
+    def _parse_parameters(self, parameters):
+        for parameter in parameters:
+            parameter.type = self._resolve_param_type(parameter.type)
+
     def _parse_get_type_function(self, func):
         # GType *_get_type(void)
         symbol = func.name
@@ -217,6 +254,8 @@ class GObjectTreeBuilder(object):
             class_.methods.append(func)
         else:
             class_.constructors.append(func)
+        self._parse_parameters(func.parameters)
+        func.retval.type = self._resolve_param_type(func.retval.type)
         return True
 
     def _parse_struct(self, struct):
@@ -253,33 +292,38 @@ class GObjectTreeBuilder(object):
 
         klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
         type_name = cgobject.type_name(type_id)
-        cenum = klass(type_name, members, symbol)
+        cenum = klass(type_name, members, type_name, symbol)
         self._strip_namespace(cenum)
         self._add_attribute(cenum, replace=True)
+        self._register_internal_type(type_name, cenum)
 
     def _introspect_object(self, type_id, symbol):
         type_name = cgobject.type_name(type_id)
-        parent_name = cgobject.type_name(cgobject.type_parent(type_id))
-        node = GLibObject(type_name, parent_name, symbol)
+        parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
+        parent_name = self._resolve_type_name(parent_type_name)
+        node = GLibObject(type_name, parent_name, type_name, symbol)
         self._introspect_properties(node, type_id)
         self._strip_namespace(node)
         self._add_attribute(node)
         self._remove_attribute(type_name)
+        self._register_internal_type(type_name, node)
 
     def _introspect_interface(self, type_id, symbol):
         type_name = cgobject.type_name(type_id)
-        node = GLibInterface(type_name, symbol)
+        node = GLibInterface(type_name, type_name, symbol)
         self._strip_namespace(node)
         self._introspect_properties(node, type_id)
         self._add_attribute(node)
         self._remove_attribute(type_name)
+        self._register_internal_type(type_name, node)
 
     def _introspect_boxed(self, type_id, symbol):
         type_name = cgobject.type_name(type_id)
-        node = GLibBoxed(type_name, symbol)
+        node = GLibBoxed(type_name, type_name, symbol)
         self._strip_namespace(node)
         self._add_attribute(node)
         self._remove_attribute(type_name)
+        self._register_internal_type(type_name, node)
 
     def _introspect_properties(self, node, type_id):
         fundamental_type_id = cgobject.type_fundamental(type_id)
index a215d9e..4a5b4ea 100755 (executable)
@@ -12,6 +12,9 @@ from giscanner.treebuilder import TreeBuilder
 
 def main(args):
     parser = optparse.OptionParser('%prog [options] sources')
+    parser.add_option("-i", "--include",
+                      action="append", dest="includes", default=[],
+                      help="include types for other gidls")
     parser.add_option("-l", "--library",
                       action="store", dest="library",
                       help="library of this unit")
@@ -70,6 +73,8 @@ def main(args):
 
     builder = GObjectTreeBuilder(options.namespace)
     builder.load_library(options.library)
+    for include in options.includes:
+        builder.register_include(include)
     builder.parse(TreeBuilder(ss).get_nodes())
 
     writer = GIDLWriter(options.namespace, builder.get_nodes())