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)
24 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
25 GLibFlags, GLibObject, GLibInterface)
26 from .xmlwriter import XMLWriter
29 class GIRWriter(XMLWriter):
30 def __init__(self, namespace, nodes):
31 super(GIRWriter, self).__init__()
32 self._write_repository(namespace, nodes)
34 def _write_repository(self, namespace, nodes):
37 ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
38 ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
39 ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
41 with self.tagcontext('repository', attrs):
42 self._write_namespace(namespace, nodes)
44 def _write_namespace(self, namespace, nodes):
45 with self.tagcontext('namespace', [('name', namespace)]):
47 self._write_node(node)
49 def _write_node(self, node):
50 if isinstance(node, Function):
51 self._write_function(node)
52 elif isinstance(node, Enum):
53 self._write_enum(node)
54 elif isinstance(node, (Class, Interface)):
55 self._write_class(node)
56 elif isinstance(node, GLibBoxed):
57 self._write_boxed(node)
58 elif isinstance(node, Callback):
59 self._write_callback(node)
61 print 'WRITER: Unhandled node', node
63 def _write_function(self, func, tag_name='function'):
64 attrs = [('name', func.name),
65 ('c:identifier', func.symbol)]
66 with self.tagcontext(tag_name, attrs):
67 self._write_return_type(func.retval)
68 self._write_parameters(func.parameters)
70 def _write_method(self, method):
71 self._write_function(method, tag_name='method')
73 def _write_constructor(self, method):
74 self._write_function(method, tag_name='constructor')
76 def _write_return_type(self, return_):
79 with self.tagcontext('return-value'):
80 if isinstance(return_.type, Sequence):
81 self._write_sequence(return_.type)
83 self._write_type(return_.type)
85 def _write_parameters(self, parameters):
88 with self.tagcontext('parameters'):
89 for parameter in parameters:
90 self._write_parameter(parameter)
92 def _write_parameter(self, parameter):
93 attrs = [('name', parameter.name)]
94 if parameter.direction != 'in':
95 attrs.append(('direction', parameter.direction))
96 if parameter.transfer != 'none':
97 attrs.append(('transfer', parameter.transfer))
98 with self.tagcontext('parameter', attrs):
99 self._write_type(parameter.type)
101 def _write_type(self, type):
102 attrs = [('name', type.name)]
103 # FIXME: figure out if type references a basic type
104 # or a boxed/class/interface etc. and skip
105 # writing the ctype if the latter.
107 attrs.append(('c:type', type.ctype))
108 self.write_tag('type', attrs)
110 def _write_sequence(self, sequence):
111 attrs = [('c:owner', sequence.cowner)]
112 with self.tagcontext('sequence', attrs):
113 attrs = [('c:identifier', sequence.element_type)]
114 self.write_tag('element-type', attrs)
116 def _write_enum(self, enum):
117 attrs = [('name', enum.name),
118 ('c:type', enum.ctype)]
119 tag_name = 'enumeration'
120 if isinstance(enum, GLibEnum):
121 attrs.extend([('glib:type-name', enum.type_name),
122 ('glib:get-type', enum.get_type)])
123 if isinstance(enum, GLibFlags):
124 tag_name = 'bitfield'
126 with self.tagcontext(tag_name, attrs):
127 for member in enum.members:
128 self._write_member(member)
130 def _write_member(self, member):
131 attrs = [('name', member.name),
132 ('value', str(member.value))]
133 if isinstance(member, GLibEnumMember):
134 attrs.append(('glib:nick', member.nick))
135 self.write_tag('member', attrs)
137 def _write_class(self, node):
138 attrs = [('name', node.name),
139 ('c:type', node.ctype)]
140 if isinstance(node, Class):
142 if node.parent is not None:
143 attrs.append(('parent', node.parent))
145 tag_name = 'interface'
146 if isinstance(node, (GLibObject, GLibInterface)):
147 attrs.append(('glib:type-name', node.type_name))
148 attrs.append(('glib:get-type', node.get_type))
149 with self.tagcontext(tag_name, attrs):
150 if isinstance(node, Class):
151 for method in node.constructors:
152 self._write_constructor(method)
153 for method in node.methods:
154 self._write_method(method)
155 for prop in node.properties:
156 self._write_property(prop)
158 def _write_boxed(self, boxed):
159 attrs = [('c:type', boxed.ctype),
160 ('glib:name', boxed.name),
161 ('glib:type-name', boxed.type_name),
162 ('glib:get-type', boxed.get_type)]
164 with self.tagcontext('glib:boxed', attrs):
165 for method in boxed.constructors:
166 self._write_constructor(method)
167 for method in boxed.methods:
168 self._write_method(method)
170 def _write_property(self, prop):
171 attrs = [('name', prop.name)]
172 with self.tagcontext('property', attrs):
173 self._write_type(prop.type)
175 def _write_callback(self, callback):
176 attrs = [('name', callback.name)]
177 with self.tagcontext('callback', attrs):
178 self._write_return_type(callback.retval)
179 self._write_parameters(callback.parameters)