#!/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."""

import emitter
from generator import AnalyzeOperation, ConstantOutputOrder, \
    DartDomNameOfAttribute, FindMatchingAttribute, IsPureInterface, \
    TypeOrNothing, ConvertToFuture, GetCallbackInfo
from copy import deepcopy
from htmlrenamer import convert_to_future_members, custom_html_constructors, \
    keep_overloaded_members, overloaded_and_renamed, private_html_members, \
    renamed_html_members, renamed_overloads, removed_html_members
from generator import TypeOrVar
import logging
import monitored
import sys

_logger = logging.getLogger('htmldartgenerator')

# 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',
}

_custom_factories = [
  'Notification',
  'EventSource',
]

class HtmlDartGenerator(object):
  def __init__(self, interface, options, dart_use_blink, logger):
    self._dart_use_blink = dart_use_blink
    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
    self._metadata = options.metadata
    self._library_name = self._renamer.GetLibraryName(self._interface)
    _logger.setLevel(logger.level)

  def EmitSupportCheck(self):
    if self.HasSupportCheck():
      check = self.GetSupportCheck()
      if type(check) != tuple:
        signature = 'get supported'
      else:
        signature = check[0]
        check = check[1]
      self._members_emitter.Emit('\n'
          '  /// Checks if this type is supported on the current platform.\n'
          '  static bool $SIGNATURE => $SUPPORT_CHECK;\n',
          SIGNATURE=signature, SUPPORT_CHECK=check)

  def EmitEventGetter(self, events_class_name):
    self._members_emitter.Emit(
        "\n  @DocsEditable()"
        "\n  @DomName('EventTarget.addEventListener, "
        "EventTarget.removeEventListener, EventTarget.dispatchEvent')"
        "\n  @deprecated"
        "\n  $TYPE get on =>\n    new $TYPE(this);\n",
        TYPE=events_class_name)

  def AddMembers(self, interface, declare_only=False, dart_js_interop=False):
    for const in sorted(interface.constants, ConstantOutputOrder):
      self.AddConstant(const)

    for attr in sorted(interface.attributes, ConstantOutputOrder):
      if attr.type.id != 'EventHandler' and 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 name.
    self._AddRenamedOverloads(interface)
    operationsByName = self._OperationsByName(interface)
    if self.OmitOperationOverrides():
      self._RemoveShadowingOperationsWithSameSignature(operationsByName,
          interface)

    # Generate operations.
    for id in sorted(operationsByName.keys()):
      operations = operationsByName[id]
      info = AnalyzeOperation(interface, operations)
      self.AddOperation(info, declare_only, dart_js_interop)
      if ('%s.%s' % (interface.id, info.declared_name) in
          convert_to_future_members):
        self.AddOperation(ConvertToFuture(info), declare_only)

  def _HoistableConstants(self, interface):
    consts = []
    if interface.parents:
      for parent in interface.parents:
        parent_interface = self._database.GetInterface(parent.type.id)
        # TODO(vsm): This should be a general check.  E.g., on private
        # interfaces?
        if parent.type.id == 'WebGLRenderingContextBase':
          consts = consts + parent_interface.constants
    return consts

  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.
    if not self._renamer.ShouldSuppressInterface(interface):
      secondary_constants = sorted(self._HoistableConstants(interface),
                                     ConstantOutputOrder)
      for const in secondary_constants:
        self.AddConstant(const)

    secondary_parents = self._database.TransitiveSecondaryParents(interface,
                          not self._dart_use_blink)
    remove_duplicate_parents = list(set(secondary_parents))
    if len(secondary_parents) != len(remove_duplicate_parents):
      secondary_parents = remove_duplicate_parents
      parent_list = ", ".join(["  %s" % (parent.id) for parent in secondary_parents])
      _logger.warn('Interface %s has duplicate parent interfaces %s - ' \
                   'ignoring duplicates. Please file a bug with the dart:html team.' % (interface.id, parent_list))

    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):
          if attr.type.id != 'EventHandler':
            self.SecondaryContext(parent_interface)
            self.AddAttribute(attr)

      # Group overloaded operations by name.
      operationsByName =self._OperationsByName(parent_interface)

      if self.OmitOperationOverrides():
        self._RemoveShadowingOperationsWithSameSignature(operationsByName,
            interface)

      # Generate operations.
      for id in sorted(operationsByName.keys()):
        if not any(op.id == id for op in interface.operations):
          operations = operationsByName[id]
          info = AnalyzeOperation(interface, operations)
          self.SecondaryContext(parent_interface)
          self.AddOperation(info)

  def _RemoveShadowingOperationsWithSameSignature(self, operationsByName,
      interface):
    if not interface.parents:
      return

    parent_name = interface.parents[0].type.id
    parent = self._database.GetInterface(parent_name)
    if parent == self._interface or parent == interface:
      return

    # Never remove operations that are added as a result of an implements they
    # are pure interfaces (mixins to this interface).
    if (IsPureInterface(parent_name)):
      return

    for operation in parent.operations:
      if operation.id in operationsByName:
        operations = operationsByName[operation.id]
        for existing_operation in operations:
          if existing_operation.SameSignatureAs(operation):
            del operationsByName[operation.id]

  def _AddRenamedOverloads(self, interface):
    """The IDL has a number of functions with the same name but that accept
    different types. This is fine for JavaScript, but results in vague type
    signatures for Dart. We rename some of these (by adding a new identical
    operation with a different DartName), but leave the original version as
    well in some cases."""
    potential_added_operations = set()
    operations_by_name = self._OperationsByName(interface)
    already_renamed = [operation.ext_attrs['DartName'] if 'DartName' in
        operation.ext_attrs else '' for operation in interface.operations]

    added_operations = []
    for operation in interface.operations:
      full_operation_str = self._GetStringRepresentation(interface, operation)
      if (full_operation_str in renamed_overloads and
          renamed_overloads[full_operation_str] not in already_renamed):
        if '%s.%s' % (interface.id, operation.id) in overloaded_and_renamed:
          cloned_operation = deepcopy(operation)
          cloned_operation.ext_attrs['DartName'] = renamed_overloads[
              full_operation_str]
          added_operations.append(cloned_operation)
        else:
          dart_name = renamed_overloads[full_operation_str]
          if not dart_name:
            continue

          operation.ext_attrs['DartName'] = dart_name
          potential_added_operations.add(operation.id)
      self._EnsureNoMultipleTypeSignatures(interface, operation,
          operations_by_name)
    interface.operations += added_operations
    self._AddDesiredOverloadedOperations(potential_added_operations, interface,
        operations_by_name)

  def _AddDesiredOverloadedOperations(self, potential_added_operations,
      interface, original_operations_by_name):
    """For some cases we desire to keep the overloaded version in dart, for
    simplicity of API, and explain the parameters accepted in documentation."""
    updated_operations_by_name = self._OperationsByName(interface)
    for operation_id in potential_added_operations:
      if (operation_id not in updated_operations_by_name and
          '%s.%s' % (interface.id, operation_id) in keep_overloaded_members):
        for operation in original_operations_by_name[operation_id]:
          cloned_operation = deepcopy(operation)
          cloned_operation.ext_attrs['DartName'] = operation_id
          interface.operations.append(cloned_operation)

  def _EnsureNoMultipleTypeSignatures(self, interface, operation,
      operations_by_name):
    """Make sure that there is now at most one operation with a particular
    operation.id. If not, stop library generation, and throw an error, requiring
    programmer input about the best name change before proceeding."""
    operation_str = '%s.%s' % (interface.id, operation.id)

    if (operation.id in operations_by_name and
        len(operations_by_name[operation.id]) > 1 and
        len(filter(lambda overload: overload.startswith(operation_str),
            renamed_overloads.keys())) == 0 and
        operation_str not in keep_overloaded_members and
        operation_str not in overloaded_and_renamed and
        operation_str not in renamed_html_members and
        operation_str not in private_html_members and
        operation_str not in removed_html_members and
        operation.id != '__getter__' and
        operation.id != '__setter__' and
        operation.id != '__delete__'):
      _logger.warn('Multiple type signatures for %s.%s. Please file a bug with'
          ' the dart:html team to determine if one of these functions should be'
          ' renamed.' % (
          interface.id, operation.id))

  def _GetStringRepresentation(self, interface, operation):
    """Given an IDLOperation, return a object-independent representation of the
    operations's signature."""
    return '%s.%s(%s)' % (interface.id, operation.id, ', '.join(
        ['%s %s' % (arg.type.id, arg.id) for arg in operation.arguments]))

  def _OperationsByName(self, interface):
    operationsByName = {}
    for operation in interface.operations:
      name = operation.ext_attrs.get('DartName', operation.id)
      operationsByName.setdefault(name, []).append(operation)
    return operationsByName

  def OmitOperationOverrides(self):
    return False

  def AddConstant(self, constant):
    const_name = self._renamer.RenameMember(
        self._interface.id, constant, constant.id, 'get:', dartify_name=False)
    if not const_name:
      return

    annotations = self._metadata.GetFormattedMetadata(
        self._library_name, self._interface, constant.id, '  ')

    type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id)
    self._members_emitter.Emit(
        '\n  $(ANNOTATIONS)static const $TYPE$NAME = $VALUE;\n',
        ANNOTATIONS=annotations,
        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:
      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, dart_js_interop=False):
    # TODO(terry): Hack window has 2 overloaded getter one returns Window and
    #              and other object (we'll always return Window)?
    if self._interface.id == "Window" and info.name == '__getter__':
      info.operations[1].type = info.operations[0].type;

    """ 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,
                                             'call:')

    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, dart_js_interop)

  def _GenerateOverloadDispatcher(self,
      info,
      signatures,
      is_void,
      declaration,
      generate_call,
      is_optional,
      emitter,
      can_omit_type_check=lambda type, pos: False):

    parameter_names = [p.name for p in info.param_infos]
    number_of_required_in_dart = info.NumberOfRequiredInDart()

    body_emitter = emitter.Emit(
        '\n'
        '  $DECLARATION {\n'
        '$!BODY'
        '  }\n',
        DECLARATION=declaration)

    version = [0]
    def GenerateCall(signature_index, argument_count, checks):
      if checks:
        (stmts_emitter, call_emitter) = body_emitter.Emit(
            '    if ($CHECKS) {\n$!STMTS$!CALL    }\n',
            INDENT='      ',
            CHECKS=' && '.join(checks))
      else:
        (stmts_emitter, call_emitter) = body_emitter.Emit(
            '$!STMTS$!CALL',
            INDENT='    ');

      if is_void:
        call_emitter = call_emitter.Emit('$(INDENT)$!CALL;\n$(INDENT)return;\n')
      else:
        call_emitter = call_emitter.Emit('$(INDENT)return $!CALL;\n')

      version[0] += 1
      generate_call(stmts_emitter, call_emitter,
          version[0], signature_index, argument_count)

    def GenerateChecksAndCall(signature_index, argument_count):
      checks = []
      typechecked_interface = \
          ('TypeChecking' in self._interface.ext_attrs) and \
          ('Interface' in self._interface.ext_attrs['TypeChecking'])

      for i in reversed(range(0, argument_count)):
        argument = signatures[signature_index][i]
        parameter_name = parameter_names[i]

        test_type = self._NarrowToImplementationType(argument.type.id)

        if test_type in ['dynamic', 'Object']:
          checks.append('%s != null' % parameter_name)
        elif not can_omit_type_check(test_type, i):
          typechecked = typechecked_interface or \
              ('TypeChecking' in argument.ext_attrs) and \
              ('Interface' in argument.ext_attrs['TypeChecking'])
          converts_null = \
              ('TreatNullAs' in argument.ext_attrs) or \
              (argument.default_value is not None) or \
              (argument.default_value_is_null)
          if argument.type.nullable or converts_null or not typechecked:
            checks.append('(%s is %s || %s == null)' % (
                parameter_name, test_type, parameter_name))
          else:
            checks.append('(%s is %s)' % (
                parameter_name, test_type))
        elif i >= number_of_required_in_dart:
          checks.append('%s != null' % parameter_name)

      # There can be multiple presence checks.  We need them all since a later
      # optional argument could have been passed by name, leaving 'holes'.
      checks.extend(['%s == null' % name for name in parameter_names[argument_count:]])

      GenerateCall(signature_index, argument_count, checks)

    # TODO: Optimize the dispatch to avoid repeated checks.
    if len(signatures) > 1:
      index_swaps = {}
      for signature_index, signature in enumerate(signatures):
        for argument_position, argument in enumerate(signature):
          if argument.type.id != 'ArrayBuffer':
            continue
          candidates = enumerate(
              signatures[signature_index + 1:], signature_index + 1)
          for candidate_index, candidate in candidates:
            if len(candidate) <= argument_position:
              continue
            if candidate[argument_position].type.id != 'ArrayBufferView':
              continue
            if len(index_swaps):
              raise Exception('Cannot deal with more than a single swap')
            index_swaps[candidate_index] = signature_index
            index_swaps[signature_index] = candidate_index

      for signature_index in range(len(signatures)):
        signature_index = index_swaps.get(signature_index, signature_index)
        signature = signatures[signature_index]
        for argument_position, argument in enumerate(signature):
          if is_optional(signature_index, argument):
            GenerateChecksAndCall(signature_index, argument_position)
        GenerateChecksAndCall(signature_index, len(signature))
      body_emitter.Emit(
          '    throw new ArgumentError("Incorrect number or type of arguments");'
          '\n');
    else:
      signature = signatures[0]
      argument_count = len(signature)
      for argument_position, argument in list(enumerate(signature))[::-1]:
        if is_optional(0, argument):
          check = '%s != null' % parameter_names[argument_position]
          # argument_count instead of argument_position + 1 is used here to cover one
          # complicated case with the effectively optional argument in the middle.
          # Consider foo(x, optional y, [Default=NullString] optional z)
          # (as of now it's modelled after HTMLMediaElement.webkitAddKey).
          # y is optional in WebCore, while z is not.
          # In this case, if y was actually passed, we'd like to emit foo(x, y, z) invocation,
          # not foo(x, y).
          GenerateCall(0, argument_count, [check])
          argument_count = argument_position
      GenerateCall(0, argument_count, [])

  def _GenerateDispatcherBody(self,
      info,
      operations,
      declaration,
      generate_call,
      is_optional,
      can_omit_type_check=lambda type, pos: False):

    def GenerateCall(
        stmts_emitter, call_emitter, version, signature_index, argument_count):
      generate_call(
          stmts_emitter, call_emitter,
          version, operations[signature_index], argument_count)

    def IsOptional(signature_index, argument):
      return is_optional(argument)

    emitter = self._members_emitter

    self._GenerateOverloadDispatcher(
        info,
        [operation.arguments for operation in operations],
        operations[0].type.id == 'void',
        declaration,
        GenerateCall,
        IsOptional,
        emitter,
        can_omit_type_check)

  def AdditionalImplementedInterfaces(self):
    # TODO: Include all implemented interfaces, including other Lists.
    implements = []
    if self._interface_type_info.list_item_type():
      item_type = self._type_registry.TypeInfo(
          self._interface_type_info.list_item_type()).dart_type()
      implements.append('List<%s>' % item_type)
    return implements

  def Mixins(self):
    mixins = []
    if self._interface_type_info.list_item_type():
      item_type = self._type_registry.TypeInfo(
          self._interface_type_info.list_item_type()).dart_type()
      mixins.append('ListMixin<%s>' % item_type)
      mixins.append('ImmutableListMixin<%s>' % item_type)

    return mixins


  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)

  def _AddConstructor(self,
      constructor_info, factory_name, factory_constructor_name):
    # Hack to ignore the Image constructor used by JavaScript.
    if ((self._interface.id == 'HTMLImageElement' or
         self._interface.id == 'Blob' or
         self._interface.id == 'DOMException')
      and not constructor_info.pure_dart_constructor):
      return

    if self.GenerateCustomFactory(constructor_info):
      return

    metadata = self._metadata.GetFormattedMetadata(
        self._library_name, self._interface, self._interface.id, '  ')

    if not factory_constructor_name:
      factory_constructor_name = '_create'
      factory_parameters = constructor_info.ParametersAsArgumentList()
    else:
      factory_parameters = ', '.join(constructor_info.factory_parameters)

    def InputType(type_name):
      conversion = self._InputConversion(
          type_name, constructor_info.declared_name)
      if conversion:
        return conversion.input_type
      else:
        return self._NarrowInputType(type_name) if type_name else 'dynamic'

    if constructor_info.pure_dart_constructor:
      # TODO(antonm): use common dispatcher generation for this case as well.
      has_optional = any(param_info.is_optional
          for param_info in constructor_info.param_infos)

      if not has_optional:
        self._members_emitter.Emit(
            '\n  $(METADATA)'
            'factory $CTOR($PARAMS) => '
            '$FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n',
            CTOR=constructor_info._ConstructorFullName(self._DartType),
            PARAMS=constructor_info.ParametersAsDeclaration(InputType),
            FACTORY=factory_name,
            METADATA=metadata,
            CTOR_FACTORY_NAME=factory_constructor_name,
            FACTORY_PARAMS=factory_parameters)
      else:
        inits = self._members_emitter.Emit(
            '\n  $(METADATA)'
            'factory $CONSTRUCTOR($PARAMS) {\n'
            '    var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n'
            '$!INITS'
            '    return e;\n'
            '  }\n',
            CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType),
            METADATA=metadata,
            FACTORY=factory_name,
            CTOR_FACTORY_NAME=factory_constructor_name,
            PARAMS=constructor_info.ParametersAsDeclaration(InputType),
            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=param_info.name)
    else:
      custom_factory_ctr = self._interface.id in _custom_factories
      constructor_full_name = constructor_info._ConstructorFullName(
          self._DartType)

      def GenerateCall(
          stmts_emitter, call_emitter,
          version, signature_index, argument_count):
        name = emitter.Format('_create_$VERSION', VERSION=version)
        arguments = constructor_info.idl_args[signature_index][:argument_count]
        args = None
        call_template = ''
        if self._dart_use_blink:
            type_ids = [p.type.id for p in arguments]
            base_name, rs = \
                self.DeriveNativeEntry("constructorCallback", 'Constructor', argument_count)
            qualified_name = \
                self.DeriveQualifiedBlinkName(self._interface.id,
                                              base_name)
            args = constructor_info.ParametersAsArgumentList(argument_count)

            # Handle converting Maps to Dictionaries, etc.
            (factory_params, converted_arguments) = self._ConvertArgumentTypes(
                stmts_emitter, arguments, argument_count, constructor_info)
            args = ', '.join(converted_arguments)
            call_template = '$FACTORY_NAME($FACTORY_PARAMS)'
        else:
            qualified_name = emitter.Format(
                '$FACTORY.$NAME',
                FACTORY=factory_name,
                NAME=name)
            (factory_params, converted_arguments) = self._ConvertArgumentTypes(
                stmts_emitter, arguments, argument_count, constructor_info)
            args = ', '.join(converted_arguments)
            call_template = '$FACTORY_NAME($FACTORY_PARAMS)'
        call_emitter.Emit(call_template, FACTORY_NAME=qualified_name, FACTORY_PARAMS=args)
        self.EmitStaticFactoryOverload(constructor_info, name, arguments)

      def IsOptional(signature_index, argument):
        return self.IsConstructorArgumentOptional(argument)

      entry_declaration = emitter.Format(
          '$(METADATA)$FACTORY_KEYWORD $CTOR($PARAMS)',
          FACTORY_KEYWORD=('factory' if not custom_factory_ctr else
                           'static %s' % constructor_full_name),
          CTOR=(('' if not custom_factory_ctr else '_factory')
                + constructor_full_name),
          METADATA=metadata,
          PARAMS=constructor_info.ParametersAsDeclaration(InputType))

      overload_emitter = self._members_emitter
      overload_declaration = entry_declaration

      self._GenerateOverloadDispatcher(
          constructor_info,
          constructor_info.idl_args,
          False,
          overload_declaration,
          GenerateCall,
          IsOptional,
          overload_emitter)

  def _AddFutureifiedOperation(self, info, html_name):
    """Given a API function that uses callbacks, convert it to using Futures.

    This conversion assumes the success callback is always provided before the
    error callback (and so far in the DOM API, this is the case)."""
    callback_info = GetCallbackInfo(
        self._database.GetInterface(info.callback_args[0].type_id))

    param_list = info.ParametersAsArgumentList()
    metadata = ''
    if '_RenamingAnnotation' in dir(self):
      metadata = (self._RenamingAnnotation(info.declared_name, html_name) +
          self._Metadata(info.type_name, info.declared_name, None))
    self._members_emitter.Emit(
        '\n'
        '  $METADATA$MODIFIERS$TYPE$FUTURE_GENERIC $NAME($PARAMS) {\n'
        '    var completer = new Completer$(FUTURE_GENERIC)();\n'
        '    $ORIGINAL_FUNCTION($PARAMS_LIST\n'
        '        $NAMED_PARAM($VARIABLE_NAME) { '
        'completer.complete($VARIABLE_NAME); }'
        '$ERROR_CALLBACK);\n'
        '    return completer.future;\n'
        '  }\n',
        METADATA=metadata,
        MODIFIERS='static ' if info.IsStatic() else '',
        TYPE=self.SecureOutputType(info.type_name),
        NAME=html_name[1:],
        PARAMS=info.ParametersAsDeclaration(self._NarrowInputType
            if '_NarrowInputType' in dir(self) else self._DartType),
        PARAMS_LIST='' if param_list == '' else param_list + ',',
        NAMED_PARAM=('%s : ' % info.callback_args[0].name
            if info.requires_named_arguments and
              info.callback_args[0].is_optional else ''),
        VARIABLE_NAME= '' if len(callback_info.param_infos) == 0 else 'value',
        ERROR_CALLBACK=('' if len(info.callback_args) == 1 else
            (',\n        %s(error) { completer.completeError(error); }' %
            ('%s : ' % info.callback_args[1].name
            if info.requires_named_arguments and
                info.callback_args[1].is_optional else ''))),
        FUTURE_GENERIC = ('' if len(callback_info.param_infos) == 0 or
            not callback_info.param_infos[0].type_id else
            '<%s>' % self._DartType(callback_info.param_infos[0].type_id)),
        ORIGINAL_FUNCTION = html_name)

  def EmitHelpers(self, base_class):
    if not self._members_emitter:
      return

    if self._interface.id not in custom_html_constructors:
      self._members_emitter.Emit(
          '  // To suppress missing implicit constructor warnings.\n'
          '  factory $CLASSNAME._() { '
          'throw new UnsupportedError("Not supported"); }\n',
          CLASSNAME=self._interface_type_info.implementation_name())

  def DeclareAttribute(self, attribute, type_name, attr_name, read_only):
    """ Declares an attribute but does not include the code to invoke it.
    """
    if read_only:
      # HACK(terry): Element is not abstract for Dartium so isContentEditable
      # must have a body see impl_Element.darttemplate
      if (self._interface.id == 'Element' and
          attr_name == 'isContentEditable' and
          self._dart_js_interop):
        return
      else:
        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.
    """
      # HACK(terry): Element is not abstract for Dartium so click
      # must have a body see impl_Element.darttemplate
    if (self._interface.id == 'Element' and
        method_name == 'click' and
        self._dart_js_interop):
      return
    else:
      template = '\n  $TYPE $NAME($PARAMS);\n'

    self._members_emitter.Emit(
             template,
             TYPE=return_type_name,
             NAME=method_name,
             PARAMS=operation.ParametersAsDeclaration(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_length = False
    has_length_setter = False

    def _HasExplicitIndexedGetter(self):
      return any(op.id == 'getItem' for op in self._interface.operations)

    def _HasCustomIndexedGetter(self):
      return 'CustomIndexedGetter' in self._interface.ext_attrs

    def _HasNativeIndexedGetter(self):
      return not (_HasCustomIndexedGetter(self) or _HasExplicitIndexedGetter(self))

    if _HasExplicitIndexedGetter(self):
      getter_name = 'getItem'
    else:
      getter_name = '_nativeIndexedGetter'

    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_LENGTH_AS_NUM_ITEMS': not has_length and has_num_items,
          'DEFINE_LENGTH_SETTER': not has_length_setter,
          'USE_NATIVE_INDEXED_GETTER': _HasNativeIndexedGetter(self) or _HasExplicitIndexedGetter(self),
        })
    self._members_emitter.Emit(template, E=element_name, GETTER=getter_name)

  def SecureOutputType(self, type_name, is_dart_type=False,
      can_narrow_type=False):
    """ Converts the type name to the secure type name for return types.
    Arguments:
      can_narrow_type - True if the output type can be narrowed further than
        what would be accepted for input, used to narrow num APIs down to double
        or int.
    """
    if is_dart_type:
      dart_name = type_name
    else:
      type_info = self._TypeInfo(type_name)
      dart_name = type_info.dart_type()
      if can_narrow_type and dart_name == 'num':
        dart_name = type_info.native_type()

    # 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 is_DOM_type(self, type_name):
    try:
        self._type_registry.TypeInfo(type_name)
        return True
    except RuntimeError:
        return False

  def _NarrowToImplementationType(self, type_name):
    return self._type_registry.TypeInfo(type_name).narrow_dart_type()

  def _NarrowInputType(self, type_name):
    return self._NarrowToImplementationType(type_name)

  def _DartType(self, type_name):
    return self._type_registry.DartType(type_name)

  def _TypeInfo(self, type_name):
    return self._type_registry.TypeInfo(type_name)

  def _ConvertArgumentTypes(self, stmts_emitter, arguments, argument_count, info):
    temp_version = [0]
    converted_arguments = []
    target_parameters = []
    for position, arg in enumerate(arguments[:argument_count]):
      conversion = self._InputConversion(arg.type.id, info.declared_name)
      param_name = arguments[position].id
      if conversion:
        temp_version[0] += 1
        temp_name = '%s_%s' % (param_name, temp_version[0])
        temp_type = conversion.output_type
        stmts_emitter.Emit(
            '$(INDENT)$TYPE $NAME = $CONVERT($ARG);\n',
            TYPE=TypeOrVar(temp_type),
            NAME=temp_name,
            CONVERT=conversion.function_name,
            ARG=info.param_infos[position].name)
        converted_arguments.append(temp_name)
        param_type = temp_type
        verified_type = temp_type  # verified by assignment in checked mode.
      else:
        converted_arguments.append(info.param_infos[position].name)
        if self._database.HasTypeDef(arg.type.id):
          param_type = 'dynamic'
        else:
          param_type = self._NarrowInputType(arg.type.id)
          # Verified by argument checking on entry to the dispatcher.
  
          verified_type = self._InputType(
              info.param_infos[position].type_id, info)
          # The native method does not need an argument type if we know the type.
          # But we do need the native methods to have correct function types, so
          # be conservative.
          if param_type == verified_type:
            if param_type in ['String', 'num', 'int', 'double', 'bool', 'Object']:
              param_type = 'dynamic'

      target_parameters.append(
          '%s%s' % (TypeOrNothing(param_type), param_name))

    return target_parameters, converted_arguments

  def _InputType(self, type_name, info):
    conversion = self._InputConversion(type_name, info.declared_name)
    if conversion:
      return conversion.input_type
    else:
      # If typedef it's a union return dynamic.
      if self._database.HasTypeDef(type_name):
        return 'dynamic'
      else:
        return self._NarrowInputType(type_name) if type_name else 'dynamic'
