Revert "Support introspectable=no attribute, add warnings framework"
[platform/upstream/gobject-introspection.git] / giscanner / ast.py
1 # -*- Mode: Python -*-
2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008  Johan Dahlin
4 # Copyright (C) 2008, 2009 Red Hat, Inc.
5 #
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2 of the License, or (at your option) any later version.
10 #
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the
18 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 # Boston, MA 02111-1307, USA.
20 #
21
22 """AST nodes
23 This file descbribes abstract data type nodes independent on the
24 implementation language.
25
26 These can later on be extended (eg subclassed) with additional information
27 which is language/library/domain specific.
28 """
29
30 ##
31 ## Basic types, modeled on GITypeTag but not equivalent
32 ##
33
34 TYPE_NONE = 'none' # We differ from repository on these first two
35 TYPE_ANY = 'any'
36 TYPE_BOOLEAN = 'boolean'
37 TYPE_INT8 = 'int8'
38 TYPE_UINT8 = 'uint8'
39 TYPE_SHORT = 'short'
40 TYPE_USHORT = 'ushort'
41 TYPE_INT16 = 'int16'
42 TYPE_UINT16 = 'uint16'
43 TYPE_INT = 'int'
44 TYPE_UINT = 'uint'
45 TYPE_INT32 = 'int32'
46 TYPE_UINT32 = 'uint32'
47 TYPE_INT64 = 'int64'
48 TYPE_UINT64 = 'uint64'
49 TYPE_LONG = 'long'
50 TYPE_ULONG = 'ulong'
51 TYPE_SSIZET = 'ssize_t'
52 TYPE_SIZET = 'size_t'
53 TYPE_TIMET = 'time_t'
54 TYPE_GTYPE = 'GType'
55 TYPE_FLOAT = 'float'
56 TYPE_DOUBLE = 'double'
57 TYPE_STRING = 'utf8' # requires zero-terminated
58 TYPE_FILENAME = 'filename'
59
60 BASIC_GIR_TYPES = [TYPE_BOOLEAN, TYPE_INT8, TYPE_UINT8, TYPE_INT16,
61                    TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64,
62                    TYPE_UINT64, TYPE_SHORT, TYPE_USHORT, TYPE_INT,
63                    TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_SSIZET,
64                    TYPE_SIZET, TYPE_FLOAT, TYPE_DOUBLE, TYPE_TIMET,
65                    TYPE_GTYPE]
66 GIR_TYPES = [TYPE_NONE, TYPE_ANY]
67 GIR_TYPES.extend(BASIC_GIR_TYPES)
68 GIR_TYPES.extend([TYPE_STRING, TYPE_FILENAME])
69
70 # Higher-level data types
71 TYPE_SEQUENCE = 'sequence' # Sequence of something
72
73 # Wide/Unicode
74 TYPE_UCHAR = 'uchar'
75 TYPE_USTRING = 'ustring'
76
77 ##
78 ## Parameters
79 ##
80
81 PARAM_DIRECTION_IN = 'in'
82 PARAM_DIRECTION_OUT = 'out'
83 PARAM_DIRECTION_INOUT = 'inout'
84
85 PARAM_SCOPE_CALL = 'call'
86 PARAM_SCOPE_ASYNC = 'async'
87 PARAM_SCOPE_NOTIFIED = 'notified'
88
89 PARAM_TRANSFER_NONE = 'none'
90 PARAM_TRANSFER_CONTAINER = 'container'
91 PARAM_TRANSFER_FULL = 'full'
92
93 type_names = {}
94 for name in GIR_TYPES:
95     type_names[name] = name
96
97 # C builtin
98 type_names['char'] = TYPE_INT8
99 type_names['signed char'] = TYPE_INT8
100 type_names['unsigned char'] = TYPE_UINT8
101 type_names['short'] = TYPE_SHORT
102 type_names['signed short'] = TYPE_SHORT
103 type_names['unsigned short'] = TYPE_USHORT
104 type_names['int'] = TYPE_INT
105 type_names['signed int'] = TYPE_INT
106 type_names['unsigned short int'] = TYPE_USHORT
107 type_names['signed'] = TYPE_INT
108 type_names['unsigned int'] = TYPE_UINT
109 type_names['unsigned'] = TYPE_UINT
110 type_names['long'] = TYPE_LONG
111 type_names['signed long'] = TYPE_LONG
112 type_names['unsigned long'] = TYPE_ULONG
113 type_names['unsigned long int'] = TYPE_ULONG
114 type_names['float'] = TYPE_FLOAT
115 type_names['double'] = TYPE_DOUBLE
116 type_names['char*'] = TYPE_STRING
117 type_names['void*'] = TYPE_ANY
118 type_names['void'] = TYPE_NONE
119
120 # Unix types that we special case here (and that have their own introspection
121 # type tag) because of wide use in GLib.
122 type_names['size_t'] = TYPE_SIZET
123 type_names['ssize_t'] = TYPE_SSIZET
124
125 # One off C unix type definitions; note some of these may be GNU Libc
126 # specific.  If someone is actually bitten by this, feel free to do
127 # the required configure goop to determine their size and replace
128 # here.
129 #
130 # We don't want to encourage people to use these in their APIs because
131 # they compromise the platform-independence that GLib gives you.
132 # These are here mostly to avoid blowing when random platform-specific
133 # methods are added under #ifdefs inside GLib itself.  We could just (skip)
134 # the relevant methods, but on the other hand, since these types are just
135 # integers it's easy enough to expand them.
136 type_names['off_t'] = TYPE_SIZET
137 type_names['pid_t'] = TYPE_INT
138 type_names['uid_t'] = TYPE_UINT
139 type_names['gid_t'] = TYPE_UINT
140 type_names['dev_t'] = TYPE_INT
141 type_names['socklen_t'] = TYPE_INT32
142
143 # Obj-C
144 type_names['id'] = TYPE_ANY
145
146 # Suppress some GLib names
147 type_names['uchar'] = TYPE_UINT8
148 type_names['ushort'] = TYPE_USHORT
149 type_names['size'] = TYPE_SIZET
150 type_names['ssize'] = TYPE_SSIZET
151 type_names['pointer'] = TYPE_ANY
152 type_names['constpointer'] = TYPE_ANY
153
154
155 # These types, when seen by reference, are converted into an Array()
156 # by default
157 # If you add/change these, be sure to update glibast.py too
158 default_array_types = {}
159 default_array_types['uint8*'] = TYPE_UINT8
160 default_array_types['utf8*'] = TYPE_STRING
161
162 # These types, when seen by reference, are interpreted as out parameters
163 default_out_types = (TYPE_SHORT, TYPE_USHORT, TYPE_INT, TYPE_UINT,
164                      TYPE_LONG, TYPE_ULONG, TYPE_FLOAT, TYPE_DOUBLE,
165                      TYPE_SIZET, TYPE_SSIZET)
166
167
168 def type_name_from_ctype(ctype):
169     return type_names.get(ctype, ctype)
170
171
172 class Node(object):
173
174     def __init__(self, name=None):
175         self.name = name
176         self.attributes = [] # (key, value)*
177         self.skip = False
178         self.deprecated = None
179         self.deprecated_version = None
180         self.version = None
181         self.foreign = False
182
183     def __cmp__(self, other):
184         return cmp(self.name, other.name)
185
186     def __repr__(self):
187         return '%s(%r)' % (self.__class__.__name__, self.name)
188
189     def remove_matching_children(self, pred):
190         pass
191
192 class Namespace(Node):
193
194     def __init__(self, name, version):
195         Node.__init__(self, name)
196         self.version = version
197         self.nodes = []
198
199     def __repr__(self):
200         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
201                                    self.version, self.nodes)
202
203     def remove_matching(self, pred):
204
205         def recursive_pred(node):
206             node.remove_matching_children(pred)
207             return pred(node)
208
209         self.nodes = filter(recursive_pred, self.nodes)
210
211 class Include(Node):
212
213     def __init__(self, name, version):
214         Node.__init__(self, 'include')
215         self.name = name
216         self.version = version
217
218     @classmethod
219     def from_string(self, string):
220         return Include(*string.split('-', 1))
221
222     def __cmp__(self, other):
223         if not isinstance(other, Include):
224             return cmp(self, other)
225         namecmp = cmp(self.name, other.name)
226         if namecmp != 0:
227             return namecmp
228         return cmp(self.version, other.version)
229
230     def __hash__(self):
231         return hash((self.name, self.version))
232
233     def __str__(self):
234         return '%s-%s' % (self.name, self.version)
235
236 class Callable(Node):
237
238     def __init__(self, name, retval, parameters, throws):
239         Node.__init__(self, name)
240         self.retval = retval
241         self.parameters = parameters
242         self.throws = not not throws
243         self.doc = None
244
245     def __repr__(self):
246         return '%s(%r, %r, %r)' % (self.__class__.__name__,
247                                    self.name, self.retval,
248                                    self.parameters)
249
250 class Function(Callable):
251
252     def __init__(self, name, retval, parameters, symbol, throws=None):
253         Callable.__init__(self, name, retval, parameters, throws)
254         self.symbol = symbol
255         self.is_method = False
256         self.doc = None
257
258     def get_parameter_index(self, name):
259         for i, parameter in enumerate(self.parameters):
260             if parameter.name == name:
261                 return i + int(self.is_method)
262
263     def get_parameter(self, name):
264         for parameter in self.parameters:
265             if parameter.name == name:
266                 return parameter
267
268
269 class VFunction(Callable):
270
271     def __init__(self, name, retval, parameters, throws):
272         Callable.__init__(self, name, retval, parameters, throws)
273         self.invoker = None
274
275     @classmethod
276     def from_callback(cls, cb):
277         obj = cls(cb.name, cb.retval, cb.parameters[1:],
278                   cb.throws)
279         return obj
280
281
282 class Type(Node):
283
284     def __init__(self, name, ctype=None):
285         Node.__init__(self, name)
286         self.ctype = ctype
287         self.resolved = False
288         self.is_const = False
289         self.canonical = None
290         self.derefed_canonical = None
291
292
293 class Varargs(Type):
294
295     def __init__(self):
296         Type.__init__(self, '<varargs>')
297
298
299 class Array(Type):
300
301     def __init__(self, name, ctype, element_type):
302         if name is None:
303             name = '<carray>'
304         Type.__init__(self, name, ctype)
305         self.element_type = element_type
306         self.zeroterminated = True
307         self.length_param_index = -1
308         self.length_param_name = None
309         self.size = None
310
311     def __repr__(self):
312         return 'Array(%r, %r)' % (self.name, self.element_type, )
313
314
315 class List(Type):
316
317     def __init__(self, name, ctype, element_type):
318         Type.__init__(self, name, ctype)
319         self.element_type = element_type
320
321     def __repr__(self):
322         return 'List(%r of %r)' % (self.name, self.element_type, )
323
324
325 class Map(Type):
326
327     def __init__(self, name, ctype, key_type, value_type):
328         Type.__init__(self, name, ctype)
329         self.key_type = key_type
330         self.value_type = value_type
331
332     def __repr__(self):
333         return 'Map(%r <%r,%r>)' % (self.name, self.key_type, self.value_type)
334
335
336 class Alias(Node):
337
338     def __init__(self, name, target, ctype=None):
339         Node.__init__(self, name)
340         self.target = target
341         self.ctype = ctype
342
343     def __repr__(self):
344         return 'Alias(%r, %r)' % (self.name, self.target)
345
346
347 class TypeContainer(Node):
348
349     def __init__(self, name, typenode, transfer):
350         Node.__init__(self, name)
351         self.type = typenode
352         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
353                         PARAM_TRANSFER_FULL]:
354             self.transfer = transfer
355         else:
356             self.transfer = None
357
358
359 class Parameter(TypeContainer):
360
361     def __init__(self, name, typenode, direction=None,
362                  transfer=None, allow_none=False, scope=None):
363         TypeContainer.__init__(self, name, typenode, transfer)
364         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
365                          PARAM_DIRECTION_INOUT, None]:
366             self.direction = direction
367         else:
368             self.direction = PARAM_DIRECTION_IN
369
370         self.caller_allocates = False
371         self.allow_none = allow_none
372         self.scope = scope
373         self.closure_index = -1
374         self.destroy_index = -1
375         self.doc = None
376
377     def __repr__(self):
378         return 'Parameter(%r, %r)' % (self.name, self.type)
379
380
381 class Enum(Node):
382
383     def __init__(self, name, symbol, members):
384         Node.__init__(self, name)
385         self.symbol = symbol
386         self.members = members
387         self.doc = None
388
389     def __repr__(self):
390         return 'Enum(%r, %r)' % (self.name, self.members)
391
392
393 class Bitfield(Node):
394
395     def __init__(self, name, symbol, members):
396         Node.__init__(self, name)
397         self.symbol = symbol
398         self.members = members
399         self.doc = None
400
401     def __repr__(self):
402         return 'Bitfield(%r, %r)' % (self.name, self.members)
403
404
405 class Member(Node):
406
407     def __init__(self, name, value, symbol):
408         Node.__init__(self, name)
409         self.value = value
410         self.symbol = symbol
411
412     def __repr__(self):
413         return 'Member(%r, %r)' % (self.name, self.value)
414
415
416 class Record(Node):
417
418     def __init__(self, name, symbol, disguised=False):
419         Node.__init__(self, name)
420         self.fields = []
421         self.constructors = []
422         self.symbol = symbol
423         self.disguised = disguised
424         self.doc = None
425         self.methods = []
426
427     def remove_matching_children(self, pred):
428         self.fields = filter(pred, self.fields)
429         self.constructors = filter(pred, self.constructors)
430         self.methods = filter(pred, self.methods)
431
432 # BW compat, remove
433 Struct = Record
434
435
436 class Field(Node):
437
438     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
439         Node.__init__(self, name)
440         self.type = typenode
441         self.symbol = symbol
442         self.readable = readable
443         self.writable = writable
444         self.bits = bits
445
446     def __repr__(self):
447         if self.bits:
448             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
449         else:
450             return 'Field(%r, %r)' % (self.name, self.type)
451
452
453 class Return(TypeContainer):
454
455     def __init__(self, rtype, transfer=None):
456         TypeContainer.__init__(self, None, rtype, transfer)
457         self.direction = PARAM_DIRECTION_OUT
458         self.doc = None
459
460     def __repr__(self):
461         return 'Return(%r)' % (self.type, )
462
463
464 class Class(Node):
465
466     def __init__(self, name, parent, is_abstract):
467         Node.__init__(self, name)
468         self.ctype = name
469         self.parent = parent
470         self.glib_type_struct = None
471         self.is_abstract = is_abstract
472         self.methods = []
473         self.virtual_methods = []
474         self.static_methods = []
475         self.interfaces = []
476         self.constructors = []
477         self.properties = []
478         self.fields = []
479         self.doc = None
480
481     def remove_matching_children(self, pred):
482         self.methods = filter(pred, self.methods)
483         self.constructors = filter(pred, self.constructors)
484         self.properties = filter(pred, self.properties)
485         self.fields = filter(pred, self.fields)
486
487     def __repr__(self):
488         return '%s(%r, %r, %r)' % (
489             self.__class__.__name__,
490             self.name, self.parent, self.methods)
491
492
493 class Interface(Node):
494
495     def __init__(self, name, parent):
496         Node.__init__(self, name)
497         self.parent = parent
498         self.methods = []
499         self.virtual_methods = []
500         self.glib_type_struct = None
501         self.properties = []
502         self.fields = []
503         self.prerequisites = []
504         self.doc = None
505
506     def __repr__(self):
507         return '%s(%r, %r)' % (
508             self.__class__.__name__,
509             self.name, self.methods)
510
511
512 class Constant(Node):
513
514     def __init__(self, name, type_name, value):
515         Node.__init__(self, name)
516         self.type = Type(type_name)
517         self.value = value
518
519     def __repr__(self):
520         return 'Constant(%r, %r, %r)' % (
521             self.name, self.type, self.value)
522
523
524 class Property(TypeContainer):
525
526     def __init__(self, name, type_name, readable, writable,
527                  construct, construct_only, ctype=None, transfer=None):
528         self.type = Type(type_name, ctype)
529         TypeContainer.__init__(self, name, self.type, transfer)
530         self.readable = readable
531         self.writable = writable
532         self.construct = construct
533         self.construct_only = construct_only
534         self.doc = None
535
536     def __repr__(self):
537         return '%s(%r, %r)' % (
538             self.__class__.__name__,
539             self.name, self.type)
540
541
542 # FIXME: Inherit from Function
543
544
545 class Callback(Node):
546
547     def __init__(self, name, retval, parameters, ctype=None):
548         Node.__init__(self, name)
549         self.retval = retval
550         self.parameters = parameters
551         self.ctype = ctype
552         self.throws = False
553         self.doc = None
554
555     def get_parameter_index(self, name):
556         for i, parameter in enumerate(self.parameters):
557             if parameter.name == name:
558                 return i
559
560     def get_parameter(self, name):
561         for parameter in self.parameters:
562             if parameter.name == name:
563                 return parameter
564
565     def __repr__(self):
566         return 'Callback(%r, %r, %r)' % (
567             self.name, self.retval, self.parameters)
568
569
570 class Union(Node):
571
572     def __init__(self, name, symbol):
573         Node.__init__(self, name)
574         self.fields = []
575         self.constructors = []
576         self.methods = []
577         self.symbol = symbol
578         self.doc = None
579
580     def __repr__(self):
581         return 'Union(%r, %r)' % (self.name, self.fields, )