~ubuntu-branches/ubuntu/trusty/gobject-introspection/trusty

« back to all changes in this revision

Viewing changes to giscanner/girwriter.py

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2011-03-22 00:32:36 UTC
  • mfrom: (1.4.1 upstream) (3.3.33 multiarch)
  • Revision ID: james.westby@ubuntu.com-20110322003236-4spdgfk1vai6xay1
Tags: 0.10.4-2
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
from __future__ import with_statement
23
23
 
24
 
from .ast import (Alias, Array, Bitfield, Callback, Class, Constant, Enum,
25
 
                  Function, Interface, List, Map, Member, Struct, Union,
26
 
                  Varargs)
27
 
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
28
 
                      GLibFlags, GLibObject, GLibInterface,
29
 
                      GLibRecord)
 
24
from . import ast
30
25
from .xmlwriter import XMLWriter
31
26
 
 
27
# Bump this for *incompatible* changes to the .gir.
 
28
# Compatible changes we just make inline
 
29
COMPATIBLE_GIR_VERSION = '1.2'
32
30
 
33
31
class GIRWriter(XMLWriter):
34
32
 
35
 
    def __init__(self, namespace, shlibs, includes, pkgs, c_includes, cprefix):
 
33
    def __init__(self, namespace, shlibs, includes, pkgs, c_includes):
36
34
        super(GIRWriter, self).__init__()
37
35
        self.write_comment(
38
36
'''This file was automatically generated from C sources - DO NOT EDIT!
39
37
To affect the contents of this file, edit the original C definitions,
40
38
and/or use gtk-doc annotations. ''')
41
39
        self._write_repository(namespace, shlibs, includes, pkgs,
42
 
                               c_includes, cprefix)
 
40
                               c_includes)
43
41
 
44
42
    def _write_repository(self, namespace, shlibs, includes=None,
45
 
                          packages=None, c_includes=None, cprefix=None):
 
43
                          packages=None, c_includes=None):
46
44
        if includes is None:
47
45
            includes = frozenset()
48
46
        if packages is None:
50
48
        if c_includes is None:
51
49
            c_includes = frozenset()
52
50
        attrs = [
53
 
            ('version', '1.0'),
 
51
            ('version', COMPATIBLE_GIR_VERSION),
54
52
            ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
55
53
            ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
56
54
            ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
62
60
                self._write_pkgconfig_pkg(pkg)
63
61
            for c_include in sorted(set(c_includes)):
64
62
                self._write_c_include(c_include)
65
 
            self._write_namespace(namespace, shlibs, cprefix)
 
63
            self._namespace = namespace
 
64
            self._write_namespace(namespace, shlibs)
 
65
            self._namespace = None
66
66
 
67
67
    def _write_include(self, include):
68
68
        attrs = [('name', include.name), ('version', include.version)]
76
76
        attrs = [('name', c_include)]
77
77
        self.write_tag('c:include', attrs)
78
78
 
79
 
    def _write_namespace(self, namespace, shlibs, cprefix):
 
79
    def _write_namespace(self, namespace, shlibs):
80
80
        attrs = [('name', namespace.name),
81
81
                 ('version', namespace.version),
82
82
                 ('shared-library', ','.join(shlibs)),
83
 
                 ('c:prefix', cprefix)]
 
83
                 ('c:identifier-prefixes', ','.join(namespace.identifier_prefixes)),
 
84
                 ('c:symbol-prefixes', ','.join(namespace.symbol_prefixes))]
84
85
        with self.tagcontext('namespace', attrs):
85
86
            # We define a custom sorting function here because
86
87
            # we want aliases to be first.  They're a bit
87
88
            # special because the typelib compiler expands them.
88
89
            def nscmp(a, b):
89
 
                if isinstance(a, Alias):
90
 
                    if isinstance(b, Alias):
 
90
                if isinstance(a, ast.Alias):
 
91
                    if isinstance(b, ast.Alias):
91
92
                        return cmp(a.name, b.name)
92
93
                    else:
93
94
                        return -1
94
 
                elif isinstance(b, Alias):
 
95
                elif isinstance(b, ast.Alias):
95
96
                    return 1
96
97
                else:
97
98
                    return cmp(a, b)
98
 
            for node in sorted(namespace.nodes, cmp=nscmp):
99
 
                if not node.skip:
100
 
                    self._write_node(node)
 
99
            for node in sorted(namespace.itervalues(), cmp=nscmp):
 
