Rename treebuilder to transformer and gobjectreebuilder to
[gnome.gobject-introspection] / giscanner / girwriter.py
1 # -*- Mode: Python -*-
2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008  Johan Dahlin
4 #
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.
9 #
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.
14 #
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  02110-1301, USA.
18 #
19
20 from __future__ import with_statement
21
22 from .glibtransformer import (GLibBoxed, GLibEnum, GLibEnumMember,
23                               GLibFlags, GLibObject, GLibInterface)
24 from .transformer import Callback, Class, Enum, Function, Interface
25 from .xmlwriter import XMLWriter
26
27
28 class GIRWriter(XMLWriter):
29     def __init__(self, namespace, nodes):
30         super(GIRWriter, self).__init__()
31         self._write_repository(namespace, nodes)
32
33     def _write_repository(self, namespace, nodes):
34         attrs = [
35             ('version', '1.0'),
36             ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
37             ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
38             ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
39             ]
40         with self.tagcontext('repository', attrs):
41             self._write_namespace(namespace, nodes)
42
43     def _write_namespace(self, namespace, nodes):
44         with self.tagcontext('namespace', [('name', namespace)]):
45             for node in nodes:
46                 self._write_node(node)
47
48     def _write_node(self, node):
49         if isinstance(node, Function):
50             self._write_function(node)
51         elif isinstance(node, Enum):
52             self._write_enum(node)
53         elif isinstance(node, (Class, Interface)):
54             self._write_class(node)
55         elif isinstance(node, GLibBoxed):
56             self._write_boxed(node)
57         elif isinstance(node, Callback):
58             self._write_callback(node)
59         else:
60             print 'WRITER: Unhandled node', node
61
62     def _write_function(self, func, tag_name='function'):
63         attrs = [('name', func.name),
64                  ('c:identifier', func.symbol)]
65         with self.tagcontext(tag_name, attrs):
66             self._write_return_type(func.retval)
67             self._write_parameters(func.parameters)
68
69     def _write_method(self, method):
70         self._write_function(method, tag_name='method')
71
72     def _write_constructor(self, method):
73         self._write_function(method, tag_name='constructor')
74
75     def _write_return_type(self, return_):
76         if not return_:
77             return
78         with self.tagcontext('return-values'):
79             with self.tagcontext('return-value'):
80                 attrs = [('name', return_.type)]
81                 if return_.transfer != 'none':
82                     attrs.append(('transfer', return_.transfer))
83                 self.write_tag('type', attrs)
84
85     def _write_parameters(self, parameters):
86         if not parameters:
87             return
88         with self.tagcontext('parameters'):
89             for parameter in parameters:
90                 self._write_parameter(parameter)
91
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('parameters', attrs):
99             self.write_tag('type', [('name', parameter.type)])
100
101     def _write_enum(self, enum):
102         attrs = [('name', enum.name)]
103         tag_name = 'enumeration'
104         if isinstance(enum, GLibEnum):
105             attrs.extend([('glib:type-name', enum.type_name),
106                           ('glib:get-type', enum.get_type)])
107             if isinstance(enum, GLibFlags):
108                 tag_name = 'bitfield'
109
110         with self.tagcontext(tag_name, attrs):
111             for member in enum.members:
112                 self._write_member(member)
113
114     def _write_member(self, member):
115         attrs = [('name', member.name),
116                  ('value', str(member.value))]
117         if isinstance(member, GLibEnumMember):
118             attrs.append(('glib:nick', member.nick))
119         self.write_tag('member', attrs)
120
121     def _write_class(self, node):
122         attrs = [('name', node.name)]
123         if isinstance(node, Class):
124             tag_name = 'class'
125             if node.parent is not None:
126                 attrs.append(('parent', node.parent))
127         else:
128             tag_name = 'interface'
129         if isinstance(node, (GLibObject, GLibInterface)):
130             attrs.append(('glib:type-name', node.type_name))
131             attrs.append(('glib:get-type', node.get_type))
132         with self.tagcontext(tag_name, attrs):
133             if isinstance(node, Class):
134                 for method in node.constructors:
135                     self._write_constructor(method)
136             for method in node.methods:
137                 self._write_method(method)
138             for prop in node.properties:
139                 self._write_property(prop)
140
141     def _write_boxed(self, boxed):
142         attrs = [('glib:name', boxed.name),
143                  ('glib:type-name', boxed.type_name),
144                  ('glib:get-type', boxed.get_type)]
145
146         with self.tagcontext('glib:boxed', attrs):
147             for method in boxed.constructors:
148                 self._write_constructor(method)
149             for method in boxed.methods:
150                 self._write_method(method)
151
152     def _write_property(self, prop):
153         attrs = [('name', prop.name),
154                  ('prop', prop.type)]
155         self.write_tag('property', attrs)
156
157     def _write_callback(self, callback):
158         attrs = [('name', callback.name)]
159         with self.tagcontext('callback', attrs):
160             self._write_return_type(callback.retval)
161             self._write_parameters(callback.parameters)