Fix glib:error-quark scanning for unregistered enum types
[gnome.gobject-introspection] / giscanner / girwriter.py
index df52709..8088628 100644 (file)
@@ -21,9 +21,6 @@
 
 from __future__ import with_statement
 
-import os
-from ctypes.util import find_library
-
 from .ast import (Alias, Array, Bitfield, Callback, Class, Constant, Enum,
                   Function, Interface, List, Map, Member, Struct, Union,
                   Varargs)
@@ -35,16 +32,17 @@ from .xmlwriter import XMLWriter
 
 class GIRWriter(XMLWriter):
 
-    def __init__(self, namespace, shlibs, includes, pkgs, c_includes):
+    def __init__(self, namespace, shlibs, includes, pkgs, c_includes, cprefix):
         super(GIRWriter, self).__init__()
         self.write_comment(
 '''This file was automatically generated from C sources - DO NOT EDIT!
 To affect the contents of this file, edit the original C definitions,
 and/or use gtk-doc annotations. ''')
-        self._write_repository(namespace, shlibs, includes, pkgs, c_includes)
+        self._write_repository(namespace, shlibs, includes, pkgs,
+                               c_includes, cprefix)
 
     def _write_repository(self, namespace, shlibs, includes=None,
-                          packages=None, c_includes=None):
+                          packages=None, c_includes=None, cprefix=None):
         if includes is None:
             includes = frozenset()
         if packages is None:
@@ -64,7 +62,7 @@ and/or use gtk-doc annotations. ''')
                 self._write_pkgconfig_pkg(pkg)
             for c_include in sorted(set(c_includes)):
                 self._write_c_include(c_include)
-            self._write_namespace(namespace, shlibs)
+            self._write_namespace(namespace, shlibs, cprefix)
 
     def _write_include(self, include):
         attrs = [('name', include.name), ('version', include.version)]
@@ -78,17 +76,11 @@ and/or use gtk-doc annotations. ''')
         attrs = [('name', c_include)]
         self.write_tag('c:include', attrs)
 
-    def _write_namespace(self, namespace, shlibs):
-        libraries = []
-        for l in shlibs:
-            found_libname = find_library(l)
-            if not found_libname:
-                found_libname = l
-            libraries.append(os.path.basename(found_libname))
-
+    def _write_namespace(self, namespace, shlibs, cprefix):
         attrs = [('name', namespace.name),
                  ('version', namespace.version),
-                 ('shared-library', ','.join(libraries))]
+                 ('shared-library', ','.join(shlibs)),
+                 ('c:prefix', cprefix)]
         with self.tagcontext('namespace', attrs):
             # We define a custom sorting function here because
             # we want aliases to be first.  They're a bit
@@ -104,7 +96,8 @@ and/or use gtk-doc annotations. ''')
                 else:
                     return cmp(a, b)
             for node in sorted(namespace.nodes, cmp=nscmp):
-                self._write_node(node)
+                if not node.skip:
+                    self._write_node(node)
 
     def _write_node(self, node):
         if isinstance(node, Function):
@@ -137,6 +130,10 @@ and/or use gtk-doc annotations. ''')
         if node.version:
             attrs.append(('version', node.version))
 
+    def _write_attributes(self, node):
+        for key, value in node.attributes:
+            self.write_tag('attribute', [('name', key), ('value', value)])
+
     def _append_deprecated(self, node, attrs):
         if node.deprecated:
             attrs.append(('deprecated', node.deprecated))
@@ -154,17 +151,24 @@ and/or use gtk-doc annotations. ''')
             attrs.append(('c:type', alias.ctype))
         self.write_tag('alias', attrs)
 
-    def _write_function(self, func, tag_name='function'):
-        attrs = [('name', func.name),
-                 ('c:identifier', func.symbol)]
-        if func.doc:
-            attrs.append(('doc', func.doc))
-        self._append_version(func, attrs)
-        self._append_deprecated(func, attrs)
-        self._append_throws(func, attrs)
+    def _write_callable(self, callable, tag_name, extra_attrs):
+        if callable.skip:
+            return
+        attrs = [('name', callable.name)]
+        attrs.extend(extra_attrs)
+        if callable.doc:
+            attrs.append(('doc', callable.doc))
+        self._append_version(callable, attrs)
+        self._append_deprecated(callable, attrs)
+        self._append_throws(callable, attrs)
         with self.tagcontext(tag_name, attrs):
-            self._write_return_type(func.retval)
-            self._write_parameters(func.parameters)
+            self._write_attributes(callable)
+            self._write_return_type(callable.retval)
+            self._write_parameters(callable.parameters)
+
+    def _write_function(self, func, tag_name='function'):
+        attrs = [('c:identifier', func.symbol)]
+        self._write_callable(func, tag_name, attrs)
 
     def _write_method(self, method):
         self._write_function(method, tag_name='method')
@@ -274,12 +278,13 @@ and/or use gtk-doc annotations. ''')
             attrs.extend([('glib:type-name', enum.type_name),
                           ('glib:get-type', enum.get_type),
                           ('c:type', enum.ctype)])
-            if enum.error_quark:
-                attrs.append(('glib:error-quark', enum.error_quark))
         else:
             attrs.append(('c:type', enum.symbol))
+        if hasattr(enum, 'error_quark') and enum.error_quark:
+            attrs.append(('glib:error-quark', enum.error_quark))
 
         with self.tagcontext('enumeration', attrs):
+            self._write_attributes(enum)
             for member in enum.members:
                 self._write_member(member)
 