100
                self._write_node(node)
101
101
 
102
102
    def _write_node(self, node):
103
 
        if isinstance(node, Function):
 
103
        if isinstance(node, ast.Function):
104
104
            self._write_function(node)
105
 
        elif isinstance(node, Enum):
 
105
        elif isinstance(node, ast.Enum):
106
106
            self._write_enum(node)
107
 
        elif isinstance(node, Bitfield):
 
107
        elif isinstance(node, ast.Bitfield):
108
108
            self._write_bitfield(node)
109
 
        elif isinstance(node, (Class, Interface)):
 
109
        elif isinstance(node, (ast.Class, ast.Interface)):
110
110
            self._write_class(node)
111
 
        elif isinstance(node, Callback):
 
111
        elif isinstance(node, ast.Callback):
112
112
            self._write_callback(node)
113
 
        elif isinstance(node, Struct):
 
113
        elif isinstance(node, ast.Record):
114
114
            self._write_record(node)
115
 
        elif isinstance(node, Union):
 
115
        elif isinstance(node, ast.Union):
116
116
            self._write_union(node)
117
 
        elif isinstance(node, GLibBoxed):
 
117
        elif isinstance(node, ast.Boxed):
118
118
            self._write_boxed(node)
119
 
        elif isinstance(node, Member):
 
119
        elif isinstance(node, ast.Member):
120
120
            # FIXME: atk_misc_instance singleton
121
121
            pass
122
 
        elif isinstance(node, Alias):
 
122
        elif isinstance(node, ast.Alias):
123
123
            self._write_alias(node)
124
 
        elif isinstance(node, Constant):
 
124
        elif isinstance(node, ast.Constant):
125
125
            self._write_constant(node)
126
126
        else:
127
127
            print 'WRITER: Unhandled node', node
130
130
        if node.version:
131
131
            attrs.append(('version', node.version))
132
132
 
133
 
    def _write_attributes(self, node):
 
133
    def _write_generic(self, node):
134
134
        for key, value in node.attributes:
135
135
            self.write_tag('attribute', [('name', key), ('value', value)])
 
136
        if hasattr(node, 'doc') and node.doc:
 
137
            self.write_tag('doc', [('xml:whitespace', 'preserve')],
 
138
                           node.doc.strip())
136
139
 
137
 
    def _append_deprecated(self, node, attrs):
 
140
    def _append_node_generic(self, node, attrs):
 
141
        if node.skip or not node.introspectable:
 
142
            attrs.append(('introspectable', '0'))
138
143
        if node.deprecated:
139
144
            attrs.append(('deprecated', node.deprecated))
140
145
            if node.deprecated_version:
146
151
            attrs.append(('throws', '1'))
147
152
 
148
153
    def _write_alias(self, alias):
149
 
        attrs = [('name', alias.name), ('target', alias.target)]
 
154
        attrs = [('name', alias.name)]
150
155
        if alias.ctype is not None:
151
156
            attrs.append(('c:type', alias.ctype))
152
 
        self.write_tag('alias', attrs)
 
157
        self._append_node_generic(alias, attrs)
 
158
        with self.tagcontext('alias', attrs):
 
159
            self._write_generic(alias)
 
160
            self._write_type_ref(alias.target)
153
161
 
154
162
    def _write_callable(self, callable, tag_name, extra_attrs):
155
 
        if callable.skip:
156
 
            return
157
163
        attrs = [('name', callable.name)]
158
164
        attrs.extend(extra_attrs)
159
 
        if callable.doc:
160
 
            attrs.append(('doc', callable.doc))
161
165
        self._append_version(callable, attrs)
162
 
        self._append_deprecated(callable, attrs)
 
166
        self._append_node_generic(callable, attrs)
163
167
        self._append_throws(callable, attrs)
164
168
        with self.tagcontext(tag_name, attrs):
165
 
            self._write_attributes(callable)
166
 
            self._write_return_type(callable.retval)
167
 
            self._write_parameters(callable.parameters)
 
169
            self._write_generic(callable)
 
170
            self._write_return_type(callable.retval, parent=callable)
 
171
            self._write_parameters(callable, callable.parameters)
168
172
 
169
173
    def _write_function(self, func, tag_name='function'):
170
 
        attrs = [('c:identifier', func.symbol)]
 
174
        attrs = []
 
175
        if hasattr(func, 'symbol'):
 
