Index: sdk/lib/html/scripts/htmldartgenerator.py |
diff --git a/sdk/lib/html/scripts/htmldartgenerator.py b/sdk/lib/html/scripts/htmldartgenerator.py |
deleted file mode 100644 |
index 5275cf131958b96b7086c851b066fcfcc7042e3c..0000000000000000000000000000000000000000 |
--- a/sdk/lib/html/scripts/htmldartgenerator.py |
+++ /dev/null |
@@ -1,418 +0,0 @@ |
-#!/usr/bin/python |
-# Copyright (c) 2012, 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. |
- |
-"""This module provides shared functionality for the system to generate |
-dart:html APIs from the IDL database.""" |
- |
-from generator import AnalyzeOperation, ConstantOutputOrder, \ |
- DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \ |
- IsPureInterface, TypeOrNothing |
- |
-# Types that are accessible cross-frame in a limited fashion. |
-# In these cases, the base type (e.g., WindowBase) provides restricted access |
-# while the subtype (e.g., Window) provides full access to the |
-# corresponding objects if there are from the same frame. |
-_secure_base_types = { |
- 'Window': 'WindowBase', |
- 'Location': 'LocationBase', |
- 'History': 'HistoryBase', |
-} |
- |
-class HtmlDartGenerator(object): |
- def __init__(self, interface, options): |
- self._database = options.database |
- self._interface = interface |
- self._type_registry = options.type_registry |
- self._interface_type_info = self._type_registry.TypeInfo(self._interface.id) |
- self._renamer = options.renamer |
- |
- def EmitAttributeDocumentation(self, attribute): |
- """ Emits the MDN dartdoc comment for an attribute. |
- """ |
- dom_name = DartDomNameOfAttribute(attribute) |
- self._members_emitter.Emit('\n /// @domName $DOMINTERFACE.$DOMNAME;' |
- ' @docsEditable true', |
- DOMINTERFACE=attribute.doc_js_interface_name, |
- DOMNAME=dom_name) |
- |
- def EmitOperationDocumentation(self, operation): |
- """ Emits the MDN dartdoc comment for an operation. |
- """ |
- self._members_emitter.Emit('\n /// @domName $DOMINTERFACE.$DOMNAME;' |
- ' @docsEditable true', |
- DOMINTERFACE=operation.overloads[0].doc_js_interface_name, |
- DOMNAME=operation.name) |
- |
- def EmitEventGetter(self, events_class_name): |
- self._members_emitter.Emit( |
- '\n /// @domName EventTarget.addEventListener, ' |
- 'EventTarget.removeEventListener, EventTarget.dispatchEvent;' |
- ' @docsEditable true' |
- '\n $TYPE get on =>\n new $TYPE(this);\n', |
- TYPE=events_class_name) |
- |
- def AddMembers(self, interface, declare_only=False): |
- for const in sorted(interface.constants, ConstantOutputOrder): |
- self.AddConstant(const) |
- |
- for attr in sorted(interface.attributes, ConstantOutputOrder): |
- if attr.type.id != 'EventListener': |
- self.AddAttribute(attr, declare_only) |
- |
- # The implementation should define an indexer if the interface directly |
- # extends List. |
- element_type = None |
- requires_indexer = False |
- if self._interface_type_info.list_item_type(): |
- self.AddIndexer(self._interface_type_info.list_item_type()) |
- else: |
- for parent in self._database.Hierarchy(self._interface): |
- if parent == self._interface: |
- continue |
- parent_type_info = self._type_registry.TypeInfo(parent.id) |
- if parent_type_info.list_item_type(): |
- self.AmendIndexer(parent_type_info.list_item_type()) |
- break |
- |
- # Group overloaded operations by id. |
- operationsById = {} |
- for operation in interface.operations: |
- if operation.id not in operationsById: |
- operationsById[operation.id] = [] |
- operationsById[operation.id].append(operation) |
- |
- # Generate operations. |
- for id in sorted(operationsById.keys()): |
- operations = operationsById[id] |
- info = AnalyzeOperation(interface, operations) |
- self.AddOperation(info, declare_only) |
- |
- def AddSecondaryMembers(self, interface): |
- # With multiple inheritance, attributes and operations of non-first |
- # interfaces need to be added. Sometimes the attribute or operation is |
- # defined in the current interface as well as a parent. In that case we |
- # avoid making a duplicate definition and pray that the signatures match. |
- secondary_parents = self._TransitiveSecondaryParents(interface) |
- for parent_interface in sorted(secondary_parents): |
- if isinstance(parent_interface, str): |
- continue |
- for attr in sorted(parent_interface.attributes, ConstantOutputOrder): |
- if not FindMatchingAttribute(interface, attr): |
- self.SecondaryContext(parent_interface) |
- self.AddAttribute(attr) |
- |
- # Group overloaded operations by id. |
- operationsById = {} |
- for operation in parent_interface.operations: |
- if operation.id not in operationsById: |
- operationsById[operation.id] = [] |
- operationsById[operation.id].append(operation) |
- |
- # Generate operations. |
- for id in sorted(operationsById.keys()): |
- if not any(op.id == id for op in interface.operations): |
- operations = operationsById[id] |
- info = AnalyzeOperation(interface, operations) |
- self.SecondaryContext(parent_interface) |
- self.AddOperation(info) |
- |
- def AddConstant(self, constant): |
- const_name = self._renamer.RenameMember( |
- self._interface.id, constant, constant.id, dartify_name=False) |
- if not const_name: |
- return |
- type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) |
- self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', |
- NAME=const_name, |
- TYPE=type, |
- VALUE=constant.value) |
- |
- def AddAttribute(self, attribute, declare_only=False): |
- """ Adds an attribute to the generated class. |
- Arguments: |
- attribute - The attribute which is to be added. |
- declare_only- True if the attribute should be declared as an abstract |
- member and not include invocation code. |
- """ |
- dom_name = DartDomNameOfAttribute(attribute) |
- attr_name = self._renamer.RenameMember( |
- self._interface.id, attribute, dom_name, 'get:') |
- if not attr_name or self._IsPrivate(attr_name): |
- return |
- |
- html_setter_name = self._renamer.RenameMember( |
- self._interface.id, attribute, dom_name, 'set:') |
- read_only = (attribute.is_read_only or 'Replaceable' in attribute.ext_attrs |
- or not html_setter_name) |
- |
- # We don't yet handle inconsistent renames of the getter and setter yet. |
- assert(not html_setter_name or attr_name == html_setter_name) |
- |
- if declare_only: |
- self.DeclareAttribute(attribute, |
- self.SecureOutputType(attribute.type.id), attr_name, read_only) |
- else: |
- self.EmitAttribute(attribute, attr_name, read_only) |
- |
- def AddOperation(self, info, declare_only=False): |
- """ Adds an operation to the generated class. |
- Arguments: |
- info - The operation info of the operation to be added. |
- declare_only- True if the operation should be declared as an abstract |
- member and not include invocation code. |
- """ |
- # FIXME: When we pass in operations[0] below, we're assuming all |
- # overloaded operations have the same security attributes. This |
- # is currently true, but we should consider filtering earlier or |
- # merging the relevant data into info itself. |
- method_name = self._renamer.RenameMember(self._interface.id, |
- info.operations[0], |
- info.name) |
- if not method_name: |
- if info.name == 'item': |
- # FIXME: item should be renamed to operator[], not removed. |
- self.EmitOperation(info, '_item') |
- return |
- |
- if declare_only: |
- self.DeclareOperation(info, |
- self.SecureOutputType(info.type_name), method_name) |
- else: |
- self.EmitOperation(info, method_name) |
- |
- def AdditionalImplementedInterfaces(self): |
- # TODO: Include all implemented interfaces, including other Lists. |
- implements = [] |
- if self._interface_type_info.is_typed_array(): |
- element_type = self._interface_type_info.list_item_type() |
- implements.append('List<%s>' % self._DartType(element_type)) |
- if self._interface_type_info.list_item_type(): |
- item_type_info = self._type_registry.TypeInfo( |
- self._interface_type_info.list_item_type()) |
- implements.append('List<%s>' % item_type_info.dart_type()) |
- return implements |
- |
- def AddConstructors(self, |
- constructors, factory_name, factory_constructor_name): |
- """ Adds all of the constructors. |
- Arguments: |
- constructors - List of the constructors to be added. |
- factory_name - Name of the factory for this class. |
- factory_constructor_name - The name of the constructor on the |
- factory_name to call (calls an autogenerated FactoryProvider |
- if unspecified) |
- """ |
- for constructor_info in constructors: |
- self._AddConstructor( |
- constructor_info, factory_name, factory_constructor_name) |
- |
- typed_array_type = None |
- for interface in self._database.Hierarchy(self._interface): |
- type_info = self._type_registry.TypeInfo(interface.id) |
- if type_info.is_typed_array(): |
- typed_array_type = type_info.list_item_type() |
- break |
- if typed_array_type: |
- self._members_emitter.Emit( |
- '\n' |
- ' factory $CTOR(int length) =>\n' |
- ' $FACTORY.create$(CTOR)(length);\n' |
- '\n' |
- ' factory $CTOR.fromList(List<$TYPE> list) =>\n' |
- ' $FACTORY.create$(CTOR)_fromList(list);\n' |
- '\n' |
- ' factory $CTOR.fromBuffer(ArrayBuffer buffer, ' |
- '[int byteOffset, int length]) => \n' |
- ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n', |
- CTOR=self._interface.id, |
- TYPE=self._DartType(typed_array_type), |
- FACTORY=factory_name) |
- |
- def _AddConstructor(self, |
- constructor_info, factory_name, factory_constructor_name): |
- self._members_emitter.Emit('\n ///@docsEditable true'); |
- |
- if not factory_constructor_name: |
- factory_constructor_name = '_create' |
- factory_parameters = constructor_info.ParametersAsArgumentList() |
- has_factory_provider = True |
- else: |
- factory_parameters = ', '.join(constructor_info.factory_parameters) |
- has_factory_provider = False |
- |
- has_optional = any(param_info.is_optional |
- for param_info in constructor_info.param_infos) |
- |
- if not has_optional: |
- self._members_emitter.Emit( |
- '\n' |
- ' factory $CTOR($PARAMS) => ' |
- '$FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n', |
- CTOR=constructor_info._ConstructorFullName(self._DartType), |
- PARAMS=constructor_info.ParametersDeclaration(self._DartType), |
- FACTORY=factory_name, |
- CTOR_FACTORY_NAME=factory_constructor_name, |
- FACTORY_PARAMS=factory_parameters) |
- else: |
- if has_factory_provider: |
- dispatcher_emitter = self._members_emitter.Emit( |
- '\n' |
- ' factory $CTOR($PARAMS) {\n' |
- '$!DISPATCHER' |
- ' return $FACTORY._create($FACTORY_PARAMS);\n' |
- ' }\n', |
- CTOR=constructor_info._ConstructorFullName(self._DartType), |
- PARAMS=constructor_info.ParametersDeclaration(self._DartType), |
- FACTORY=factory_name, |
- FACTORY_PARAMS=constructor_info.ParametersAsArgumentList()) |
- |
- for index, param_info in enumerate(constructor_info.param_infos): |
- if param_info.is_optional: |
- dispatcher_emitter.Emit( |
- ' if (!?$OPT_PARAM_NAME) {\n' |
- ' return $FACTORY._create($FACTORY_PARAMS);\n' |
- ' }\n', |
- OPT_PARAM_NAME=constructor_info.param_infos[index].name, |
- FACTORY=factory_name, |
- FACTORY_PARAMS=constructor_info.ParametersAsArgumentList(index)) |
- else: |
- inits = self._members_emitter.Emit( |
- '\n' |
- ' factory $CONSTRUCTOR($PARAMS) {\n' |
- ' var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n' |
- '$!INITS' |
- ' return e;\n' |
- ' }\n', |
- CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType), |
- FACTORY=factory_name, |
- CTOR_FACTORY_NAME=factory_constructor_name, |
- PARAMS=constructor_info.ParametersDeclaration(self._DartType), |
- FACTORY_PARAMS=factory_parameters) |
- |
- for index, param_info in enumerate(constructor_info.param_infos): |
- if param_info.is_optional: |
- inits.Emit(' if ($E != null) e.$E = $E;\n', |
- E=constructor_info.param_infos[index].name) |
- |
- if not constructor_info.pure_dart_constructor: |
- template_file = ('factoryprovider_%s.darttemplate' % self._interface.doc_js_name) |
- template = self._template_loader.TryLoad(template_file) |
- if template: |
- # There is a class specific factory. |
- # TODO(antonm): should move into the class template. |
- self._members_emitter.Emit(template) |
- else: |
- self.EmitStaticFactory(constructor_info) |
- |
- def EmitHelpers(self, base_class): |
- pass |
- |
- def DeclareAttribute(self, attribute, type_name, attr_name, read_only): |
- """ Declares an attribute but does not include the code to invoke it. |
- """ |
- self.EmitAttributeDocumentation(attribute) |
- if read_only: |
- template = '\n $TYPE get $NAME;\n' |
- else: |
- template = '\n $TYPE $NAME;\n' |
- |
- self._members_emitter.Emit(template, |
- NAME=attr_name, |
- TYPE=type_name) |
- |
- def DeclareOperation(self, operation, return_type_name, method_name): |
- """ Declares an operation but does not include the code to invoke it. |
- Arguments: |
- operation - The operation to be declared. |
- return_type_name - The name of the return type. |
- method_name - The name of the method. |
- """ |
- self.EmitOperationDocumentation(operation) |
- self._members_emitter.Emit( |
- '\n' |
- ' $TYPE $NAME($PARAMS);\n', |
- TYPE=return_type_name, |
- NAME=method_name, |
- PARAMS=operation.ParametersDeclaration(self._DartType)) |
- |
- def EmitListMixin(self, element_name): |
- # TODO(sra): Use separate mixins for mutable implementations of List<T>. |
- # TODO(sra): Use separate mixins for typed array implementations of List<T>. |
- template_file = 'immutable_list_mixin.darttemplate' |
- has_contains = any(op.id == 'contains' for op in self._interface.operations) |
- has_clear = any(op.id == 'clear' for op in self._interface.operations) |
- has_length = False |
- has_length_setter = False |
- for attr in self._interface.attributes: |
- if attr.id == 'length': |
- has_length = True |
- has_length_setter = not attr.is_read_only |
- |
- has_num_items = any(attr.id == 'numberOfItems' |
- for attr in self._interface.attributes) |
- |
- template = self._template_loader.Load( |
- template_file, |
- { |
- 'DEFINE_CONTAINS': not has_contains, |
- 'DEFINE_CLEAR': not has_clear, |
- 'DEFINE_LENGTH_AS_NUM_ITEMS': not has_length and has_num_items, |
- 'DEFINE_LENGTH_SETTER': not has_length_setter, |
- }) |
- self._members_emitter.Emit(template, E=element_name) |
- |
- def SecureOutputType(self, type_name, is_dart_type=False): |
- """ Converts the type name to the secure type name for return types. |
- """ |
- if is_dart_type: |
- dart_name = type_name |
- else: |
- dart_name = self._DartType(type_name) |
- # We only need to secure Window. Only local History and Location are |
- # returned in generated code. |
- assert(dart_name != 'HistoryBase' and dart_name != 'LocationBase') |
- if dart_name == 'Window': |
- return _secure_base_types[dart_name] |
- return dart_name |
- |
- def SecureBaseName(self, type_name): |
- if type_name in _secure_base_types: |
- return _secure_base_types[type_name] |
- |
- def _TransitiveSecondaryParents(self, interface): |
- """Returns a list of all non-primary parents. |
- |
- The list contains the interface objects for interfaces defined in the |
- database, and the name for undefined interfaces. |
- """ |
- def walk(parents): |
- for parent in parents: |
- parent_name = parent.type.id |
- if parent_name == 'EventTarget': |
- # Currently EventTarget is implemented as a mixin, not a proper |
- # super interface---ignore its members. |
- continue |
- if IsDartCollectionType(parent_name): |
- result.append(parent_name) |
- continue |
- if self._database.HasInterface(parent_name): |
- parent_interface = self._database.GetInterface(parent_name) |
- result.append(parent_interface) |
- walk(parent_interface.parents) |
- |
- result = [] |
- if interface.parents: |
- parent = interface.parents[0] |
- if IsPureInterface(parent.type.id): |
- walk(interface.parents) |
- else: |
- walk(interface.parents[1:]) |
- return result |
- |
- def _DartType(self, type_name): |
- return self._type_registry.DartType(type_name) |
- |
- def _IsPrivate(self, name): |
- return name.startswith('_') |