@@ -296,10 +301,13 @@ and/or use gtk-doc annotations. ''')
         else:
             attrs.append(('c:type', bitfield.symbol))
         with self.tagcontext('bitfield', attrs):
+            self._write_attributes(bitfield)
             for member in bitfield.members:
                 self._write_member(member)
 
     def _write_member(self, member):
+        if member.skip:
+            return
         attrs = [('name', member.name),
                  ('value', str(member.value)),
                  ('c:identifier', member.symbol)]
@@ -335,6 +343,7 @@ and/or use gtk-doc annotations. ''')
             if node.glib_type_struct:
                 attrs.append(('glib:type-struct', node.glib_type_struct.name))
         with self.tagcontext(tag_name, attrs):
+            self._write_attributes(node)
             if isinstance(node, GLibObject):
                 for iface in node.interfaces:
                     self.write_tag('implements', [('name', iface)])
@@ -346,6 +355,8 @@ and/or use gtk-doc annotations. ''')
                     self._write_constructor(method)
                 for method in node.static_methods:
                     self._write_static_method(method)
+            for vfunc in node.virtual_methods:
+                self._write_vfunc(vfunc)
             for method in node.methods:
                 self._write_method(method)
             for prop in node.properties:
@@ -362,12 +373,15 @@ and/or use gtk-doc annotations. ''')
             attrs.append(('doc', boxed.doc))
         attrs.extend(self._boxed_attrs(boxed))
         with self.tagcontext('glib:boxed', attrs):
+            self._write_attributes(boxed)
             for method in boxed.constructors:
                 self._write_constructor(method)
             for method in boxed.methods:
                 self._write_method(method)
 
     def _write_property(self, prop):
+        if prop.skip:
+            return
         attrs = [('name', prop.name)]
         self._append_version(prop, attrs)
         self._append_deprecated(prop, attrs)
@@ -383,25 +397,25 @@ and/or use gtk-doc annotations. ''')
         if prop.doc:
             attrs.append(('doc', prop.doc))
         with self.tagcontext('property', attrs):
+            self._write_attributes(prop)
             self._write_type(prop.type)
 
+    def _write_vfunc(self, vf):
+        attrs = []
+        if vf.invoker:
+            attrs.append(('invoker', vf.invoker))
+        self._write_callable(vf, 'virtual-method', attrs)
+
     def _write_callback(self, callback):
-        # FIXME: reuse _write_function
-        attrs = [('name', callback.name), ('c:type', callback.ctype)]
-        if callback.doc:
-            attrs.append(('doc', callback.doc))
-        self._append_version(callback, attrs)
-        self._append_deprecated(callback, attrs)
-        self._append_throws(callback, attrs)
-        with self.tagcontext('callback', attrs):
-            self._write_return_type(callback.retval)
-            self._write_parameters(callback.parameters)
+        attrs = [('c:type', callback.ctype)]
+        self._write_callable(callback, 'callback', attrs)
 
     def _boxed_attrs(self, boxed):
         return [('glib:type-name', boxed.type_name),
                 ('glib:get-type', boxed.get_type)]
 
     def _write_record(self, record, extra_attrs=[]):
+        is_gtype_struct = False
         attrs = list(extra_attrs)
         if record.name is not None:
             attrs.append(('name', record.name))
@@ -411,6 +425,7 @@ and/or use gtk-doc annotations. ''')
             attrs.append(('disguised', '1'))
         if isinstance(record, GLibRecord):
             if record.is_gtype_struct_for:
+                is_gtype_struct = True
                 attrs.append(('glib:is-gtype-struct-for',
                               record.is_gtype_struct_for))
         if record.doc:
@@ -420,9 +435,10 @@ and/or use gtk-doc annotations. ''')
         if isinstance(record, GLibBoxed):
             attrs.extend(self._boxed_attrs(record))
         with self.tagcontext('record', attrs):
+            self._write_attributes(record)
             if record.fields:
                 for field in record.fields:
-                    self._write_field(field)
+                    self._write_field(field, is_gtype_struct)
             for method in record.constructors:
                 self._write_constructor(method)
             for method in record.methods:
@@ -441,6 +457,7 @@ and/or use gtk-doc annotations. ''')
         if isinstance(union, GLibBoxed):
             attrs.extend(self._boxed_attrs(union))
         with self.tagcontext('union', attrs):
+            self._write_attributes(union)
             if union.fields:
                 for field in union.fields:
                     self._write_field(field)
@@ -449,13 +466,20 @@ and/or use gtk-doc annotations. ''')
             for method in union.methods:
                 self._write_method(method)
 
-    def _write_field(self, field):
+    def _write_field(self, field, is_gtype_struct=False):
         if isinstance(field, Function):
             self._write_method(field)
             return
 
         if isinstance(field, Callback):
-            self._write_callback(field)
+            attrs = [('name', field.name)]
+            with self.tagcontext('field', attrs):
+                self._write_attributes(field)
+                if is_gtype_struct:
+                    self._write_callback(field)
+                else:
+                    attrs = [('name', 'any'), ('c:type', 'pointer')]
+                    self.write_tag('type', attrs)
         elif isinstance(field, Struct):
             self._write_record(field)
         elif isinstance(field, Union):
@@ -471,14 +495,18 @@ and/or use gtk-doc annotations. ''')
             if field.bits:
                 attrs.append(('bits', str(field.bits)))
             with self.tagcontext('field', attrs):
+                self._write_attributes(field)
                 self._write_type(field.type)
 
     def _write_signal(self, signal):
+        if signal.skip:
+            return
         attrs = [('name', signal.name)]
         if signal.doc:
             attrs.append(('doc', signal.doc))
         self._append_version(signal, attrs)
         self._append_deprecated(signal, attrs)
         with self.tagcontext('glib:signal', attrs):
+            self._write_attributes(signal)
             self._write_return_type(signal.retval)
             self._write_parameters(signal.parameters)