176
            attrs.append(('c:identifier', func.symbol))
 
177
        if func.shadowed_by:
 
178
            attrs.append(('shadowed-by', func.shadowed_by))
 
179
        elif func.shadows:
 
180
            attrs.append(('shadows', func.shadows))
171
181
        self._write_callable(func, tag_name, attrs)
172
182
 
173
183
    def _write_method(self, method):
179
189
    def _write_constructor(self, method):
180
190
        self._write_function(method, tag_name='constructor')
181
191
 
182
 
    def _write_return_type(self, return_):
 
192
    def _write_return_type(self, return_, parent=None):
183
193
        if not return_:
184
194
            return
185
195
 
186
 
        assert return_.transfer is not None, return_
187
 
 
188
196
        attrs = []
189
 
        attrs.append(('transfer-ownership', return_.transfer))
190
 
        if return_.doc:
191
 
            attrs.append(('doc', return_.doc))
 
197
        if return_.transfer:
 
198
            attrs.append(('transfer-ownership', return_.transfer))
192
199
        with self.tagcontext('return-value', attrs):
193
 
            self._write_type(return_.type)
 
200
            self._write_generic(return_)
 
201
            self._write_type(return_.type, function=parent)
194
202
 
195
 
    def _write_parameters(self, parameters):
 
203
    def _write_parameters(self, parent, parameters):
196
204
        if not parameters:
197
205
            return
198
206
        with self.tagcontext('parameters'):
199
207
            for parameter in parameters:
200
 
                self._write_parameter(parameter)
201
 
 
202
 
    def _write_parameter(self, parameter):
203
 
        assert parameter.transfer is not None, parameter
204
 
 
 
208
                self._write_parameter(parent, parameter)
 
209
 
 
210
    def _write_parameter(self, parent, parameter):
205
211
        attrs = []
206
 
        if parameter.name is not None:
207
 
            attrs.append(('name', parameter.name))
208
 
        if parameter.direction != 'in':
 
212
        if parameter.argname is not None:
 
213
            attrs.append(('name', parameter.argname))
 
214
        if (parameter.direction is not None) and (parameter.direction != 'in'):
209
215
            attrs.append(('direction', parameter.direction))
210
216
            attrs.append(('caller-allocates',
211
217
                          '1' if parameter.caller_allocates else '0'))
212
 
        attrs.append(('transfer-ownership',
213
 
                     parameter.transfer))
 
218
        if parameter.transfer:
 
219
            attrs.append(('transfer-ownership',
 
220
                          parameter.transfer))
214
221
        if parameter.allow_none:
215
222
            attrs.append(('allow-none', '1'))
216
223
        if parameter.scope:
217
224
            attrs.append(('scope', parameter.scope))
218
 
        if parameter.closure_index >= 0:
219
 
            attrs.append(('closure', '%d' % parameter.closure_index))
220
 
        if parameter.destroy_index >= 0:
221
 
            attrs.append(('destroy', '%d' % parameter.destroy_index))
222
 
        if parameter.doc:
223
 
            attrs.append(('doc', parameter.doc))
 
225
        if parameter.closure_name is not None:
 
226
            idx = parent.get_parameter_index(parameter.closure_name)
 
227
            attrs.append(('closure', '%d' % (idx, )))
 
228
        if parameter.destroy_name is not None:
 
229
            idx = parent.get_parameter_index(parameter.destroy_name)
 
230
            attrs.append(('destroy', '%d' % (idx, )))
224
231
        with self.tagcontext('parameter', attrs):
225
 
            self._write_type(parameter.type)
226
 
 
227
 
    def _type_to_string(self, ntype):
228
 
        if isinstance(ntype, basestring):
229
 
            return ntype
230
 
        return ntype.name
231
 
 
232
 
    def _write_type(self, ntype, relation=None):
233
 
        if isinstance(ntype, basestring):
234
 
            typename = ntype
235
 
            type_cname = None
 
232
            self._write_generic(parameter)
 
233
            self._write_type(parameter.type, function=parent)
 
234
 
 
235
    def _type_to_name(self, typeval):
 
236
        if not typeval.resolved:
 
237
            raise AssertionError("Caught unresolved type %r (ctype=%r)" % (typeval, typeval.ctype))
 
238
        assert typeval.target_giname is not None
 
239
        prefix = self._namespace.name + '.'
 
240
        if typeval.target_giname.startswith(prefix):
 
