Add support for source/header annotations.
[gnome.gobject-introspection] / giscanner / girwriter.py
1 from __future__ import with_statement
2
3 from .gobjecttreebuilder import (GLibBoxed, GLibEnum, GLibEnumMember,
4                                  GLibFlags, GLibObject, GLibInterface)
5 from .treebuilder import Callback, Class, Enum, Function, Interface
6 from .xmlwriter import XMLWriter
7
8
9 class GIRWriter(XMLWriter):
10     def __init__(self, namespace, nodes):
11         super(GIRWriter, self).__init__()
12         self._write_repository(namespace, nodes)
13
14     def _write_repository(self, namespace, nodes):
15         attrs = [
16             ('version', '1.0'),
17             ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
18             ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
19             ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
20             ]
21         with self.tagcontext('repository', attrs):
22             self._write_namespace(namespace, nodes)
23
24     def _write_namespace(self, namespace, nodes):
25         with self.tagcontext('namespace', [('name', namespace)]):
26             for node in nodes:
27                 self._write_node(node)
28
29     def _write_node(self, node):
30         if isinstance(node, Function):
31             self._write_function(node)
32         elif isinstance(node, Enum):
33             self._write_enum(node)
34         elif isinstance(node, (Class, Interface)):
35             self._write_class(node)
36         elif isinstance(node, GLibBoxed):
37             self._write_boxed(node)
38         elif isinstance(node, Callback):
39             self._write_callback(node)
40         else:
41             print 'WRITER: Unhandled node', node
42
43     def _write_function(self, func, tag_name='function'):
44         attrs = [('name', func.name),
45                  ('c:identifier', func.symbol)]
46         with self.tagcontext(tag_name, attrs):
47             self._write_return_type(func.retval)
48             self._write_parameters(func.parameters)
49
50     def _write_method(self, method):
51         self._write_function(method, tag_name='method')
52
53     def _write_constructor(self, method):
54         self._write_function(method, tag_name='constructor')
55
56     def _write_return_type(self, return_):
57         if not return_:
58             return
59         with self.tagcontext('return-values'):
60             with self.tagcontext('return-value'):
61                 attrs = [('name', return_.type)]
62                 if return_.transfer != 'none':
63                     attrs.append(('transfer', return_.transfer))
64                 self.write_tag('type', attrs)
65
66     def _write_parameters(self, parameters):
67         if not parameters:
68             return
69         with self.tagcontext('parameters'):
70             for parameter in parameters:
71                 self._write_parameter(parameter)
72
73     def _write_parameter(self, parameter):
74         attrs = [('name', parameter.name)]
75         if parameter.direction != 'in':
76             attrs.append(('direction', parameter.direction))
77         if parameter.transfer != 'none':
78             attrs.append(('transfer', parameter.transfer))
79         with self.tagcontext('parameters', attrs):
80             self.write_tag('type', [('name', parameter.type)])
81
82     def _write_enum(self, enum):
83         attrs = [('name', enum.name)]
84         tag_name = 'enumeration'
85         if isinstance(enum, GLibEnum):
86             attrs.extend([('glib:type-name', enum.type_name),
87                           ('glib:get-type', enum.get_type)])
88             if isinstance(enum, GLibFlags):
89                 tag_name = 'bitfield'
90
91         with self.tagcontext(tag_name, attrs):
92             for member in enum.members:
93                 self._write_member(member)
94
95     def _write_member(self, member):
96         attrs = [('name', member.name),
97                  ('value', str(member.value))]
98         if isinstance(member, GLibEnumMember):
99             attrs.append(('glib:nick', member.nick))
100         self.write_tag('member', attrs)
101
102     def _write_class(self, node):
103         attrs = [('name', node.name)]
104         if isinstance(node, Class):
105             tag_name = 'class'
106             if node.parent is not None:
107                 attrs.append(('parent', node.parent))
108         else:
109             tag_name = 'interface'
110         if isinstance(node, (GLibObject, GLibInterface)):
111             attrs.append(('glib:type-name', node.type_name))
112             attrs.append(('glib:get-type', node.get_type))
113         with self.tagcontext(tag_name, attrs):
114             if isinstance(node, Class):
115                 for method in node.constructors:
116                     self._write_constructor(method)
117             for method in node.methods:
118                 self._write_method(method)
119             for prop in node.properties:
120                 self._write_property(prop)
121
122     def _write_boxed(self, boxed):
123         attrs = [('glib:name', boxed.name),
124                  ('glib:type-name', boxed.type_name),
125                  ('glib:get-type', boxed.get_type)]
126
127         with self.tagcontext('glib:boxed', attrs):
128             for method in boxed.constructors:
129                 self._write_constructor(method)
130             for method in boxed.methods:
131                 self._write_method(method)
132
133     def _write_property(self, prop):
134         attrs = [('name', prop.name),
135                  ('prop', prop.type)]
136         self.write_tag('property', attrs)
137
138     def _write_callback(self, callback):
139         attrs = [('name', callback.name)]
140         with self.tagcontext('callback', attrs):
141             self._write_return_type(callback.retval)
142             self._write_parameters(callback.parameters)