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):
99 self._write_node(node)
101 def _write_node(self, node):
102 if isinstance(node, Function):
103 self._write_function(node)
104 elif isinstance(node, Enum):
105 self._write_enum(node)
106 elif isinstance(node, Bitfield):
107 self._write_bitfield(node)
108 elif isinstance(node, (Class, Interface)):
109 self._write_class(node)
110 elif isinstance(node, Callback):
111 self._write_callback(node)
112 elif isinstance(node, Struct):
113 self._write_record(node)
114 elif isinstance(node, Union):
115 self._write_union(node)
116 elif isinstance(node, GLibBoxed):
117 self._write_boxed(node)
118 elif isinstance(node, Member):
119 # FIXME: atk_misc_instance singleton
121 elif isinstance(node, Alias):
122 self._write_alias(node)
123 elif isinstance(node, Constant):
124 self._write_constant(node)
126 print 'WRITER: Unhandled node', node
128 def _append_version(self, node, attrs):
130 attrs.append(('version', node.version))
132 def _write_attributes(self, node):
133 for key, value in node.attributes:
134 self.write_tag('attribute', [('name', key), ('value', value)])
136 def _append_deprecated(self, node, attrs):
138 attrs.append(('deprecated', node.deprecated))
139 if node.deprecated_version:
140 attrs.append(('deprecated-version',
141 node.deprecated_version))
143 def _append_throws(self, func, attrs):
145 attrs.append(('throws', '1'))
147 def _write_alias(self, alias):
148 attrs = [('name', alias.name), ('target', alias.target)]
149 if alias.ctype is not None:
150 attrs.append(('c:type', alias.ctype))
151 self.write_tag('alias', attrs)
153 def _write_callable(self, callable, tag_name, extra_attrs):
154 attrs = [('name', callable.name)]
155 attrs.extend(extra_attrs)
157 attrs.append(('doc', callable.doc))
158 self._append_version(callable, attrs)
159 self._append_deprecated(callable, attrs)
160 self._append_throws(callable, attrs)
161 with self.tagcontext(tag_name, attrs):
162 self._write_attributes(callable)
163 self._write_return_type(callable.retval)
164 self._write_parameters(callable.parameters)
166 def _write_function(self, func, tag_name='function'):
167 attrs = [('c:identifier', func.symbol)]
168 self._write_callable(func, tag_name, attrs)
170 def _write_method(self, method):
171 self._write_function(method, tag_name='method')
173 def _write_static_method(self, method):
174 self._write_function(method, tag_name='function')
176 def _write_constructor(self, method):
177 self._write_function(method, tag_name='constructor')
179 def _write_return_type(self, return_):
183 assert return_.transfer is not None, return_
186 attrs.append(('transfer-ownership', return_.transfer))
188 attrs.append(('doc', return_.doc))
189 with self.tagcontext('return-value', attrs):
190 self._write_type(return_.type)
192 def _write_parameters(self, parameters):
195 with self.tagcontext('parameters'):
196 for parameter in parameters:
197 self._write_parameter(parameter)
199 def _write_parameter(self, parameter):
200 assert parameter.transfer is not None, parameter
203 if parameter.name is not None:
204 attrs.append(('name', parameter.name))
205 if parameter.direction != 'in':
206 attrs.append(('direction', parameter.direction))
207 attrs.append(('transfer-ownership',
209 if parameter.allow_none:
210 attrs.append(('allow-none', '1'))
212 attrs.append(('scope', parameter.scope))
213 if parameter.closure_index >= 0:
214 attrs.append(('closure', '%d' % parameter.closure_index))
215 if parameter.destroy_index >= 0:
216 attrs.append(('destroy', '%d' % parameter.destroy_index))
218 attrs.append(('doc', parameter.doc))
219 with self.tagcontext('parameter', attrs):
220 self._write_type(parameter.type)
222 def _type_to_string(self, ntype):
223 if isinstance(ntype, basestring):
227 def _write_type(self, ntype, relation=None):
228 if isinstance(ntype, basestring):
232 typename = ntype.name
233 type_cname = ntype.ctype
234 if isinstance(ntype, Varargs):
235 with self.tagcontext('varargs', []):
238 if isinstance(ntype, Array):
240 if not ntype.zeroterminated:
241 attrs.append(('zero-terminated', '0'))
242 if ntype.length_param_index >= 0:
243 attrs.append(('length', '%d' % (ntype.length_param_index, )))
244 attrs.append(('c:type', ntype.ctype))
245 if ntype.size is not None:
246 attrs.append(('fixed-size', ntype.size))
247 with self.tagcontext('array', attrs):
248 self._write_type(ntype.element_type)
250 attrs = [('name', self._type_to_string(ntype))]
251 # FIXME: figure out if type references a basic type
252 # or a boxed/class/interface etc. and skip
253 # writing the ctype if the latter.
254 if type_cname is not None:
255 attrs.append(('c:type', type_cname))
256 if isinstance(ntype, List) and ntype.element_type:
257 with self.tagcontext('type', attrs):
258 self._write_type(ntype.element_type)
260 if isinstance(ntype, Map) and ntype.key_type:
261 with self.tagcontext('type', attrs):
262 self._write_type(ntype.key_type)
263 self._write_type(ntype.value_type)
265 # Not a special type, just write it out
266 self.write_tag('type', attrs)
268 def _write_enum(self, enum):
269 attrs = [('name', enum.name)]
271 attrs.append(('doc', enum.doc))
272 self._append_version(enum, attrs)
273 self._append_deprecated(enum, attrs)
274 if isinstance(enum, GLibEnum):
275 attrs.extend([('glib:type-name', enum.type_name),
276 ('glib:get-type', enum.get_type),
277 ('c:type', enum.ctype)])
279 attrs.append(('glib:error-quark', enum.error_quark))
281 attrs.append(('c:type', enum.symbol))
283 with self.tagcontext('enumeration', attrs):
284 self._write_attributes(enum)
285 for member in enum.members:
286 self._write_member(member)
288 def _write_bitfield(self, bitfield):
289 attrs = [('name', bitfield.name)]
291 attrs.append(('doc', bitfield.doc))
292 self._append_version(bitfield, attrs)
293 self._append_deprecated(bitfield, attrs)
294 if isinstance(bitfield, GLibFlags):
295 attrs.extend([('glib:type-name', bitfield.type_name),
296 ('glib:get-type', bitfield.get_type),
297 ('c:type', bitfield.ctype)])
299 attrs.append(('c:type', bitfield.symbol))
300 with self.tagcontext('bitfield', attrs):
301 self._write_attributes(bitfield)
302 for member in bitfield.members:
303 self._write_member(member)
305 def _write_member(self, member):
306 attrs = [('name', member.name),
307 ('value', str(member.value)),
308 ('c:identifier', member.symbol)]
309 if isinstance(member, GLibEnumMember):
310 attrs.append(('glib:nick', member.nick))
311 self.write_tag('member', attrs)
313 def _write_constant(self, constant):
314 attrs = [('name', constant.name),
315 ('value', str(constant.value))]
316 with self.tagcontext('constant', attrs):
317 self._write_type(constant.type)
319 def _write_class(self, node):
320 attrs = [('name', node.name),
321 ('c:type', node.ctype)]
323 attrs.append(('doc', node.doc))
324 self._append_version(node, attrs)
325 self._append_deprecated(node, attrs)
326 if isinstance(node, Class):
328 if node.parent is not None:
329 attrs.append(('parent', node.parent))
331 attrs.append(('abstract', '1'))
333 tag_name = 'interface'
334 if isinstance(node, (GLibObject, GLibInterface)):
335 attrs.append(('glib:type-name', node.type_name))
337 attrs.append(('glib:get-type', node.get_type))
338 if node.glib_type_struct:
339 attrs.append(('glib:type-struct', node.glib_type_struct.name))
340 with self.tagcontext(tag_name, attrs):
341 self._write_attributes(node)
342 if isinstance(node, GLibObject):
343 for iface in node.interfaces:
344 self.write_tag('implements', [('name', iface)])
345 if isinstance(node, Interface):
346 for iface in node.prerequisites:
347 self.write_tag('prerequisite', [('name', iface)])
348 if isinstance(node, Class):
349 for method in node.constructors:
350 self._write_constructor(method)
351 for method in node.static_methods:
352 self._write_static_method(method)
353 for vfunc in node.virtual_methods:
354 self._write_vfunc(vfunc)
355 for method in node.methods:
356 self._write_method(method)
357 for prop in node.properties:
358 self._write_property(prop)
359 for field in node.fields:
360 self._write_field(field)
361 for signal in node.signals:
362 self._write_signal(signal)
364 def _write_boxed(self, boxed):
365 attrs = [('c:type', boxed.ctype),
366 ('glib:name', boxed.name)]
368 attrs.append(('doc', boxed.doc))
369 attrs.extend(self._boxed_attrs(boxed))
370 with self.tagcontext('glib:boxed', attrs):
371 self._write_attributes(boxed)
372 for method in boxed.constructors:
373 self._write_constructor(method)
374 for method in boxed.methods:
375 self._write_method(method)
377 def _write_property(self, prop):
378 attrs = [('name', prop.name)]
379 self._append_version(prop, attrs)
380 self._append_deprecated(prop, attrs)
381 # Properties are assumed to be readable (see also generate.c)
382 if not prop.readable:
383 attrs.append(('readable', '0'))
385 attrs.append(('writable', '1'))
387 attrs.append(('construct', '1'))
388 if prop.construct_only:
389 attrs.append(('construct-only', '1'))
391 attrs.append(('doc', prop.doc))
392 with self.tagcontext('property', attrs):
393 self._write_attributes(prop)
394 self._write_type(prop.type)
396 def _write_vfunc(self, vf):
399 attrs.append(('invoker', vf.invoker))
400 self._write_callable(vf, 'virtual-method', attrs)
402 def _write_callback(self, callback):
403 attrs = [('c:type', callback.ctype)]
404 self._write_callable(callback, 'callback', attrs)
406 def _boxed_attrs(self, boxed):
407 return [('glib:type-name', boxed.type_name),
408 ('glib:get-type', boxed.get_type)]
410 def _write_record(self, record, extra_attrs=[]):
411 attrs = list(extra_attrs)
412 if record.name is not None:
413 attrs.append(('name', record.name))
414 if record.symbol is not None: # the record might be anonymous
415 attrs.append(('c:type', record.symbol))
417 attrs.append(('disguised', '1'))
418 if isinstance(record, GLibRecord):
419 if record.is_gtype_struct_for:
420 attrs.append(('glib:is-gtype-struct-for',
421 record.is_gtype_struct_for))
423 attrs.append(('doc', record.doc))
424 self._append_version(record, attrs)
425 self._append_deprecated(record, attrs)
426 if isinstance(record, GLibBoxed):
427 attrs.extend(self._boxed_attrs(record))
428 with self.tagcontext('record', attrs):
429 self._write_attributes(record)
431 for field in record.fields:
432 self._write_field(field)
433 for method in record.constructors:
434 self._write_constructor(method)
435 for method in record.methods:
436 self._write_method(method)
438 def _write_union(self, union):
440 if union.name is not None:
441 attrs.append(('name', union.name))
442 if union.symbol is not None: # the union might be anonymous
443 attrs.append(('c:type', union.symbol))
445 attrs.append(('doc', union.doc))
446 self._append_version(union, attrs)
447 self._append_deprecated(union, attrs)
448 if isinstance(union, GLibBoxed):
449 attrs.extend(self._boxed_attrs(union))
450 with self.tagcontext('union', attrs):
451 self._write_attributes(union)
453 for field in union.fields:
454 self._write_field(field)
455 for method in union.constructors:
456 self._write_constructor(method)
457 for method in union.methods:
458 self._write_method(method)
460 def _write_field(self, field):
461 if isinstance(field, Function):
462 self._write_method(field)
465 if isinstance(field, Callback):
466 self._write_callback(field)
467 elif isinstance(field, Struct):
468 self._write_record(field)
469 elif isinstance(field, Union):
470 self._write_union(field)
472 attrs = [('name', field.name)]
473 # Fields are assumed to be read-only
474 # (see also girparser.c and generate.c)
475 if not field.readable:
476 attrs.append(('readable', '0'))
478 attrs.append(('writable', '1'))
480 attrs.append(('bits', str(field.bits)))
481 with self.tagcontext('field', attrs):
482 self._write_attributes(field)
483 self._write_type(field.type)
485 def _write_signal(self, signal):
486 attrs = [('name', signal.name)]
488 attrs.append(('doc', signal.doc))
489 self._append_version(signal, attrs)
490 self._append_deprecated(signal, attrs)
491 with self.tagcontext('glib:signal', attrs):
492 self._write_attributes(signal)
493 self._write_return_type(signal.retval)
494 self._write_parameters(signal.parameters)