241
            return typeval.target_giname[len(prefix):]
 
242
        return typeval.target_giname
 
243
 
 
244
    def _write_type_ref(self, ntype):
 
245
        """ Like _write_type, but only writes the type name rather than the full details """
 
246
        assert isinstance(ntype, ast.Type), ntype
 
247
        attrs = []
 
248
        if ntype.ctype:
 
249
            attrs.append(('c:type', ntype.ctype))
 
250
        if isinstance(ntype, ast.Array):
 
251
            if ntype.array_type != ast.Array.C:
 
252
                attrs.insert(0, ('name', ntype.array_type))
 
253
        elif isinstance(ntype, ast.List):
 
254
            if ntype.name:
 
255
                attrs.insert(0, ('name', ntype.name))
 
256
        elif isinstance(ntype, ast.Map):
 
257
            attrs.insert(0, ('name', 'GLib.HashTable'))
236
258
        else:
237
 
            typename = ntype.name
238
 
            type_cname = ntype.ctype
239
 
        if isinstance(ntype, Varargs):
 
259
            if ntype.target_giname:
 
260
                attrs.insert(0, ('name', self._type_to_name(ntype)))
 
261
            elif ntype.target_fundamental:
 
262
                attrs.insert(0, ('name', ntype.target_fundamental))
 
263
 
 
264
        self.write_tag('type', attrs)
 
265
 
 
266
    def _write_type(self, ntype, relation=None, function=None):
 
267
        assert isinstance(ntype, ast.Type), ntype
 
268
        attrs = []
 
269
        if ntype.ctype:
 
270
            attrs.append(('c:type', ntype.ctype))
 
271
        if isinstance(ntype, ast.Varargs):
240
272
            with self.tagcontext('varargs', []):
241
273
                pass
242
 
            return
243
 
        if isinstance(ntype, Array):
244
 
            attrs = []
 
274
        elif isinstance(ntype, ast.Array):
 
275
            if ntype.array_type != ast.Array.C:
 
276
                attrs.insert(0, ('name', ntype.array_type))
245
277
            if not ntype.zeroterminated:
246
 
                attrs.append(('zero-terminated', '0'))
247
 
            if ntype.length_param_index >= 0:
248
 
                attrs.append(('length', '%d' % (ntype.length_param_index, )))
249
 
            if ntype.name in ['GLib.Array', 'GLib.PtrArray', 'GLib.ByteArray']:
250
 
                attrs.append(('name', ntype.name))
251
 
            attrs.append(('c:type', ntype.ctype))
 
278
                attrs.insert(0, ('zero-terminated', '0'))
252
279
            if ntype.size is not None:
253
 
                attrs.append(('fixed-size', ntype.size))
 
280
                attrs.append(('fixed-size', '%d' % (ntype.size, )))
 
281
            if ntype.length_param_name is not None:
 
282
                assert function
 
283
                attrs.insert(0, ('length', '%d'
 
284
                            % (function.get_parameter_index(ntype.length_param_name, ))))
254
285
 
255
286
            with self.tagcontext('array', attrs):
256
 
                if ntype.element_type is not None:
257
 
                    self._write_type(ntype.element_type)
258
 
            return
259
 
        attrs = [('name', self._type_to_string(ntype))]
260
 
        # FIXME: figure out if type references a basic type
261
 
        #        or a boxed/class/interface etc. and skip
262
 
        #        writing the ctype if the latter.
263
 
        if type_cname is not None:
264
 
            attrs.append(('c:type', type_cname))
265
 
        if isinstance(ntype, List) and ntype.element_type:
 
287
                self._write_type(ntype.element_type)
 
288
        elif isinstance(ntype, ast.List):
 
289
            if ntype.name:
 
290
                attrs.insert(0, ('name', ntype.name))
266
291
            with self.tagcontext('type', attrs):
267
292
                self._write_type(ntype.element_type)
268
 
            return
269
 
        if isinstance(ntype, Map) and ntype.key_type:
 
293
        elif isinstance(ntype, ast.Map):
 
294
            attrs.insert(0, ('name', 'GLib.HashTable'))
270
295
            with self.tagcontext('type', attrs):
271
296
                self._write_type(ntype.key_type)
272
297
                self._write_type(ntype.value_type)
273
 
            return
274
 
        # Not a special type, just write it out
275
 
        self.write_tag('type', attrs)
 
