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
25 from .ast import (Callback, Class, Enum, Function, Interface, Member,
26 Sequence, Struct, Alias, Union)
27 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
28 GLibFlags, GLibObject, GLibInterface)
29 from .xmlwriter import XMLWriter
32 class GIRWriter(XMLWriter):
34 def __init__(self, namespace, shlib, includes):
35 super(GIRWriter, self).__init__()
36 self._write_repository(namespace, shlib, includes)
38 def _write_repository(self, namespace, shlib, includes=set()):
41 ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
42 ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
43 ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
45 with self.tagcontext('repository', attrs):
46 for include in includes:
47 self._write_include(include)
48 self._write_namespace(namespace, shlib)
50 def _write_include(self, include):
51 attrs = [('name', include)]
52 self.write_tag('include', attrs)
54 def _write_namespace(self, namespace, shlib):
55 attrs = [('name', namespace.name),
56 ('shared-library', os.path.basename(shlib))]
57 with self.tagcontext('namespace', attrs):
58 for node in namespace.nodes:
59 self._write_node(node)
61 def _write_node(self, node):
62 if isinstance(node, Function):
63 self._write_function(node)
64 elif isinstance(node, Enum):
65 self._write_enum(node)
66 elif isinstance(node, (Class, Interface)):
67 self._write_class(node)
68 elif isinstance(node, GLibBoxed):
69 self._write_boxed(node)
70 elif isinstance(node, Callback):
71 self._write_callback(node)
72 elif isinstance(node, Struct):
73 self._write_record(node)
74 elif isinstance(node, Union):
75 self._write_union(node)
76 elif isinstance(node, Member):
77 # FIXME: atk_misc_instance singleton
79 elif isinstance(node, Alias):
80 self._write_alias(node)
82 print 'WRITER: Unhandled node', node
84 def _write_alias(self, alias):
85 attrs = [('name', alias.name), ('target', alias.target)]
86 if alias.ctype is not None:
87 attrs.append(('c:type', alias.ctype))
88 self.write_tag('alias', attrs)
90 def _write_function(self, func, tag_name='function'):
91 attrs = [('name', func.name),
92 ('c:identifier', func.symbol)]
93 with self.tagcontext(tag_name, attrs):
94 self._write_return_type(func.retval)
95 self._write_parameters(func.parameters)
97 def _write_method(self, method):
98 self._write_function(method, tag_name='method')
100 def _write_constructor(self, method):
101 self._write_function(method, tag_name='constructor')
103 def _write_return_type(self, return_):
109 attrs.append(('transfer-ownership',
110 str(int(return_.transfer))))
111 with self.tagcontext('return-value', attrs):
112 self._write_type(return_.type)
114 def _write_parameters(self, parameters):
117 with self.tagcontext('parameters'):
118 for parameter in parameters:
119 self._write_parameter(parameter)
121 def _write_parameter(self, parameter):
123 if parameter.name is not None:
124 attrs.append(('name', parameter.name))
125 if parameter.direction != 'in':
126 attrs.append(('direction', parameter.direction))
127 if parameter.transfer:
128 attrs.append(('transfer-ownership',
129 str(int(parameter.transfer))))
130 if parameter.allow_none:
131 attrs.append(('allow-none', '1'))
132 with self.tagcontext('parameter', attrs):
133 self._write_type(parameter.type)
135 def _write_type(self, ntype, relation=None):
136 if isinstance(ntype, basestring):
140 typename = ntype.name
141 type_cname = ntype.ctype
142 attrs = [('name', typename)]
144 attrs.append(('relation', relation))
145 if isinstance(ntype, Sequence):
147 attrs.append(('transfer-ownership',
148 str(int(ntype.transfer))))
149 with self.tagcontext('type', attrs):
150 self._write_type(ntype.element_type, relation="element")
152 # FIXME: figure out if type references a basic type
153 # or a boxed/class/interface etc. and skip
154 # writing the ctype if the latter.
155 if type_cname is not None:
156 attrs.append(('c:type', type_cname))
157 self.write_tag('type', attrs)
159 def _write_enum(self, enum):
160 attrs = [('name', enum.name),
161 ('c:type', enum.symbol)]
162 tag_name = 'enumeration'
163 if isinstance(enum, GLibEnum):
164 attrs.extend([('glib:type-name', enum.type_name),
165 ('glib:get-type', enum.get_type)])
166 if isinstance(enum, GLibFlags):
167 tag_name = 'bitfield'
169 with self.tagcontext(tag_name, attrs):
170 for member in enum.members:
171 self._write_member(member)
173 def _write_member(self, member):
174 attrs = [('name', member.name),
175 ('value', str(member.value)),
176 ('c:identifier', member.symbol)]
177 if isinstance(member, GLibEnumMember):
178 attrs.append(('glib:nick', member.nick))
179 self.write_tag('member', attrs)
181 def _write_class(self, node):
182 attrs = [('name', node.name),
183 ('c:type', node.ctype)]
184 if isinstance(node, Class):
186 if node.parent is not None:
187 attrs.append(('parent', node.parent))
189 tag_name = 'interface'
190 if isinstance(node, (GLibObject, GLibInterface)):
191 attrs.append(('glib:type-name', node.type_name))
193 attrs.append(('glib:get-type', node.get_type))
194 with self.tagcontext(tag_name, attrs):
195 if isinstance(node, Class):
196 for method in node.constructors:
197 self._write_constructor(method)
198 for method in node.methods:
199 self._write_method(method)
200 for prop in node.properties:
201 self._write_property(prop)
202 for field in node.fields:
203 self._write_field(field)
204 for signal in node.signals:
205 self._write_signal(signal)
207 def _write_boxed(self, boxed):
208 attrs = [('c:type', boxed.ctype),
209 ('glib:name', boxed.name),
210 ('glib:type-name', boxed.type_name),
211 ('glib:get-type', boxed.get_type)]
213 with self.tagcontext('glib:boxed', attrs):
214 for method in boxed.constructors:
215 self._write_constructor(method)
216 for method in boxed.methods:
217 self._write_method(method)
219 def _write_property(self, prop):
220 attrs = [('name', prop.name)]
221 with self.tagcontext('property', attrs):
222 self._write_type(prop.type)
224 def _write_callback(self, callback):
225 # FIXME: reuse _write_function
226 attrs = [('name', callback.name), ('c:type', callback.ctype)]
227 with self.tagcontext('callback', attrs):
228 self._write_return_type(callback.retval)
229 self._write_parameters(callback.parameters)
231 def _write_record(self, record):
232 attrs = [('name', record.name),
233 ('c:type', record.symbol)]
235 with self.tagcontext('record', attrs):
236 for field in record.fields:
237 self._write_field(field)
239 self.write_tag('record', attrs)
241 def _write_union(self, union):
242 attrs = [('name', union.name),
243 ('c:type', union.symbol)]
245 with self.tagcontext('union', attrs):
246 for field in union.fields:
247 self._write_field(field)
249 self.write_tag('union', attrs)
251 def _write_field(self, field):
252 # FIXME: Just function
253 if isinstance(field, (Callback, Function)):
254 self._write_callback(field)
257 attrs = [('name', field.name)]
258 with self.tagcontext('field', attrs):
259 self._write_type(field.type)
261 def _write_signal(self, signal):
262 attrs = [('name', signal.name)]
263 with self.tagcontext('glib:signal', attrs):
264 self._write_return_type(signal.retval)
265 self._write_parameters(signal.parameters)