Write property.type as a child node.
[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 .ast import (Callback, Class, Enum, Function, Interface, Sequence)
23 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
24                       GLibFlags, GLibObject, GLibInterface)
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         attrs = [('c:identifer', return_.type.name)]
79         with self.tagcontext('return-value', attrs):
80             if isinstance(return_.type, Sequence):
81                 self._write_sequence(return_.type)
82             else:
83                 self._write_type(return_.type)
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('parameter', attrs):
99             self._write_type(parameter.type)
100
101     def _write_type(self, type):
102         self.write_tag('type', [('name', type.name)])
103
104     def _write_sequence(self, sequence):
105         attrs = [('c:owner', sequence.cowner)]
106         with self.tagcontext('sequence', attrs):
107             attrs = [('c:identifier', sequence.element_type)]
108             self.write_tag('element-type', attrs)
109
110     def _write_enum(self, enum):
111         attrs = [('name', enum.name)]
112         tag_name = 'enumeration'
113         if isinstance(enum, GLibEnum):
114             attrs.extend([('glib:type-name', enum.type_name),
115                           ('glib:get-type', enum.get_type)])
116             if isinstance(enum, GLibFlags):
117                 tag_name = 'bitfield'
118
119         with self.tagcontext(tag_name, attrs):
120             for member in enum.members:
121                 self._write_member(member)
122
123     def _write_member(self, member):
124         attrs = [('name', member.name),
125                  ('value', str(member.value))]
126         if isinstance(member, GLibEnumMember):
127             attrs.append(('glib:nick', member.nick))
128         self.write_tag('member', attrs)
129
130     def _write_class(self, node):
131         attrs = [('name', node.name)]
132         if isinstance(node, Class):
133             tag_name = 'class'
134             if node.parent is not None:
135                 attrs.append(('parent', node.parent))
136         else:
137             tag_name = 'interface'
138         if isinstance(node, (GLibObject, GLibInterface)):
139             attrs.append(('glib:type-name', node.type_name))
140             attrs.append(('glib:get-type', node.get_type))
141         with self.tagcontext(tag_name, attrs):
142             if isinstance(node, Class):
143                 for method in node.constructors:
144                     self._write_constructor(method)
145             for method in node.methods:
146                 self._write_method(method)
147             for prop in node.properties:
148                 self._write_property(prop)
149
150     def _write_boxed(self, boxed):
151         attrs = [('glib:name', boxed.name),
152                  ('glib:type-name', boxed.type_name),
153                  ('glib:get-type', boxed.get_type)]
154
155         with self.tagcontext('glib:boxed', attrs):
156             for method in boxed.constructors:
157                 self._write_constructor(method)
158             for method in boxed.methods:
159                 self._write_method(method)
160
161     def _write_property(self, prop):
162         attrs = [('name', prop.name)]
163         with self.tagcontext('property', attrs):
164             self._write_type(prop.type)
165
166     def _write_callback(self, callback):
167         attrs = [('name', callback.name)]
168         with self.tagcontext('callback', attrs):
169             self._write_return_type(callback.retval)
170             self._write_parameters(callback.parameters)