298
        else:
 
299
            # REWRITEFIXME - enable this for 1.2
 
300
            if ntype.target_giname:
 
301
                attrs.insert(0, ('name', self._type_to_name(ntype)))
 
302
            elif ntype.target_fundamental:
 
303
                # attrs = [('fundamental', ntype.target_fundamental)]
 
304
                attrs.insert(0, ('name', ntype.target_fundamental))
 
305
            elif ntype.target_foreign:
 
306
                attrs.insert(0, ('foreign', '1'))
 
307
            self.write_tag('type', attrs)
 
308
 
 
309
    def _append_registered(self, node, attrs):
 
310
        assert isinstance(node, ast.Registered)
 
311
        if node.get_type:
 
312
            attrs.extend([('glib:type-name', node.gtype_name),
 
313
                          ('glib:get-type', node.get_type)])
276
314
 
277
315
    def _write_enum(self, enum):
278
316
        attrs = [('name', enum.name)]
279
 
        if enum.doc:
280
 
            attrs.append(('doc', enum.doc))
281
317
        self._append_version(enum, attrs)
282
 
        self._append_deprecated(enum, attrs)
283
 
        if isinstance(enum, GLibEnum):
284
 
            attrs.extend([('glib:type-name', enum.type_name),
285
 
                          ('glib:get-type', enum.get_type),
286
 
                          ('c:type', enum.ctype)])
287
 
        else:
288
 
            attrs.append(('c:type', enum.symbol))
289
 
        if hasattr(enum, 'error_quark') and enum.error_quark:
 
318
        self._append_node_generic(enum, attrs)
 
319
        self._append_registered(enum, attrs)
 
320
        attrs.append(('c:type', enum.ctype))
 
321
        if enum.error_quark:
290
322
            attrs.append(('glib:error-quark', enum.error_quark))
291
323
 
292
324
        with self.tagcontext('enumeration', attrs):
293
 
            self._write_attributes(enum)
 
325
            self._write_generic(enum)
294
326
            for member in enum.members:
295
327
                self._write_member(member)
296
328
 
297
329
    def _write_bitfield(self, bitfield):
298
330
        attrs = [('name', bitfield.name)]
299
 
        if bitfield.doc:
300
 
            attrs.append(('doc', bitfield.doc))
301
331
        self._append_version(bitfield, attrs)
302
 
        self._append_deprecated(bitfield, attrs)
303
 
        if isinstance(bitfield, GLibFlags):
304
 
            attrs.extend([('glib:type-name', bitfield.type_name),
305
 
                          ('glib:get-type', bitfield.get_type),
306
 
                          ('c:type', bitfield.ctype)])
307
 
        else:
308
 
            attrs.append(('c:type', bitfield.symbol))
 
332
        self._append_node_generic(bitfield, attrs)
 
333
        self._append_registered(bitfield, attrs)
 
334
        attrs.append(('c:type', bitfield.ctype))
309
335
        with self.tagcontext('bitfield', attrs):
310
 
            self._write_attributes(bitfield)
 
336
            self._write_generic(bitfield)
311
337
            for member in bitfield.members:
312
338
                self._write_member(member)
313
339
 
314
340
    def _write_member(self, member):
315
 
        if member.skip:
316
 
            return
317
341
        attrs = [('name', member.name),
318
342
                 ('value', str(member.value)),
319
343
                 ('c:identifier', member.symbol)]
320
 
        if isinstance(member, GLibEnumMember):
 
344
        if member.nick is not None:
321
345
            attrs.append(('glib:nick', member.nick))
322
346
        self.write_tag('member', attrs)
323
347
 
324
348
    def _write_constant(self, constant):
325
 
        attrs = [('name', constant.name),
326
 
                 ('value', str(constant.value))]
 
349
        attrs = [('name', constant.name), ('value', constant.value)]
327
350
        with self.tagcontext('constant', attrs):
328
 
            self._write_type(constant.type)
 
351
            self._write_type(constant.value_type)
329
352
 
330
353
    def _write_class(self, node):
331
354
        attrs = [('name', node.name),
 
355
                 ('c:symbol-prefix', node.c_symbol_prefix),
332
356
                 ('c:type', node.ctype)]
333
 
        if node.doc:
334
 
            attrs.append(('doc', node.doc))
335
357
        self._append_version(node, attrs)
336
 
        self._append_deprecated(node, attrs)
