2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008 Johan Dahlin
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 from __future__ import with_statement
23 from .ast import (Callback, Class, Enum, Function, Interface, Member,
24 Sequence, Struct, Alias)
25 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
26 GLibFlags, GLibObject, GLibInterface)
27 from .xmlwriter import XMLWriter
30 class GIRWriter(XMLWriter):
32 def __init__(self, namespace):
33 super(GIRWriter, self).__init__()
34 self._write_repository(namespace)
36 def _write_repository(self, namespace):
39 ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
40 ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
41 ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
43 with self.tagcontext('repository', attrs):
44 self._write_namespace(namespace)
46 def _write_namespace(self, namespace):
47 attrs = [('name', namespace.name)]
48 with self.tagcontext('namespace', attrs):
49 for node in namespace.nodes:
50 self._write_node(node)
52 def _write_node(self, node):
53 if isinstance(node, Function):
54 self._write_function(node)
55 elif isinstance(node, Enum):
56 self._write_enum(node)
57 elif isinstance(node, (Class, Interface)):
58 self._write_class(node)
59 elif isinstance(node, GLibBoxed):
60 self._write_boxed(node)
61 elif isinstance(node, Callback):
62 self._write_callback(node)
63 elif isinstance(node, Struct):
64 self._write_record(node)
65 elif isinstance(node, Member):
66 # FIXME: atk_misc_instance singleton
68 elif isinstance(node, Alias):
69 self._write_alias(node)
71 print 'WRITER: Unhandled node', node
73 def _write_alias(self, alias):
74 attrs = [('name', alias.name), ('target', alias.target)]
75 if alias.ctype is not None:
76 attrs.append(('c:type', alias.ctype))
77 self.write_tag('alias', attrs)
79 def _write_function(self, func, tag_name='function'):
80 attrs = [('name', func.name),
81 ('c:identifier', func.symbol)]
82 with self.tagcontext(tag_name, attrs):
83 self._write_return_type(func.retval)
84 self._write_parameters(func.parameters)
86 def _write_method(self, method):
87 self._write_function(method, tag_name='method')
89 def _write_constructor(self, method):
90 self._write_function(method, tag_name='constructor')
92 def _write_return_type(self, return_):
98 attrs.append(('transfer-ownership',
99 str(int(return_.transfer))))
100 with self.tagcontext('return-value', attrs):
101 if isinstance(return_.type, Sequence):
102 self._write_sequence(return_.type)
104 self._write_type(return_.type)
106 def _write_parameters(self, parameters):
109 with self.tagcontext('parameters'):
110 for parameter in parameters:
111 self._write_parameter(parameter)
113 def _write_parameter(self, parameter):
115 if parameter.name is not None:
116 attrs.append(('name', parameter.name))
117 if parameter.direction != 'in':
118 attrs.append(('direction', parameter.direction))
119 if parameter.transfer:
120 attrs.append(('transfer-ownership',
121 str(int(parameter.transfer))))
122 if parameter.allow_none:
123 attrs.append(('allow-none', '1'))
124 with self.tagcontext('parameter', attrs):
125 self._write_type(parameter.type)
127 def _write_type(self, ntype):
128 attrs = [('name', ntype.name)]
129 # FIXME: figure out if type references a basic type
130 # or a boxed/class/interface etc. and skip
131 # writing the ctype if the latter.
132 if ntype.ctype is not None:
133 attrs.append(('c:type', ntype.ctype))
134 self.write_tag('type', attrs)
136 def _write_sequence(self, sequence):
138 if sequence.transfer:
139 attrs.append(('transfer-ownership',
140 str(int(sequence.transfer))))
141 with self.tagcontext('sequence', attrs):
142 attrs = [('c:identifier', sequence.element_type)]
143 self.write_tag('element-type', attrs)
145 def _write_enum(self, enum):
146 attrs = [('name', enum.name),
147 ('c:type', enum.symbol)]
148 tag_name = 'enumeration'
149 if isinstance(enum, GLibEnum):
150 attrs.extend([('glib:type-name', enum.type_name),
151 ('glib:get-type', enum.get_type)])
152 if isinstance(enum, GLibFlags):
153 tag_name = 'bitfield'
155 with self.tagcontext(tag_name, attrs):
156 for member in enum.members:
157 self._write_member(member)
159 def _write_member(self, member):
160 attrs = [('name', member.name),
161 ('value', str(member.value)),
162 ('c:identifier', member.symbol)]
163 if isinstance(member, GLibEnumMember):
164 attrs.append(('glib:nick', member.nick))
165 self.write_tag('member', attrs)
167 def _write_class(self, node):
168 attrs = [('name', node.name),
169 ('c:type', node.ctype)]
170 if isinstance(node, Class):
172 if node.parent is not None:
173 attrs.append(('parent', node.parent))
175 tag_name = 'interface'
176 if isinstance(node, (GLibObject, GLibInterface)):
177 attrs.append(('glib:type-name', node.type_name))
179 attrs.append(('glib:get-type', node.get_type))
180 with self.tagcontext(tag_name, attrs):
181 if isinstance(node, Class):
182 for method in node.constructors:
183 self._write_constructor(method)
184 for method in node.methods:
185 self._write_method(method)
186 for prop in node.properties:
187 self._write_property(prop)
188 for field in node.fields:
189 self._write_field(field)
190 for signal in node.signals:
191 self._write_signal(signal)
193 def _write_boxed(self, boxed):
194 attrs = [('c:type', boxed.ctype),
195 ('glib:name', boxed.name),
196 ('glib:type-name', boxed.type_name),
197 ('glib:get-type', boxed.get_type)]
199 with self.tagcontext('glib:boxed', attrs):
200 for method in boxed.constructors:
201 self._write_constructor(method)
202 for method in boxed.methods:
203 self._write_method(method)
205 def _write_property(self, prop):
206 attrs = [('name', prop.name)]
207 with self.tagcontext('property', attrs):
208 self._write_type(prop.type)
210 def _write_callback(self, callback):
211 # FIXME: reuse _write_function
212 attrs = [('name', callback.name)]
213 with self.tagcontext('callback', attrs):
214 self._write_return_type(callback.retval)
215 self._write_parameters(callback.parameters)
217 def _write_record(self, record):
218 attrs = [('name', record.name),
219 ('c:type', record.symbol)]
221 with self.tagcontext('record', attrs):
222 for field in record.fields:
223 self._write_field(field)
225 self.write_tag('record', attrs)
227 def _write_field(self, field):
228 # FIXME: Just function
229 if isinstance(field, (Callback, Function)):
230 self._write_callback(field)
233 attrs = [('name', field.name)]
234 with self.tagcontext('field', attrs):
235 self._write_type(field.type)
237 def _write_signal(self, signal):
238 attrs = [('name', signal.name)]
239 with self.tagcontext('glib:signal', attrs):
240 self._write_return_type(signal.retval)
241 self._write_parameters(signal.parameters)