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, Union)
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, Union):
66 self._write_union(node)
67 elif isinstance(node, Member):
68 # FIXME: atk_misc_instance singleton
70 elif isinstance(node, Alias):
71 self._write_alias(node)
73 print 'WRITER: Unhandled node', node
75 def _write_alias(self, alias):
76 attrs = [('name', alias.name), ('target', alias.target)]
77 if alias.ctype is not None:
78 attrs.append(('c:type', alias.ctype))
79 self.write_tag('alias', attrs)
81 def _write_function(self, func, tag_name='function'):
82 attrs = [('name', func.name),
83 ('c:identifier', func.symbol)]
84 with self.tagcontext(tag_name, attrs):
85 self._write_return_type(func.retval)
86 self._write_parameters(func.parameters)
88 def _write_method(self, method):
89 self._write_function(method, tag_name='method')
91 def _write_constructor(self, method):
92 self._write_function(method, tag_name='constructor')
94 def _write_return_type(self, return_):
100 attrs.append(('transfer-ownership',
101 str(int(return_.transfer))))
102 with self.tagcontext('return-value', attrs):
103 self._write_type(return_.type)
105 def _write_parameters(self, parameters):
108 with self.tagcontext('parameters'):
109 for parameter in parameters:
110 self._write_parameter(parameter)
112 def _write_parameter(self, parameter):
114 if parameter.name is not None:
115 attrs.append(('name', parameter.name))
116 if parameter.direction != 'in':
117 attrs.append(('direction', parameter.direction))
118 if parameter.transfer:
119 attrs.append(('transfer-ownership',
120 str(int(parameter.transfer))))
121 if parameter.allow_none:
122 attrs.append(('allow-none', '1'))
123 with self.tagcontext('parameter', attrs):
124 self._write_type(parameter.type)
126 def _write_type(self, ntype, relation=None):
127 if isinstance(ntype, basestring):
131 typename = ntype.name
132 type_cname = ntype.ctype
133 attrs = [('name', typename)]
135 attrs.append(('relation', relation))
136 if isinstance(ntype, Sequence):
138 attrs.append(('transfer-ownership',
139 str(int(ntype.transfer))))
140 with self.tagcontext('type', attrs):
141 self._write_type(ntype.element_type, relation="element")
143 # FIXME: figure out if type references a basic type
144 # or a boxed/class/interface etc. and skip
145 # writing the ctype if the latter.
146 if type_cname is not None:
147 attrs.append(('c:type', type_cname))
148 self.write_tag('type', attrs)
150 def _write_enum(self, enum):
151 attrs = [('name', enum.name),
152 ('c:type', enum.symbol)]
153 tag_name = 'enumeration'
154 if isinstance(enum, GLibEnum):
155 attrs.extend([('glib:type-name', enum.type_name),
156 ('glib:get-type', enum.get_type)])
157 if isinstance(enum, GLibFlags):
158 tag_name = 'bitfield'
160 with self.tagcontext(tag_name, attrs):
161 for member in enum.members:
162 self._write_member(member)
164 def _write_member(self, member):
165 attrs = [('name', member.name),
166 ('value', str(member.value)),
167 ('c:identifier', member.symbol)]
168 if isinstance(member, GLibEnumMember):
169 attrs.append(('glib:nick', member.nick))
170 self.write_tag('member', attrs)
172 def _write_class(self, node):
173 attrs = [('name', node.name),
174 ('c:type', node.ctype)]
175 if isinstance(node, Class):
177 if node.parent is not None:
178 attrs.append(('parent', node.parent))
180 tag_name = 'interface'
181 if isinstance(node, (GLibObject, GLibInterface)):
182 attrs.append(('glib:type-name', node.type_name))
184 attrs.append(('glib:get-type', node.get_type))
185 with self.tagcontext(tag_name, attrs):
186 if isinstance(node, Class):
187 for method in node.constructors:
188 self._write_constructor(method)
189 for method in node.methods:
190 self._write_method(method)
191 for prop in node.properties:
192 self._write_property(prop)
193 for field in node.fields:
194 self._write_field(field)
195 for signal in node.signals:
196 self._write_signal(signal)
198 def _write_boxed(self, boxed):
199 attrs = [('c:type', boxed.ctype),
200 ('glib:name', boxed.name),
201 ('glib:type-name', boxed.type_name),
202 ('glib:get-type', boxed.get_type)]
204 with self.tagcontext('glib:boxed', attrs):
205 for method in boxed.constructors:
206 self._write_constructor(method)
207 for method in boxed.methods:
208 self._write_method(method)
210 def _write_property(self, prop):
211 attrs = [('name', prop.name)]
212 with self.tagcontext('property', attrs):
213 self._write_type(prop.type)
215 def _write_callback(self, callback):
216 # FIXME: reuse _write_function
217 attrs = [('name', callback.name), ('c:type', callback.ctype)]
218 with self.tagcontext('callback', attrs):
219 self._write_return_type(callback.retval)
220 self._write_parameters(callback.parameters)
222 def _write_record(self, record):
223 attrs = [('name', record.name),
224 ('c:type', record.symbol)]
226 with self.tagcontext('record', attrs):
227 for field in record.fields:
228 self._write_field(field)
230 self.write_tag('record', attrs)
232 def _write_union(self, union):
233 attrs = [('name', union.name),
234 ('c:type', union.symbol)]
236 with self.tagcontext('union', attrs):
237 for field in union.fields:
238 self._write_field(field)
240 self.write_tag('union', attrs)
242 def _write_field(self, field):
243 # FIXME: Just function
244 if isinstance(field, (Callback, Function)):
245 self._write_callback(field)
248 attrs = [('name', field.name)]
249 with self.tagcontext('field', attrs):
250 self._write_type(field.type)
252 def _write_signal(self, signal):
253 attrs = [('name', signal.name)]
254 with self.tagcontext('glib:signal', attrs):
255 self._write_return_type(signal.retval)
256 self._write_parameters(signal.parameters)