337
 
        if isinstance(node, Class):
 
358
        self._append_node_generic(node, attrs)
 
359
        if isinstance(node, ast.Class):
338
360
            tag_name = 'class'
339
361
            if node.parent is not None:
340
 
                attrs.append(('parent', node.parent))
 
362
                attrs.append(('parent',
 
363
                              self._type_to_name(node.parent)))
341
364
            if node.is_abstract:
342
365
                attrs.append(('abstract', '1'))
343
366
        else:
 
367
            assert isinstance(node, ast.Interface)
344
368
            tag_name = 'interface'
345
 
        if isinstance(node, (GLibObject, GLibInterface)):
346
 
            attrs.append(('glib:type-name', node.type_name))
347
 
            if node.get_type:
348
 
                attrs.append(('glib:get-type', node.get_type))
349
 
            if node.glib_type_struct:
350
 
                attrs.append(('glib:type-struct', node.glib_type_struct.name))
 
369
        attrs.append(('glib:type-name', node.gtype_name))
 
370
        if node.get_type is not None:
 
371
            attrs.append(('glib:get-type', node.get_type))
 
372
        if node.glib_type_struct is not None:
 
373
            attrs.append(('glib:type-struct',
 
374
                          self._type_to_name(node.glib_type_struct)))
 
375
        if isinstance(node, ast.Class):
 
376
            if node.fundamental:
 
377
                attrs.append(('glib:fundamental', '1'))
 
378
            if node.ref_func:
 
379
                attrs.append(('glib:ref-func', node.ref_func))
 
380
            if node.unref_func:
 
381
                attrs.append(('glib:unref-func', node.unref_func))
 
382
            if node.set_value_func:
 
383
                attrs.append(('glib:set-value-func', node.set_value_func))
 
384
            if node.get_value_func:
 
385
                attrs.append(('glib:get-value-func', node.get_value_func))
351
386
        with self.tagcontext(tag_name, attrs):
352
 
            self._write_attributes(node)
353
 
            if isinstance(node, GLibObject):
354
 
                for iface in node.interfaces:
355
 
                    self.write_tag('implements', [('name', iface)])
356
 
            if isinstance(node, Interface):
357
 
                for iface in node.prerequisites:
358
 
                    self.write_tag('prerequisite', [('name', iface)])
359
 
            if isinstance(node, Class):
360
 
                for method in node.constructors:
 
387
            self._write_generic(node)
 
388
            if isinstance(node, ast.Class):
 
389
                for iface in sorted(node.interfaces):
 
390
                    self.write_tag('implements',
 
391
                                   [('name', self._type_to_name(iface))])
 
392
            if isinstance(node, ast.Interface):
 
393
                for iface in sorted(node.prerequisites):
 
394
                    self.write_tag('prerequisite',
 
395
                                   [('name', self._type_to_name(iface))])
 
396
            if isinstance(node, ast.Class):
 
397
                for method in sorted(node.constructors):
361
398
                    self._write_constructor(method)
362
 
                for method in node.static_methods:
 
399
            if isinstance(node, (ast.Class, ast.Interface)):
 
400
                for method in sorted(node.static_methods):
363
401
                    self._write_static_method(method)
364
 
            for vfunc in node.virtual_methods:
 
402
            for vfunc in sorted(node.virtual_methods):
365
403
                self._write_vfunc(vfunc)
366
 
            for method in node.methods:
 
404
            for method in sorted(node.methods):
367
405
                self._write_method(method)
368
 
            for prop in node.properties:
 
406
            for prop in sorted(node.properties):
369
407
                self._write_property(prop)
370
408
            for field in node.fields:
371
409
                self._write_field(field)
372
 
            for signal in node.signals:
 
410
            for signal in sorted(node.signals):
373
411
                self._write_signal(signal)
374
412
 
375
413
    def _write_boxed(self, boxed):
376
 
        attrs = [('c:type', boxed.ctype),
377
 
                 ('glib:name', boxed.name)]
378
 
        if boxed.doc:
379
 
            attrs.append(('doc', boxed.doc))
380
 
        attrs.extend(self._boxed_attrs(boxed))
 
414
        attrs = [('glib:name', boxed.name)]
 
415
        if boxed.c_symbol_prefix is not None:
 
416
            attrs.append(('c:symbol-prefix', boxed.c_symbol_prefix))
 
417
        self._append_registered(boxed, attrs)
