Index: client/dom/scripts/idlnode.py |
=================================================================== |
--- client/dom/scripts/idlnode.py (revision 5796) |
+++ client/dom/scripts/idlnode.py (working copy) |
@@ -1,495 +0,0 @@ |
-#!/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 sys |
- |
- |
-class IDLNode(object): |
- """Base class for all IDL elements. |
- IDLNode may contain various child nodes, and have properties. Examples |
- of IDLNode are modules, 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 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: |
- 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) |
- 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 |
- |
- 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 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 |
- modules or interfaces.""" |
- |
- def __init__(self, ast, filename=None): |
- IDLNode.__init__(self, ast) |
- self.filename = filename |
- self.modules = self._convert_all(ast, 'Module', IDLModule) |
- self.interfaces = self._convert_all(ast, 'Interface', IDLInterface) |
- |
- |
-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) |
- self.typeDefs = self._convert_all(ast, 'TypeDef', IDLTypeDef) |
- 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 |
- 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') |
- |
- func_value = self._find_first(value, 'ExtAttrFunctionValue') |
- if func_value: |
- # E.g. NamedConstructor=Audio(in [Optional] DOMString src) |
- self[name] = IDLExtAttrFunctionValue( |
- func_value, |
- self._find_first(func_value, 'ExtAttrArgList')) |
- continue |
- |
- ctor_args = not value and self._find_first(ext_attr, 'ExtAttrArgList') |
- if ctor_args: |
- # E.g. Constructor(Element host) |
- self[name] = IDLExtAttrFunctionValue(None, ctor_args) |
- 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): |
- IDLNode.__init__(self, func_value_ast) |
- 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) |
- # 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 |
- for childAst in ast: |
- (label, childAst) = childAst |
- if label.endswith('Type'): |
- self.id = self._label_to_type(label, ast) |
- break |
- 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 |
- if not self.id: |
- raise SyntaxError('Could not parse type %s' % (ast)) |
- |
- def _label_to_type(self, label, ast): |
- if label == 'AnyArrayType': |
- return 'any[]' |
- if label == 'DOMStringArrayType': |
- return 'DOMString[]' |
- 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 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) |
- self.operations = self._convert_all(ast, 'Operation', IDLOperation) |
- self.attributes = self._convert_all(ast, 'Attribute', IDLAttribute) |
- self.constants = self._convert_all(ast, 'Const', IDLConstant) |
- self.is_supplemental = 'Supplemental' in self.ext_attrs |
- self.is_no_interface_object = 'NoInterfaceObject' in self.ext_attrs |
- self.is_fc_suppressed = 'Suppressed' in self.ext_attrs |
- self.javascript_binding_name = self.id |
- |
- def has_attribute(self, candidate): |
- for attribute in self.attributes: |
- if (attribute.id == candidate.id and |
- attribute.is_fc_getter == candidate.is_fc_getter and |
- attribute.is_fc_setter == candidate.is_fc_setter): |
- 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): |
- IDLNode.__init__(self, ast) |
- self.type = self._convert_first(ast, 'Type', IDLType) |
- self._convert_ext_attrs(ast) |
- self._convert_annotations(ast) |
- self.is_fc_suppressed = 'Suppressed' in self.ext_attrs |
- |
- |
-class IDLOperation(IDLMember): |
- """IDLNode specialization for 'type name(args)' declarations.""" |
- def __init__(self, ast): |
- IDLMember.__init__(self, ast) |
- self.type = self._convert_first(ast, 'ReturnType', IDLType) |
- self.arguments = self._convert_all(ast, 'Argument', IDLArgument) |
- self.raises = self._convert_first(ast, 'Raises', IDLType) |
- self.specials = self._find_all(ast, 'Special') |
- self.is_stringifier = self._has(ast, 'Stringifier') |
- self.is_static = self._has(ast, 'Static') |
- def _extra_repr(self): |
- return [self.arguments] |
- |
- |
-class IDLAttribute(IDLMember): |
- """IDLNode specialization for 'attribute type name' declarations.""" |
- def __init__(self, ast): |
- IDLMember.__init__(self, ast) |
- self.is_read_only = self._has(ast, 'ReadOnly') |
- # There are various ways to define exceptions for attributes: |
- self.raises = self._convert_first(ast, 'Raises', IDLType) |
- self.get_raises = self.raises \ |
- or self._convert_first(ast, 'GetRaises', IDLType) |
- self.set_raises = self.raises \ |
- or self._convert_first(ast, 'SetRaises', IDLType) |
- # FremontCut IDL syntax defines getters and setters separately: |
- self.is_fc_getter = self._has(ast, 'AttrGetter') |
- self.is_fc_setter = self._has(ast, 'AttrSetter') |
- def _extra_repr(self): |
- extra = [] |
- if self.is_fc_getter: extra.append('get') |
- if self.is_fc_setter: extra.append('set') |
- if self.is_read_only: extra.append('readonly') |
- if self.raises: extra.append('raises') |
- return extra |
- |
-class IDLConstant(IDLMember): |
- """IDLNode specialization for 'const type name = value' declarations.""" |
- def __init__(self, ast): |
- IDLMember.__init__(self, ast) |
- self.value = self._find_first(ast, 'ConstExpr') |
- |
- |
-class IDLArgument(IDLNode): |
- """IDLNode specialization for operation arguments.""" |
- def __init__(self, ast): |
- IDLNode.__init__(self, ast) |
- self.type = self._convert_first(ast, 'Type', IDLType) |
- self._convert_ext_attrs(ast) |
- # WebKit and Web IDL differ in how Optional is declared: |
- self.is_optional = self._has(ast, 'Optional') \ |
- or ('Optional' in self.ext_attrs) |
- |
- |
-class IDLImplementsStatement(IDLNode): |
- """IDLNode specialization for 'X implements Y' declarations.""" |
- def __init__(self, ast): |
- IDLNode.__init__(self, ast) |
- 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 |