Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(764)

Side by Side Diff: Source/bindings/scripts/idl_definitions.py

Issue 177233006: Merge idl_definitions_builder.py into idl_definitions.py (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebased (correctly) Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (C) 2013 Google Inc. All rights reserved. 1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the 11 # in the documentation and/or other materials provided with the
12 # distribution. 12 # distribution.
13 # * Neither the name of Google Inc. nor the names of its 13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from 14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission. 15 # this software without specific prior written permission.
16 # 16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 28
29 """Blink IDL Intermediate Representation (IR) classes.""" 29 """Blink IDL Intermediate Representation (IR) classes.
30
31 Classes are primarily constructors, which build an IdlDefinitions object
32 (and various contained objects) from an AST (produced by blink_idl_parser).
33
34 This is in two steps:
35 * Constructors walk the AST, creating objects.
36 * Typedef resolution.
37
38 Typedefs are all resolved here, and not stored in IR.
39
40 Typedef resolution uses some auxiliary classes and OOP techniques to make this
41 a generic call, via the resolve_typedefs() method.
42
43 Class hierarchy (mostly containment, '<' for inheritance):
44
45 IdlDefinitions
46 IdlCallbackFunction < TypedObject
47 IdlEnum :: FIXME: remove
48 IdlInterface
49 IdlAttribute < TypedObject
50 IdlConstant < TypedObject
51 IdlOperation < TypedObject
52 IdlArgument < TypedObject
53 IdlException < IdlInterface
54 (same contents as IdlInterface)
55
56 IdlUnionType :: FIXME: remove
57
58 Auxiliary classes for typedef resolution:
59 IdlType
60 TypedObject
61 """
62
30 63
31 # pylint doesn't understand ABCs. 64 # pylint doesn't understand ABCs.
32 # pylint: disable=W0232, E0203, W0201 65 # pylint: disable=W0232, E0203, W0201
33 66
34 import abc 67 import abc
35 import re 68 import re
36 69
37 70
38 # Type classes 71 SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
72 STANDARD_TYPEDEFS = {
73 # http://www.w3.org/TR/WebIDL/#common-DOMTimeStamp
74 'DOMTimeStamp': 'unsigned long long',
75 }
76
77
78 ################################################################################
79 # Type classes (for typedef resolution)
80 ################################################################################
81
82 class TypedObject(object):
83 """Object with a type, such as an Attribute or Operation (return value).
84
85 The type can be an actual type, or can be a typedef, which must be resolved
86 before passing data to the code generator.
87 """
88 __metaclass__ = abc.ABCMeta
89 idl_type = None
90 extended_attributes = None
91
92 def resolve_typedefs(self, typedefs):
93 """Resolve typedefs to actual types in the object."""
94 # Constructors don't have their own return type, because it's the
95 # interface itself.
96 if not self.idl_type:
97 return
98 # (Types are represented either as strings or as IdlUnionType objects.)
99 # Union types are objects, which have a member function for this
100 if isinstance(self.idl_type, IdlUnionType):
101 # Method 'resolve_typedefs' call is ok, but pylint can't infer this
102 # pylint: disable=E1101
103 self.idl_type.resolve_typedefs(typedefs)
104 return
105 # Otherwise, IDL type is represented as string, so use a function
106 self.idl_type = resolve_typedefs(self.idl_type, typedefs)
39 107
40 class IdlType(object): 108 class IdlType(object):
41 # FIXME: replace type strings with these objects, 109 # FIXME: replace type strings with these objects,
42 # so don't need to parse everywhere types are used. 110 # so don't need to parse everywhere types are used.
43 # Types are stored internally as strings, not objects, 111 # Types are stored internally as strings, not objects,
44 # e.g., as 'sequence<Foo>' or 'Foo[]', 112 # e.g., as 'sequence<Foo>' or 'Foo[]',
45 # hence need to parse the string whenever a type is used. 113 # hence need to parse the string whenever a type is used.
46 # FIXME: incorporate Nullable, Variadic, etc. 114 # FIXME: incorporate Nullable, Variadic, etc.
47 # FIXME: properly should nest types 115 # FIXME: properly should nest types
48 # Formally types are nested, e.g., short?[] vs. short[]?, 116 # Formally types are nested, e.g., short?[] vs. short[]?,
(...skipping 30 matching lines...) Expand all
79 return cls(type_string) 147 return cls(type_string)
80 148
81 def resolve_typedefs(self, typedefs): 149 def resolve_typedefs(self, typedefs):
82 if self.base_type in typedefs: 150 if self.base_type in typedefs:
83 self.base_type = typedefs[self.base_type] 151 self.base_type = typedefs[self.base_type]
84 return self # Fluent interface 152 return self # Fluent interface
85 153
86 154
87 class IdlUnionType(object): 155 class IdlUnionType(object):
88 # FIXME: remove class, just treat as tuple 156 # FIXME: remove class, just treat as tuple
89 def __init__(self, union_member_types=None): 157 def __init__(self, node):
90 self.union_member_types = union_member_types or [] 158 self.union_member_types = [type_node_to_type(member_type_node)
159 for member_type_node in node.GetChildren()]
91 160
92 def resolve_typedefs(self, typedefs): 161 def resolve_typedefs(self, typedefs):
93 self.union_member_types = [ 162 self.union_member_types = [
94 typedefs.get(union_member_type, union_member_type) 163 typedefs.get(union_member_type, union_member_type)
95 for union_member_type in self.union_member_types] 164 for union_member_type in self.union_member_types]
96 165
97 166
98 class TypedObject(object):
99 """Object with a type, such as an Attribute or Operation (return value).
100
101 The type can be an actual type, or can be a typedef, which must be resolved
102 before passing data to the code generator.
103 """
104 __metaclass__ = abc.ABCMeta
105 idl_type = None
106 extended_attributes = None
107
108 def resolve_typedefs(self, typedefs):
109 """Resolve typedefs to actual types in the object."""
110 # Constructors don't have their own return type, because it's the
111 # interface itself.
112 if not self.idl_type:
113 return
114 # (Types are represented either as strings or as IdlUnionType objects.)
115 # Union types are objects, which have a member function for this
116 if isinstance(self.idl_type, IdlUnionType):
117 # Method 'resolve_typedefs' call is ok, but pylint can't infer this
118 # pylint: disable=E1101
119 self.idl_type.resolve_typedefs(typedefs)
120 return
121 # Otherwise, IDL type is represented as string, so use a function
122 self.idl_type = resolve_typedefs(self.idl_type, typedefs)
123
124
125 def resolve_typedefs(idl_type, typedefs): 167 def resolve_typedefs(idl_type, typedefs):
126 """Return an IDL type (as string) with typedefs resolved.""" 168 """Return an IDL type (as string) with typedefs resolved."""
127 # FIXME: merge into above, as only one use 169 # FIXME: merge into above, as only one use
128 # Converts a string representation to and from an IdlType object to handle 170 # Converts a string representation to and from an IdlType object to handle
129 # parsing of composite types (arrays and sequences) and encapsulate typedef 171 # parsing of composite types (arrays and sequences) and encapsulate typedef
130 # resolution, e.g., GLint[] -> unsigned long[] requires parsing the '[]'. 172 # resolution, e.g., GLint[] -> unsigned long[] requires parsing the '[]'.
131 # Use fluent interface to avoid auxiliary variable. 173 # Use fluent interface to avoid auxiliary variable.
132 return str(IdlType.from_string(idl_type).resolve_typedefs(typedefs)) 174 return str(IdlType.from_string(idl_type).resolve_typedefs(typedefs))
133 175
134 176
135 # IDL classes 177 ################################################################################
136 178 # Definitions (main container class)
179 ################################################################################
137 180
138 class IdlDefinitions(object): 181 class IdlDefinitions(object):
139 def __init__(self, callback_functions=None, enumerations=None, interfaces=No ne, typedefs=None): 182 def __init__(self, node):
140 self.callback_functions = callback_functions or {} 183 """Args: node: AST root node, class == 'File'"""
141 self.enumerations = enumerations or {} 184 self.callback_functions = {}
142 self.interfaces = interfaces or {} 185 self.enumerations = {}
143 # Typedefs are not exposed by bindings; resolve typedefs with the 186 self.interfaces = {}
144 # actual types and then discard the Typedefs. 187
188 node_class = node.GetClass()
189 if node_class != 'File':
190 raise ValueError('Unrecognized node class: %s' % node_class)
191
192 typedefs = STANDARD_TYPEDEFS
193
194 children = node.GetChildren()
195 for child in children:
196 child_class = child.GetClass()
197 if child_class == 'Interface':
198 interface = IdlInterface(child)
199 self.interfaces[interface.name] = interface
200 elif child_class == 'Exception':
201 exception = IdlException(child)
202 # For simplicity, treat exceptions as interfaces
203 self.interfaces[exception.name] = exception
204 elif child_class == 'Typedef':
205 type_name = child.GetName()
206 typedefs[type_name] = typedef_node_to_type(child)
207 elif child_class == 'Enum':
208 enumeration = IdlEnum(child)
209 self.enumerations[enumeration.name] = enumeration
210 elif child_class == 'Callback':
211 callback_function = IdlCallbackFunction(child)
212 self.callback_functions[callback_function.name] = callback_funct ion
213 elif child_class == 'Implements':
214 # Implements is handled at the interface merging step
215 pass
216 else:
217 raise ValueError('Unrecognized node class: %s' % child_class)
218
219 # Typedefs are not stored in IR:
220 # Resolve typedefs with the actual types and then discard the Typedefs.
145 # http://www.w3.org/TR/WebIDL/#idl-typedefs 221 # http://www.w3.org/TR/WebIDL/#idl-typedefs
146 if typedefs: 222 self.resolve_typedefs(typedefs)
147 self.resolve_typedefs(typedefs)
148 223
149 def resolve_typedefs(self, typedefs): 224 def resolve_typedefs(self, typedefs):
150 for callback_function in self.callback_functions.itervalues(): 225 for callback_function in self.callback_functions.itervalues():
151 callback_function.resolve_typedefs(typedefs) 226 callback_function.resolve_typedefs(typedefs)
152 for interface in self.interfaces.itervalues(): 227 for interface in self.interfaces.itervalues():
153 interface.resolve_typedefs(typedefs) 228 interface.resolve_typedefs(typedefs)
154 229
155 230
231 ################################################################################
232 # Callback Functions
233 ################################################################################
234
156 class IdlCallbackFunction(TypedObject): 235 class IdlCallbackFunction(TypedObject):
157 def __init__(self, name=None, idl_type=None, arguments=None): 236 def __init__(self, node):
158 self.idl_type = idl_type 237 children = node.GetChildren()
159 self.name = name 238 num_children = len(children)
160 self.arguments = arguments or [] 239 if num_children != 2:
240 raise ValueError('Expected 2 children, got %s' % num_children)
241 type_node, arguments_node = children
242 arguments_node_class = arguments_node.GetClass()
243 if arguments_node_class != 'Arguments':
244 raise ValueError('Expected Arguments node, got %s' % arguments_node_ class)
245
246 self.name = node.GetName()
247 self.idl_type = type_node_to_type(type_node)
248 self.arguments = arguments_node_to_arguments(arguments_node)
161 249
162 def resolve_typedefs(self, typedefs): 250 def resolve_typedefs(self, typedefs):
163 TypedObject.resolve_typedefs(self, typedefs) 251 TypedObject.resolve_typedefs(self, typedefs)
164 for argument in self.arguments: 252 for argument in self.arguments:
165 argument.resolve_typedefs(typedefs) 253 argument.resolve_typedefs(typedefs)
166 254
167 255
256 ################################################################################
257 # Enumerations
258 ################################################################################
259
168 class IdlEnum(object): 260 class IdlEnum(object):
169 # FIXME: remove, just treat enums as a dictionary 261 # FIXME: remove, just treat enums as a dictionary
170 def __init__(self, name=None, values=None): 262 def __init__(self, node):
171 self.name = name 263 self.name = node.GetName()
172 self.values = values or [] # FIXME: unnecessary, can't be empty 264 self.values = []
265 for child in node.GetChildren():
266 self.values.append(child.GetName())
173 267
174 268
269 ################################################################################
270 # Interfaces and Exceptions
271 ################################################################################
272
175 class IdlInterface(object): 273 class IdlInterface(object):
176 def __init__(self, attributes=None, constants=None, constructors=None, custo m_constructors=None, extended_attributes=None, operations=None, is_callback=Fals e, is_partial=False, name=None, parent=None): 274 def __init__(self, node=None):
177 self.attributes = attributes or [] 275 self.attributes = []
178 self.constants = constants or [] 276 self.constants = []
179 self.constructors = constructors or [] 277 self.constructors = []
180 self.custom_constructors = custom_constructors or [] 278 self.custom_constructors = []
181 self.extended_attributes = extended_attributes or {} 279 self.extended_attributes = {}
182 self.operations = operations or [] 280 self.operations = []
183 self.is_callback = is_callback 281 self.parent = None
184 self.is_partial = is_partial 282 if not node: # Early exit for IdlException.__init__
283 return
284
285 self.is_callback = node.GetProperty('CALLBACK') or False
185 self.is_exception = False 286 self.is_exception = False
186 self.name = name 287 # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser
187 self.parent = parent 288 self.is_partial = node.GetProperty('Partial') or False
289 self.name = node.GetName()
290
291 children = node.GetChildren()
292 for child in children:
293 child_class = child.GetClass()
294 if child_class == 'Attribute':
295 self.attributes.append(IdlAttribute(child))
296 elif child_class == 'Const':
297 self.constants.append(IdlConstant(child))
298 elif child_class == 'ExtAttributes':
299 extended_attributes = ext_attributes_node_to_extended_attributes (child)
300 self.constructors, self.custom_constructors = (
301 extended_attributes_to_constructors(extended_attributes))
302 clear_constructor_attributes(extended_attributes)
303 self.extended_attributes = extended_attributes
304 elif child_class == 'Operation':
305 self.operations.append(IdlOperation(child))
306 elif child_class == 'Inherit':
307 self.parent = child.GetName()
308 else:
309 raise ValueError('Unrecognized node class: %s' % child_class)
188 310
189 def resolve_typedefs(self, typedefs): 311 def resolve_typedefs(self, typedefs):
190 for attribute in self.attributes: 312 for attribute in self.attributes:
191 attribute.resolve_typedefs(typedefs) 313 attribute.resolve_typedefs(typedefs)
192 for constant in self.constants: 314 for constant in self.constants:
193 constant.resolve_typedefs(typedefs) 315 constant.resolve_typedefs(typedefs)
194 for constructor in self.constructors: 316 for constructor in self.constructors:
195 constructor.resolve_typedefs(typedefs) 317 constructor.resolve_typedefs(typedefs)
196 for custom_constructor in self.custom_constructors: 318 for custom_constructor in self.custom_constructors:
197 custom_constructor.resolve_typedefs(typedefs) 319 custom_constructor.resolve_typedefs(typedefs)
198 for operation in self.operations: 320 for operation in self.operations:
199 operation.resolve_typedefs(typedefs) 321 operation.resolve_typedefs(typedefs)
200 322
201 323
202 class IdlException(IdlInterface): 324 class IdlException(IdlInterface):
203 # Properly exceptions and interfaces are distinct, and thus should inherit a 325 # Properly exceptions and interfaces are distinct, and thus should inherit a
204 # common base class (say, "IdlExceptionOrInterface"). 326 # common base class (say, "IdlExceptionOrInterface").
205 # However, there is only one exception (DOMException), and new exceptions 327 # However, there is only one exception (DOMException), and new exceptions
206 # are not expected. Thus it is easier to implement exceptions as a 328 # are not expected. Thus it is easier to implement exceptions as a
207 # restricted subclass of interfaces. 329 # restricted subclass of interfaces.
208 # http://www.w3.org/TR/WebIDL/#idl-exceptions 330 # http://www.w3.org/TR/WebIDL/#idl-exceptions
209 def __init__(self, name=None, constants=None, operations=None, attributes=No ne, extended_attributes=None): 331 def __init__(self, node):
210 IdlInterface.__init__(self, name=name, constants=constants, operations=o perations, attributes=attributes, extended_attributes=extended_attributes) 332 # Exceptions are similar to Interfaces, but simpler
333 IdlInterface.__init__(self)
334 self.is_callback = False
211 self.is_exception = True 335 self.is_exception = True
336 self.is_partial = False
337 self.name = node.GetName()
338
339 children = node.GetChildren()
340 for child in children:
341 child_class = child.GetClass()
342 if child_class == 'Attribute':
343 attribute = IdlAttribute(child)
344 self.attributes.append(attribute)
345 elif child_class == 'Const':
346 self.constants.append(IdlConstant(child))
347 elif child_class == 'ExtAttributes':
348 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
349 elif child_class == 'ExceptionOperation':
350 self.operations.append(IdlOperation.from_exception_operation_nod e(child))
351 else:
352 raise ValueError('Unrecognized node class: %s' % child_class)
212 353
213 354
355 ################################################################################
356 # Attributes
357 ################################################################################
358
214 class IdlAttribute(TypedObject): 359 class IdlAttribute(TypedObject):
215 def __init__(self, idl_type=None, extended_attributes=None, getter_exception s=None, is_nullable=False, is_static=False, is_read_only=False, name=None, sette r_exceptions=None): 360 def __init__(self, node):
216 self.idl_type = idl_type 361 self.is_read_only = node.GetProperty('READONLY') or False
217 self.extended_attributes = extended_attributes or {} 362 self.is_static = node.GetProperty('STATIC') or False
218 self.getter_exceptions = getter_exceptions or [] 363 self.name = node.GetName()
219 self.is_nullable = is_nullable 364 # Defaults, overridden below
220 self.is_static = is_static 365 self.idl_type = None
221 self.is_read_only = is_read_only 366 self.is_nullable = False
222 self.name = name 367 self.extended_attributes = {}
223 self.setter_exceptions = setter_exceptions or [] 368
369 children = node.GetChildren()
370 for child in children:
371 child_class = child.GetClass()
372 if child_class == 'Type':
373 self.idl_type = type_node_to_type(child)
374 self.is_nullable = child.GetProperty('NULLABLE') or False
375 elif child_class == 'ExtAttributes':
376 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
377 else:
378 raise ValueError('Unrecognized node class: %s' % child_class)
224 379
225 380
381 ################################################################################
382 # Constants
383 ################################################################################
384
226 class IdlConstant(TypedObject): 385 class IdlConstant(TypedObject):
227 def __init__(self, name=None, idl_type=None, value=None, extended_attributes =None): 386 def __init__(self, node):
228 self.idl_type = idl_type 387 children = node.GetChildren()
229 self.extended_attributes = extended_attributes or {} 388 num_children = len(children)
230 self.name = name 389 if num_children < 2 or num_children > 3:
231 self.value = value 390 raise ValueError('Expected 2 or 3 children, got %s' % num_children)
391 type_node = children[0]
392 value_node = children[1]
393 value_node_class = value_node.GetClass()
394 if value_node_class != 'Value':
395 raise ValueError('Expected Value node, got %s' % value_node_class)
396
397 self.name = node.GetName()
398 # ConstType is more limited than Type, so subtree is smaller and
399 # we don't use the full type_node_to_type function.
400 self.idl_type = type_node_inner_to_type(type_node)
401 self.value = value_node.GetName()
402
403 if num_children == 3:
404 ext_attributes_node = children[2]
405 self.extended_attributes = ext_attributes_node_to_extended_attribute s(ext_attributes_node)
406 else:
407 self.extended_attributes = {}
232 408
233 409
410 ################################################################################
411 # Operations
412 ################################################################################
413
234 class IdlOperation(TypedObject): 414 class IdlOperation(TypedObject):
235 def __init__(self, is_static=False, name=None, idl_type=None, extended_attri butes=None, specials=None, arguments=None, overloaded_index=None): 415 def __init__(self, node=None):
236 self.is_static = is_static 416 self.arguments = []
237 self.name = name or '' 417 self.extended_attributes = {}
238 self.idl_type = idl_type 418 self.specials = []
239 self.extended_attributes = extended_attributes or {} 419
240 self.specials = specials or [] 420 if not node:
241 self.arguments = arguments or [] 421 self.is_static = False
422 return
423 self.name = node.GetName() # FIXME: should just be: or ''
424 # FIXME: AST should use None internally
425 if self.name == '_unnamed_':
426 self.name = ''
427
428 self.is_static = node.GetProperty('STATIC') or False
429 property_dictionary = node.GetProperties()
430 for special_keyword in SPECIAL_KEYWORD_LIST:
431 if special_keyword in property_dictionary:
432 self.specials.append(special_keyword.lower())
433
434 self.idl_type = None
435 children = node.GetChildren()
436 for child in children:
437 child_class = child.GetClass()
438 if child_class == 'Arguments':
439 self.arguments = arguments_node_to_arguments(child)
440 elif child_class == 'Type':
441 self.idl_type = type_node_to_type(child)
442 elif child_class == 'ExtAttributes':
443 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
444 else:
445 raise ValueError('Unrecognized node class: %s' % child_class)
446
447 @classmethod
448 def from_exception_operation_node(cls, node):
449 # Needed to handle one case in DOMException.idl:
450 # // Override in a Mozilla compatible format
451 # [NotEnumerable] DOMString toString();
452 # FIXME: can we remove this? replace with a stringifier?
453 operation = cls()
454 operation.name = node.GetName()
455 children = node.GetChildren()
456 if len(children) < 1 or len(children) > 2:
457 raise ValueError('ExceptionOperation node with %s children, expected 1 or 2' % len(children))
458
459 type_node = children[0]
460 operation.idl_type = type_node_to_type(type_node)
461
462 if len(children) > 1:
463 ext_attributes_node = children[1]
464 operation.extended_attributes = ext_attributes_node_to_extended_attr ibutes(ext_attributes_node)
465
466 return operation
467
468 @classmethod
469 def constructor_from_arguments_node(cls, name, arguments_node):
470 constructor = cls()
471 constructor.name = name
472 constructor.arguments = arguments_node_to_arguments(arguments_node)
473 return constructor
242 474
243 def resolve_typedefs(self, typedefs): 475 def resolve_typedefs(self, typedefs):
244 TypedObject.resolve_typedefs(self, typedefs) 476 TypedObject.resolve_typedefs(self, typedefs)
245 for argument in self.arguments: 477 for argument in self.arguments:
246 argument.resolve_typedefs(typedefs) 478 argument.resolve_typedefs(typedefs)
247 479
248 480
481 ################################################################################
482 # Arguments
483 ################################################################################
484
249 class IdlArgument(TypedObject): 485 class IdlArgument(TypedObject):
250 def __init__(self, name=None, idl_type=None, extended_attributes=None, is_op tional=False, is_nullable=False, is_variadic=False): 486 def __init__(self, node):
251 self.idl_type = idl_type 487 self.extended_attributes = {}
252 self.extended_attributes = extended_attributes or {} 488 self.idl_type = None
253 self.is_nullable = is_nullable # (T?) 489 self.is_nullable = False # (T?)
254 self.is_optional = is_optional # (optional T) 490 self.is_optional = node.GetProperty('OPTIONAL') # (optional T)
255 self.is_variadic = is_variadic # (T...) 491 self.is_variadic = False # (T...)
256 self.name = name 492 self.name = node.GetName()
493
494 children = node.GetChildren()
495 for child in children:
496 child_class = child.GetClass()
497 if child_class == 'Type':
498 self.idl_type = type_node_to_type(child)
499 # FIXME: Doesn't handle nullable arrays (Foo[]?), and arrays of
500 # nullable (Foo?[]) are treated as nullable arrays. No actual us e.
501 self.is_nullable = child.GetProperty('NULLABLE')
502 elif child_class == 'ExtAttributes':
503 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
504 elif child_class == 'Argument':
505 child_name = child.GetName()
506 if child_name != '...':
507 raise ValueError('Unrecognized Argument node; expected "..." , got "%s"' % child_name)
508 self.is_variadic = child.GetProperty('ELLIPSIS') or False
509 else:
510 raise ValueError('Unrecognized node class: %s' % child_class)
511
512
513 def arguments_node_to_arguments(node):
514 # [Constructor] and [CustomConstructor] without arguments (the bare form)
515 # have None instead of an arguments node, but have the same meaning as using
516 # an empty argument list, [Constructor()], so special-case this.
517 # http://www.w3.org/TR/WebIDL/#Constructor
518 if node is None:
519 return []
520 return [IdlArgument(argument_node)
521 for argument_node in node.GetChildren()]
522
523
524 ################################################################################
525 # Extended attributes
526 ################################################################################
527
528 def ext_attributes_node_to_extended_attributes(node):
529 """
530 Returns:
531 Dictionary of {ExtAttributeName: ExtAttributeValue}.
532 Value is usually a string, with three exceptions:
533 Constructors: value is a list of Arguments nodes, corresponding to
534 possible signatures of the constructor.
535 CustomConstructors: value is a list of Arguments nodes, corresponding to
536 possible signatures of the custom constructor.
537 NamedConstructor: value is a Call node, corresponding to the single
538 signature of the named constructor.
539 """
540 # Primarily just make a dictionary from the children.
541 # The only complexity is handling various types of constructors:
542 # Constructors and Custom Constructors can have duplicate entries due to
543 # overloading, and thus are stored in temporary lists.
544 # However, Named Constructors cannot be overloaded, and thus do not have
545 # a list.
546 # FIXME: move Constructor logic into separate function, instead of modifying
547 # extended attributes in-place.
548 constructors = []
549 custom_constructors = []
550 extended_attributes = {}
551
552 def child_node(extended_attribute_node):
553 children = extended_attribute_node.GetChildren()
554 if not children:
555 return None
556 if len(children) > 1:
557 raise ValueError('ExtAttributes node with %s children, expected at m ost 1' % len(children))
558 return children[0]
559
560 extended_attribute_node_list = node.GetChildren()
561 for extended_attribute_node in extended_attribute_node_list:
562 name = extended_attribute_node.GetName()
563 child = child_node(extended_attribute_node)
564 child_class = child and child.GetClass()
565 if name == 'Constructor':
566 if child_class and child_class != 'Arguments':
567 raise ValueError('Constructor only supports Arguments as child, but has child of class: %s' % child_class)
568 constructors.append(child)
569 elif name == 'CustomConstructor':
570 if child_class and child_class != 'Arguments':
571 raise ValueError('[CustomConstructor] only supports Arguments as child, but has child of class: %s' % child_class)
572 custom_constructors.append(child)
573 elif name == 'NamedConstructor':
574 if child_class and child_class != 'Call':
575 raise ValueError('[NamedConstructor] only supports Call as child , but has child of class: %s' % child_class)
576 extended_attributes[name] = child
577 elif name == 'SetWrapperReferenceTo':
578 if not child:
579 raise ValueError('[SetWrapperReferenceTo] requires a child, but has none.')
580 if child_class != 'Arguments':
581 raise ValueError('[SetWrapperReferenceTo] only supports Argument s as child, but has child of class: %s' % child_class)
582 extended_attributes[name] = arguments_node_to_arguments(child)
583 elif child:
584 raise ValueError('ExtAttributes node with unexpected children: %s' % name)
585 else:
586 value = extended_attribute_node.GetProperty('VALUE')
587 extended_attributes[name] = value
588
589 # Store constructors and custom constructors in special list attributes,
590 # which are deleted later. Note plural in key.
591 if constructors:
592 extended_attributes['Constructors'] = constructors
593 if custom_constructors:
594 extended_attributes['CustomConstructors'] = custom_constructors
595
596 return extended_attributes
597
598
599 def extended_attributes_to_constructors(extended_attributes):
600 """Returns constructors and custom_constructors (lists of IdlOperations).
601
602 Auxiliary function for IdlInterface.__init__.
603 """
604
605 constructor_list = extended_attributes.get('Constructors', [])
606 constructors = [
607 IdlOperation.constructor_from_arguments_node('Constructor', arguments_no de)
608 for arguments_node in constructor_list]
609
610 custom_constructor_list = extended_attributes.get('CustomConstructors', [])
611 custom_constructors = [
612 IdlOperation.constructor_from_arguments_node('CustomConstructor', argume nts_node)
613 for arguments_node in custom_constructor_list]
614
615 if 'NamedConstructor' in extended_attributes:
616 # FIXME: support overloaded named constructors, and make homogeneous
617 name = 'NamedConstructor'
618 call_node = extended_attributes['NamedConstructor']
619 extended_attributes['NamedConstructor'] = call_node.GetName()
620 children = call_node.GetChildren()
621 if len(children) != 1:
622 raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children))
623 arguments_node = children[0]
624 named_constructor = IdlOperation.constructor_from_arguments_node('NamedC onstructor', arguments_node)
625 # FIXME: should return named_constructor separately; appended for Perl
626 constructors.append(named_constructor)
627
628 return constructors, custom_constructors
629
630
631 def clear_constructor_attributes(extended_attributes):
632 # Deletes Constructor*s* (plural), sets Constructor (singular)
633 if 'Constructors' in extended_attributes:
634 del extended_attributes['Constructors']
635 extended_attributes['Constructor'] = None
636 if 'CustomConstructors' in extended_attributes:
637 del extended_attributes['CustomConstructors']
638 extended_attributes['CustomConstructor'] = None
639
640
641 ################################################################################
642 # Types
643 ################################################################################
644
645 def type_node_to_type(node):
646 children = node.GetChildren()
647 if len(children) < 1 or len(children) > 2:
648 raise ValueError('Type node expects 1 or 2 children (type + optional arr ay []), got %s (multi-dimensional arrays are not supported).' % len(children))
649
650 type_node_child = children[0]
651 idl_type = type_node_inner_to_type(type_node_child)
652
653 if len(children) == 2:
654 array_node = children[1]
655 array_node_class = array_node.GetClass()
656 if array_node_class != 'Array':
657 raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class)
658 idl_type += '[]'
659
660 return idl_type
661
662
663 def type_node_inner_to_type(node):
664 node_class = node.GetClass()
665 # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
666 # either a typedef shorthand (but not a Typedef declaration itself) or an
667 # interface type. We do not distinguish these, and just use the type name.
668 if node_class in ['PrimitiveType', 'Typeref']:
669 return node.GetName()
670 elif node_class == 'Any':
671 return 'any'
672 elif node_class == 'Sequence':
673 return sequence_node_to_type(node)
674 elif node_class == 'UnionType':
675 return IdlUnionType(node)
676 raise ValueError('Unrecognized node class: %s' % node_class)
677
678
679 def sequence_node_to_type(node):
680 children = node.GetChildren()
681 if len(children) != 1:
682 raise ValueError('Sequence node expects exactly 1 child, got %s' % len(c hildren))
683 sequence_child = children[0]
684 sequence_child_class = sequence_child.GetClass()
685 if sequence_child_class != 'Type':
686 raise ValueError('Unrecognized node class: %s' % sequence_child_class)
687 sequence_type = type_node_to_type(sequence_child)
688 return 'sequence<%s>' % sequence_type
689
690
691 def typedef_node_to_type(node):
692 children = node.GetChildren()
693 if len(children) != 1:
694 raise ValueError('Typedef node with %s children, expected 1' % len(child ren))
695 child = children[0]
696 child_class = child.GetClass()
697 if child_class != 'Type':
698 raise ValueError('Unrecognized node class: %s' % child_class)
699 return type_node_to_type(child)
OLDNEW
« no previous file with comments | « Source/bindings/generated_bindings.gyp ('k') | Source/bindings/scripts/idl_definitions_builder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698