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):
35 super(GIRWriter, self).__init__()
36 self._write_repository(namespace, shlib)
38 def _write_repository(self, namespace, shlib):
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 self._write_namespace(namespace, shlib)
48 def _write_namespace(self, namespace, shlib):
49 attrs = [('name', namespace.name),
50 ('shared-library', os.path.basename(shlib))]
51 with self.tagcontext('namespace', attrs):
52 for node in namespace.nodes:
53 self._write_node(node)
55 def _write_node(self, node):
56 if isinstance(node, Function):
57 self._write_function(node)
58 elif isinstance(node, Enum):
59 self._write_enum(node)
60 elif isinstance(node, (Class, Interface)):
61 self._write_class(node)
62 elif isinstance(node, GLibBoxed):
63 self._write_boxed(node)
64 elif isinstance(node, Callback):
65 self._write_callback(node)
66 elif isinstance(node, Struct):
67 self._write_record(node)
68 elif isinstance(node, Union):
69 self._write_union(node)
70 elif isinstance(node, Member):
71 # FIXME: atk_misc_instance singleton
73 elif isinstance(node, Alias):
74 self._write_alias(node)
76 print 'WRITER: Unhandled node', node
78 def _write_alias(self, alias):
79 attrs = [('name', alias.name), ('target', alias.target)]
80 if alias.ctype is not None:
81 attrs.append(('c:type', alias.ctype))
82 self.write_tag('alias', attrs)
84 def _write_function(self, func, tag_name='function'):
85 attrs = [('name', func.name),
86 ('c:identifier', func.symbol)]
87 with self.tagcontext(tag_name, attrs):
88 self._write_return_type(func.retval)
89 self._write_parameters(func.parameters)
91 def _write_method(self, method):
92 self._write_function(method, tag_name='method')
94 def _write_constructor(self, method):
95 self._write_function(method, tag_name='constructor')
97 def _write_return_type(self, return_):
103 attrs.append(('transfer-ownership',
104 str(int(return_.transfer))))
105 with self.tagcontext('return-value', attrs):
106 self._write_type(return_.type)
108 def _write_parameters(self, parameters):
111 with self.tagcontext('parameters'):
112 for parameter in parameters:
113 self._write_parameter(parameter)
115 def _write_parameter(self, parameter):
117 if parameter.name is not None:
118 attrs.append(('name', parameter.name))
119 if parameter.direction != 'in':
120 attrs.append(('direction', parameter.direction))
121 if parameter.transfer:
122 attrs.append(('transfer-ownership',
123 str(int(parameter.transfer))))
124 if parameter.allow_none:
125 attrs.append(('allow-none', '1'))
126 with self.tagcontext('parameter', attrs):
127 self._write_type(parameter.type)
129 def _write_type(self, ntype, relation=None):
130 if isinstance(ntype, basestring):
134 typename = ntype.name
135 type_cname = ntype.ctype
136 attrs = [('name', typename)]
138 attrs.append(('relation', relation))
139 if isinstance(ntype, Sequence):
141 attrs.append(('transfer-ownership',
142 str(int(ntype.transfer))))
143 with self.tagcontext('type', attrs):
144 self._write_type(ntype.element_type, relation="element")
146 # FIXME: figure out if type references a basic type
147 # or a boxed/class/interface etc. and skip
148 # writing the ctype if the latter.
149 if type_cname is not None:
150 attrs.append(('c:type', type_cname))
151 self.write_tag('type', attrs)
153 def _write_enum(self, enum):
154 attrs = [('name', enum.name),
155 ('c:type', enum.symbol)]
156 tag_name = 'enumeration'
157 if isinstance(enum, GLibEnum):
158 attrs.extend([('glib:type-name', enum.type_name),
159 ('glib:get-type', enum.get_type)])
160 if isinstance(enum, GLibFlags):
161 tag_name = 'bitfield'
163 with self.tagcontext(tag_name, attrs):
164 for member in enum.members:
165 self._write_member(member)
167 def _write_member(self, member):
168 attrs = [('name', member.name),
169 ('value', str(member.value)),
170 ('c:identifier', member.symbol)]
171 if isinstance(member, GLibEnumMember):
172 attrs.append(('glib:nick', member.nick))
173 self.write_tag('member', attrs)
175 def _write_class(self, node):
176 attrs = [('name', node.name),
177 ('c:type', node.ctype)]
178 if isinstance(node, Class):
180 if node.parent is not None:
181 attrs.append(('parent', node.parent))
183 tag_name = 'interface'
184 if isinstance(node, (GLibObject, GLibInterface)):
185 attrs.append(('glib:type-name', node.type_name))
187 attrs.append(('glib:get-type', node.get_type))
188 with self.tagcontext(tag_name, attrs):
189 if isinstance(node, Class):
190 for method in node.constructors:
191 self._write_constructor(method)
192 for method in node.methods:
193 self._write_method(method)
194 for prop in node.properties:
195 self._write_property(prop)
196 for field in node.fields:
197 self._write_field(field)
198 for signal in node.signals:
199 self._write_signal(signal)
201 def _write_boxed(self, boxed):
202 attrs = [('c:type', boxed.ctype),
203 ('glib:name', boxed.name),
204 ('glib:type-name', boxed.type_name),
205 ('glib:get-type', boxed.get_type)]
207 with self.tagcontext('glib:boxed', attrs):
208 for method in boxed.constructors:
209 self._write_constructor(method)
210 for method in boxed.methods:
211 self._write_method(method)
213 def _write_property(self, prop):
214 attrs = [('name', prop.name)]
215 with self.tagcontext('property', attrs):
216 self._write_type(prop.type)
218 def _write_callback(self, callback):
219 # FIXME: reuse _write_function
220 attrs = [('name', callback.name), ('c:type', callback.ctype)]
221 with self.tagcontext('callback', attrs):
222 self._write_return_type(callback.retval)
223 self._write_parameters(callback.parameters)
225 def _write_record(self, record):
226 attrs = [('name', record.name),
227 ('c:type', record.symbol)]
229 with self.tagcontext('record', attrs):
230 for field in record.fields:
231 self._write_field(field)
233 self.write_tag('record', attrs)
235 def _write_union(self, union):
236 attrs = [('name', union.name),
237 ('c:type', union.symbol)]
239 with self.tagcontext('union', attrs):
240 for field in union.fields:
241 self._write_field(field)
243 self.write_tag('union', attrs)
245 def _write_field(self, field):
246 # FIXME: Just function
247 if isinstance(field, (Callback, Function)):
248 self._write_callback(field)
251 attrs = [('name', field.name)]
252 with self.tagcontext('field', attrs):
253 self._write_type(field.type)
255 def _write_signal(self, signal):
256 attrs = [('name', signal.name)]
257 with self.tagcontext('glib:signal', attrs):
258 self._write_return_type(signal.retval)
259 self._write_parameters(signal.parameters)