381
418
        with self.tagcontext('glib:boxed', attrs):
382
 
            self._write_attributes(boxed)
383
 
            for method in boxed.constructors:
 
419
            self._write_generic(boxed)
 
420
            for method in sorted(boxed.constructors):
384
421
                self._write_constructor(method)
385
 
            for method in boxed.methods:
 
422
            for method in sorted(boxed.methods):
386
423
                self._write_method(method)
 
424
            for method in sorted(boxed.static_methods):
 
425
                self._write_static_method(method)
387
426
 
388
427
    def _write_property(self, prop):
389
 
        if prop.skip:
390
 
            return
391
428
        attrs = [('name', prop.name)]
392
429
        self._append_version(prop, attrs)
393
 
        self._append_deprecated(prop, attrs)
 
430
        self._append_node_generic(prop, attrs)
394
431
        # Properties are assumed to be readable (see also generate.c)
395
432
        if not prop.readable:
396
433
            attrs.append(('readable', '0'))
400
437
            attrs.append(('construct', '1'))
401
438
        if prop.construct_only:
402
439
            attrs.append(('construct-only', '1'))
403
 
        if prop.doc:
404
 
            attrs.append(('doc', prop.doc))
 
440
        if prop.transfer:
 
441
            attrs.append(('transfer-ownership', prop.transfer))
405
442
        with self.tagcontext('property', attrs):
406
 
            self._write_attributes(prop)
 
443
            self._write_generic(prop)
407
444
            self._write_type(prop.type)
408
445
 
409
446
    def _write_vfunc(self, vf):
413
450
        self._write_callable(vf, 'virtual-method', attrs)
414
451
 
415
452
    def _write_callback(self, callback):
416
 
        attrs = [('c:type', callback.ctype)]
 
453
        attrs = []
 
454
        if callback.namespace:
 
455
            attrs.append(('c:type', callback.ctype or callback.c_name))
417
456
        self._write_callable(callback, 'callback', attrs)
418
457
 
419
 
    def _boxed_attrs(self, boxed):
420
 
        return [('glib:type-name', boxed.type_name),
421
 
                ('glib:get-type', boxed.get_type)]
422
 
 
423
458
    def _write_record(self, record, extra_attrs=[]):
424
459
        is_gtype_struct = False
425
460
        attrs = list(extra_attrs)
426
461
        if record.name is not None:
427
462
            attrs.append(('name', record.name))
428
 
        if record.symbol is not None: # the record might be anonymous
429
 
            attrs.append(('c:type', record.symbol))
 
463
        if record.ctype is not None: # the record might be anonymous
 
464
            attrs.append(('c:type', record.ctype))
430
465
        if record.disguised:
431
466
            attrs.append(('disguised', '1'))
432
467
        if record.foreign:
433
468
            attrs.append(('foreign', '1'))
434
 
        if isinstance(record, GLibRecord):
435
 
            if record.is_gtype_struct_for:
436
 
                is_gtype_struct = True
437
 
                attrs.append(('glib:is-gtype-struct-for',
438
 
                              record.is_gtype_struct_for))
439
 
        if record.doc:
440
 
            attrs.append(('doc', record.doc))
 
469
        if record.is_gtype_struct_for is not None:
 
470
            is_gtype_struct = True
 
471
            attrs.append(('glib:is-gtype-struct-for',
 
472
                          self._type_to_name(record.is_gtype_struct_for)))
441
473
        self._append_version(record, attrs)
442
 
        self._append_deprecated(record, attrs)
443
 
        if isinstance(record, GLibBoxed):
444
 
            attrs.extend(self._boxed_attrs(record))
 
474
        self._append_node_generic(record, attrs)
 
475
        self._append_registered(record, attrs)
 
476
        if record.c_symbol_prefix:
 
477
            attrs.append(('c:symbol-prefix', record.c_symbol_prefix))
445
478
        with self.tagcontext('record', attrs):
446
 
            self._write_attributes(record)
 
479
            self._write_generic(record)
447
480
            if record.fields:
448
481
                for field in record.fields:
449
482
                    self._write_field(field, is_gtype_struct)
450
 
            for method in record.constructors:
 
483
            for method in sorted(record.constructors):
451
484
                self._write_constructor(method)
452
 
            for method in record.methods:
 
485
            for method in sorted(record.methods):
453
486
                self._write_method(method)
 
487
            for method in sorted(record.static_methods):
 
