Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
idlnode.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5
6import os
7import sys
8
9import idl_definitions
10from generator import MultitypeSortKey
11from idl_types import IdlType, IdlNullableType, IdlUnionType, IdlArrayOrSequenceType
12import dependency
13
14new_asts = {}
15
16# Report of union types mapped to any.
17_unions_to_any = []
18
19
21 global _unions_to_any
22
23 warnings = []
24 for union_id in sorted(_unions_to_any):
25 warnings.append('Union type %s is mapped to \'any\'' % union_id)
26
27 return warnings
28
29
30# Ugly but Chrome IDLs can reference typedefs in any IDL w/o an include. So we
31# need to remember any typedef seen then alias any reference to a typedef.
32_typeDefsFixup = []
33
34
35def _addTypedef(typedef):
36 _typeDefsFixup.append(typedef)
37
38
39def resolveTypedef(type):
40 """ Given a type if it's a known typedef (only typedef's that aren't union)
41 are remembered for fixup. typedefs that are union type are mapped to
42 any so those we don't need to alias. typedefs referenced in the file
43 where the typedef was defined are automatically aliased to the real type.
44 This resolves typedef where the declaration is in another IDL file.
45 """
46 for typedef in _typeDefsFixup:
47 if typedef.id == type.id:
48 return typedef.type
49
50 return type
51
52
53_operation_suffix_map = {
54 '__getter__': "Getter",
55 '__setter__': "Setter",
56 '__delete__': "Deleter",
57}
58
59class IDLNode(object):
60 """Base class for all IDL elements.
61 IDLNode may contain various child nodes, and have properties. Examples
62 of IDLNode are interfaces, interface members, function arguments,
63 etc.
64 """
65
66 def __init__(self, ast, id=None):
67 """Initializes an IDLNode from a PegParser AST output."""
68 if ast:
69 self.id = self._find_first(ast, 'Id') if ast is not None else None
70 else:
71 # Support synthesized IDLNode created w/o an AST (e.g., setlike support).
72 self.id = id
73
74 def __repr__(self):
75 """Generates string of the form <class id extra extra ... 0x12345678>."""
76 extras = self._extra_repr()
77 if isinstance(extras, list):
78 extras = ' '.join([str(e) for e in extras])
79 try:
80 if self.id:
81 return '<%s %s 0x%x>' % (type(self).__name__,
82 ('%s %s' % (self.id, extras)).strip(),
83 hash(self))
84 return '<%s %s 0x%x>' % (type(self).__name__, extras, hash(self))
85 except Exception as e:
86 return "can't convert to string: %s" % e
87
88 def _extra_repr(self):
89 """Returns string of extra info for __repr__()."""
90 return ''
91
92 def __eq__(self, other):
93 """Override default equals operation.
94 IDLNodes are equal if all their properties are equal."""
95 if other is None or not isinstance(other, IDLNode):
96 return 1
97 return self.__dict__.__eq__(other.__dict__)
98
99 def __hash__(self):
100 """Define default hashing behavior.
101 In order to comply with a == b => hash(a) == hash(b), we recursively iterate
102 self.__dict__ and convert all objects to hashable objects."""
103 return self.to_hash()
104
105 def reset_id(self, newId):
106 """Reset the id of the Node. This is typically done during a normalization
107 phase (e.g., "DOMWindow" -> "Window")."""
108 self.id = newId
109
110 def all(self, type_filter=None):
111 """Returns a list containing this node and all it child nodes
112 (recursive).
113
114 Args:
115 type_filter -- can be used to limit the results to a specific
116 node type (e.g. IDLOperation).
117 """
118 res = []
119 if type_filter is None or isinstance(self, type_filter):
120 res.append(self)
121 for v in self._all_subnodes():
122 if isinstance(v, IDLNode):
123 res.extend(v.all(type_filter))
124 elif isinstance(v, list):
125 for item in v:
126 if isinstance(item, IDLNode):
127 res.extend(item.all(type_filter))
128 return res
129
130 def _all_subnodes(self):
131 """Accessor used by all() to find subnodes."""
132 return self.__dict__.values()
133
134 def to_dict(self):
135 """Converts the IDLNode and its children into a dictionary.
136 This method is useful mostly for debugging and pretty printing.
137 """
138 res = {}
139 for (k, v) in self.__dict__.items():
140 if v == None or v == False or v == [] or v == {}:
141 # Skip empty/false members.
142 continue
143 elif isinstance(v, IDLDictNode) and not len(v):
144 # Skip empty dict sub-nodes.
145 continue
146 elif isinstance(v, list):
147 # Convert lists:
148 new_v = []
149 for sub_node in v:
150 if isinstance(sub_node, IDLNode):
151 # Convert sub-node:
152 new_v.append(sub_node.to_dict())
153 else:
154 new_v.append(sub_node)
155 v = new_v
156 elif isinstance(v, IDLNode):
157 # Convert sub-node:
158 v = v.to_dict()
159 res[k] = v
160 return res
161
162 def to_hash(self):
163 return hash(self._to_hashable(self))
164
165 def _to_hashable(self, obj):
166 # By default, lists and dicts are not hashable, and user-defined objects
167 # are unordered. In order to make a consistent hash for a given object,
168 # this converts unhashable types and sorts properties.
169 if isinstance(obj, list):
170 # Convert lists to tuples.
171 new_obj = []
172 for item in obj:
173 new_obj.append(self._to_hashable(item))
174 return tuple(new_obj)
175 elif isinstance(obj, dict):
176 # Convert dicts to frozensets of tuples.
177 new_obj = set()
178 # Sort to ensure fixed order.
179 for (k2, v2) in sorted(obj.items(), key=MultitypeSortKey):
180 new_obj.add((self._to_hashable(k2), self._to_hashable(v2)))
181 return frozenset(new_obj)
182 elif hasattr(obj, '__dict__'):
183 items = []
184 # Sort properties to ensure fixed order.
185 for (k, v) in sorted(obj.__dict__.items(), key=MultitypeSortKey):
186 items.append((k, self._to_hashable(v)))
187 return tuple(items)
188 else:
189 return obj
190
191 def _find_all(self, ast, label, max_results=sys.maxsize):
192 """Searches the AST for tuples with a given label. The PegParser
193 output is composed of lists and tuples, where the tuple 1st argument
194 is a label. If ast root is a list, will search recursively inside each
195 member in the list.
196
197 Args:
198 ast -- the AST to search.
199 label -- the label to look for.
200 res -- results are put into this list.
201 max_results -- maximum number of results.
202 """
203 res = []
204 if max_results <= 0:
205 return res
206
207 if isinstance(ast, list):
208 for childAst in ast:
209 if childAst and \
210 not(isinstance(childAst, dict)) and \
211 not(isinstance(childAst, str)) and \
212 not(isinstance(childAst, tuple)) and \
213 childAst.__module__ == "idl_definitions":
214 field_name = self._convert_label_to_field(label)
215 if hasattr(childAst, field_name):
216 field_value = getattr(childAst, field_name)
217 # It's an IdlType we need the string name of the type.
218 if field_name == 'idl_type':
219 field_value = getattr(field_value, 'base_type')
220 res.append(field_value)
221 else:
222 sub_res = self._find_all(childAst, label,
223 max_results - len(res))
224 res.extend(sub_res)
225 elif isinstance(ast, tuple):
226 (nodeLabel, value) = ast
227 if nodeLabel == label:
228 res.append(value)
229 # TODO(terry): Seems bogus to check for so many things probably better to just
230 # pass in blink_compile and drive it off from that...
231 elif (ast and not (isinstance(ast, dict)) and
232 not (isinstance(ast, str)) and
233 (ast.__module__ == "idl_definitions" or
234 ast.__module__ == "idl_types")):
235 field_name = self._convert_label_to_field(label)
236 if hasattr(ast, field_name):
237 field_value = getattr(ast, field_name)
238 if field_value:
239 if label == 'Interface' or label == 'Enum' or label == "Dictionary":
240 for key in field_value:
241 value = field_value[key]
242 res.append(value)
243 elif isinstance(field_value, list):
244 for item in field_value:
245 res.append(item)
246 elif label == 'ParentInterface' or label == 'InterfaceType':
247 # Fetch the AST for the parent interface.
248 parent_idlnode = new_asts[field_value]
249 res.append(parent_idlnode.interfaces[field_value])
250 else:
251 res.append(field_value)
252
253 return res
254
255 def _find_first(self, ast, label):
256 """Convenience method for _find_all(..., max_results=1).
257 Returns a single element instead of a list, or None if nothing
258 is found."""
259 res = self._find_all(ast, label, max_results=1)
260 if len(res):
261 return res[0]
262 return None
263
264 def _has(self, ast, label):
265 """Returns true if an element with the given label is
266 in the AST by searching for it."""
267 return len(self._find_all(ast, label, max_results=1)) == 1
268
269 # Mapping from original AST tuple names to new AST field names idl_definitions.Idl*.
270 def _convert_label_to_field(self, label):
271 label_field = {
272 # Keys old AST names, Values Blink IdlInterface names.
273 'ParentInterface': 'parent',
274 'Id': 'name',
275 'Interface': 'interfaces',
276 'Callback_Function': 'callback_functions',
277 'Callback': 'is_callback',
278 'Partial': 'is_partial',
279 'Operation': 'operations',
280 'Attribute': 'attributes',
281 'Const': 'constants',
282 'Type': 'idl_type',
283 'ExtAttrs': 'extended_attributes',
284 'Special': 'specials',
285 'ReturnType': 'idl_type',
286 'Argument': 'arguments',
287 'InterfaceType': 'name',
288 'ConstExpr': 'value',
289 'Static': 'is_static',
290 'ReadOnly': 'is_read_only',
291 'Optional': 'is_optional',
292 'Nullable': 'is_nullable',
293 'Enum': 'enumerations',
294 'Annotation':
295 '', # TODO(terry): Ignore annotation used for database cache.
296 'TypeDef': '', # typedef in an IDL are already resolved.
297 'Dictionary': 'dictionaries',
298 'Member': 'members',
299 'Default': 'default_value', # Dictionary member default value
300 }
301 result = label_field.get(label)
302 if result != '' and not (result):
303 print('FATAL ERROR: AST mapping name not found %s.' % label)
304 return result if result else ''
305
306 def _convert_all(self, ast, label, idlnode_ctor):
307 """Converts AST elements into IDLNode elements.
308 Uses _find_all to find elements with a given label and converts
309 them into IDLNodes with a given constructor.
310 Returns:
311 A list of the converted nodes.
312 Args:
313 ast -- the ast element to start a search at.
314 label -- the element label to look for.
315 idlnode_ctor -- a constructor function of one of the IDLNode
316 sub-classes.
317 """
318 res = []
319 found = self._find_all(ast, label)
320 if not found:
321 return res
322 if not isinstance(found, list):
323 raise RuntimeError("Expected list but %s found" % type(found))
324 for childAst in found:
325 converted = idlnode_ctor(childAst)
326 res.append(converted)
327 return res
328
329 def _convert_first(self, ast, label, idlnode_ctor):
330 """Like _convert_all, but only converts the first found results."""
331 childAst = self._find_first(ast, label)
332 if not childAst:
333 return None
334 return idlnode_ctor(childAst)
335
336 def _convert_ext_attrs(self, ast):
337 """Helper method for uniform conversion of extended attributes."""
339
340 def _convert_annotations(self, ast):
341 """Helper method for uniform conversion of annotations."""
343
344 def _convert_constants(self, ast, js_name):
345 """Helper method for uniform conversion of dictionary members."""
346 self.members = IDLDictionaryMembers(ast, js_name)
347
348
350 """Base class for dictionary-like IDL nodes such as extended attributes
351 and annotations. The base class implements various dict interfaces."""
352
353 def __init__(self, ast):
354 IDLNode.__init__(self, None)
355 if ast is not None and isinstance(ast, dict):
356 self.__map = ast
357 else:
358 self.__map = {}
359
360 def __len__(self):
361 return len(self.__map)
362
363 def __getitem__(self, key):
364 return self.__map[key]
365
366 def __setitem__(self, key, value):
367 self.__map[key] = value
368
369 def __delitem__(self, key):
370 del self.__map[key]
371
372 def __contains__(self, key):
373 return key in self.__map
374
375 def __iter__(self):
376 return self.__map.__iter__()
377
378 def get(self, key, default=None):
379 return self.__map.get(key, default)
380
381 def setdefault(self, key, value=None):
382 return self.__map.setdefault(key, value)
383
384 def items(self):
385 return self.__map.items()
386
387 def keys(self):
388 return self.__map.keys()
389
390 def values(self):
391 return self.__map.values()
392
393 def clear(self):
394 self.__map = {}
395
396 def to_dict(self):
397 """Overrides the default IDLNode.to_dict behavior.
398 The IDLDictNode members are copied into a new dictionary, and
399 IDLNode members are recursively converted into dicts as well.
400 """
401 res = {}
402 for (k, v) in self.__map.items():
403 if isinstance(v, IDLNode):
404 v = v.to_dict()
405 res[k] = v
406 return res
407
408 def _all_subnodes(self):
409 # Usually an IDLDictNode does not contain further IDLNodes.
410 return []
411
412
414 """IDLFile is the top-level node in each IDL file. It may contain interfaces."""
415
416 DART_IDL = 'dart.idl'
417
418 def __init__(self, ast, filename=None):
419 IDLNode.__init__(self, ast)
420 self.filename = filename
421
422 filename_basename = os.path.basename(filename)
423
424 # Report of union types mapped to any.
425
426 # Remember all the typedefs before we start walking the AST. Some
427 # IDLs now have typedefs before interfaces. So we need to remember
428 # to resolve the typedefs.
429 self.typeDefs = self._convert_all(ast, 'TypeDef', IDLTypeDef)
430 for typedefName in ast.typedefs:
431 typedef_type = ast.typedefs[typedefName]
432 # Ignore unions and dictionaries for now we just want normal typedefs to resolve our arguments/types.
433 if not (isinstance(typedef_type.idl_type, IdlUnionType)) and not (
434 typedef_type.idl_type.base_type == 'Dictionary'):
435 _addTypedef(IDLTypeDef(typedef_type))
436
437 self.interfaces = self._convert_all(ast, 'Interface', IDLInterface)
438 self.dictionaries = self._convert_all(ast, 'Dictionary', IDLDictionary)
439
440 if len(ast.callback_functions) > 0:
441 callback_functions = self._convert_all(ast, 'Callback_Function',
442 IDLCallbackFunction)
443 for callback_function in callback_functions:
444 for annotation in callback_function.annotations:
445 callback = callback_function.annotations[annotation]
446 cb_interface = IDLInterface(None, callback.name)
447 cb_interface.ext_attrs['Callback'] = len(callback.arguments)
448 op = IDLOperation(None, cb_interface.id, "handleEvent")
449 op.type = IDLType(callback.idl_type)
450 op.type = resolveTypedef(op.type)
451
452 if len(callback.arguments) > 0:
453 op.arguments = self._convert_all(
454 callback, 'Argument', IDLArgument)
455
456 cb_interface.operations = [op]
457 self.interfaces.append(cb_interface)
458
459 is_blink = not (isinstance(
460 ast, list)) and ast.__module__ == 'idl_definitions'
461
462 if is_blink:
463 # implements is handled by the interface merging step (see the function
464 # merge_interface_dependencies).
465 for interface in self.interfaces:
466 blink_interface = ast.interfaces.get(interface.id)
467 if filename_basename == self.DART_IDL:
468 # Special handling for dart.idl we need to remember the interface,
469 # since we could have many (not one interface / file). Then build up
470 # the IDLImplementsStatement for any implements in dart.idl.
471 interface_info = dependency.get_interfaces_info(
472 )['__dart_idl___']
473
475
476 implement_pairs = interface_info['implement_pairs']
477 for implement_pair in implement_pairs:
478 interface_name = implement_pair[0]
479 implemented_name = implement_pair[1]
480
481 implementor = new_asts[interface_name].interfaces.get(
482 interface_name)
483 implement_statement = self._createImplementsStatement(
484 implementor, implemented_name)
485
486 self.implementsStatements.append(implement_statement)
487 elif interface.id in dependency.get_interfaces_info():
488 interface_info = dependency.get_interfaces_info()[interface.
489 id]
490
491 implements = []
492 if 'implements_interfaces' in interface_info:
493 implements = interface_info['implements_interfaces']
494 if not (blink_interface.is_partial) and len(implements) > 0:
495 implementor = new_asts[interface.id].interfaces.get(
496 interface.id)
497
498 self.implementsStatements = []
499
500 # TODO(terry): Need to handle more than one implements.
501 for implemented_name in implements:
502 implement_statement = self._createImplementsStatement(
503 implementor, implemented_name)
505 implement_statement)
506 else:
507 self.implementsStatements = []
508 else:
510 ast, 'ImplStmt', IDLImplementsStatement)
511
512 # Record typedefs that are unions.
513 for typedefName in ast.typedefs:
514 typedef_type = ast.typedefs[typedefName]
515 if isinstance(typedef_type.idl_type, IdlUnionType):
516 self.typeDefs.append(IDLTypeDef(typedef_type))
517 elif typedef_type.idl_type.base_type == 'Dictionary':
518 dictionary = IDLDictionary(typedef_type, True)
519 self.dictionaries.append(dictionary)
520
521 self.enums = self._convert_all(ast, 'Enum', IDLEnum)
522
523 def _createImplementsStatement(self, implementor, implemented_name):
524 implemented = new_asts[implemented_name].interfaces.get(
525 implemented_name)
526
527 implement_statement = IDLImplementsStatement(implemented)
528
529 implement_statement.implementor = IDLType(implementor)
530 implement_statement.implemented = IDLType(implemented)
531
532 return implement_statement
533
534
536 """IDLModule has an id, and may contain interfaces, type defs and
537 implements statements."""
538
539 def __init__(self, ast):
540 IDLNode.__init__(self, ast)
541 self._convert_ext_attrs(ast)
542 self._convert_annotations(ast)
543 self.interfaces = self._convert_all(ast, 'Interface', IDLInterface)
544
545 is_blink = ast.__module__ == 'idl_definitions'
546
547 # No reason to handle typedef they're already aliased in Blink's AST.
548 self.typeDefs = [] if is_blink else self._convert_all(
549 ast, 'TypeDef', IDLTypeDef)
550
551 self.enums = self._convert_all(ast, 'Enum', IDLNode)
552
553 if is_blink:
554 # implements is handled by the interface merging step (see the function
555 # merge_interface_dependencies).
556 for interface in self.interfaces:
557 interface_info = get_interfaces_info()[interface.id]
558 # TODO(terry): Same handling for implementsStatements as in IDLFile?
559 self.implementsStatements = interface_info[
560 'implements_interfaces']
561 else:
563 ast, 'ImplStmt', IDLImplementsStatement)
564
565
567 """IDLExtAttrs is an IDLDictNode that stores IDL Extended Attributes.
568 Modules, interfaces, members and arguments can all own IDLExtAttrs."""
569
570 def __init__(self, ast=None):
571 IDLDictNode.__init__(self, None)
572 if not ast:
573 return
574 if not (isinstance(ast, list)) and ast.__module__ == "idl_definitions":
575 # Pull out extended attributes from Blink AST.
576 for name, value in ast.extended_attributes.items():
577 # TODO(terry): Handle constructors...
578 if name == 'NamedConstructor' or name == 'Constructor':
579 for constructor in ast.constructors:
580 if constructor.name == 'NamedConstructor':
581 constructor_name = ast.extended_attributes[
582 'NamedConstructor']
583 else:
584 constructor_name = None
585 func_value = IDLExtAttrFunctionValue(
586 constructor_name, constructor.arguments, True)
587 if name == 'Constructor':
588 self.setdefault('Constructor',
589 []).append(func_value)
590 else:
591 self[name] = func_value
592 elif name == 'SetWrapperReferenceTo':
593 # NOTE: No need to process handling for GC wrapper. But if its a reference
594 # to another type via an IdlArgument we'd need to convert to IDLArgument
595 # otherwise the type might be a reference to another type and the circularity
596 # will break deep_copy which is done later to the interfaces in the
597 # database. If we every need SetWrapperReferenceTo then we'd need to
598 # convert IdlArgument to IDLArgument.
599 continue
600 else:
601 self[name] = value
602 else:
603 ext_attrs_ast = self._find_first(ast, 'ExtAttrs')
604 if not ext_attrs_ast:
605 return
606 for ext_attr in self._find_all(ext_attrs_ast, 'ExtAttr'):
607 name = self._find_first(ext_attr, 'Id')
608 value = self._find_first(ext_attr, 'ExtAttrValue')
609
610 if name == 'Constructor':
611 # There might be multiple constructor attributes, collect them
612 # as a list. Represent plain Constructor attribute
613 # (without any signature) as None.
614 assert value is None
615 func_value = None
616 ctor_args = self._find_first(ext_attr, 'ExtAttrArgList')
617 if ctor_args:
618 func_value = IDLExtAttrFunctionValue(None, ctor_args)
619 self.setdefault('Constructor', []).append(func_value)
620 continue
621
622 func_value = self._find_first(value, 'ExtAttrFunctionValue')
623 if func_value:
624 # E.g. NamedConstructor=Audio(optional DOMString src)
625 self[name] = IDLExtAttrFunctionValue(
626 func_value,
627 self._find_first(func_value, 'ExtAttrArgList'))
628 continue
629
630 self[name] = value
631
632 def _all_subnodes(self):
633 # Extended attributes may contain IDLNodes, e.g. IDLExtAttrFunctionValue
634 return self.values()
635
636
637# IDLExtAttrFunctionValue is used for constructors defined in the IDL.
639 """IDLExtAttrFunctionValue."""
640
641 def __init__(self, func_value_ast, arg_list_ast, is_blink=False):
642 IDLNode.__init__(self, func_value_ast)
643 if is_blink:
644 # Blink path
645 self.idid = func_value_ast # func_value_ast is the function name for Blink.
646 self.arguments = []
647 for argument in arg_list_ast:
648 self.arguments.append(IDLArgument(argument))
649 else:
650 self.arguments = self._convert_all(arg_list_ast, 'Argument',
651 IDLArgument)
652
653
655 """IDLType is used to describe constants, attributes and operations'
656 return and input types. IDLType matches AST labels such as ScopedName,
657 StringType, VoidType, IntegerType, etc.
658 NOTE: AST of None implies synthesize IDLType the id is passed in used by
659 setlike."""
660
661 def __init__(self, ast, id=None):
662 global _unions_to_any
663
664 IDLNode.__init__(self, ast, id)
665
666 if not ast:
667 # Support synthesized IDLType with no AST (e.g., setlike support).
668 return
669
670 self.nullable = self._has(ast, 'Nullable')
671 # Search for a 'ScopedName' or any label ending with 'Type'.
672 if isinstance(ast, list):
673 self.idid = self._find_first(ast, 'ScopedName')
674 if not self.idid:
675 # FIXME: use regexp search instead
676 def findType(ast):
677 for label, childAst in ast:
678 if label.endswith('Type'):
679 type = self._label_to_type(label, ast)
680 if type != 'sequence':
681 return type
682 type_ast = self._find_first(childAst, 'Type')
683 if not type_ast:
684 return type
685 return 'sequence<%s>' % findType(type_ast)
686 raise Exception('No type declaration found in %s' % ast)
687
688 self.idid = findType(ast)
689 # TODO(terry): Remove array_modifiers id has [] appended, keep for old
690 # parsing.
691 array_modifiers = self._find_first(ast, 'ArrayModifiers')
692 if array_modifiers:
693 self.idid += array_modifiers
694 elif isinstance(ast, tuple):
695 (label, value) = ast
696 if label == 'ScopedName':
697 self.idid = value
698 else:
699 self.idid = self._label_to_type(label, ast)
700 elif isinstance(ast, str):
701 self.idid = ast
702 # New blink handling.
703 elif ast.__module__ == "idl_types":
704 if isinstance(ast, IdlType) or isinstance(ast, IdlArrayOrSequenceType) or \
705 isinstance(ast, IdlNullableType):
706 if isinstance(ast,
707 IdlNullableType) and ast.inner_type.is_union_type:
708 # Report of union types mapped to any.
709 if not (self.idid in _unions_to_any):
710 _unions_to_any.append(self.idid)
711 # TODO(terry): For union types use any otherwise type is unionType is
712 # not found and is removed during merging.
713 self.idid = 'any'
714 else:
715 type_name = str(ast)
716 # TODO(terry): For now don't handle unrestricted types see
717 # https://code.google.com/p/chromium/issues/detail?id=354298
718 type_name = type_name.replace('unrestricted ', '', 1)
719
720 # TODO(terry): Handled USVString as a DOMString.
721 type_name = type_name.replace('USVString', 'DOMString', 1)
722 type_name = type_name.replace('HTMLString', 'DOMString', 1)
723
724 # TODO(terry); WindowTimers setInterval/setTimeout overloads with a
725 # Function type - map to any until the IDL uses union.
726 type_name = type_name.replace('Function', 'any', 1)
727
728 self.idid = type_name
729 else:
730 # IdlUnionType
731 if ast.is_union_type:
732 if not (self.idid in _unions_to_any):
733 _unions_to_any.append(self.idid)
734 # TODO(terry): For union types use any otherwise type is unionType is
735 # not found and is removed during merging.
736 self.idid = 'any'
737 # TODO(terry): Any union type e.g. 'type1 or type2 or type2',
738 # 'typedef (Type1 or Type2) UnionType'
739 # Is a problem we need to extend IDLType and IDLTypeDef to handle more
740 # than one type.
741 #
742 # Also for typedef's e.g.,
743 # typedef (Type1 or Type2) UnionType
744 # should consider synthesizing a new interface (e.g., UnionType) that's
745 # both Type1 and Type2.
746 if not self.idid:
747 print('>>>> __module__ %s' % ast.__module__)
748 raise SyntaxError('Could not parse type %s' % (ast))
749
750 def _label_to_type(self, label, ast):
751 if label == 'LongLongType':
752 label = 'long long'
753 elif label.endswith('Type'):
754 # Omit 'Type' suffix and lowercase the rest.
755 label = '%s%s' % (label[0].lower(), label[1:-4])
756
757 # Add unsigned qualifier.
758 if self._has(ast, 'Unsigned'):
759 label = 'unsigned %s' % label
760 return label
761
762
764 """IDLNode for 'enum [id] { [string]+ }'"""
765
766 def __init__(self, ast):
767 IDLNode.__init__(self, ast)
768 self._convert_annotations(ast)
769 if not (isinstance(ast, list)) and ast.__module__ == "idl_definitions":
770 # Blink AST
771 self.values = ast.values
772 else:
773 self.values = self._find_all(ast, 'StringLiteral')
774
775 # TODO(terry): Need to handle emitting of enums for dart:html
776
777
779 """IDLNode for 'callback [type] [id]' declarations."""
780
781 def __init__(self, ast):
782 IDLNode.__init__(self, ast)
783 self._convert_annotations(ast)
784 self.type = self._convert_first(ast, 'Type', IDLType)
785
786
788 """IDLNode for 'typedef [type] [id]' declarations."""
789
790 def __init__(self, ast):
791 IDLNode.__init__(self, ast)
792 self._convert_annotations(ast)
793 self.type = self._convert_first(ast, 'Type', IDLType)
794
795
797 """IDLDictionary node contains members,
798 as well as parent references."""
799
800 def __init__(self, ast, typedefDictionary=False):
801 IDLNode.__init__(self, ast)
802
804 if (typedefDictionary):
805 # Dictionary is a typedef to a union.
806 self._convert_ext_attrs(None)
807 else:
808 self._convert_ext_attrs(ast)
809 self._convert_constants(ast, self.idid)
810
811
813 """IDLDictionaryMembers specialization for a list of FremontCut dictionary values."""
814
815 def __init__(self, ast=None, js_name=None):
816 IDLDictNode.__init__(self, ast)
817 self.idid = None
818 if not ast:
819 return
820 for member in self._find_all(ast, 'Member'):
821 name = self._find_first(member, 'Id')
822 value = IDLDictionaryMember(member, js_name)
823 self[name] = value
824
825
826def generate_callback(interface_name, result_type, arguments):
827 syn_op = IDLOperation(None, interface_name, 'callback')
828
829 syn_op.type = resolveTypedef(result_type)
830 syn_op.arguments = arguments
831
832 return syn_op
833
834
835def generate_operation(interface_name,
836 result_type_name,
837 oper_name,
838 arguments,
839 result_nullable=False):
840 """ Synthesize an IDLOperation with no AST used for support of setlike."""
841 """ Arguments is a list of argument where each argument is:
842 [IDLType, argument_name, optional_boolean] """
843
844 syn_op = IDLOperation(None, interface_name, oper_name)
845
846 syn_op.type = IDLType(None, result_type_name)
847 syn_op.type = resolveTypedef(syn_op.type)
848 syn_op.type.nullable = result_nullable
849
850 for argument in arguments:
851 arg = IDLArgument(None, argument[1])
852 arg.type = argument[0]
853 arg.optional = argument[2] if len(argument) > 2 else False
854 syn_op.arguments.append(arg)
855
856 return syn_op
857
858
860 """
861 Need to create (in our database) a number of operations. This is a new IDL
862 syntax, the implied operations for a set now use setlike<T> where T is a known
863 type e.g., setlike<FontFace> setlike implies these operations are generated:
864
865 void forEach(any callback, optional any thisArg);
866 boolean has(FontFace fontFace);
867 boolean has(FontFace fontFace);
868
869 if setlike is not read-only these operations are generated:
870
871 FontFaceSet add(FontFace value);
872 boolean delete(FontFace value);
873 void clear();
874 """
875 setlike_ops = []
876 """
877 Need to create a typedef for a function callback e.g.,
878 a setlike will need a callback that has the proper args in FontFaceSet that is
879 three arguments, etc.
880
881 typedef void FontFaceSetForEachCallback(
882 FontFace fontFace, FontFace fontFaceAgain, FontFaceSet set);
883
884 void forEach(FontFaceSetForEachCallback callback, [Object thisArg]);
885 """
886 callback_name = '%sForEachCallback' % interface.id
887 set_op = generate_operation(interface.id, 'void', 'forEach',
888 [[IDLType(None, callback_name), 'callback'],
889 [IDLType(None, 'any'), 'thisArg', True]])
890 setlike_ops.append(set_op)
891
892 set_op = generate_operation(
893 interface.id, 'boolean', 'has',
894 [[IDLType(None, set_like.value_type.base_type), 'arg']])
895 setlike_ops.append(set_op)
896
897 if not set_like.is_read_only:
898 # Issue #45676: `add` can return null on Firefox, so this should be
899 # typed nullable.
900 add_result_nullable = True
901 set_op = generate_operation(
902 interface.id, interface.id, 'add',
903 [[IDLType(None, set_like.value_type.base_type), 'arg']],
904 add_result_nullable)
905 setlike_ops.append(set_op)
906 set_op = generate_operation(
907 interface.id, 'boolean', 'delete',
908 [[IDLType(None, set_like.value_type.base_type), 'arg']])
909 setlike_ops.append(set_op)
910 set_op = generate_operation(interface.id, 'void', 'clear', [])
911 setlike_ops.append(set_op)
912
913 return setlike_ops
914
915
917 """IDLInterface node contains operations, attributes, constants,
918 as well as parent references."""
919
920 def __init__(self, ast, id=None):
921 IDLNode.__init__(self, ast)
922
923 if id:
924 self.idid = id
925
926 self._convert_ext_attrs(ast)
927 self._convert_annotations(ast)
928
929 self.parents = self._convert_all(ast, 'ParentInterface',
930 IDLParentInterface)
931
932 javascript_interface_name = self.ext_attrs.get('InterfaceName', self.idid)
933 self.javascript_binding_name = javascript_interface_name
934 self.doc_js_name = javascript_interface_name
935
936 if not (self._find_first(ast, 'Callback') is None):
937 self.ext_attrs['Callback'] = None
938 if not (self._find_first(ast, 'Partial') is None):
939 self.is_supplemental = True
940 self.ext_attrs['DartSupplemental'] = None
941 self.isMaplike = False
942 self.isMaplike_ro = False
943 self.maplike_key_value = [None, None]
944 if ast is not None and ast.maplike is not None:
945 self.isMaplike = True
946 self.isMaplike_ro = ast.maplike.is_read_only
947 self.maplike_key_value = [
948 IDLType(ast.maplike.key_type),
949 IDLType(ast.maplike.value_type)
950 ]
951
953 ast, 'Operation', lambda ast: IDLOperation(ast, self.doc_js_name))
954
955 if not (id) and ast.setlike:
957 self, ast.setlike)
958 for op in setlike_ops:
959 self.operations.append(op)
960
962 ast, 'Attribute', lambda ast: IDLAttribute(ast, self.doc_js_name))
964 ast, 'Const', lambda ast: IDLConstant(ast, self.doc_js_name))
965 self.is_supplemental = 'DartSupplemental' in self.ext_attrs
966 self.is_no_interface_object = 'NoInterfaceObject' in self.ext_attrs
967 # TODO(terry): Can eliminate Suppressed when we're only using blink parser.
968 self.is_fc_suppressed = 'Suppressed' in self.ext_attrs or \
969 'DartSuppress' in self.ext_attrs
970
971 def reset_id(self, new_id):
972 """Reset the id of the Interface and corresponding the JS names."""
973 if self.idid != new_id:
974 self.idid = new_id
975 self.doc_js_name = new_id
976 self.javascript_binding_name = new_id
977 for member in self.operations:
978 member.doc_js_interface_name = new_id
979 for member in self.attributes:
980 member.doc_js_interface_name = new_id
981 for member in self.constants:
982 member.doc_js_interface_name = new_id
983
984 def has_attribute(self, candidate):
985 for attribute in self.attributes:
986 if (attribute.id == candidate.id and
987 attribute.is_read_only == candidate.is_read_only):
988 return True
989 return False
990
991
993 """This IDLNode specialization is for 'Interface Child : Parent {}'
994 declarations."""
995
996 def __init__(self, ast):
997 IDLNode.__init__(self, ast)
998 self._convert_annotations(ast)
999 self.type = self._convert_first(ast, 'InterfaceType', IDLType)
1000
1001
1003 """A base class for constants, attributes and operations."""
1004
1005 def __init__(self, ast, doc_js_interface_name, member_id=None):
1006 if ast:
1007 IDLNode.__init__(self, ast)
1008 else:
1009 # The ast is None to support synthesizing an IDLMember, member_id is only
1010 # used when ast is None.
1011 IDLNode.__init__(self, ast, member_id)
1012 self.type = None
1013 self.doc_js_interface_name = doc_js_interface_name
1014 return
1015
1016 self.type = self._convert_first(ast, 'Type', IDLType)
1017 self.type = resolveTypedef(self.type)
1018
1019 self._convert_ext_attrs(ast)
1020 self._convert_annotations(ast)
1021 self.doc_js_interface_name = doc_js_interface_name
1022 # TODO(terry): Can eliminate Suppressed when we're only using blink parser.
1023 self.is_fc_suppressed = 'Suppressed' in self.ext_attrs or \
1024 'DartSuppress' in self.ext_attrs
1025 self.is_static = self._has(ast, 'Static')
1026
1027
1029 """IDLNode specialization for 'type name(args)' declarations."""
1030
1031 def __init__(self, ast, doc_js_interface_name, id=None):
1032 IDLMember.__init__(self, ast, doc_js_interface_name, id)
1033
1034 if not ast:
1035 # Synthesize an IDLOperation with no ast used for setlike.
1039 self.specials = []
1041 self.arguments = []
1042 return
1043
1044 self.typetype = self._convert_first(ast, 'ReturnType', IDLType)
1045 self.typetype = resolveTypedef(self.typetype)
1046
1047 self.arguments = self._convert_all(ast, 'Argument', IDLArgument)
1048 self.specials = self._find_all(ast, 'Special')
1049 # Special case: there are getters of the form
1050 # getter <ReturnType>(args). For now force the name to be __getter__,
1051 # but it should be operator[] later.
1052 if self.idid is None:
1053 if self.specials == ['getter']:
1054 if self.ext_attrsext_attrs.get('Custom') == 'PropertyQuery':
1055 # Handling __propertyQuery__ the extended attribute is:
1056 # [Custom=PropertyQuery] getter boolean (DOMString name);
1057 self.idid = '__propertyQuery__'
1058 elif self.ext_attrsext_attrs.get('ImplementedAs'):
1059 self.idid = self.ext_attrsext_attrs.get('ImplementedAs')
1060 else:
1061 self.idid = '__getter__'
1062 elif self.specials == ['setter']:
1063 self.idid = '__setter__'
1064 # Special case: if it's a setter, ignore 'declared' return type
1065 self.typetype = IDLType([('VoidType', None)])
1066 elif self.specials == ['deleter']:
1067 self.idid = '__delete__'
1068 else:
1069 raise Exception('Cannot handle %s: operation has no id' % ast)
1070
1071 if len(self.arguments) >= 1 and (
1072 self.idid in _operation_suffix_map
1073 ) and not self.ext_attrsext_attrs.get('ImplementedAs'):
1074 arg = self.arguments[0]
1075 operation_category = 'Named' if arg.type.id == 'DOMString' else 'Indexed'
1076 self.ext_attrsext_attrs.setdefault(
1077 'ImplementedAs', 'anonymous%s%s' %
1078 (operation_category, _operation_suffix_map[self.idid]))
1079
1080 def __repr__(self):
1081 return '<IDLOperation(id = %s)>' % (self.idid)
1082
1083 def _extra_repr(self):
1084 return [self.arguments]
1085
1086 def SameSignatureAs(self, operation):
1087 if self.typetype != operation.type:
1088 return False
1089 return [a.type for a in self.arguments] == [
1090 a.type for a in operation.arguments
1091 ]
1092
1094 """IDLNode specialization for 'attribute type name' declarations."""
1095
1096 def __init__(self, ast, doc_js_interface_name):
1097 IDLMember.__init__(self, ast, doc_js_interface_name)
1098 self.is_read_only = self._has(ast, 'ReadOnly')
1099 # There are various ways to define exceptions for attributes:
1100
1101 def _extra_repr(self):
1102 extra = []
1103 if self.is_read_only: extra.append('readonly')
1104 return extra
1105
1106
1108 """IDLNode specialization for 'const type name = value' declarations."""
1109
1110 def __init__(self, ast, doc_js_interface_name):
1111 IDLMember.__init__(self, ast, doc_js_interface_name)
1112 self.value = self._find_first(ast, 'ConstExpr')
1113
1114
1116 """IDLNode specialization for operation arguments."""
1117
1118 def __init__(self, ast, id=None):
1119 if ast:
1120 IDLNode.__init__(self, ast)
1121 else:
1122 # Synthesize an IDLArgument with no ast used for setlike.
1123 IDLNode.__init__(self, ast, id)
1125 self.default_value = None
1127 return
1128
1129 self.default_value = None
1130 self.default_value_is_null = False
1131 # Handle the 'argType arg = default'. IDL syntax changed from
1132 # [default=NullString].
1133 if not isinstance(ast, list):
1134 if isinstance(ast.default_value,
1135 idl_definitions.IdlLiteral) and ast.default_value:
1136 self.default_value = ast.default_value.value
1137 self.default_value_is_null = ast.default_value.is_null
1138 elif 'Default' in ast.extended_attributes:
1139 # Work around [Default=Undefined] for arguments - only look in the model's
1140 # default_value
1141 self.default_value = ast.extended_attributes.get('Default')
1142 self.default_value_is_null = False
1143
1144 self.type = self._convert_first(ast, 'Type', IDLType)
1145 self.type = resolveTypedef(self.type)
1146
1147 self.optional = self._has(ast, 'Optional')
1148 self._convert_ext_attrs(ast)
1149 # TODO(vsm): Recover this from the type instead.
1150 if 'Callback' in self.type.id:
1151 self.ext_attrsext_attrs['Callback'] = None
1152
1153 def __repr__(self):
1154 return '<IDLArgument(type = %s, id = %s)>' % (self.type, self.idid)
1155
1156
1158 """IDLNode specialization for 'const type name = value' declarations."""
1159
1160 def __init__(self, ast, doc_js_interface_name):
1161 IDLMember.__init__(self, ast, doc_js_interface_name)
1162 default_value = self._find_first(ast, 'Default')
1163 self.value = default_value.value if default_value else None
1164
1165
1167 """IDLNode specialization for 'IMPLEMENTOR implements IMPLEMENTED' declarations."""
1168
1169 def __init__(self, ast):
1170 IDLNode.__init__(self, ast)
1171 if isinstance(ast, list) or ast.__module__ != 'idl_definitions':
1172 self.implementor = self._convert_first(ast, 'ImplStmtImplementor',
1173 IDLType)
1174 self.implemented = self._convert_first(ast, 'ImplStmtImplemented',
1175 IDLType)
1176
1177
1179 """IDLDictNode specialization for a list of FremontCut annotations."""
1180
1181 def __init__(self, ast=None):
1182 IDLDictNode.__init__(self, ast)
1183 self.idid = None
1184 if not ast:
1185 return
1186 for annotation in self._find_all(ast, 'Annotation'):
1187 name = self._find_first(annotation, 'Id')
1188 value = IDLAnnotation(annotation)
1189 self[name] = value
1190
1191
1193 """IDLDictNode specialization for one annotation."""
1194
1195 def __init__(self, ast=None):
1196 IDLDictNode.__init__(self, ast)
1197 self.idid = None
1198 if not ast:
1199 return
1200 for arg in self._find_all(ast, 'AnnotationArg'):
1201 name = self._find_first(arg, 'Id')
1202 value = self._find_first(arg, 'AnnotationArgValue')
1203 self[name] = value
static uint32_t hash(const SkShaderBase::GradientInfo &v)
void print(void *str)
Definition bridge.cpp:126
__init__(self, ast, id=None)
Definition idlnode.py:1118
__init__(self, ast, doc_js_interface_name)
Definition idlnode.py:1096
__init__(self, ast, doc_js_interface_name)
Definition idlnode.py:1110
get(self, key, default=None)
Definition idlnode.py:378
__setitem__(self, key, value)
Definition idlnode.py:366
setdefault(self, key, value=None)
Definition idlnode.py:381
__init__(self, ast, doc_js_interface_name)
Definition idlnode.py:1160
__init__(self, ast=None, js_name=None)
Definition idlnode.py:815
__init__(self, ast, typedefDictionary=False)
Definition idlnode.py:800
__init__(self, func_value_ast, arg_list_ast, is_blink=False)
Definition idlnode.py:641
__init__(self, ast=None)
Definition idlnode.py:570
__init__(self, ast, filename=None)
Definition idlnode.py:418
_createImplementsStatement(self, implementor, implemented_name)
Definition idlnode.py:523
__init__(self, ast, id=None)
Definition idlnode.py:920
has_attribute(self, candidate)
Definition idlnode.py:984
__init__(self, ast, doc_js_interface_name, member_id=None)
Definition idlnode.py:1005
_convert_ext_attrs(self, ast)
Definition idlnode.py:336
_has(self, ast, label)
Definition idlnode.py:264
_convert_annotations(self, ast)
Definition idlnode.py:340
all(self, type_filter=None)
Definition idlnode.py:110
__init__(self, ast, id=None)
Definition idlnode.py:66
reset_id(self, newId)
Definition idlnode.py:105
_find_all(self, ast, label, max_results=sys.maxsize)
Definition idlnode.py:191
_find_first(self, ast, label)
Definition idlnode.py:255
__eq__(self, other)
Definition idlnode.py:92
_convert_first(self, ast, label, idlnode_ctor)
Definition idlnode.py:329
_convert_all(self, ast, label, idlnode_ctor)
Definition idlnode.py:306
_convert_label_to_field(self, label)
Definition idlnode.py:270
_convert_constants(self, ast, js_name)
Definition idlnode.py:344
_to_hashable(self, obj)
Definition idlnode.py:165
SameSignatureAs(self, operation)
Definition idlnode.py:1086
__init__(self, ast, doc_js_interface_name, id=None)
Definition idlnode.py:1031
__init__(self, ast, id=None)
Definition idlnode.py:661
_label_to_type(self, label, ast)
Definition idlnode.py:750
static void append(char **dst, size_t *count, const char *src, size_t n)
Definition editor.cpp:211
get_interfaces_info()
Definition dependency.py:9
_addTypedef(typedef)
Definition idlnode.py:35
generate_operation(interface_name, result_type_name, oper_name, arguments, result_nullable=False)
Definition idlnode.py:839
report_unions_to_any()
Definition idlnode.py:20
generate_setLike_operations_properties(interface, set_like)
Definition idlnode.py:859
generate_callback(interface_name, result_type, arguments)
Definition idlnode.py:826