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

Unified Diff: sky/engine/bindings2/scripts/idlnode.py

Issue 914413004: Add a new bindings2/scripts directory for Dart bindings (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Remove idlrenderer.py it's not used Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: sky/engine/bindings2/scripts/idlnode.py
diff --git a/sky/engine/bindings2/scripts/idlnode.py b/sky/engine/bindings2/scripts/idlnode.py
new file mode 100755
index 0000000000000000000000000000000000000000..ee930abb3b37b770b9bfcfd04c7880ca5df809ef
--- /dev/null
+++ b/sky/engine/bindings2/scripts/idlnode.py
@@ -0,0 +1,814 @@
+#!/usr/bin/python
+# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import os
+import sys
+
+import idl_definitions
+from idl_types import IdlType, IdlUnionType, IdlArrayOrSequenceType
+
+from compute_interfaces_info_overall import interfaces_info
+
+
+new_asts = {}
+
+
+_operation_suffix_map = {
+ '__getter__': "Getter",
+ '__setter__': "Setter",
+ '__delete__': "Deleter",
+}
+
+class IDLNode(object):
+ """Base class for all IDL elements.
+ IDLNode may contain various child nodes, and have properties. Examples
+ of IDLNode are interfaces, interface members, function arguments,
+ etc.
+ """
+
+ def __init__(self, ast):
+ """Initializes an IDLNode from a PegParser AST output."""
+ self.id = self._find_first(ast, 'Id') if ast is not None else None
+
+
+ def __repr__(self):
+ """Generates string of the form <class id extra extra ... 0x12345678>."""
+ extras = self._extra_repr()
+ if isinstance(extras, list):
+ extras = ' '.join([str(e) for e in extras])
+ try:
+ if self.id:
+ return '<%s %s 0x%x>' % (
+ type(self).__name__,
+ ('%s %s' % (self.id, extras)).strip(),
+ hash(self))
+ return '<%s %s 0x%x>' % (
+ type(self).__name__,
+ extras,
+ hash(self))
+ except Exception, e:
+ return "can't convert to string: %s" % e
+
+ def _extra_repr(self):
+ """Returns string of extra info for __repr__()."""
+ return ''
+
+ def __cmp__(self, other):
+ """Override default compare operation.
+ IDLNodes are equal if all their properties are equal."""
+ if other is None or not isinstance(other, IDLNode):
+ return 1
+ return self.__dict__.__cmp__(other.__dict__)
+
+ def reset_id(self, newId):
+ """Reset the id of the Node. This is typically done during a normalization
+ phase (e.g., "DOMWindow" -> "Window")."""
+ self.id = newId
+
+ def all(self, type_filter=None):
+ """Returns a list containing this node and all it child nodes
+ (recursive).
+
+ Args:
+ type_filter -- can be used to limit the results to a specific
+ node type (e.g. IDLOperation).
+ """
+ res = []
+ if type_filter is None or isinstance(self, type_filter):
+ res.append(self)
+ for v in self._all_subnodes():
+ if isinstance(v, IDLNode):
+ res.extend(v.all(type_filter))
+ elif isinstance(v, list):
+ for item in v:
+ if isinstance(item, IDLNode):
+ res.extend(item.all(type_filter))
+ return res
+
+ def _all_subnodes(self):
+ """Accessor used by all() to find subnodes."""
+ return self.__dict__.values()
+
+ def to_dict(self):
+ """Converts the IDLNode and its children into a dictionary.
+ This method is useful mostly for debugging and pretty printing.
+ """
+ res = {}
+ for (k, v) in self.__dict__.items():
+ if v == None or v == False or v == [] or v == {}:
+ # Skip empty/false members.
+ continue
+ elif isinstance(v, IDLDictNode) and not len(v):
+ # Skip empty dict sub-nodes.
+ continue
+ elif isinstance(v, list):
+ # Convert lists:
+ new_v = []
+ for sub_node in v:
+ if isinstance(sub_node, IDLNode):
+ # Convert sub-node:
+ new_v.append(sub_node.to_dict())
+ else:
+ new_v.append(sub_node)
+ v = new_v
+ elif isinstance(v, IDLNode):
+ # Convert sub-node:
+ v = v.to_dict()
+ res[k] = v
+ return res
+
+ def _find_all(self, ast, label, max_results=sys.maxint):
+ """Searches the AST for tuples with a given label. The PegParser
+ output is composed of lists and tuples, where the tuple 1st argument
+ is a label. If ast root is a list, will search recursively inside each
+ member in the list.
+
+ Args:
+ ast -- the AST to search.
+ label -- the label to look for.
+ res -- results are put into this list.
+ max_results -- maximum number of results.
+ """
+ res = []
+ if max_results <= 0:
+ return res
+
+ if isinstance(ast, list):
+ for childAst in ast:
+ if childAst and \
+ not(isinstance(childAst, dict)) and \
+ not(isinstance(childAst, str)) and \
+ not(isinstance(childAst, tuple)) and \
+ childAst.__module__ == "idl_definitions":
+ field_name = self._convert_label_to_field(label)
+ if hasattr(childAst, field_name):
+ field_value = getattr(childAst, field_name)
+ # It's an IdlType we need the string name of the type.
+ if field_name == 'idl_type':
+ field_value = getattr(field_value, 'base_type')
+ res.append(field_value)
+ else:
+ sub_res = self._find_all(childAst, label,
+ max_results - len(res))
+ res.extend(sub_res)
+ elif isinstance(ast, tuple):
+ (nodeLabel, value) = ast
+ if nodeLabel == label:
+ res.append(value)
+ # TODO(terry): Seems bogus to check for so many things probably better to just
+ # pass in blink_compile and drive it off from that...
+ elif (ast and not(isinstance(ast, dict)) and
+ not(isinstance(ast, str)) and
+ (ast.__module__ == "idl_definitions" or ast.__module__ == "idl_types")):
+ field_name = self._convert_label_to_field(label)
+ if hasattr(ast, field_name):
+ field_value = getattr(ast, field_name)
+ if field_value:
+ if label == 'Interface' or label == 'Enum':
+ for key in field_value:
+ value = field_value[key]
+ res.append(value)
+ elif isinstance(field_value, list):
+ for item in field_value:
+ res.append(item)
+ elif label == 'ParentInterface' or label == 'InterfaceType':
+ # Fetch the AST for the parent interface.
+ parent_idlnode = new_asts[field_value]
+ res.append(parent_idlnode.interfaces[field_value])
+ else:
+ res.append(field_value)
+
+ return res
+
+ def _find_first(self, ast, label):
+ """Convenience method for _find_all(..., max_results=1).
+ Returns a single element instead of a list, or None if nothing
+ is found."""
+ res = self._find_all(ast, label, max_results=1)
+ if len(res):
+ return res[0]
+ return None
+
+ def _has(self, ast, label):
+ """Returns true if an element with the given label is
+ in the AST by searching for it."""
+ return len(self._find_all(ast, label, max_results=1)) == 1
+
+ # Mapping from original AST tuple names to new AST field names idl_definitions.Idl*.
+ def _convert_label_to_field(self, label):
+ label_field = {
+ # Keys old AST names, Values Blink IdlInterface names.
+ 'ParentInterface': 'parent',
+ 'Id': 'name',
+ 'Interface': 'interfaces',
+ 'Callback': 'is_callback',
+ 'Partial': 'is_partial',
+ 'Operation': 'operations',
+ 'Attribute': 'attributes',
+ 'Const': 'constants',
+ 'Type': 'idl_type',
+ 'ExtAttrs': 'extended_attributes',
+ 'Special': 'specials',
+ 'ReturnType': 'idl_type',
+ 'Argument': 'arguments',
+ 'InterfaceType': 'name',
+ 'ConstExpr': 'value',
+ 'Static': 'is_static',
+ 'ReadOnly': 'is_read_only',
+ 'Optional': 'is_optional',
+ 'Nullable': 'is_nullable',
+ 'Enum': 'enumerations',
+ 'Annotation': '', # TODO(terry): Ignore annotation used for database cache.
+ 'TypeDef': '', # typedef in an IDL are already resolved.
+ }
+ result = label_field.get(label)
+ if result != '' and not(result):
+ print 'FATAL ERROR: AST mapping name not found %s.' % label
+ return result if result else ''
+
+ def _convert_all(self, ast, label, idlnode_ctor):
+ """Converts AST elements into IDLNode elements.
+ Uses _find_all to find elements with a given label and converts
+ them into IDLNodes with a given constructor.
+ Returns:
+ A list of the converted nodes.
+ Args:
+ ast -- the ast element to start a search at.
+ label -- the element label to look for.
+ idlnode_ctor -- a constructor function of one of the IDLNode
+ sub-classes.
+ """
+ res = []
+ found = self._find_all(ast, label)
+ if not found:
+ return res
+ if not isinstance(found, list):
+ raise RuntimeError("Expected list but %s found" % type(found))
+ for childAst in found:
+ converted = idlnode_ctor(childAst)
+ res.append(converted)
+ return res
+
+ def _convert_first(self, ast, label, idlnode_ctor):
+ """Like _convert_all, but only converts the first found results."""
+ childAst = self._find_first(ast, label)
+ if not childAst:
+ return None
+ return idlnode_ctor(childAst)
+
+ def _convert_ext_attrs(self, ast):
+ """Helper method for uniform conversion of extended attributes."""
+ self.ext_attrs = IDLExtAttrs(ast)
+
+ def _convert_annotations(self, ast):
+ """Helper method for uniform conversion of annotations."""
+ self.annotations = IDLAnnotations(ast)
+
+
+class IDLDictNode(IDLNode):
+ """Base class for dictionary-like IDL nodes such as extended attributes
+ and annotations. The base class implements various dict interfaces."""
+
+ def __init__(self, ast):
+ IDLNode.__init__(self, None)
+ if ast is not None and isinstance(ast, dict):
+ self.__map = ast
+ else:
+ self.__map = {}
+
+ def __len__(self):
+ return len(self.__map)
+
+ def __getitem__(self, key):
+ return self.__map[key]
+
+ def __setitem__(self, key, value):
+ self.__map[key] = value
+
+ def __delitem__(self, key):
+ del self.__map[key]
+
+ def __contains__(self, key):
+ return key in self.__map
+
+ def __iter__(self):
+ return self.__map.__iter__()
+
+ def get(self, key, default=None):
+ return self.__map.get(key, default)
+
+ def setdefault(self, key, value=None):
+ return self.__map.setdefault(key, value)
+
+ def items(self):
+ return self.__map.items()
+
+ def keys(self):
+ return self.__map.keys()
+
+ def values(self):
+ return self.__map.values()
+
+ def clear(self):
+ self.__map = {}
+
+ def to_dict(self):
+ """Overrides the default IDLNode.to_dict behavior.
+ The IDLDictNode members are copied into a new dictionary, and
+ IDLNode members are recursively converted into dicts as well.
+ """
+ res = {}
+ for (k, v) in self.__map.items():
+ if isinstance(v, IDLNode):
+ v = v.to_dict()
+ res[k] = v
+ return res
+
+ def _all_subnodes(self):
+ # Usually an IDLDictNode does not contain further IDLNodes.
+ return []
+
+
+class IDLFile(IDLNode):
+ """IDLFile is the top-level node in each IDL file. It may contain interfaces."""
+
+ DART_IDL = 'dart.idl'
+
+ def __init__(self, ast, filename=None):
+ IDLNode.__init__(self, ast)
+ self.filename = filename
+
+ filename_basename = os.path.basename(filename)
+
+ self.interfaces = self._convert_all(ast, 'Interface', IDLInterface)
+
+ is_blink = not(isinstance(ast, list)) and ast.__module__ == 'idl_definitions'
+
+ if is_blink:
+ # implements is handled by the interface merging step (see the function
+ # merge_interface_dependencies).
+ for interface in self.interfaces:
+ blink_interface = ast.interfaces.get(interface.id)
+ if filename_basename == self.DART_IDL:
+ # Special handling for dart.idl we need to remember the interface,
+ # since we could have many (not one interface / file). Then build up
+ # the IDLImplementsStatement for any implements in dart.idl.
+ interface_info = interfaces_info['__dart_idl___'];
+
+ self.implementsStatements = []
+
+ implement_pairs = interface_info['implement_pairs']
+ for implement_pair in implement_pairs:
+ interface_name = implement_pair[0]
+ implemented_name = implement_pair[1]
+
+ implementor = new_asts[interface_name].interfaces.get(interface_name)
+ implement_statement = self._createImplementsStatement(implementor,
+ implemented_name)
+
+ self.implementsStatements.append(implement_statement)
+ else:
+ interface_info = interfaces_info[interface.id]
+
+ implements = interface_info['implements_interfaces']
+ if not(blink_interface.is_partial) and len(implements) > 0:
+ implementor = new_asts[interface.id].interfaces.get(interface.id)
+
+ self.implementsStatements = []
+
+ # TODO(terry): Need to handle more than one implements.
+ for implemented_name in implements:
+ implement_statement = self._createImplementsStatement(implementor,
+ implemented_name)
+ self.implementsStatements.append(implement_statement)
+ else:
+ self.implementsStatements = []
+ else:
+ self.implementsStatements = self._convert_all(ast, 'ImplStmt',
+ IDLImplementsStatement)
+
+ # No reason to handle typedef they're already aliased in Blink's AST.
+ self.typeDefs = [] if is_blink else self._convert_all(ast, 'TypeDef', IDLTypeDef)
+
+ self.enums = self._convert_all(ast, 'Enum', IDLEnum)
+
+ def _createImplementsStatement(self, implementor, implemented_name):
+ implemented = new_asts[implemented_name].interfaces.get(implemented_name)
+
+ implement_statement = IDLImplementsStatement(implemented)
+
+ implement_statement.implementor = IDLType(implementor)
+ implement_statement.implemented = IDLType(implemented)
+
+ return implement_statement
+
+
+class IDLModule(IDLNode):
+ """IDLModule has an id, and may contain interfaces, type defs and
+ implements statements."""
+ def __init__(self, ast):
+ IDLNode.__init__(self, ast)
+ self._convert_ext_attrs(ast)
+ self._convert_annotations(ast)
+ self.interfaces = self._convert_all(ast, 'Interface', IDLInterface)
+
+ is_blink = ast.__module__ == 'idl_definitions'
+
+ # No reason to handle typedef they're already aliased in Blink's AST.
+ self.typeDefs = [] if is_blink else self._convert_all(ast, 'TypeDef', IDLTypeDef)
+
+ self.enums = self._convert_all(ast, 'Enum', IDLNode)
+
+ if is_blink:
+ # implements is handled by the interface merging step (see the function
+ # merge_interface_dependencies).
+ for interface in self.interfaces:
+ interface_info = interfaces_info[interface.id]
+ # TODO(terry): Same handling for implementsStatements as in IDLFile?
+ self.implementsStatements = interface_info['implements_interfaces']
+ else:
+ self.implementsStatements = self._convert_all(ast, 'ImplStmt',
+ IDLImplementsStatement)
+
+
+class IDLExtAttrs(IDLDictNode):
+ """IDLExtAttrs is an IDLDictNode that stores IDL Extended Attributes.
+ Modules, interfaces, members and arguments can all own IDLExtAttrs."""
+ def __init__(self, ast=None):
+ IDLDictNode.__init__(self, None)
+ if not ast:
+ return
+ if not(isinstance(ast, list)) and ast.__module__ == "idl_definitions":
+ # Pull out extended attributes from Blink AST.
+ for name, value in ast.extended_attributes.items():
+ # TODO(terry): Handle constructors...
+ if name == 'NamedConstructor' or name == 'Constructor':
+ for constructor in ast.constructors:
+ if constructor.name == 'NamedConstructor':
+ constructor_name = ast.extended_attributes['NamedConstructor']
+ else:
+ constructor_name = None
+ func_value = IDLExtAttrFunctionValue(constructor_name, constructor.arguments, True)
+ if name == 'Constructor':
+ self.setdefault('Constructor', []).append(func_value)
+ else:
+ self[name] = func_value
+ else:
+ self[name] = value
+ else:
+ ext_attrs_ast = self._find_first(ast, 'ExtAttrs')
+ if not ext_attrs_ast:
+ return
+ for ext_attr in self._find_all(ext_attrs_ast, 'ExtAttr'):
+ name = self._find_first(ext_attr, 'Id')
+ value = self._find_first(ext_attr, 'ExtAttrValue')
+
+ if name == 'Constructor':
+ # There might be multiple constructor attributes, collect them
+ # as a list. Represent plain Constructor attribute
+ # (without any signature) as None.
+ assert value is None
+ func_value = None
+ ctor_args = self._find_first(ext_attr, 'ExtAttrArgList')
+ if ctor_args:
+ func_value = IDLExtAttrFunctionValue(None, ctor_args)
+ self.setdefault('Constructor', []).append(func_value)
+ continue
+
+ func_value = self._find_first(value, 'ExtAttrFunctionValue')
+ if func_value:
+ # E.g. NamedConstructor=Audio(optional DOMString src)
+ self[name] = IDLExtAttrFunctionValue(
+ func_value,
+ self._find_first(func_value, 'ExtAttrArgList'))
+ continue
+
+ self[name] = value
+
+ def _all_subnodes(self):
+ # Extended attributes may contain IDLNodes, e.g. IDLExtAttrFunctionValue
+ return self.values()
+
+
+class IDLExtAttrFunctionValue(IDLNode):
+ """IDLExtAttrFunctionValue."""
+ def __init__(self, func_value_ast, arg_list_ast, is_blink=False):
+ IDLNode.__init__(self, func_value_ast)
+ if is_blink:
+ # Blink path
+ self.id = func_value_ast # func_value_ast is the function name for Blink.
+ self.arguments = []
+ for argument in arg_list_ast:
+ self.arguments.append(IDLArgument(argument))
+ else:
+ self.arguments = self._convert_all(arg_list_ast, 'Argument', IDLArgument)
+
+
+class IDLType(IDLNode):
+ """IDLType is used to describe constants, attributes and operations'
+ return and input types. IDLType matches AST labels such as ScopedName,
+ StringType, VoidType, IntegerType, etc."""
+
+ def __init__(self, ast):
+ IDLNode.__init__(self, ast)
+
+ self.nullable = self._has(ast, 'Nullable')
+ # Search for a 'ScopedName' or any label ending with 'Type'.
+ if isinstance(ast, list):
+ self.id = self._find_first(ast, 'ScopedName')
+ if not self.id:
+ # FIXME: use regexp search instead
+ def findType(ast):
+ for label, childAst in ast:
+ if label.endswith('Type'):
+ type = self._label_to_type(label, ast)
+ if type != 'sequence':
+ return type
+ type_ast = self._find_first(childAst, 'Type')
+ if not type_ast:
+ return type
+ return 'sequence<%s>' % findType(type_ast)
+ raise Exception('No type declaration found in %s' % ast)
+ self.id = findType(ast)
+ # TODO(terry): Remove array_modifiers id has [] appended, keep for old
+ # parsing.
+ array_modifiers = self._find_first(ast, 'ArrayModifiers')
+ if array_modifiers:
+ self.id += array_modifiers
+ elif isinstance(ast, tuple):
+ (label, value) = ast
+ if label == 'ScopedName':
+ self.id = value
+ else:
+ self.id = self._label_to_type(label, ast)
+ elif isinstance(ast, str):
+ self.id = ast
+ # New blink handling.
+ elif ast.__module__ == "idl_types":
+ if isinstance(ast, IdlType) or isinstance(ast, IdlArrayOrSequenceType):
+ type_name = str(ast)
+
+ # TODO(terry): For now don't handle unrestricted types see
+ # https://code.google.com/p/chromium/issues/detail?id=354298
+ type_name = type_name.replace('unrestricted ', '', 1);
+
+ # TODO(terry): Handled ScalarValueString as a DOMString.
+ type_name = type_name.replace('ScalarValueString', 'DOMString', 1)
+
+ self.id = type_name
+ else:
+ # IdlUnionType
+ if ast.is_union_type:
+ print 'WARNING type %s is union mapped to \'any\'' % self.id
+ # TODO(terry): For union types use any otherwise type is unionType is
+ # not found and is removed during merging.
+ self.id = 'any'
+ # TODO(terry): Any union type e.g. 'type1 or type2 or type2',
+ # 'typedef (Type1 or Type2) UnionType'
+ # Is a problem we need to extend IDLType and IDLTypeDef to handle more
+ # than one type.
+ #
+ # Also for typedef's e.g.,
+ # typedef (Type1 or Type2) UnionType
+ # should consider synthesizing a new interface (e.g., UnionType) that's
+ # both Type1 and Type2.
+ if not self.id:
+ print '>>>> __module__ %s' % ast.__module__
+ raise SyntaxError('Could not parse type %s' % (ast))
+
+ def _label_to_type(self, label, ast):
+ if label == 'LongLongType':
+ label = 'long long'
+ elif label.endswith('Type'):
+ # Omit 'Type' suffix and lowercase the rest.
+ label = '%s%s' % (label[0].lower(), label[1:-4])
+
+ # Add unsigned qualifier.
+ if self._has(ast, 'Unsigned'):
+ label = 'unsigned %s' % label
+ return label
+
+
+class IDLEnum(IDLNode):
+ """IDLNode for 'enum [id] { [string]+ }'"""
+ def __init__(self, ast):
+ IDLNode.__init__(self, ast)
+ self._convert_annotations(ast)
+ if not(isinstance(ast, list)) and ast.__module__ == "idl_definitions":
+ # Blink AST
+ self.values = ast.values
+ else:
+ self.values = self._find_all(ast, 'StringLiteral')
+
+ # TODO(terry): Need to handle emitting of enums for dart:html
+
+
+class IDLTypeDef(IDLNode):
+ """IDLNode for 'typedef [type] [id]' declarations."""
+ def __init__(self, ast):
+ IDLNode.__init__(self, ast)
+ self._convert_annotations(ast)
+ self.type = self._convert_first(ast, 'Type', IDLType)
+
+
+class IDLInterface(IDLNode):
+ """IDLInterface node contains operations, attributes, constants,
+ as well as parent references."""
+
+ def __init__(self, ast):
+ IDLNode.__init__(self, ast)
+ self._convert_ext_attrs(ast)
+ self._convert_annotations(ast)
+
+ self.parents = self._convert_all(ast, 'ParentInterface',
+ IDLParentInterface)
+
+ javascript_interface_name = self.ext_attrs.get('InterfaceName', self.id)
+ self.javascript_binding_name = javascript_interface_name
+ self.doc_js_name = javascript_interface_name
+
+ if not (self._find_first(ast, 'Callback') is None):
+ self.ext_attrs['Callback'] = None
+ if not (self._find_first(ast, 'Partial') is None):
+ self.is_supplemental = True
+ self.ext_attrs['DartSupplemental'] = None
+
+ self.operations = self._convert_all(ast, 'Operation',
+ lambda ast: IDLOperation(ast, self.doc_js_name))
+ self.attributes = self._convert_all(ast, 'Attribute',
+ lambda ast: IDLAttribute(ast, self.doc_js_name))
+ self.constants = self._convert_all(ast, 'Const',
+ lambda ast: IDLConstant(ast, self.doc_js_name))
+ self.is_supplemental = 'DartSupplemental' in self.ext_attrs
+ self.is_no_interface_object = 'NoInterfaceObject' in self.ext_attrs
+
+
+ def reset_id(self, new_id):
+ """Reset the id of the Interface and corresponding the JS names."""
+ if self.id != new_id:
+ self.id = new_id
+ self.doc_js_name = new_id
+ self.javascript_binding_name = new_id
+ for member in self.operations:
+ member.doc_js_interface_name = new_id
+ for member in self.attributes:
+ member.doc_js_interface_name = new_id
+ for member in self.constants:
+ member.doc_js_interface_name = new_id
+
+ def has_attribute(self, candidate):
+ for attribute in self.attributes:
+ if (attribute.id == candidate.id and
+ attribute.is_read_only == candidate.is_read_only):
+ return True
+ return False
+
+
+class IDLParentInterface(IDLNode):
+ """This IDLNode specialization is for 'Interface Child : Parent {}'
+ declarations."""
+ def __init__(self, ast):
+ IDLNode.__init__(self, ast)
+ self._convert_annotations(ast)
+ self.type = self._convert_first(ast, 'InterfaceType', IDLType)
+
+
+class IDLMember(IDLNode):
+ """A base class for constants, attributes and operations."""
+
+ def __init__(self, ast, doc_js_interface_name):
+ IDLNode.__init__(self, ast)
+
+ self.type = self._convert_first(ast, 'Type', IDLType)
+ self._convert_ext_attrs(ast)
+ self._convert_annotations(ast)
+ self.doc_js_interface_name = doc_js_interface_name
+ self.is_static = self._has(ast, 'Static')
+
+
+class IDLOperation(IDLMember):
+ """IDLNode specialization for 'type name(args)' declarations."""
+ def __init__(self, ast, doc_js_interface_name):
+ IDLMember.__init__(self, ast, doc_js_interface_name)
+
+ self.type = self._convert_first(ast, 'ReturnType', IDLType)
+ self.arguments = self._convert_all(ast, 'Argument', IDLArgument)
+ self.specials = self._find_all(ast, 'Special')
+ # Special case: there are getters of the form
+ # getter <ReturnType>(args). For now force the name to be __getter__,
+ # but it should be operator[] later.
+ if self.id is None:
+ if self.specials == ['getter']:
+ if self.ext_attrs.get('Custom') == 'PropertyQuery':
+ # Handling __propertyQuery__ the extended attribute is:
+ # [Custom=PropertyQuery] getter boolean (DOMString name);
+ self.id = '__propertyQuery__'
+ else:
+ self.id = '__getter__'
+ elif self.specials == ['setter']:
+ self.id = '__setter__'
+ # Special case: if it's a setter, ignore 'declared' return type
+ self.type = IDLType([('VoidType', None)])
+ elif self.specials == ['deleter']:
+ self.id = '__delete__'
+ else:
+ raise Exception('Cannot handle %s: operation has no id' % ast)
+
+ if len(self.arguments) >= 1 and (self.id in _operation_suffix_map) and not self.ext_attrs.get('ImplementedAs'):
+ arg = self.arguments[0]
+ operation_category = 'Named' if arg.type.id == 'DOMString' else 'Indexed'
+ self.ext_attrs.setdefault('ImplementedAs', 'anonymous%s%s' % (operation_category, _operation_suffix_map[self.id]))
+
+ def _extra_repr(self):
+ return [self.arguments]
+
+ def SameSignatureAs(self, operation):
+ if self.type != operation.type:
+ return False
+ return [a.type for a in self.arguments] == [a.type for a in operation.arguments]
+
+class IDLAttribute(IDLMember):
+ """IDLNode specialization for 'attribute type name' declarations."""
+ def __init__(self, ast, doc_js_interface_name):
+ IDLMember.__init__(self, ast, doc_js_interface_name)
+ self.is_read_only = self._has(ast, 'ReadOnly')
+ # There are various ways to define exceptions for attributes:
+
+ def _extra_repr(self):
+ extra = []
+ if self.is_read_only: extra.append('readonly')
+ return extra
+
+
+class IDLConstant(IDLMember):
+ """IDLNode specialization for 'const type name = value' declarations."""
+ def __init__(self, ast, doc_js_interface_name):
+ IDLMember.__init__(self, ast, doc_js_interface_name)
+ self.value = self._find_first(ast, 'ConstExpr')
+
+
+class IDLArgument(IDLNode):
+ """IDLNode specialization for operation arguments."""
+ def __init__(self, ast):
+ IDLNode.__init__(self, ast)
+
+ self.default_value = None
+ self.default_value_is_null = False
+ # Handle the 'argType arg = default'. IDL syntax changed from
+ # [default=NullString].
+ if not isinstance(ast, list):
+ if isinstance(ast.default_value, idl_definitions.IdlLiteral) and ast.default_value:
+ self.default_value = ast.default_value.value
+ self.default_value_is_null = ast.default_value.is_null
+ elif 'Default' in ast.extended_attributes:
+ # Work around [Default=Undefined] for arguments - only look in the model's
+ # default_value
+ self.default_value = ast.extended_attributes.get('Default')
+ self.default_value_is_null = False
+
+ self.type = self._convert_first(ast, 'Type', IDLType)
+ self.optional = self._has(ast, 'Optional')
+ self._convert_ext_attrs(ast)
+ # TODO(vsm): Recover this from the type instead.
+ if 'Callback' in self.type.id:
+ self.ext_attrs['Callback'] = None
+
+ def __repr__(self):
+ return '<IDLArgument(type = %s, id = %s)>' % (self.type, self.id)
+
+
+class IDLImplementsStatement(IDLNode):
+ """IDLNode specialization for 'IMPLEMENTOR implements IMPLEMENTED' declarations."""
+ def __init__(self, ast):
+ IDLNode.__init__(self, ast)
+ if isinstance(ast, list) or ast.__module__ != 'idl_definitions':
+ self.implementor = self._convert_first(ast, 'ImplStmtImplementor', IDLType)
+ self.implemented = self._convert_first(ast, 'ImplStmtImplemented', IDLType)
+
+
+class IDLAnnotations(IDLDictNode):
+ """IDLDictNode specialization for a list of FremontCut annotations."""
+ def __init__(self, ast=None):
+ IDLDictNode.__init__(self, ast)
+ self.id = None
+ if not ast:
+ return
+ for annotation in self._find_all(ast, 'Annotation'):
+ name = self._find_first(annotation, 'Id')
+ value = IDLAnnotation(annotation)
+ self[name] = value
+
+
+class IDLAnnotation(IDLDictNode):
+ """IDLDictNode specialization for one annotation."""
+ def __init__(self, ast=None):
+ IDLDictNode.__init__(self, ast)
+ self.id = None
+ if not ast:
+ return
+ for arg in self._find_all(ast, 'AnnotationArg'):
+ name = self._find_first(arg, 'Id')
+ value = self._find_first(arg, 'AnnotationArgValue')
+ self[name] = value
« no previous file with comments | « sky/engine/bindings2/scripts/idl_validator.py ('k') | sky/engine/bindings2/scripts/interface_dependency_resolver.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698