488
                self._write_static_method(method)
454
489
 
455
490
    def _write_union(self, union):
456
491
        attrs = []
457
492
        if union.name is not None:
458
493
            attrs.append(('name', union.name))
459
 
        if union.symbol is not None: # the union might be anonymous
460
 
            attrs.append(('c:type', union.symbol))
461
 
        if union.doc:
462
 
            attrs.append(('doc', union.doc))
 
494
        if union.ctype is not None: # the union might be anonymous
 
495
            attrs.append(('c:type', union.ctype))
463
496
        self._append_version(union, attrs)
464
 
        self._append_deprecated(union, attrs)
465
 
        if isinstance(union, GLibBoxed):
466
 
            attrs.extend(self._boxed_attrs(union))
 
497
        self._append_node_generic(union, attrs)
 
498
        self._append_registered(union, attrs)
 
499
        if union.c_symbol_prefix:
 
500
            attrs.append(('c:symbol-prefix', union.c_symbol_prefix))
467
501
        with self.tagcontext('union', attrs):
468
 
            self._write_attributes(union)
 
502
            self._write_generic(union)
469
503
            if union.fields:
470
504
                for field in union.fields:
471
505
                    self._write_field(field)
472
 
            for method in union.constructors:
 
506
            for method in sorted(union.constructors):
473
507
                self._write_constructor(method)
474
 
            for method in union.methods:
 
508
            for method in sorted(union.methods):
475
509
                self._write_method(method)
 
510
            for method in sorted(union.static_methods):
 
511
                self._write_static_method(method)
476
512
 
477
513
    def _write_field(self, field, is_gtype_struct=False):
478
 
        if isinstance(field, Function):
479
 
            self._write_method(field)
480
 
            return
481
 
 
482
 
        if isinstance(field, Callback):
483
 
            attrs = [('name', field.name)]
484
 
            with self.tagcontext('field', attrs):
485
 
                self._write_attributes(field)
486
 
                if is_gtype_struct:
487
 
                    self._write_callback(field)
488
 
                else:
489
 
                    attrs = [('name', 'any'), ('c:type', 'pointer')]
490
 
                    self.write_tag('type', attrs)
491
 
        elif isinstance(field, Struct):
492
 
            self._write_record(field)
493
 
        elif isinstance(field, Union):
494
 
            self._write_union(field)
 
514
        if field.anonymous_node:
 
515
            if isinstance(field.anonymous_node, ast.Callback):
 
516
                attrs = [('name', field.name)]
 
517
                self._append_node_generic(field, attrs)
 
518
                with self.tagcontext('field', attrs):
 
519
                    self._write_callback(field.anonymous_node)
 
520
            elif isinstance(field.anonymous_node, ast.Record):
 
521
                self._write_record(field.anonymous_node)
 
522
            elif isinstance(field.anonymous_node, ast.Union):
 
523
                self._write_union(field.anonymous_node)
 
524
            else:
 
525
                raise AssertionError("Unknown field anonymous: %r" \
 
526
                                         % (field.anonymous_node, ))
495
527
        else:
496
528
            attrs = [('name', field.name)]
 
529
            self._append_node_generic(field, attrs)
497
530
            # Fields are assumed to be read-only
498
531
            # (see also girparser.c and generate.c)
499
532
            if not field.readable:
502
535
                attrs.append(('writable', '1'))
503
536
            if field.bits:
504
537
                attrs.append(('bits', str(field.bits)))
 
538
            if field.private:
 
539
                attrs.append(('private', '1'))
505
540
            with self.tagcontext('field', attrs):
506
 
                self._write_attributes(field)
 
541
                self._write_generic(field)
507
542
                self._write_type(field.type)
508
543
 
509
544
    def _write_signal(self, signal):
510
 
        if signal.skip:
511
 
            return
512
545
        attrs = [('name', signal.name)]
513
 
        if signal.doc:
514
 
            attrs.append(('doc', signal.doc))
515
546
        self._append_version(signal, attrs)
516
 
        self._append_deprecated(signal, attrs)
 
547
        self._append_node_generic(signal, attrs)
517
548
        with self.tagcontext('glib:signal', attrs):
518
 
            self._write_attributes(signal)
 
549
            self._write_generic(signal)
519
550
            self._write_return_type(signal.retval)
520
 
            self._write_parameters(signal.parameters)
 
551
            self._write_parameters(signal, signal.parameters)