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

Side by Side Diff: Source/bindings/scripts/idl_definitions_builder.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
« no previous file with comments | « Source/bindings/scripts/idl_definitions.py ('k') | Source/bindings/scripts/idl_reader.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
12 # distribution.
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
28
29 """Builds an IdlDefinitions object from an AST (produced by blink_idl_parser)."" "
30
31 import os
32
33 from idl_definitions import IdlDefinitions, IdlInterface, IdlException, IdlOpera tion, IdlCallbackFunction, IdlArgument, IdlAttribute, IdlConstant, IdlEnum, IdlU nionType
34
35 SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
36 STANDARD_TYPEDEFS = {
37 # http://www.w3.org/TR/WebIDL/#common-DOMTimeStamp
38 'DOMTimeStamp': 'unsigned long long',
39 }
40
41
42 def build_idl_definitions_from_ast(node):
43 if node is None:
44 return None
45 node_class = node.GetClass()
46 if node_class != 'File':
47 raise ValueError('Unrecognized node class: %s' % node_class)
48 return file_node_to_idl_definitions(node)
49
50
51 def file_node_to_idl_definitions(node):
52 callback_functions = {}
53 enumerations = {}
54 interfaces = {}
55 typedefs = STANDARD_TYPEDEFS
56
57 children = node.GetChildren()
58 for child in children:
59 child_class = child.GetClass()
60 if child_class == 'Interface':
61 interface = interface_node_to_idl_interface(child)
62 interfaces[interface.name] = interface
63 elif child_class == 'Exception':
64 exception = exception_node_to_idl_exception(child)
65 # For simplicity, treat exceptions as interfaces
66 interfaces[exception.name] = exception
67 elif child_class == 'Typedef':
68 type_name = child.GetName()
69 typedefs[type_name] = typedef_node_to_type(child)
70 elif child_class == 'Enum':
71 enumeration = enum_node_to_idl_enum(child)
72 enumerations[enumeration.name] = enumeration
73 elif child_class == 'Callback':
74 callback_function = callback_node_to_idl_callback_function(child)
75 callback_functions[callback_function.name] = callback_function
76 elif child_class == 'Implements':
77 # Implements is handled at the interface merging step
78 pass
79 else:
80 raise ValueError('Unrecognized node class: %s' % child_class)
81
82 return IdlDefinitions(callback_functions=callback_functions, enumerations=en umerations, interfaces=interfaces, typedefs=typedefs)
83
84 # Constructors for Interface definitions and interface members
85
86
87 def interface_node_to_idl_interface(node):
88 attributes = []
89 constants = []
90 constructors = None
91 custom_constructors = None
92 extended_attributes = None
93 operations = []
94 is_callback = node.GetProperty('CALLBACK') or False
95 # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser
96 is_partial = node.GetProperty('Partial') or False
97 name = node.GetName()
98 parent = None
99
100 children = node.GetChildren()
101 for child in children:
102 child_class = child.GetClass()
103 if child_class == 'Attribute':
104 attributes.append(attribute_node_to_idl_attribute(child))
105 elif child_class == 'Const':
106 constants.append(constant_node_to_idl_constant(child))
107 elif child_class == 'ExtAttributes':
108 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
109 constructors, custom_constructors = extended_attributes_to_construct ors(extended_attributes)
110 clear_constructor_attributes(extended_attributes)
111 elif child_class == 'Operation':
112 operations.append(operation_node_to_idl_operation(child))
113 elif child_class == 'Inherit':
114 parent = child.GetName()
115 else:
116 raise ValueError('Unrecognized node class: %s' % child_class)
117
118 return IdlInterface(name=name, attributes=attributes, constants=constants, c onstructors=constructors, custom_constructors=custom_constructors, extended_attr ibutes=extended_attributes, operations=operations, is_callback=is_callback, is_p artial=is_partial, parent=parent)
119
120
121 def attribute_node_to_idl_attribute(node):
122 idl_type = None
123 extended_attributes = {}
124 is_nullable = False
125 is_read_only = node.GetProperty('READONLY') or False
126 is_static = node.GetProperty('STATIC') or False
127 name = node.GetName()
128
129 children = node.GetChildren()
130 for child in children:
131 child_class = child.GetClass()
132 if child_class == 'Type':
133 idl_type = type_node_to_type(child)
134 is_nullable = child.GetProperty('NULLABLE') or False
135 elif child_class == 'ExtAttributes':
136 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
137 else:
138 raise ValueError('Unrecognized node class: %s' % child_class)
139
140 return IdlAttribute(idl_type=idl_type, extended_attributes=extended_attribut es, is_nullable=is_nullable, is_read_only=is_read_only, is_static=is_static, nam e=name)
141
142
143 def constant_node_to_idl_constant(node):
144 name = node.GetName()
145
146 children = node.GetChildren()
147 num_children = len(children)
148 if num_children < 2 or num_children > 3:
149 raise ValueError('Expected 2 or 3 children, got %s' % num_children)
150
151 type_node = children[0]
152 # ConstType is more limited than Type, so subtree is smaller and we don't
153 # use the full type_node_to_type function.
154 idl_type = type_node_inner_to_type(type_node)
155
156 value_node = children[1]
157 value_node_class = value_node.GetClass()
158 if value_node_class != 'Value':
159 raise ValueError('Expected Value node, got %s' % value_node_class)
160 value = value_node.GetName()
161
162 extended_attributes = None
163 if num_children == 3:
164 ext_attributes_node = children[2]
165 extended_attributes = ext_attributes_node_to_extended_attributes(ext_att ributes_node)
166
167 return IdlConstant(idl_type=idl_type, extended_attributes=extended_attribute s, name=name, value=value)
168
169
170 def operation_node_to_idl_operation(node):
171 name = node.GetName()
172 # FIXME: AST should use None internally
173 if name == '_unnamed_':
174 name = None
175
176 is_static = node.GetProperty('STATIC') or False
177 specials = []
178 property_dictionary = node.GetProperties()
179 for special_keyword in SPECIAL_KEYWORD_LIST:
180 if special_keyword in property_dictionary:
181 specials.append(special_keyword.lower())
182
183 extended_attributes = None
184 arguments = []
185 return_type = None
186 children = node.GetChildren()
187 for child in children:
188 child_class = child.GetClass()
189 if child_class == 'Arguments':
190 arguments = arguments_node_to_arguments(child)
191 elif child_class == 'Type':
192 return_type = type_node_to_type(child)
193 elif child_class == 'ExtAttributes':
194 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
195 else:
196 raise ValueError('Unrecognized node class: %s' % child_class)
197
198 return IdlOperation(name=name, idl_type=return_type, extended_attributes=ext ended_attributes, is_static=is_static, arguments=arguments, specials=specials)
199
200
201 def arguments_node_to_arguments(node):
202 # [Constructor] and [CustomConstructor] without arguments (the bare form)
203 # have None instead of an arguments node, but have the same meaning as using
204 # an empty argument list, [Constructor()], so special-case this.
205 # http://www.w3.org/TR/WebIDL/#Constructor
206 if node is None:
207 return []
208 arguments = []
209 argument_node_list = node.GetChildren()
210 for argument_node in argument_node_list:
211 arguments.append(argument_node_to_idl_argument(argument_node))
212 return arguments
213
214
215 def argument_node_to_idl_argument(node):
216 name = node.GetName()
217
218 idl_type = None
219 extended_attributes = {}
220 is_nullable = False
221 is_optional = node.GetProperty('OPTIONAL')
222 is_variadic = False
223 children = node.GetChildren()
224 for child in children:
225 child_class = child.GetClass()
226 if child_class == 'Type':
227 idl_type = type_node_to_type(child)
228 # FIXME: Doesn't handle nullable arrays (Foo[]?), and arrays of
229 # nullable (Foo?[]) are treated as nullable arrays. No actual use.
230 is_nullable = child.GetProperty('NULLABLE')
231 elif child_class == 'ExtAttributes':
232 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
233 elif child_class == 'Argument':
234 child_name = child.GetName()
235 if child_name != '...':
236 raise ValueError('Unrecognized Argument node; expected "...", go t "%s"' % child_name)
237 is_variadic = child.GetProperty('ELLIPSIS') or False
238 else:
239 raise ValueError('Unrecognized node class: %s' % child_class)
240
241 return IdlArgument(name=name, idl_type=idl_type, extended_attributes=extende d_attributes, is_nullable=is_nullable, is_optional=is_optional, is_variadic=is_v ariadic)
242
243 # Constructors for for non-interface definitions
244
245
246 def callback_node_to_idl_callback_function(node):
247 name = node.GetName()
248 children = node.GetChildren()
249 num_children = len(children)
250 if num_children != 2:
251 raise ValueError('Expected 2 children, got %s' % num_children)
252
253 type_node = children[0]
254 idl_type = type_node_to_type(type_node)
255
256 arguments_node = children[1]
257 arguments_node_class = arguments_node.GetClass()
258 if arguments_node_class != 'Arguments':
259 raise ValueError('Expected Value node, got %s' % arguments_node_class)
260 arguments = arguments_node_to_arguments(arguments_node)
261
262 return IdlCallbackFunction(name=name, idl_type=idl_type, arguments=arguments )
263
264
265 def enum_node_to_idl_enum(node):
266 name = node.GetName()
267 values = []
268 for child in node.GetChildren():
269 values.append(child.GetName())
270 return IdlEnum(name=name, values=values)
271
272
273 def exception_operation_node_to_idl_operation(node):
274 # Needed to handle one case in DOMException.idl:
275 # // Override in a Mozilla compatible format
276 # [NotEnumerable] DOMString toString();
277 # FIXME: can we remove this? replace with a stringifier?
278 extended_attributes = {}
279 name = node.GetName()
280 children = node.GetChildren()
281 if len(children) < 1 or len(children) > 2:
282 raise ValueError('ExceptionOperation node with %s children, expected 1 o r 2' % len(children))
283
284 type_node = children[0]
285 return_type = type_node_to_type(type_node)
286
287 if len(children) > 1:
288 ext_attributes_node = children[1]
289 extended_attributes = ext_attributes_node_to_extended_attributes(ext_att ributes_node)
290
291 return IdlOperation(name=name, idl_type=return_type, extended_attributes=ext ended_attributes)
292
293
294 def exception_node_to_idl_exception(node):
295 # Exceptions are similar to Interfaces, but simpler
296 attributes = []
297 constants = []
298 extended_attributes = None
299 operations = []
300 name = node.GetName()
301
302 children = node.GetChildren()
303 for child in children:
304 child_class = child.GetClass()
305 if child_class == 'Attribute':
306 attribute = attribute_node_to_idl_attribute(child)
307 attributes.append(attribute)
308 elif child_class == 'Const':
309 constants.append(constant_node_to_idl_constant(child))
310 elif child_class == 'ExtAttributes':
311 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
312 elif child_class == 'ExceptionOperation':
313 operations.append(exception_operation_node_to_idl_operation(child))
314 else:
315 raise ValueError('Unrecognized node class: %s' % child_class)
316
317 return IdlException(name=name, attributes=attributes, constants=constants, e xtended_attributes=extended_attributes, operations=operations)
318
319
320 def typedef_node_to_type(node):
321 children = node.GetChildren()
322 if len(children) != 1:
323 raise ValueError('Typedef node with %s children, expected 1' % len(child ren))
324 child = children[0]
325 child_class = child.GetClass()
326 if child_class != 'Type':
327 raise ValueError('Unrecognized node class: %s' % child_class)
328 return type_node_to_type(child)
329
330 # Extended attributes
331
332
333 def ext_attributes_node_to_extended_attributes(node):
334 """
335 Returns:
336 Dictionary of {ExtAttributeName: ExtAttributeValue}.
337 Value is usually a string, with three exceptions:
338 Constructors: value is a list of Arguments nodes, corresponding to
339 possibly signatures of the constructor.
340 CustomConstructors: value is a list of Arguments nodes, corresponding to
341 possibly signatures of the custom constructor.
342 NamedConstructor: value is a Call node, corresponding to the single
343 signature of the named constructor.
344 """
345 # Primarily just make a dictionary from the children.
346 # The only complexity is handling various types of constructors:
347 # Constructors and Custom Constructors can have duplicate entries due to
348 # overloading, and thus are stored in temporary lists.
349 # However, Named Constructors cannot be overloaded, and thus do not have
350 # a list.
351 # FIXME: move Constructor logic into separate function, instead of modifying
352 # extended attributes in-place.
353 constructors = []
354 custom_constructors = []
355 extended_attributes = {}
356
357 def child_node(extended_attribute_node):
358 children = extended_attribute_node.GetChildren()
359 if not children:
360 return None
361 if len(children) > 1:
362 raise ValueError('ExtAttributes node with %s children, expected at m ost 1' % len(children))
363 return children[0]
364
365 extended_attribute_node_list = node.GetChildren()
366 for extended_attribute_node in extended_attribute_node_list:
367 name = extended_attribute_node.GetName()
368 child = child_node(extended_attribute_node)
369 child_class = child and child.GetClass()
370 if name == 'Constructor':
371 if child_class and child_class != 'Arguments':
372 raise ValueError('Constructor only supports Arguments as child, but has child of class: %s' % child_class)
373 constructors.append(child)
374 elif name == 'CustomConstructor':
375 if child_class and child_class != 'Arguments':
376 raise ValueError('[CustomConstructor] only supports Arguments as child, but has child of class: %s' % child_class)
377 custom_constructors.append(child)
378 elif name == 'NamedConstructor':
379 if child_class and child_class != 'Call':
380 raise ValueError('[NamedConstructor] only supports Call as child , but has child of class: %s' % child_class)
381 extended_attributes[name] = child
382 elif name == 'SetWrapperReferenceTo':
383 if not child:
384 raise ValueError('[SetWrapperReferenceTo] requires a child, but has none.')
385 if child_class != 'Arguments':
386 raise ValueError('[SetWrapperReferenceTo] only supports Argument s as child, but has child of class: %s' % child_class)
387 extended_attributes[name] = arguments_node_to_arguments(child)
388 elif child:
389 raise ValueError('ExtAttributes node with unexpected children: %s' % name)
390 else:
391 value = extended_attribute_node.GetProperty('VALUE')
392 extended_attributes[name] = value
393
394 # Store constructors and custom constructors in special list attributes,
395 # which are deleted later. Note plural in key.
396 if constructors:
397 extended_attributes['Constructors'] = constructors
398 if custom_constructors:
399 extended_attributes['CustomConstructors'] = custom_constructors
400
401 return extended_attributes
402
403
404 def extended_attributes_to_constructors(extended_attributes):
405 """Returns constructors and custom_constructors (lists of IdlOperations).
406
407 Auxiliary function for interface_node_to_idl_interface.
408 """
409 constructors = []
410 custom_constructors = []
411 if 'Constructors' in extended_attributes:
412 constructor_list = extended_attributes['Constructors']
413 # If not overloaded, have index 0, otherwise index from 1
414 overloaded_index = 0 if len(constructor_list) == 1 else 1
415 for arguments_node in constructor_list:
416 name = 'Constructor'
417 arguments = arguments_node_to_arguments(arguments_node)
418 constructor = IdlOperation(name=name, extended_attributes=extended_a ttributes, overloaded_index=overloaded_index, arguments=arguments)
419 constructors.append(constructor)
420 overloaded_index += 1
421
422 if 'CustomConstructors' in extended_attributes:
423 custom_constructor_list = extended_attributes['CustomConstructors']
424 # If not overloaded, have index 0, otherwise index from 1
425 overloaded_index = 0 if len(custom_constructor_list) == 1 else 1
426 for arguments_node in custom_constructor_list:
427 name = 'CustomConstructor'
428 arguments = arguments_node_to_arguments(arguments_node)
429 custom_constructor = IdlOperation(name=name, extended_attributes=ext ended_attributes, overloaded_index=overloaded_index, arguments=arguments)
430 custom_constructors.append(custom_constructor)
431 overloaded_index += 1
432
433 if 'NamedConstructor' in extended_attributes:
434 name = 'NamedConstructor'
435 call_node = extended_attributes['NamedConstructor']
436 extended_attributes['NamedConstructor'] = call_node.GetName()
437 overloaded_index = None # named constructors are not overloaded
438 children = call_node.GetChildren()
439 if len(children) != 1:
440 raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children))
441 arguments_node = children[0]
442 arguments = arguments_node_to_arguments(arguments_node)
443 named_constructor = IdlOperation(name=name, extended_attributes=extended _attributes, overloaded_index=overloaded_index, arguments=arguments)
444 # FIXME: should return named_constructor separately; appended for Perl
445 constructors.append(named_constructor)
446
447 return constructors, custom_constructors
448
449
450 def clear_constructor_attributes(extended_attributes):
451 # Deletes Constructor*s* (plural), sets Constructor (singular)
452 if 'Constructors' in extended_attributes:
453 del extended_attributes['Constructors']
454 extended_attributes['Constructor'] = None
455 if 'CustomConstructors' in extended_attributes:
456 del extended_attributes['CustomConstructors']
457 extended_attributes['CustomConstructor'] = None
458
459
460 # Types
461
462
463 def type_node_to_type(node):
464 children = node.GetChildren()
465 if len(children) < 1 or len(children) > 2:
466 raise ValueError('Type node expects 1 or 2 children (type + optional arr ay []), got %s (multi-dimensional arrays are not supported).' % len(children))
467
468 type_node_child = children[0]
469 idl_type = type_node_inner_to_type(type_node_child)
470
471 if len(children) == 2:
472 array_node = children[1]
473 array_node_class = array_node.GetClass()
474 if array_node_class != 'Array':
475 raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class)
476 idl_type += '[]'
477
478 return idl_type
479
480
481 def type_node_inner_to_type(node):
482 node_class = node.GetClass()
483 # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
484 # either a typedef shorthand (but not a Typedef declaration itself) or an
485 # interface type. We do not distinguish these, and just use the type name.
486 if node_class in ['PrimitiveType', 'Typeref']:
487 return node.GetName()
488 elif node_class == 'Any':
489 return 'any'
490 elif node_class == 'Sequence':
491 return sequence_node_to_type(node)
492 elif node_class == 'UnionType':
493 return union_type_node_to_idl_union_type(node)
494 raise ValueError('Unrecognized node class: %s' % node_class)
495
496
497 def sequence_node_to_type(node):
498 children = node.GetChildren()
499 if len(children) != 1:
500 raise ValueError('Sequence node expects exactly 1 child, got %s' % len(c hildren))
501 sequence_child = children[0]
502 sequence_child_class = sequence_child.GetClass()
503 if sequence_child_class != 'Type':
504 raise ValueError('Unrecognized node class: %s' % sequence_child_class)
505 sequence_type = type_node_to_type(sequence_child)
506 return 'sequence<%s>' % sequence_type
507
508
509 def union_type_node_to_idl_union_type(node):
510 union_member_types = []
511 for member_type_node in node.GetChildren():
512 member_type = type_node_to_type(member_type_node)
513 union_member_types.append(member_type)
514 return IdlUnionType(union_member_types=union_member_types)
OLDNEW
« no previous file with comments | « Source/bindings/scripts/idl_definitions.py ('k') | Source/bindings/scripts/idl_reader.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698