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, Sequence,
25 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
26 GLibFlags, GLibObject, GLibInterface)
27 from .xmlwriter import XMLWriter
30 class GIRWriter(XMLWriter):
31 def __init__(self, namespace, nodes):
32 super(GIRWriter, self).__init__()
33 self._write_repository(namespace, nodes)
35 def _write_repository(self, namespace, nodes):
38 ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
39 ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
40 ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
42 with self.tagcontext('repository', attrs):
43 self._write_namespace(namespace, nodes)
45 def _write_namespace(self, namespace, nodes):
46 with self.tagcontext('namespace', [('name', namespace)]):
48 self._write_node(node)
50 def _write_node(self, node):
51 if isinstance(node, Function):
52 self._write_function(node)
53 elif isinstance(node, Enum):
54 self._write_enum(node)
55 elif isinstance(node, (Class, Interface)):
56 self._write_class(node)
57 elif isinstance(node, GLibBoxed):
58 self._write_boxed(node)
59 elif isinstance(node, Callback):
60 self._write_callback(node)
61 elif isinstance(node, Struct):
62 self._write_record(node)
64 print 'WRITER: Unhandled node', node
66 def _write_function(self, func, tag_name='function'):
67 attrs = [('name', func.name),
68 ('c:identifier', func.symbol)]
69 with self.tagcontext(tag_name, attrs):
70 self._write_return_type(func.retval)
71 self._write_parameters(func.parameters)
73 def _write_method(self, method):
74 self._write_function(method, tag_name='method')
76 def _write_constructor(self, method):
77 self._write_function(method, tag_name='constructor')
79 def _write_return_type(self, return_):
82 with self.tagcontext('return-value'):
83 if isinstance(return_.type, Sequence):
84 self._write_sequence(return_.type)
86 self._write_type(return_.type)
88 def _write_parameters(self, parameters):
91 with self.tagcontext('parameters'):
92 for parameter in parameters:
93 self._write_parameter(parameter)
95 def _write_parameter(self, parameter):
96 attrs = [('name', parameter.name)]
97 if parameter.direction != 'in':
98 attrs.append(('direction', parameter.direction))
99 if parameter.transfer != 'none':
100 attrs.append(('transfer', parameter.transfer))
101 with self.tagcontext('parameter', attrs):
102 self._write_type(parameter.type)
104 def _write_type(self, type):
105 attrs = [('name', type.name)]
106 # FIXME: figure out if type references a basic type
107 # or a boxed/class/interface etc. and skip
108 # writing the ctype if the latter.
110 attrs.append(('c:type', type.ctype))
111 self.write_tag('type', attrs)
113 def _write_sequence(self, sequence):
114 attrs = [('c:owner', sequence.cowner)]
115 with self.tagcontext('sequence', attrs):
116 attrs = [('c:identifier', sequence.element_type)]
117 self.write_tag('element-type', attrs)
119 def _write_enum(self, enum):
120 attrs = [('name', enum.name),
121 ('c:type', enum.ctype)]
122 tag_name = 'enumeration'
123 if isinstance(enum, GLibEnum):
124 attrs.extend([('glib:type-name', enum.type_name),
125 ('glib:get-type', enum.get_type)])
126 if isinstance(enum, GLibFlags):
127 tag_name = 'bitfield'
129 with self.tagcontext(tag_name, attrs):
130 for member in enum.members:
131 self._write_member(member)
133 def _write_member(self, member):
134 attrs = [('name', member.name),
135 ('value', str(member.value))]
136 if isinstance(member, GLibEnumMember):
137 attrs.append(('glib:nick', member.nick))
138 self.write_tag('member', attrs)
140 def _write_class(self, node):
141 attrs = [('name', node.name),
142 ('c:type', node.ctype)]
143 if isinstance(node, Class):
145 if node.parent is not None:
146 attrs.append(('parent', node.parent))
148 tag_name = 'interface'
149 if isinstance(node, (GLibObject, GLibInterface)):
150 attrs.append(('glib:type-name', node.type_name))
151 attrs.append(('glib:get-type', node.get_type))
152 with self.tagcontext(tag_name, attrs):
153 if isinstance(node, Class):
154 for method in node.constructors:
155 self._write_constructor(method)
156 for method in node.methods:
157 self._write_method(method)
158 for prop in node.properties:
159 self._write_property(prop)
160 for field in node.fields:
161 self._write_field(field)
162 for signal in node.signals:
163 self._write_signal(signal)
165 def _write_boxed(self, boxed):
166 attrs = [('c:type', boxed.ctype),
167 ('glib:name', boxed.name),
168 ('glib:type-name', boxed.type_name),
169 ('glib:get-type', boxed.get_type)]
171 with self.tagcontext('glib:boxed', attrs):
172 for method in boxed.constructors:
173 self._write_constructor(method)
174 for method in boxed.methods:
175 self._write_method(method)
177 def _write_property(self, prop):
178 attrs = [('name', prop.name)]
179 with self.tagcontext('property', attrs):
180 self._write_type(prop.type)
182 def _write_callback(self, callback):
183 attrs = [('name', callback.name)]
184 with self.tagcontext('callback', attrs):
185 self._write_return_type(callback.retval)
186 self._write_parameters(callback.parameters)
188 def _write_record(self, record):
189 attrs = [('name', record.name),
190 ('c:type', record.symbol)]
192 with self.tagcontext('record', attrs):
193 for field in record.fields:
194 self._write_field(field)
196 self.write_tag('record', attrs)
198 def _write_field(self, field):
199 if isinstance(field, Callback):
200 self._write_callback(field)
203 attrs = [('name', field.name),
204 ('type', str(field.type))]
205 self.write_tag('field', attrs)
207 def _write_signal(self, signal):
208 attrs = [('name', signal.name)]
209 with self.tagcontext('glib:signal', attrs):
210 self._write_return_type(signal.retval)
211 self._write_parameters(signal.parameters)