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):
155 attrs = [('name', callable.name)]
156 attrs.extend(extra_attrs)
158 attrs.append(('doc', callable.doc))
159 self._append_version(callable, attrs)
160 self._append_deprecated(callable, attrs)
161 self._append_throws(callable, attrs)
162 with self.tagcontext(tag_name, attrs):
163 self._write_attributes(callable)
164 self._write_return_type(callable.retval)
165 self._write_parameters(callable.parameters)
167 def _write_function(self, func, tag_name='function'):
168 attrs = [('c:identifier', func.symbol)]
169 self._write_callable(func, tag_name, attrs)
171 def _write_method(self, method):
172 self._write_function(method, tag_name='method')
174 def _write_static_method(self, method):
175 self._write_function(method, tag_name='function')
177 def _write_constructor(self, method):
178 self._write_function(method, tag_name='constructor')
180 def _write_return_type(self, return_):
184 assert return_.transfer is not None, return_
187 attrs.append(('transfer-ownership', return_.transfer))
189 attrs.append(('doc', return_.doc))
190 with self.tagcontext('return-value', attrs):
191 self._write_type(return_.type)
193 def _write_parameters(self, parameters):
196 with self.tagcontext('parameters'):
197 for parameter in parameters:
198 self._write_parameter(parameter)
200 def _write_parameter(self, parameter):
201 assert parameter.transfer is not None, parameter
204 if parameter.name is not None:
205 attrs.append(('name', parameter.name))
206 if parameter.direction != 'in':
207 attrs.append(('direction', parameter.direction))
208 attrs.append(('transfer-ownership',
210 if parameter.allow_none:
211 attrs.append(('allow-none', '1'))
213 attrs.append(('scope', parameter.scope))
214 if parameter.closure_index >= 0:
215 attrs.append(('closure', '%d' % parameter.closure_index))
216 if parameter.destroy_index >= 0:
217 attrs.append(('destroy', '%d' % parameter.destroy_index))
219 attrs.append(('doc', parameter.doc))
220 with self.tagcontext('parameter', attrs):
221 self._write_type(parameter.type)
223 def _type_to_string(self, ntype):
224 if isinstance(ntype, basestring):
228 def _write_type(self, ntype, relation=None):
229 if isinstance(ntype, basestring):
233 typename = ntype.name
234 type_cname = ntype.ctype
235 if isinstance(ntype, Varargs):
236 with self.tagcontext('varargs', []):
239 if isinstance(ntype, Array):
241 if not ntype.zeroterminated:
242 attrs.append(('zero-terminated', '0'))
243 if ntype.length_param_index >= 0:
244 attrs.append(('length', '%d' % (ntype.length_param_index, )))
245 attrs.append(('c:type', ntype.ctype))
246 if ntype.size is not None:
247 attrs.append(('fixed-size', ntype.size))
248 with self.tagcontext('array', attrs):
249 self._write_type(ntype.element_type)
251 attrs = [('name', self._type_to_string(ntype))]
252 # FIXME: figure out if type references a basic type
253 # or a boxed/class/interface etc. and skip
254 # writing the ctype if the latter.
255 if type_cname is not None:
256 attrs.append(('c:type', type_cname))
257 if isinstance(ntype, List) and ntype.element_type:
258 with self.tagcontext('type', attrs):
259 self._write_type(ntype.element_type)
261 if isinstance(ntype, Map) and ntype.key_type:
262 with self.tagcontext('type', attrs):
263 self._write_type(ntype.key_type)
264 self._write_type(ntype.value_type)
266 # Not a special type, just write it out
267 self.write_tag('type', attrs)
269 def _write_enum(self, enum):
270 attrs = [('name', enum.name)]
272 attrs.append(('doc', enum.doc))
273 self._append_version(enum, attrs)
274 self._append_deprecated(enum, attrs)
275 if isinstance(enum, GLibEnum):
276 attrs.extend([('glib:type-name', enum.type_name),
277 ('glib:get-type', enum.get_type),
278 ('c:type', enum.ctype)])
280 attrs.append(('glib:error-quark', enum.error_quark))
282 attrs.append(('c:type', enum.symbol))
284 with self.tagcontext('enumeration', attrs):
285 self._write_attributes(enum)
286 for member in enum.members:
287 self._write_member(member)
289 def _write_bitfield(self, bitfield):
290 attrs = [('name', bitfield.name)]
292 attrs.append(('doc', bitfield.doc))
293 self._append_version(bitfield, attrs)
294 self._append_deprecated(bitfield, attrs)
295 if isinstance(bitfield, GLibFlags):
296 attrs.extend([('glib:type-name', bitfield.type_name),
297 ('glib:get-type', bitfield.get_type),
298 ('c:type', bitfield.ctype)])
300 attrs.append(('c:type', bitfield.symbol))
301 with self.tagcontext('bitfield', attrs):
302 self._write_attributes(bitfield)
303 for member in bitfield.members:
304 self._write_member(member)
306 def _write_member(self, member):
307 attrs = [('name', member.name),
308 ('value', str(member.value)),
309 ('c:identifier', member.symbol)]
310 if isinstance(member, GLibEnumMember):
311 attrs.append(('glib:nick', member.nick))
312 self.write_tag('member', attrs)
314 def _write_constant(self, constant):
315 attrs = [('name', constant.name),
316 ('value', str(constant.value))]
317 with self.tagcontext('constant', attrs):
318 self._write_type(constant.type)
320 def _write_class(self, node):
321 attrs = [('name', node.name),
322 ('c:type', node.ctype)]
324 attrs.append(('doc', node.doc))
325 self._append_version(node, attrs)
326 self._append_deprecated(node, attrs)
327 if isinstance(node, Class):
329 if node.parent is not None:
330 attrs.append(('parent', node.parent))
332 attrs.append(('abstract', '1'))
334 tag_name = 'interface'
335 if isinstance(node, (GLibObject, GLibInterface)):
336 attrs.append(('glib:type-name', node.type_name))
338 attrs.append(('glib:get-type', node.get_type))
339 if node.glib_type_struct:
340 attrs.append(('glib:type-struct', node.glib_type_struct.name))
341 with self.tagcontext(tag_name, attrs):
342 self._write_attributes(node)
343 if isinstance(node, GLibObject):
344 for iface in node.interfaces:
345 self.write_tag('implements', [('name', iface)])
346 if isinstance(node, Interface):
347 for iface in node.prerequisites:
348 self.write_tag('prerequisite', [('name', iface)])
349 if isinstance(node, Class):
350 for method in node.constructors:
351 self._write_constructor(method)
352 for method in node.static_methods:
353 self._write_static_method(method)
354 for vfunc in node.virtual_methods:
355 self._write_vfunc(vfunc)
356 for method in node.methods:
357 self._write_method(method)
358 for prop in node.properties:
359 self._write_property(prop)
360 for field in node.fields:
361 self._write_field(field)
362 for signal in node.signals:
363 self._write_signal(signal)
365 def _write_boxed(self, boxed):
366 attrs = [('c:type', boxed.ctype),
367 ('glib:name', boxed.name)]
369 attrs.append(('doc', boxed.doc))
370 attrs.extend(self._boxed_attrs(boxed))
371 with self.tagcontext('glib:boxed', attrs):
372 self._write_attributes(boxed)
373 for method in boxed.constructors:
374 self._write_constructor(method)
375 for method in boxed.methods:
376 self._write_method(method)
378 def _write_property(self, prop):
379 attrs = [('name', prop.name)]
380 self._append_version(prop, attrs)
381 self._append_deprecated(prop, attrs)
382 # Properties are assumed to be readable (see also generate.c)
383 if not prop.readable:
384 attrs.append(('readable', '0'))
386 attrs.append(('writable', '1'))
388 attrs.append(('construct', '1'))
389 if prop.construct_only:
390 attrs.append(('construct-only', '1'))
392 attrs.append(('doc', prop.doc))
393 with self.tagcontext('property', attrs):
394 self._write_attributes(prop)
395 self._write_type(prop.type)
397 def _write_vfunc(self, vf):
400 attrs.append(('invoker', vf.invoker))
401 self._write_callable(vf, 'virtual-method', attrs)
403 def _write_callback(self, callback):
404 attrs = [('c:type', callback.ctype)]
405 self._write_callable(callback, 'callback', attrs)
407 def _boxed_attrs(self, boxed):
408 return [('glib:type-name', boxed.type_name),
409 ('glib:get-type', boxed.get_type)]
411 def _write_record(self, record, extra_attrs=[]):
412 attrs = list(extra_attrs)
413 if record.name is not None:
414 attrs.append(('name', record.name))
415 if record.symbol is not None: # the record might be anonymous
416 attrs.append(('c:type', record.symbol))
418 attrs.append(('disguised', '1'))
419 if isinstance(record, GLibRecord):
420 if record.is_gtype_struct_for:
421 attrs.append(('glib:is-gtype-struct-for',
422 record.is_gtype_struct_for))
424 attrs.append(('doc', record.doc))
425 self._append_version(record, attrs)
426 self._append_deprecated(record, attrs)
427 if isinstance(record, GLibBoxed):
428 attrs.extend(self._boxed_attrs(record))
429 with self.tagcontext('record', attrs):
430 self._write_attributes(record)
432 for field in record.fields:
433 self._write_field(field)
434 for method in record.constructors:
435 self._write_constructor(method)
436 for method in record.methods:
437 self._write_method(method)
439 def _write_union(self, union):
441 if union.name is not None:
442 attrs.append(('name', union.name))
443 if union.symbol is not None: # the union might be anonymous
444 attrs.append(('c:type', union.symbol))
446 attrs.append(('doc', union.doc))
447 self._append_version(union, attrs)
448 self._append_deprecated(union, attrs)
449 if isinstance(union, GLibBoxed):
450 attrs.extend(self._boxed_attrs(union))
451 with self.tagcontext('union', attrs):
452 self._write_attributes(union)
454 for field in union.fields:
455 self._write_field(field)
456 for method in union.constructors:
457 self._write_constructor(method)
458 for method in union.methods:
459 self._write_method(method)
461 def _write_field(self, field):
462 if isinstance(field, Function):
463 self._write_method(field)
466 if isinstance(field, Callback):
467 attrs = [('name', field.name)]
468 with self.tagcontext('field', attrs):
469 self._write_attributes(field)
470 self._write_callback(field)
471 elif isinstance(field, Struct):
472 self._write_record(field)
473 elif isinstance(field, Union):
474 self._write_union(field)
476 attrs = [('name', field.name)]
477 # Fields are assumed to be read-only
478 # (see also girparser.c and generate.c)
479 if not field.readable:
480 attrs.append(('readable', '0'))
482 attrs.append(('writable', '1'))
484 attrs.append(('bits', str(field.bits)))
485 with self.tagcontext('field', attrs):
486 self._write_attributes(field)
487 self._write_type(field.type)
489 def _write_signal(self, signal):
490 attrs = [('name', signal.name)]
492 attrs.append(('doc', signal.doc))
493 self._append_version(signal, attrs)
494 self._append_deprecated(signal, attrs)
495 with self.tagcontext('glib:signal', attrs):
496 self._write_attributes(signal)
497 self._write_return_type(signal.retval)
498 self._write_parameters(signal.parameters)