summaryrefslogtreecommitdiff
path: root/giscanner/gidlwriter.py
blob: 8d23e01f926c490b74eed7860633fa7810871f59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
from __future__ import with_statement

from .gobjecttreebuilder import (GLibBoxed, GLibEnum, GLibEnumMember,
                                 GLibFlags, GLibObject, GLibInterface)
from .treebuilder import Callback, Class, Enum, Function, Interface
from .xmlwriter import XMLWriter


class GIDLWriter(XMLWriter):
    def __init__(self, namespace, nodes):
        super(GIDLWriter, self).__init__()
        self._write_api(namespace, nodes)

    def _write_api(self, namespace, nodes):
        with self.tagcontext('api', [('version', '1.0')]):
            self._write_namespace(namespace, nodes)

    def _write_namespace(self, namespace, nodes):
        with self.tagcontext('namespace', [('name', namespace)]):
            for node in nodes:
                self._write_node(node)

    def _write_node(self, node):
        if isinstance(node, Function):
            self._write_function(node)
        elif isinstance(node, Enum):
            self._write_enum(node)
        elif isinstance(node, (Class, Interface)):
            self._write_class(node)
        elif isinstance(node, GLibBoxed):
            self._write_boxed(node)
        elif isinstance(node, Callback):
            self._write_callback(node)
        else:
            print 'WRITER: Unhandled node', node

    def _write_function(self, func, tag_name='function'):
        attrs = [('name', func.name),
                 ('symbol', func.symbol)]
        with self.tagcontext(tag_name, attrs):
            self._write_return_type(func.retval)
            self._write_parameters(func.parameters)

    def _write_method(self, method):
        self._write_function(method, tag_name='method')

    def _write_constructor(self, method):
        self._write_function(method, tag_name='constructor')

    def _write_return_type(self, return_):
        if not return_:
            return
        attrs = [('type', return_.type)]
        if return_.transfer != 'none':
            attrs.append(('transfer', return_.transfer))
        self.write_tag('return-type', attrs)

    def _write_parameters(self, parameters):
        if not parameters:
            return
        with self.tagcontext('parameters'):
            for parameter in parameters:
                self._write_parameter(parameter)

    def _write_parameter(self, parameter):
        attrs = [('name', parameter.name),
                 ('type', parameter.type)]
        if parameter.direction != 'in':
            attrs.append(('direction', parameter.direction))
        if parameter.transfer != 'none':
            attrs.append(('transfer', parameter.transfer))
        self.write_tag('parameter', attrs)

    def _write_enum(self, enum):
        attrs = [('name', enum.name)]
        tag_name = 'enum'
        if isinstance(enum, GLibEnum):
            attrs.extend([('type-name', enum.type_name),
                          ('get-type', enum.get_type)])
            if isinstance(enum, GLibFlags):
                tag_name = 'flags'

        with self.tagcontext(tag_name, attrs):
            for member in enum.members:
                self._write_member(member)

    def _write_member(self, member):
        attrs = [('name', member.name),
                 ('value', str(member.value))]
        if isinstance(member, GLibEnumMember):
            attrs.append(('nick', member.nick))
        self.write_tag('member', attrs)

    def _write_class(self, node):
        attrs = [('name', node.name)]
        if isinstance(node, Class):
            tag_name = 'object'
            if node.parent is not None:
                attrs.append(('parent', node.parent))
        else:
            tag_name = 'interface'
        if isinstance(node, (GLibObject, GLibInterface)):
            attrs.append(('type-name', node.type_name))
            attrs.append(('get-type', node.get_type))
        with self.tagcontext(tag_name, attrs):
            if isinstance(node, Class):
                for method in node.constructors:
                    self._write_constructor(method)
            for method in node.methods:
                self._write_method(method)
            for prop in node.properties:
                self._write_property(prop)

    def _write_boxed(self, boxed):
        attrs = [('name', boxed.name),
                 ('type-name', boxed.type_name),
                 ('get-type', boxed.get_type)]

        with self.tagcontext('boxed', attrs):
            for method in boxed.constructors:
                self._write_constructor(method)
            for method in boxed.methods:
                self._write_method(method)

    def _write_property(self, prop):
        attrs = [('name', prop.name),
                 ('prop', prop.type)]
        self.write_tag('property', attrs)

    def _write_callback(self, func):
        attrs = [('name', func.name)]
        with self.tagcontext('callback', attrs):
            self._write_return_type(func.retval)
            self._write_parameters(func.parameters)