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

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

Issue 24156003: Revert IDL compiler build flow to Perl, rename 'deprecated' (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 7 years, 3 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_parser.pm » ('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, IdlT ypedef, IdlUnionType
34
35 SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
36
37
38 def build_idl_definitions_from_ast(node):
39 if node is None:
40 return None
41 node_class = node.GetClass()
42 if node_class != 'File':
43 raise ValueError('Unrecognized node class: %s' % node_class)
44 return file_node_to_idl_definitions(node)
45
46
47 def file_node_to_idl_definitions(node):
48 callback_functions = {}
49 enumerations = {}
50 exceptions = {}
51 interfaces = {}
52 typedefs = {}
53
54 # FIXME: only needed for Perl, remove later
55 file_name = os.path.abspath(node.GetName())
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 exceptions[exception.name] = exception
66 elif child_class == 'Typedef':
67 type_name = child.GetName()
68 typedefs[type_name] = typedef_node_to_idl_typedef(child)
69 elif child_class == 'Enum':
70 enumeration = enum_node_to_idl_enum(child)
71 enumerations[enumeration.name] = enumeration
72 elif child_class == 'Callback':
73 callback_function = callback_node_to_idl_callback_function(child)
74 callback_functions[callback_function.name] = callback_function
75 elif child_class == 'Implements':
76 # Implements is handled at the interface merging step
77 pass
78 else:
79 raise ValueError('Unrecognized node class: %s' % child_class)
80
81 return IdlDefinitions(callback_functions=callback_functions, enumerations=en umerations, exceptions=exceptions, file_name=file_name, interfaces=interfaces, t ypedefs=typedefs)
82
83 # Constructors for Interface definitions and interface members
84
85
86 def interface_node_to_idl_interface(node):
87 attributes = []
88 constants = []
89 constructors = None
90 custom_constructors = None
91 extended_attributes = None
92 operations = []
93 is_callback = node.GetProperty('CALLBACK') or False
94 # FIXME: uppercase 'Partial' in base IDL parser
95 is_partial = node.GetProperty('Partial') or False
96 name = node.GetName()
97 parent = None
98
99 children = node.GetChildren()
100 for child in children:
101 child_class = child.GetClass()
102 if child_class == 'Attribute':
103 attribute = attribute_node_to_idl_attribute(child)
104 # FIXME: This is a hack to support [CustomConstructor] for
105 # window.HTMLImageElement. Remove the hack.
106 clear_constructor_attributes(attribute.extended_attributes)
107 attributes.append(attribute)
108 elif child_class == 'Const':
109 constants.append(constant_node_to_idl_constant(child))
110 elif child_class == 'ExtAttributes':
111 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
112 constructors, custom_constructors = extended_attributes_to_construct ors(extended_attributes)
113 clear_constructor_attributes(extended_attributes)
114 elif child_class == 'Operation':
115 operations.append(operation_node_to_idl_operation(child))
116 elif child_class == 'Inherit':
117 parent = child.GetName()
118 else:
119 raise ValueError('Unrecognized node class: %s' % child_class)
120
121 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)
122
123
124 def attribute_node_to_idl_attribute(node):
125 data_type = None
126 extended_attributes = {}
127 is_nullable = False
128 is_read_only = node.GetProperty('READONLY') or False
129 is_static = node.GetProperty('STATIC') or False
130 name = node.GetName()
131
132 children = node.GetChildren()
133 for child in children:
134 child_class = child.GetClass()
135 if child_class == 'Type':
136 data_type = type_node_to_type(child)
137 is_nullable = child.GetProperty('NULLABLE') or False
138 elif child_class == 'ExtAttributes':
139 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
140 else:
141 raise ValueError('Unrecognized node class: %s' % child_class)
142
143 return IdlAttribute(data_type=data_type, extended_attributes=extended_attrib utes, is_nullable=is_nullable, is_read_only=is_read_only, is_static=is_static, n ame=name)
144
145
146 def constant_node_to_idl_constant(node):
147 name = node.GetName()
148
149 children = node.GetChildren()
150 num_children = len(children)
151 if num_children < 2 or num_children > 3:
152 raise ValueError('Expected 2 or 3 children, got %s' % num_children)
153
154 type_node = children[0]
155 # ConstType is more limited than Type, so subtree is smaller and we don't
156 # use the full type_node_to_type function.
157 data_type = type_node_inner_to_type(type_node)
158
159 value_node = children[1]
160 value_node_class = value_node.GetClass()
161 if value_node_class != 'Value':
162 raise ValueError('Expected Value node, got %s' % value_node_class)
163 value = value_node.GetName()
164
165 extended_attributes = None
166 if num_children == 3:
167 ext_attributes_node = children[2]
168 extended_attributes = ext_attributes_node_to_extended_attributes(ext_att ributes_node)
169
170 return IdlConstant(data_type=data_type, extended_attributes=extended_attribu tes, name=name, value=value)
171
172
173 def operation_node_to_idl_operation(node):
174 name = node.GetName()
175 # FIXME: AST should use None internally
176 if name == '_unnamed_':
177 name = None
178
179 is_static = node.GetProperty('STATIC') or False
180 specials = []
181 property_dictionary = node.GetProperties()
182 for special_keyword in SPECIAL_KEYWORD_LIST:
183 if special_keyword in property_dictionary:
184 specials.append(special_keyword.lower())
185
186 extended_attributes = None
187 arguments = []
188 return_type = None
189 children = node.GetChildren()
190 for child in children:
191 child_class = child.GetClass()
192 if child_class == 'Arguments':
193 arguments = arguments_node_to_arguments(child)
194 elif child_class == 'Type':
195 return_type = type_node_to_type(child)
196 elif child_class == 'ExtAttributes':
197 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
198 else:
199 raise ValueError('Unrecognized node class: %s' % child_class)
200
201 return IdlOperation(name=name, data_type=return_type, extended_attributes=ex tended_attributes, is_static=is_static, arguments=arguments, specials=specials)
202
203
204 def arguments_node_to_arguments(node):
205 # [Constructor] and [CustomConstructor] without arguments (the bare form)
206 # have None instead of an arguments node, but have the same meaning as using
207 # an empty argument list, [Constructor()], so special-case this.
208 # http://www.w3.org/TR/WebIDL/#Constructor
209 if node is None:
210 return []
211 arguments = []
212 argument_node_list = node.GetChildren()
213 for argument_node in argument_node_list:
214 arguments.append(argument_node_to_idl_argument(argument_node))
215 return arguments
216
217
218 def argument_node_to_idl_argument(node):
219 name = node.GetName()
220
221 data_type = None
222 extended_attributes = {}
223 # FIXME: Boolean values are inconsistent due to Perl compatibility.
224 # Make all default to False once Perl removed.
225 is_nullable = False
226 is_optional = node.GetProperty('OPTIONAL')
227 is_variadic = None
228 children = node.GetChildren()
229 for child in children:
230 child_class = child.GetClass()
231 if child_class == 'Type':
232 data_type = type_node_to_type(child)
233 is_nullable = child.GetProperty('NULLABLE')
234 elif child_class == 'ExtAttributes':
235 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
236 elif child_class == 'Argument':
237 child_name = child.GetName()
238 if child_name != '...':
239 raise ValueError('Unrecognized Argument node; expected "...", go t "%s"' % child_name)
240 is_variadic = child.GetProperty('ELLIPSIS') or False
241 else:
242 raise ValueError('Unrecognized node class: %s' % child_class)
243
244 return IdlArgument(name=name, data_type=data_type, extended_attributes=exten ded_attributes, is_nullable=is_nullable, is_optional=is_optional, is_variadic=is _variadic)
245
246 # Constructors for for non-interface definitions
247
248
249 def callback_node_to_idl_callback_function(node):
250 name = node.GetName()
251 children = node.GetChildren()
252 num_children = len(children)
253 if num_children != 2:
254 raise ValueError('Expected 2 children, got %s' % num_children)
255
256 type_node = children[0]
257 data_type = type_node_to_type(type_node)
258
259 arguments_node = children[1]
260 arguments_node_class = arguments_node.GetClass()
261 if arguments_node_class != 'Arguments':
262 raise ValueError('Expected Value node, got %s' % arguments_node_class)
263 arguments = arguments_node_to_arguments(arguments_node)
264
265 return IdlCallbackFunction(name=name, data_type=data_type, arguments=argumen ts)
266
267
268 def enum_node_to_idl_enum(node):
269 name = node.GetName()
270 values = []
271 for child in node.GetChildren():
272 values.append(child.GetName())
273 return IdlEnum(name=name, values=values)
274
275
276 def exception_operation_node_to_idl_operation(node):
277 # Needed to handle one case in DOMException.idl:
278 # // Override in a Mozilla compatible format
279 # [NotEnumerable] DOMString toString();
280 # FIXME: can we remove this? replace with a stringifier?
281 extended_attributes = {}
282 name = node.GetName()
283 children = node.GetChildren()
284 if len(children) < 1 or len(children) > 2:
285 raise ValueError('ExceptionOperation node with %s children, expected 1 o r 2' % len(children))
286
287 type_node = children[0]
288 return_type = type_node_to_type(type_node)
289
290 if len(children) > 1:
291 ext_attributes_node = children[1]
292 extended_attributes = ext_attributes_node_to_extended_attributes(ext_att ributes_node)
293
294 return IdlOperation(name=name, data_type=return_type, extended_attributes=ex tended_attributes)
295
296
297 def exception_node_to_idl_exception(node):
298 # Exceptions are similar to Interfaces, but simpler
299 attributes = []
300 constants = []
301 extended_attributes = None
302 operations = []
303 name = node.GetName()
304
305 children = node.GetChildren()
306 for child in children:
307 child_class = child.GetClass()
308 if child_class == 'Attribute':
309 attribute = attribute_node_to_idl_attribute(child)
310 attributes.append(attribute)
311 elif child_class == 'Const':
312 constants.append(constant_node_to_idl_constant(child))
313 elif child_class == 'ExtAttributes':
314 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
315 elif child_class == 'ExceptionOperation':
316 operations.append(exception_operation_node_to_idl_operation(child))
317 else:
318 raise ValueError('Unrecognized node class: %s' % child_class)
319
320 return IdlException(name=name, attributes=attributes, constants=constants, e xtended_attributes=extended_attributes, operations=operations)
321
322
323 def typedef_node_to_idl_typedef(node):
324 data_type = None
325 extended_attributes = None
326
327 children = node.GetChildren()
328 for child in children:
329 child_class = child.GetClass()
330 if child_class == 'Type':
331 data_type = type_node_to_type(child)
332 elif child_class == 'ExtAttributes':
333 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
334 raise ValueError('Extended attributes in a typedef are untested!')
335 else:
336 raise ValueError('Unrecognized node class: %s' % child_class)
337
338 return IdlTypedef(data_type=data_type, extended_attributes=extended_attribut es)
339
340 # Extended attributes
341
342
343 def ext_attributes_node_to_extended_attributes(node):
344 """
345 Returns:
346 Dictionary of {ExtAttributeName: ExtAttributeValue}.
347 Value is usually a string, with three exceptions:
348 Constructors: value is a list of Arguments nodes, corresponding to
349 possibly signatures of the constructor.
350 CustomConstructors: value is a list of Arguments nodes, corresponding to
351 possibly signatures of the custom constructor.
352 NamedConstructor: value is a Call node, corresponding to the single
353 signature of the named constructor.
354 """
355 # Primarily just make a dictionary from the children.
356 # The only complexity is handling various types of constructors:
357 # Constructors and Custom Constructors can have duplicate entries due to
358 # overloading, and thus are stored in temporary lists.
359 # However, Named Constructors cannot be overloaded, and thus do not have
360 # a list.
361 # FIXME: Add overloading for Named Constructors and remove custom bindings
362 # for HTMLImageElement
363 constructors = []
364 custom_constructors = []
365 extended_attributes = {}
366
367 attribute_list = node.GetChildren()
368 for attribute in attribute_list:
369 name = attribute.GetName()
370 children = attribute.GetChildren()
371 if name in ['Constructor', 'CustomConstructor', 'NamedConstructor']:
372 child = None
373 child_class = None
374 if children:
375 if len(children) > 1:
376 raise ValueError('ExtAttributes node with %s children, expec ted at most 1' % len(children))
377 child = children[0]
378 child_class = child.GetClass()
379 if name == 'Constructor':
380 if child_class and child_class != 'Arguments':
381 raise ValueError('Constructor only supports Arguments as chi ld, but has child of class: %s' % child_class)
382 constructors.append(child)
383 elif name == 'CustomConstructor':
384 if child_class and child_class != 'Arguments':
385 raise ValueError('Custom Constructor only supports Arguments as child, but has child of class: %s' % child_class)
386 custom_constructors.append(child)
387 else: # name == 'NamedConstructor'
388 if child_class and child_class != 'Call':
389 raise ValueError('Named Constructor only supports Call as ch ild, but has child of class: %s' % child_class)
390 extended_attributes[name] = child
391 elif children:
392 raise ValueError('Non-constructor ExtAttributes node with children: %s' % name)
393 else:
394 value = attribute.GetProperty('VALUE')
395 extended_attributes[name] = value
396
397 # Store constructors and custom constructors in special list attributes,
398 # which are deleted later. Note plural in key.
399 if constructors:
400 extended_attributes['Constructors'] = constructors
401 if custom_constructors:
402 extended_attributes['CustomConstructors'] = custom_constructors
403
404 return extended_attributes
405
406
407 def extended_attributes_to_constructors(extended_attributes):
408 """Returns constructors and custom_constructors (lists of IdlOperations).
409
410 Auxiliary function for interface_node_to_idl_interface.
411 """
412 constructors = []
413 custom_constructors = []
414 if 'Constructors' in extended_attributes:
415 constructor_list = extended_attributes['Constructors']
416 # If not overloaded, have index 0, otherwise index from 1
417 overloaded_index = 0 if len(constructor_list) == 1 else 1
418 for arguments_node in constructor_list:
419 name = 'Constructor'
420 arguments = arguments_node_to_arguments(arguments_node)
421 constructor = IdlOperation(name=name, extended_attributes=extended_a ttributes, overloaded_index=overloaded_index, arguments=arguments)
422 constructors.append(constructor)
423 overloaded_index += 1
424
425 # Prefix 'CallWith' and 'RaisesException' with 'Constructor'
426 # FIXME: Change extended attributes to include prefix explicitly.
427 if 'CallWith' in extended_attributes:
428 extended_attributes['ConstructorCallWith'] = extended_attributes['Ca llWith']
429 del extended_attributes['CallWith']
430 if 'RaisesException' in extended_attributes:
431 extended_attributes['ConstructorRaisesException'] = extended_attribu tes['RaisesException']
432 del extended_attributes['RaisesException']
433
434 if 'CustomConstructors' in extended_attributes:
435 custom_constructor_list = extended_attributes['CustomConstructors']
436 # If not overloaded, have index 0, otherwise index from 1
437 overloaded_index = 0 if len(custom_constructor_list) == 1 else 1
438 for arguments_node in custom_constructor_list:
439 name = 'CustomConstructor'
440 arguments = arguments_node_to_arguments(arguments_node)
441 custom_constructor = IdlOperation(name=name, extended_attributes=ext ended_attributes, overloaded_index=overloaded_index, arguments=arguments)
442 custom_constructors.append(custom_constructor)
443 overloaded_index += 1
444
445 if 'NamedConstructor' in extended_attributes:
446 name = 'NamedConstructor'
447 call_node = extended_attributes['NamedConstructor']
448 extended_attributes['NamedConstructor'] = call_node.GetName()
449 overloaded_index = None # named constructors are not overloaded
450 children = call_node.GetChildren()
451 if len(children) != 1:
452 raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children))
453 arguments_node = children[0]
454 arguments = arguments_node_to_arguments(arguments_node)
455 named_constructor = IdlOperation(name=name, extended_attributes=extended _attributes, overloaded_index=overloaded_index, arguments=arguments)
456 constructors.append(named_constructor)
457
458 return constructors, custom_constructors
459
460
461 def clear_constructor_attributes(extended_attributes):
462 # Deletes Constructor*s* (plural), sets Constructor (singular)
463 if 'Constructors' in extended_attributes:
464 del extended_attributes['Constructors']
465 extended_attributes['Constructor'] = None
466 if 'CustomConstructors' in extended_attributes:
467 del extended_attributes['CustomConstructors']
468 extended_attributes['CustomConstructor'] = None
469
470
471 # Types
472
473
474 def type_node_to_type(node):
475 children = node.GetChildren()
476 if len(children) < 1 or len(children) > 2:
477 raise ValueError('Type node expects 1 or 2 children (type + optional arr ay []), got %s (multi-dimensional arrays are not supported).' % len(children))
478
479 type_node_child = children[0]
480 data_type = type_node_inner_to_type(type_node_child)
481
482 if len(children) == 2:
483 array_node = children[1]
484 array_node_class = array_node.GetClass()
485 if array_node_class != 'Array':
486 raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class)
487 data_type += '[]'
488
489 return data_type
490
491
492 def type_node_inner_to_type(node):
493 node_class = node.GetClass()
494 # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
495 # either a typedef shorthand (but not a Typedef declaration itself) or an
496 # interface type. We do not distinguish these, and just use the type name.
497 if node_class in ['PrimitiveType', 'Typeref']:
498 return node.GetName()
499 elif node_class == 'Any':
500 return 'any'
501 elif node_class == 'Sequence':
502 return sequence_node_to_type(node)
503 elif node_class == 'UnionType':
504 return union_type_node_to_idl_union_type(node)
505 raise ValueError('Unrecognized node class: %s' % node_class)
506
507
508 def sequence_node_to_type(node):
509 children = node.GetChildren()
510 if len(children) != 1:
511 raise ValueError('Sequence node expects exactly 1 child, got %s' % len(c hildren))
512 sequence_child = children[0]
513 sequence_child_class = sequence_child.GetClass()
514 if sequence_child_class != 'Type':
515 raise ValueError('Unrecognized node class: %s' % sequence_child_class)
516 sequence_type = type_node_to_type(sequence_child)
517 return 'sequence<%s>' % sequence_type
518
519
520 def union_type_node_to_idl_union_type(node):
521 union_member_types = []
522 for member_type_node in node.GetChildren():
523 member_type = type_node_to_type(member_type_node)
524 union_member_types.append(member_type)
525 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_parser.pm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698