2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008 Johan Dahlin
4 # Copyright (C) 2008, 2009 Red Hat, Inc.
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2 of the License, or (at your option) any later version.
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the
18 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 # Boston, MA 02111-1307, USA.
22 from __future__ import with_statement
24 from .ast import (Alias, Array, Bitfield, Callback, Class, Constant, Enum,
25 Function, Interface, List, Map, Member, Struct, Union,
27 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
28 GLibFlags, GLibObject, GLibInterface,
30 from .xmlwriter import XMLWriter
33 class GIRWriter(XMLWriter):
35 def __init__(self, namespace, shlibs, includes, pkgs, c_includes, cprefix):
36 super(GIRWriter, self).__init__()
38 '''This file was automatically generated from C sources - DO NOT EDIT!
39 To affect the contents of this file, edit the original C definitions,
40 and/or use gtk-doc annotations. ''')
41 self._write_repository(namespace, shlibs, includes, pkgs,
44 def _write_repository(self, namespace, shlibs, includes=None,
45 packages=None, c_includes=None, cprefix=None):
47 includes = frozenset()
49 packages = frozenset()
50 if c_includes is None:
51 c_includes = frozenset()
54 ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
55 ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
56 ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
58 with self.tagcontext('repository', attrs):
59 for include in sorted(includes):
60 self._write_include(include)
61 for pkg in sorted(set(packages)):
62 self._write_pkgconfig_pkg(pkg)
63 for c_include in sorted(set(c_includes)):
64 self._write_c_include(c_include)
65 self._write_namespace(namespace, shlibs, cprefix)
67 def _write_include(self, include):
68 attrs = [('name', include.name), ('version', include.version)]
69 self.write_tag('include', attrs)
71 def _write_pkgconfig_pkg(self, package):
72 attrs = [('name', package)]
73 self.write_tag('package', attrs)
75 def _write_c_include(self, c_include):
76 attrs = [('name', c_include)]
77 self.write_tag('c:include', attrs)
79 def _write_namespace(self, namespace, shlibs, cprefix):
80 attrs = [('name', namespace.name),
81 ('version', namespace.version),
82 ('shared-library', ','.join(shlibs)),
83 ('c:prefix', cprefix)]
84 with self.tagcontext('namespace', attrs):
85 # We define a custom sorting function here because
86 # we want aliases to be first. They're a bit
87 # special because the typelib compiler expands them.
89 if isinstance(a, Alias):
90 if isinstance(b, Alias):
91 return cmp(a.name, b.name)
94 elif isinstance(b, Alias):
98 for node in sorted(namespace.nodes, cmp=nscmp):
100 self._write_node(node)
102 def _write_node(self, node):
103 if isinstance(node, Function):
104 self._write_function(node)
105 elif isinstance(node, Enum):
106 self._write_enum(node)
107 elif isinstance(node, Bitfield):
108 self._write_bitfield(node)
109 elif isinstance(node, (Class, Interface)):
110 self._write_class(node)
111 elif isinstance(node, Callback):
112 self._write_callback(node)
113 elif isinstance(node, Struct):
114 self._write_record(node)
115 elif isinstance(node, Union):
116 self._write_union(node)
117 elif isinstance(node, GLibBoxed):
118 self._write_boxed(node)
119 elif isinstance(node, Member):
120 # FIXME: atk_misc_instance singleton
122 elif isinstance(node, Alias):
123 self._write_alias(node)
124 elif isinstance(node, Constant):
125 self._write_constant(node)
127 print 'WRITER: Unhandled node', node
129 def _append_version(self, node, attrs):
131 attrs.append(('version', node.version))
133 def _write_attributes(self, node):
134 for key, value in node.attributes:
135 self.write_tag('attribute', [('name', key), ('value', value)])
137 def _append_deprecated(self, node, attrs):
139 attrs.append(('deprecated', node.deprecated))
140 if node.deprecated_version:
141 attrs.append(('deprecated-version',
142 node.deprecated_version))
144 def _append_throws(self, func, attrs):
146 attrs.append(('throws', '1'))
148 def _write_alias(self, alias):
149 attrs = [('name', alias.name), ('target', alias.target)]
150 if alias.ctype is not None:
151 attrs.append(('c:type', alias.ctype))
152 self.write_tag('alias', attrs)
154 def _write_callable(self, callable, tag_name, extra_attrs):
157 attrs = [('name', callable.name)]
158 attrs.extend(extra_attrs)
160 attrs.append(('doc', callable.doc))
161 self._append_version(callable, attrs)
162 self._append_deprecated(callable, attrs)
163 self._append_throws(callable, attrs)
164 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 def _write_function(self, func, tag_name='function'):
170 attrs = [('c:identifier', func.symbol)]
171 self._write_callable(func, tag_name, attrs)
173 def _write_method(self, method):
174 self._write_function(method, tag_name='method')
176 def _write_static_method(self, method):
177 self._write_function(method, tag_name='function')
179 def _write_constructor(self, method):
180 self._write_function(method, tag_name='constructor')
182 def _write_return_type(self, return_):
186 assert return_.transfer is not None, return_
189 attrs.append(('transfer-ownership', return_.transfer))
191 attrs.append(('doc', return_.doc))
192 with self.tagcontext('return-value', attrs):
193 self._write_type(return_.type)
195 def _write_parameters(self, parameters):
198 with self.tagcontext('parameters'):
199 for parameter in parameters:
200 self._write_parameter(parameter)
202 def _write_parameter(self, parameter):
203 assert parameter.transfer is not None, parameter
206 if parameter.name is not None:
207 attrs.append(('name', parameter.name))
208 if parameter.direction != 'in':
209 attrs.append(('direction', parameter.direction))
210 attrs.append(('transfer-ownership',
212 if parameter.allow_none:
213 attrs.append(('allow-none', '1'))
215 attrs.append(('scope', parameter.scope))
216 if parameter.closure_index >= 0:
217 attrs.append(('closure', '%d' % parameter.closure_index))
218 if parameter.destroy_index >= 0:
219 attrs.append(('destroy', '%d' % parameter.destroy_index))
221 attrs.append(('doc', parameter.doc))
222 with self.tagcontext('parameter', attrs):
223 self._write_type(parameter.type)
225 def _type_to_string(self, ntype):
226 if isinstance(ntype, basestring):
230 def _write_type(self, ntype, relation=None):
231 if isinstance(ntype, basestring):
235 typename = ntype.name
236 type_cname = ntype.ctype
237 if isinstance(ntype, Varargs):
238 with self.tagcontext('varargs', []):
241 if isinstance(ntype, Array):
243 if not ntype.zeroterminated:
244 attrs.append(('zero-terminated', '0'))
245 if ntype.length_param_index >= 0:
246 attrs.append(('length', '%d' % (ntype.length_param_index, )))
247 attrs.append(('c:type', ntype.ctype))
248 if ntype.size is not None:
249 attrs.append(('fixed-size', ntype.size))
250 with self.tagcontext('array', attrs):
251 self._write_type(ntype.element_type)
253 attrs = [('name', self._type_to_string(ntype))]
254 # FIXME: figure out if type references a basic type
255 # or a boxed/class/interface etc. and skip
256 # writing the ctype if the latter.
257 if type_cname is not None:
258 attrs.append(('c:type', type_cname))
259 if isinstance(ntype, List) and ntype.element_type:
260 with self.tagcontext('type', attrs):
261 self._write_type(ntype.element_type)
263 if isinstance(ntype, Map) and ntype.key_type:
264 with self.tagcontext('type', attrs):
265 self._write_type(ntype.key_type)
266 self._write_type(ntype.value_type)
268 # Not a special type, just write it out
269 self.write_tag('type', attrs)
271 def _write_enum(self, enum):
272 attrs = [('name', enum.name)]
274 attrs.append(('doc', enum.doc))
275 self._append_version(enum, attrs)
276 self._append_deprecated(enum, attrs)
277 if isinstance(enum, GLibEnum):
278 attrs.extend([('glib:type-name', enum.type_name),
279 ('glib:get-type', enum.get_type),
280 ('c:type', enum.ctype)])
282 attrs.append(('glib:error-quark', enum.error_quark))
284 attrs.append(('c:type', enum.symbol))
286 with self.tagcontext('enumeration', attrs):
287 self._write_attributes(enum)
288 for member in enum.members:
289 self._write_member(member)
291 def _write_bitfield(self, bitfield):
292 attrs = [('name', bitfield.name)]
294 attrs.append(('doc', bitfield.doc))
295 self._append_version(bitfield, attrs)
296 self._append_deprecated(bitfield, attrs)
297 if isinstance(bitfield, GLibFlags):
298 attrs.extend([('glib:type-name', bitfield.type_name),
299 ('glib:get-type', bitfield.get_type),
300 ('c:type', bitfield.ctype)])
302 attrs.append(('c:type', bitfield.symbol))
303 with self.tagcontext('bitfield', attrs):
304 self._write_attributes(bitfield)
305 for member in bitfield.members:
306 self._write_member(member)
308 def _write_member(self, member):
311 attrs = [('name', member.name),
312 ('value', str(member.value)),
313 ('c:identifier', member.symbol)]
314 if isinstance(member, GLibEnumMember):
315 attrs.append(('glib:nick', member.nick))
316 self.write_tag('member', attrs)
318 def _write_constant(self, constant):
319 attrs = [('name', constant.name),
320 ('value', str(constant.value))]
321 with self.tagcontext('constant', attrs):
322 self._write_type(constant.type)
324 def _write_class(self, node):
325 attrs = [('name', node.name),
326 ('c:type', node.ctype)]
328 attrs.append(('doc', node.doc))
329 self._append_version(node, attrs)
330 self._append_deprecated(node, attrs)
331 if isinstance(node, Class):
333 if node.parent is not None:
334 attrs.append(('parent', node.parent))
336 attrs.append(('abstract', '1'))
338 tag_name = 'interface'
339 if isinstance(node, (GLibObject, GLibInterface)):
340 attrs.append(('glib:type-name', node.type_name))
342 attrs.append(('glib:get-type', node.get_type))
343 if node.glib_type_struct:
344 attrs.append(('glib:type-struct', node.glib_type_struct.name))
345 with self.tagcontext(tag_name, attrs):
346 self._write_attributes(node)
347 if isinstance(node, GLibObject):
348 for iface in node.interfaces:
349 self.write_tag('implements', [('name', iface)])
350 if isinstance(node, Interface):
351 for iface in node.prerequisites:
352 self.write_tag('prerequisite', [('name', iface)])
353 if isinstance(node, Class):
354 for method in node.constructors:
355 self._write_constructor(method)
356 for method in node.static_methods:
357 self._write_static_method(method)
358 for vfunc in node.virtual_methods:
359 self._write_vfunc(vfunc)
360 for method in node.methods:
361 self._write_method(method)
362 for prop in node.properties:
363 self._write_property(prop)
364 for field in node.fields:
365 self._write_field(field)
366 for signal in node.signals:
367 self._write_signal(signal)
369 def _write_boxed(self, boxed):
370 attrs = [('c:type', boxed.ctype),
371 ('glib:name', boxed.name)]
373 attrs.append(('doc', boxed.doc))
374 attrs.extend(self._boxed_attrs(boxed))
375 with self.tagcontext('glib:boxed', attrs):
376 self._write_attributes(boxed)
377 for method in boxed.constructors:
378 self._write_constructor(method)
379 for method in boxed.methods:
380 self._write_method(method)
382 def _write_property(self, prop):
385 attrs = [('name', prop.name)]
386 self._append_version(prop, attrs)
387 self._append_deprecated(prop, attrs)
388 # Properties are assumed to be readable (see also generate.c)
389 if not prop.readable:
390 attrs.append(('readable', '0'))
392 attrs.append(('writable', '1'))
394 attrs.append(('construct', '1'))
395 if prop.construct_only:
396 attrs.append(('construct-only', '1'))
398 attrs.append(('doc', prop.doc))
399 with self.tagcontext('property', attrs):
400 self._write_attributes(prop)
401 self._write_type(prop.type)
403 def _write_vfunc(self, vf):
406 attrs.append(('invoker', vf.invoker))
407 self._write_callable(vf, 'virtual-method', attrs)
409 def _write_callback(self, callback):
410 attrs = [('c:type', callback.ctype)]
411 self._write_callable(callback, 'callback', attrs)
413 def _boxed_attrs(self, boxed):
414 return [('glib:type-name', boxed.type_name),
415 ('glib:get-type', boxed.get_type)]
417 def _write_record(self, record, extra_attrs=[]):
418 is_gtype_struct = False
419 attrs = list(extra_attrs)
420 if record.name is not None:
421 attrs.append(('name', record.name))
422 if record.symbol is not None: # the record might be anonymous
423 attrs.append(('c:type', record.symbol))
425 attrs.append(('disguised', '1'))
426 if isinstance(record, GLibRecord):
427 if record.is_gtype_struct_for:
428 is_gtype_struct = True
429 attrs.append(('glib:is-gtype-struct-for',
430 record.is_gtype_struct_for))
432 attrs.append(('doc', record.doc))
433 self._append_version(record, attrs)
434 self._append_deprecated(record, attrs)
435 if isinstance(record, GLibBoxed):
436 attrs.extend(self._boxed_attrs(record))
437 with self.tagcontext('record', attrs):
438 self._write_attributes(record)
440 for field in record.fields:
441 self._write_field(field, is_gtype_struct)
442 for method in record.constructors:
443 self._write_constructor(method)
444 for method in record.methods:
445 self._write_method(method)
447 def _write_union(self, union):
449 if union.name is not None:
450 attrs.append(('name', union.name))
451 if union.symbol is not None: # the union might be anonymous
452 attrs.append(('c:type', union.symbol))
454 attrs.append(('doc', union.doc))
455 self._append_version(union, attrs)
456 self._append_deprecated(union, attrs)
457 if isinstance(union, GLibBoxed):
458 attrs.extend(self._boxed_attrs(union))
459 with self.tagcontext('union', attrs):
460 self._write_attributes(union)
462 for field in union.fields:
463 self._write_field(field)
464 for method in union.constructors:
465 self._write_constructor(method)
466 for method in union.methods:
467 self._write_method(method)
469 def _write_field(self, field, is_gtype_struct=False):
470 if isinstance(field, Function):
471 self._write_method(field)
474 if isinstance(field, Callback):
475 attrs = [('name', field.name)]
476 with self.tagcontext('field', attrs):
477 self._write_attributes(field)
479 self._write_callback(field)
481 attrs = [('name', 'any'), ('c:type', 'pointer')]
482 self.write_tag('type', attrs)
483 elif isinstance(field, Struct):
484 self._write_record(field)
485 elif isinstance(field, Union):
486 self._write_union(field)
488 attrs = [('name', field.name)]
489 # Fields are assumed to be read-only
490 # (see also girparser.c and generate.c)
491 if not field.readable:
492 attrs.append(('readable', '0'))
494 attrs.append(('writable', '1'))
496 attrs.append(('bits', str(field.bits)))
497 with self.tagcontext('field', attrs):
498 self._write_attributes(field)
499 self._write_type(field.type)
501 def _write_signal(self, signal):
504 attrs = [('name', signal.name)]
506 attrs.append(('doc', signal.doc))
507 self._append_version(signal, attrs)
508 self._append_deprecated(signal, attrs)
509 with self.tagcontext('glib:signal', attrs):
510 self._write_attributes(signal)
511 self._write_return_type(signal.retval)
512 self._write_parameters(signal.parameters)