// 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.

library dart2js.typechecker;

import 'common/names.dart' show Identifiers;
import 'common/resolution.dart' show Resolution;
import 'common/tasks.dart' show CompilerTask;
import 'common.dart';
import 'compiler.dart' show Compiler;
import 'constants/expressions.dart';
import 'constants/values.dart';
import 'common_elements.dart';
import 'elements/resolution_types.dart';
import 'elements/elements.dart'
    show
        AbstractFieldElement,
        AstElement,
        ClassElement,
        ConstructorElement,
        Element,
        Elements,
        EnumClassElement,
        EnumConstantElement,
        ExecutableElement,
        FieldElement,
        FunctionElement,
        GetterElement,
        InitializingFormalElement,
        LibraryElement,
        MemberSignature,
        ParameterElement,
        ResolvedAst,
        SetterElement,
        TypeDeclarationElement,
        TypedElement,
        VariableElement;
import 'elements/entities.dart' show AsyncMarker;
import 'elements/names.dart';
import 'enqueue.dart' show DeferredAction;
import 'resolution/class_members.dart' show MembersCreator, ErroneousMember;
import 'resolution/tree_elements.dart' show TreeElements;
import 'tree/tree.dart';
import 'util/util.dart' show Link, LinkBuilder;

class TypeCheckerTask extends CompilerTask {
  final Compiler compiler;
  TypeCheckerTask(Compiler compiler)
      : compiler = compiler,
        super(compiler.measurer);

  String get name => "Type checker";
  DiagnosticReporter get reporter => compiler.reporter;

  void check(AstElement element) {
    if (element.isClass) return;
    if (element.isTypedef) return;
    ResolvedAst resolvedAst = element.resolvedAst;
    reporter.withCurrentElement(element.implementation, () {
      measure(() {
        TypeCheckerVisitor visitor = new TypeCheckerVisitor(
            compiler, resolvedAst.elements, compiler.types);
        if (element.isField) {
          visitor.analyzingInitializer = true;
          ResolutionDartType type =
              visitor.analyzeVariableTypeAnnotation(resolvedAst.node);
          visitor.analyzeVariableInitializer(element, type, resolvedAst.body);
        } else {
          resolvedAst.node.accept(visitor);
        }
      });
    });
  }
}

/**
 * Class used to report different warnings for different kinds of members.
 */
class MemberKind {
  static const MemberKind METHOD = const MemberKind("method");
  static const MemberKind OPERATOR = const MemberKind("operator");
  static const MemberKind GETTER = const MemberKind("getter");
  static const MemberKind SETTER = const MemberKind("setter");

  final String name;

  const MemberKind(this.name);

  String toString() => name;
}

/**
 * [ElementAccess] represents the access of [element], either as a property
 * access or invocation.
 */
abstract class ElementAccess {
  Element get element;

  String get name => element.name;

  ResolutionDartType computeType(Resolution resolution);

  /// Returns [: true :] if the element can be access as an invocation.
  bool isCallable(Compiler compiler) {
    if (element != null && element.isAbstractField) {
      AbstractFieldElement abstractFieldElement = element;
      if (abstractFieldElement.getter == null) {
        // Setters cannot be invoked as function invocations.
        return false;
      }
    }
    ResolutionInterfaceType functionType = compiler.commonElements.functionType;
    return compiler.types
        .isAssignable(computeType(compiler.resolution), functionType);
  }
}

/// An access of a instance member.
class MemberAccess extends ElementAccess {
  final MemberSignature member;

  MemberAccess(MemberSignature this.member);

  Element get element => member.declarations.first.element;

  ResolutionDartType computeType(Resolution resolution) => member.type;

  String toString() => 'MemberAccess($member)';
}

/// An access of an unresolved element.
class DynamicAccess implements ElementAccess {
  const DynamicAccess();

  Element get element => null;

  String get name => 'dynamic';

  ResolutionDartType computeType(Resolution resolution) =>
      const ResolutionDynamicType();

  bool isCallable(Compiler compiler) => true;

  String toString() => 'DynamicAccess';
}

/**
 * An access of a resolved top-level or static property or function, or an
 * access of a resolved element through [:this:].
 */
class ResolvedAccess extends ElementAccess {
  final Element element;

  ResolvedAccess(Element this.element) {
    assert(element != null);
  }

  ResolutionDartType computeType(Resolution resolution) {
    if (element.isGetter) {
      GetterElement getter = element;
      ResolutionFunctionType functionType = getter.computeType(resolution);
      return functionType.returnType;
    } else if (element.isSetter) {
      SetterElement setter = element;
      ResolutionFunctionType functionType = setter.computeType(resolution);
      if (functionType.parameterTypes.length != 1) {
        // TODO(johnniwinther,karlklose): this happens for malformed static
        // setters. Treat them the same as instance members.
        return const ResolutionDynamicType();
      }
      return functionType.parameterTypes.first;
    } else if (element.isTypedef || element.isClass) {
      TypeDeclarationElement typeDeclaration = element;
      typeDeclaration.computeType(resolution);
      return typeDeclaration.thisType;
    } else {
      TypedElement typedElement = element;
      typedElement.computeType(resolution);
      return typedElement.type;
    }
  }

  String toString() => 'ResolvedAccess($element)';
}

/// An access to a promoted variable.
class PromotedAccess extends ElementAccess {
  final VariableElement element;
  final ResolutionDartType type;

  PromotedAccess(VariableElement this.element, ResolutionDartType this.type) {
    assert(element != null);
    assert(type != null);
  }

  ResolutionDartType computeType(Resolution resolution) => type;

  String toString() => 'PromotedAccess($element,$type)';
}

/**
 * An access of a resolved top-level or static property or function, or an
 * access of a resolved element through [:this:].
 */
class TypeAccess extends ElementAccess {
  final ResolutionDartType type;
  TypeAccess(ResolutionDartType this.type) {
    assert(type != null);
  }

  Element get element => type.element;

  ResolutionDartType computeType(Resolution resolution) => type;

  String toString() => 'TypeAccess($type)';
}

/**
 * An access of a type literal.
 */
class TypeLiteralAccess extends ElementAccess {
  final ResolutionDartType type;

  TypeLiteralAccess(this.type) {
    assert(type != null);
  }

  Element get element => type.element;

  String get name => type.name;

  ResolutionInterfaceType computeType(Resolution resolution) =>
      resolution.commonElements.typeType;

  String toString() => 'TypeLiteralAccess($type)';
}

/// An access to the 'call' method of a function type.
class FunctionCallAccess implements ElementAccess {
  final Element element;
  final ResolutionDartType type;

  const FunctionCallAccess(this.element, this.type);

  String get name => 'call';

  ResolutionDartType computeType(Resolution resolution) => type;

  bool isCallable(Compiler compiler) => true;

  String toString() => 'FunctionAccess($element, $type)';
}

/// An is-expression that potentially promotes a variable.
class TypePromotion {
  final Send node;
  final VariableElement variable;
  final ResolutionDartType type;
  final List<TypePromotionMessage> messages = <TypePromotionMessage>[];

  TypePromotion(this.node, this.variable, this.type);

  bool get isValid => messages.isEmpty;

  TypePromotion copy() {
    return new TypePromotion(node, variable, type)..messages.addAll(messages);
  }

  void addHint(DiagnosticMessage hint,
      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
    messages.add(new TypePromotionMessage(hint, infos));
  }

  String toString() {
    return 'Promote ${variable} to ${type}${isValid ? '' : ' (invalid)'}';
  }
}

/// A hint or info message attached to a type promotion.
class TypePromotionMessage {
  DiagnosticMessage hint;
  List<DiagnosticMessage> infos;

  TypePromotionMessage(this.hint, this.infos);
}

class TypeCheckerVisitor extends Visitor<ResolutionDartType> {
  final Compiler compiler;
  final TreeElements elements;
  final Types types;

  Node lastSeenNode;
  ResolutionDartType expectedReturnType;
  AsyncMarker currentAsyncMarker = AsyncMarker.SYNC;

  final ClassElement currentClass;

  /// The immediately enclosing field, method or constructor being analyzed.
  ExecutableElement executableContext;

  CommonElements get commonElements => compiler.commonElements;

  DiagnosticReporter get reporter => compiler.reporter;

  Resolution get resolution => compiler.resolution;

  ResolutionInterfaceType get intType => commonElements.intType;
  ResolutionInterfaceType get doubleType => commonElements.doubleType;
  ResolutionInterfaceType get boolType => commonElements.boolType;
  ResolutionInterfaceType get stringType => commonElements.stringType;

  ResolutionDartType thisType;
  ResolutionDartType superType;

  Link<ResolutionDartType> cascadeTypes = const Link<ResolutionDartType>();

  bool analyzingInitializer = false;

  Map<Node, List<TypePromotion>> shownTypePromotionsMap =
      new Map<Node, List<TypePromotion>>();

  Map<VariableElement, Link<TypePromotion>> typePromotionsMap =
      new Map<VariableElement, Link<TypePromotion>>();

  Set<TypePromotion> reportedTypePromotions = new Set<TypePromotion>();

  void showTypePromotion(Node node, TypePromotion typePromotion) {
    List<TypePromotion> shownTypePromotions =
        shownTypePromotionsMap.putIfAbsent(node, () => <TypePromotion>[]);
    shownTypePromotions.add(typePromotion);
  }

  void registerKnownTypePromotion(TypePromotion typePromotion) {
    VariableElement variable = typePromotion.variable;
    Link<TypePromotion> knownTypes = typePromotionsMap.putIfAbsent(
        variable, () => const Link<TypePromotion>());
    typePromotionsMap[variable] = knownTypes.prepend(typePromotion);
  }

  void unregisterKnownTypePromotion(TypePromotion typePromotion) {
    VariableElement variable = typePromotion.variable;
    Link<TypePromotion> knownTypes = typePromotionsMap[variable].tail;
    if (knownTypes.isEmpty) {
      typePromotionsMap.remove(variable);
    } else {
      typePromotionsMap[variable] = knownTypes;
    }
  }

  List<TypePromotion> getShownTypePromotionsFor(Node node) {
    List<TypePromotion> shownTypePromotions = shownTypePromotionsMap[node];
    return shownTypePromotions != null ? shownTypePromotions : const [];
  }

  TypePromotion getKnownTypePromotion(VariableElement element) {
    Link<TypePromotion> promotions = typePromotionsMap[element];
    if (promotions != null) {
      while (!promotions.isEmpty) {
        TypePromotion typePromotion = promotions.head;
        if (typePromotion.isValid) {
          return typePromotion;
        }
        promotions = promotions.tail;
      }
    }
    return null;
  }

  ResolutionDartType getKnownType(VariableElement element) {
    TypePromotion typePromotion = getKnownTypePromotion(element);
    if (typePromotion != null) return typePromotion.type;
    return element.type;
  }

  TypeCheckerVisitor(this.compiler, TreeElements elements, this.types)
      : this.elements = elements,
        this.executableContext = elements.analyzedElement,
        this.currentClass = elements.analyzedElement != null
            ? elements.analyzedElement.enclosingClass
            : null {
    if (currentClass != null) {
      thisType = currentClass.thisType;
      superType = currentClass.supertype;
    } else {
      // If these are used, an error should have been reported by the resolver.
      thisType = const ResolutionDynamicType();
      superType = const ResolutionDynamicType();
    }
  }

  LibraryElement get currentLibrary => elements.analyzedElement.library;

  reportTypeWarning(Spannable spannable, MessageKind kind,
      [Map arguments = const {}]) {
    reporter.reportWarningMessage(spannable, kind, arguments);
  }

  reportMessage(Spannable spannable, MessageKind kind, Map arguments,
      {bool isHint: false}) {
    if (isHint) {
      reporter.reportHintMessage(spannable, kind, arguments);
    } else {
      reporter.reportWarningMessage(spannable, kind, arguments);
    }
  }

  reportTypePromotionHint(TypePromotion typePromotion) {
    if (!reportedTypePromotions.contains(typePromotion)) {
      reportedTypePromotions.add(typePromotion);
      for (TypePromotionMessage message in typePromotion.messages) {
        reporter.reportHint(message.hint, message.infos);
      }
    }
  }

  // TODO(karlklose): remove these functions.
  ResolutionDartType unhandledExpression() => const ResolutionDynamicType();

  ResolutionDartType analyzeNonVoid(Node node) {
    ResolutionDartType type = analyze(node);
    if (type.isVoid) {
      reportTypeWarning(node, MessageKind.VOID_EXPRESSION);
    }
    return type;
  }

  ResolutionDartType analyzeWithDefault(
      Node node, ResolutionDartType defaultValue) {
    return node != null ? analyze(node) : defaultValue;
  }

  /// If [inInitializer] is true, assignment should be interpreted as write to
  /// a field and not to a setter.
  ResolutionDartType analyze(Node node,
      {bool inInitializer: false, bool mustHaveType: true}) {
    if (node == null) {
      final String error = 'Unexpected node: null';
      if (lastSeenNode != null) {
        reporter.internalError(lastSeenNode, error);
      } else {
        reporter.internalError(executableContext, error);
      }
    } else {
      lastSeenNode = node;
    }
    bool previouslyInitializer = analyzingInitializer;
    analyzingInitializer = inInitializer;
    ResolutionDartType result = node.accept(this);
    analyzingInitializer = previouslyInitializer;
    if (result == null && mustHaveType) {
      reporter.internalError(node, 'Type is null.');
    }
    return result;
  }

  void analyzeUntyped(Node node, {bool inInitializer: false}) {
    if (node != null) {
      analyze(node, inInitializer: inInitializer, mustHaveType: false);
    }
  }

  void checkTypePromotion(Node node, TypePromotion typePromotion,
      {bool checkAccesses: false}) {
    VariableElement variable = typePromotion.variable;
    String variableName = variable.name;
    List<Node> potentialMutationsIn =
        elements.getPotentialMutationsIn(node, variable);
    if (!potentialMutationsIn.isEmpty) {
      DiagnosticMessage hint = reporter.createMessage(
          typePromotion.node,
          MessageKind.POTENTIAL_MUTATION,
          {'variableName': variableName, 'shownType': typePromotion.type});
      List<DiagnosticMessage> infos = <DiagnosticMessage>[];
      for (Node mutation in potentialMutationsIn) {
        infos.add(reporter.createMessage(
            mutation,
            MessageKind.POTENTIAL_MUTATION_HERE,
            {'variableName': variableName}));
      }
      typePromotion.addHint(hint, infos);
    }
    List<Node> potentialMutationsInClosures =
        elements.getPotentialMutationsInClosure(variable);
    if (!potentialMutationsInClosures.isEmpty) {
      DiagnosticMessage hint = reporter.createMessage(
          typePromotion.node,
          MessageKind.POTENTIAL_MUTATION_IN_CLOSURE,
          {'variableName': variableName, 'shownType': typePromotion.type});
      List<DiagnosticMessage> infos = <DiagnosticMessage>[];
      for (Node mutation in potentialMutationsInClosures) {
        infos.add(reporter.createMessage(
            mutation,
            MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE,
            {'variableName': variableName}));
      }
      typePromotion.addHint(hint, infos);
    }
    if (checkAccesses) {
      List<Node> accesses = elements.getAccessesByClosureIn(node, variable);
      List<Node> mutations = elements.getPotentialMutations(variable);
      if (!accesses.isEmpty && !mutations.isEmpty) {
        DiagnosticMessage hint = reporter.createMessage(
            typePromotion.node,
            MessageKind.ACCESSED_IN_CLOSURE,
            {'variableName': variableName, 'shownType': typePromotion.type});
        List<DiagnosticMessage> infos = <DiagnosticMessage>[];
        for (Node access in accesses) {
          infos.add(reporter.createMessage(
              access,
              MessageKind.ACCESSED_IN_CLOSURE_HERE,
              {'variableName': variableName}));
        }
        for (Node mutation in mutations) {
          infos.add(reporter.createMessage(
              mutation,
              MessageKind.POTENTIAL_MUTATION_HERE,
              {'variableName': variableName}));
        }
        typePromotion.addHint(hint, infos);
      }
    }
  }

  /// Show type promotions from [left] and [right] in [node] given that the
  /// promoted variables are not potentially mutated in [right].
  void reshowTypePromotions(Node node, Node left, Node right) {
    for (TypePromotion typePromotion in getShownTypePromotionsFor(left)) {
      typePromotion = typePromotion.copy();
      checkTypePromotion(right, typePromotion);
      showTypePromotion(node, typePromotion);
    }

    for (TypePromotion typePromotion in getShownTypePromotionsFor(right)) {
      typePromotion = typePromotion.copy();
      checkTypePromotion(right, typePromotion);
      showTypePromotion(node, typePromotion);
    }
  }

  /// Analyze [node] in the context of the known types shown in [context].
  ResolutionDartType analyzeInPromotedContext(Node context, Node node,
      {bool mustHaveType: true}) {
    Link<TypePromotion> knownForNode = const Link<TypePromotion>();
    for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) {
      typePromotion = typePromotion.copy();
      checkTypePromotion(node, typePromotion, checkAccesses: true);
      knownForNode = knownForNode.prepend(typePromotion);
      registerKnownTypePromotion(typePromotion);
    }

    final ResolutionDartType type = analyze(node, mustHaveType: mustHaveType);

    while (!knownForNode.isEmpty) {
      unregisterKnownTypePromotion(knownForNode.head);
      knownForNode = knownForNode.tail;
    }

    return type;
  }

  /**
   * Check if a value of type [from] can be assigned to a variable, parameter or
   * return value of type [to].  If `isConst == true`, an error is emitted in
   * checked mode, otherwise a warning is issued.
   */
  bool checkAssignable(
      Spannable spannable, ResolutionDartType from, ResolutionDartType to,
      {bool isConst: false}) {
    if (!types.isAssignable(from, to)) {
      if (compiler.options.enableTypeAssertions && isConst) {
        reporter.reportErrorMessage(spannable, MessageKind.NOT_ASSIGNABLE,
            {'fromType': from, 'toType': to});
      } else {
        reporter.reportWarningMessage(spannable, MessageKind.NOT_ASSIGNABLE,
            {'fromType': from, 'toType': to});
      }
      return false;
    }
    return true;
  }

  checkCondition(Expression condition) {
    checkAssignable(condition, analyze(condition), boolType);
  }

  void pushCascadeType(ResolutionDartType type) {
    cascadeTypes = cascadeTypes.prepend(type);
  }

  ResolutionDartType popCascadeType() {
    ResolutionDartType type = cascadeTypes.head;
    cascadeTypes = cascadeTypes.tail;
    return type;
  }

  visitAssert(Assert node) {
    analyze(node.condition);
    if (node.hasMessage) analyze(node.message);
  }

  visitBlock(Block node) {
    analyzeUntyped(node.statements);
  }

  ResolutionDartType visitCascade(Cascade node) {
    analyze(node.expression);
    return popCascadeType();
  }

  ResolutionDartType visitCascadeReceiver(CascadeReceiver node) {
    ResolutionDartType type = analyze(node.expression);
    pushCascadeType(type);
    return type;
  }

  visitDoWhile(DoWhile node) {
    analyzeUntyped(node.body);
    checkCondition(node.condition);
  }

  visitExpressionStatement(ExpressionStatement node) {
    Expression expression = node.expression;
    analyze(expression);
  }

  /** Dart Programming Language Specification: 11.5.1 For Loop */
  visitFor(For node) {
    if (node.initializer != null) {
      analyzeUntyped(node.initializer);
    }
    if (node.condition != null) {
      checkCondition(node.condition);
    }
    if (node.update != null) {
      analyzeUntyped(node.update);
    }
    analyzeUntyped(node.body);
  }

  visitFunctionDeclaration(FunctionDeclaration node) {
    analyze(node.function);
  }

  ResolutionDartType visitFunctionExpression(FunctionExpression node) {
    ResolutionDartType type;
    ResolutionDartType returnType;
    final FunctionElement element = elements.getFunctionDefinition(node);
    assert(
        element != null, failedAt(node, 'FunctionExpression with no element'));
    if (Elements.isUnresolved(element)) return const ResolutionDynamicType();
    if (element.isGenerativeConstructor) {
      type = const ResolutionDynamicType();
      returnType = const ResolutionVoidType();

      element.functionSignature.forEachParameter((ParameterElement parameter) {
        if (parameter.isInitializingFormal) {
          InitializingFormalElement fieldParameter = parameter;
          checkAssignable(parameter, parameter.type,
              fieldParameter.fieldElement.computeType(resolution));
        }
      });
      if (node.initializers != null) {
        analyzeUntyped(node.initializers, inInitializer: true);
      }
    } else {
      ResolutionFunctionType functionType = element.computeType(resolution);
      returnType = functionType.returnType;
      type = functionType;
    }
    ExecutableElement previousExecutableContext = executableContext;
    ResolutionDartType previousReturnType = expectedReturnType;
    expectedReturnType = returnType;
    AsyncMarker previousAsyncMarker = currentAsyncMarker;

    executableContext = element;
    currentAsyncMarker = element.asyncMarker;
    analyzeUntyped(node.body);

    executableContext = previousExecutableContext;
    expectedReturnType = previousReturnType;
    currentAsyncMarker = previousAsyncMarker;
    return type;
  }

  ResolutionDartType visitIdentifier(Identifier node) {
    if (node.isThis()) {
      return thisType;
    } else if (node.isSuper()) {
      return superType;
    } else {
      TypedElement element = elements[node];
      assert(element != null, failedAt(node, 'Missing element for identifier'));
      assert(element.isVariable || element.isParameter || element.isField,
          failedAt(node, 'Unexpected context element ${element}'));
      return element.computeType(resolution);
    }
  }

  visitIf(If node) {
    Expression condition = node.condition.expression;
    Statement thenPart = node.thenPart;

    checkCondition(node.condition);
    analyzeInPromotedContext(condition, thenPart, mustHaveType: false);
    if (node.elsePart != null) {
      analyzeUntyped(node.elsePart);
    }
  }

  void checkPrivateAccess(Node node, Element element, String name) {
    if (name != null &&
        Name.isPrivateName(name) &&
        element.library != currentLibrary) {
      reportTypeWarning(node, MessageKind.PRIVATE_ACCESS,
          {'name': name, 'libraryName': element.library.name});
    }
  }

  ElementAccess lookupMember(Node node, ResolutionDartType receiverType,
      String name, MemberKind memberKind, Element receiverElement,
      {bool lookupClassMember: false, bool isHint: false}) {
    if (receiverType.treatAsDynamic) {
      return const DynamicAccess();
    }

    Name memberName = new Name(name, currentLibrary,
        isSetter: memberKind == MemberKind.SETTER);

    // Lookup the class or interface member [name] in [interface].
    MemberSignature lookupMemberSignature(
        Name name, ResolutionInterfaceType interface) {
      MembersCreator.computeClassMembersByName(
          resolution, interface.element, name.text);
      return lookupClassMember || analyzingInitializer
          ? interface.lookupClassMember(name)
          : interface.lookupInterfaceMember(name);
    }

    // Compute the access of [name] on [type]. This function takes the special
    // 'call' method into account.
    ElementAccess getAccess(Name name, ResolutionDartType unaliasedBound,
        ResolutionInterfaceType interface) {
      MemberSignature member = lookupMemberSignature(memberName, interface);
      if (member != null) {
        if (member is ErroneousMember) {
          return const DynamicAccess();
        } else {
          return new MemberAccess(member);
        }
      }
      if (name == const PublicName('call')) {
        if (unaliasedBound.isFunctionType) {
          // This is an access the implicit 'call' method of a function type.
          return new FunctionCallAccess(receiverElement, unaliasedBound);
        }
        ResolutionInterfaceType functionType = commonElements.functionType;
        if (types.isSubtype(interface, functionType)) {
          // This is an access of the special 'call' method implicitly defined
          // on 'Function'. This method can be called with any arguments, which
          // we ensure by giving it the type 'dynamic'.
          return new FunctionCallAccess(null, const ResolutionDynamicType());
        }
      }
      return null;
    }

    ResolutionDartType unaliasedBound =
        Types.computeUnaliasedBound(resolution, receiverType);
    if (unaliasedBound.treatAsDynamic) {
      return new DynamicAccess();
    }
    ResolutionInterfaceType interface =
        Types.computeInterfaceType(resolution, unaliasedBound);
    ElementAccess access = getAccess(memberName, unaliasedBound, interface);
    if (access != null) {
      return access;
    }
    if (receiverElement != null &&
        (receiverElement.isVariable || receiverElement.isParameter)) {
      Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement];
      if (typePromotions != null) {
        while (!typePromotions.isEmpty) {
          TypePromotion typePromotion = typePromotions.head;
          if (!typePromotion.isValid) {
            ResolutionDartType unaliasedBound =
                Types.computeUnaliasedBound(resolution, typePromotion.type);
            if (!unaliasedBound.treatAsDynamic) {
              ResolutionInterfaceType interface =
                  Types.computeInterfaceType(resolution, unaliasedBound);
              if (getAccess(memberName, unaliasedBound, interface) != null) {
                reportTypePromotionHint(typePromotion);
              }
            }
          }
          typePromotions = typePromotions.tail;
        }
      }
    }
    // We didn't find a member with the correct name.  If this lookup is for a
    // super or redirecting initializer, the resolver has already emitted an
    // error message.  If the target is a proxy, no warning needs to be emitted.
    // Otherwise, try to emit the most precise warning.
    if (!interface.element.isProxy && !analyzingInitializer) {
      bool foundPrivateMember = false;
      if (memberName.isPrivate) {
        void findPrivateMember(MemberSignature member) {
          if (memberName.isSimilarTo(member.name)) {
            PrivateName privateName = member.name;
            LibraryElement library = privateName.library;
            reportMessage(node, MessageKind.PRIVATE_ACCESS,
                {'name': name, 'libraryName': library.name},
                isHint: isHint);
            foundPrivateMember = true;
          }
        }

        // TODO(johnniwinther): Avoid computation of all class members.
        MembersCreator.computeAllClassMembers(resolution, interface.element);
        if (lookupClassMember) {
          interface.element.forEachClassMember(findPrivateMember);
        } else {
          interface.element.forEachInterfaceMember(findPrivateMember);
        }
      }
      if (!foundPrivateMember) {
        switch (memberKind) {
          case MemberKind.METHOD:
            reportMessage(node, MessageKind.UNDEFINED_METHOD,
                {'className': receiverType.name, 'memberName': name},
                isHint: isHint);
            break;
          case MemberKind.OPERATOR:
            reportMessage(node, MessageKind.UNDEFINED_OPERATOR,
                {'className': receiverType.name, 'memberName': name},
                isHint: isHint);
            break;
          case MemberKind.GETTER:
            if (lookupMemberSignature(memberName.setter, interface) != null) {
              // A setter is present so warn explicitly about the missing
              // getter.
              reportMessage(
                  node,
                  MessageKind.UNDEFINED_INSTANCE_GETTER_BUT_SETTER,
                  {'className': receiverType.name, 'memberName': name},
                  isHint: isHint);
            } else if (name == 'await') {
              Map arguments = {'className': receiverType.name};
              String functionName = executableContext.name;
              MessageKind kind;
              if (functionName == '') {
                kind = MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE;
              } else {
                kind = MessageKind.AWAIT_MEMBER_NOT_FOUND;
                arguments['functionName'] = functionName;
              }
              reportMessage(node, kind, arguments, isHint: isHint);
            } else {
              reportMessage(node, MessageKind.UNDEFINED_GETTER,
                  {'className': receiverType.name, 'memberName': name},
                  isHint: isHint);
            }
            break;
          case MemberKind.SETTER:
            reportMessage(node, MessageKind.UNDEFINED_SETTER,
                {'className': receiverType.name, 'memberName': name},
                isHint: isHint);
            break;
        }
      }
    }
    return const DynamicAccess();
  }

  ResolutionDartType lookupMemberType(
      Node node, ResolutionDartType type, String name, MemberKind memberKind,
      {bool isHint: false}) {
    return lookupMember(node, type, name, memberKind, null, isHint: isHint)
        .computeType(resolution);
  }

  void analyzeArguments(Send send, Element element, ResolutionDartType type,
      [LinkBuilder<ResolutionDartType> argumentTypes]) {
    Link<Node> arguments = send.arguments;
    type.computeUnaliased(resolution);
    ResolutionDartType unaliasedType = type.unaliased;
    if (identical(unaliasedType.kind, ResolutionTypeKind.FUNCTION)) {
      /// Report [warning] including info(s) about the declaration of [element]
      /// or [type].
      void reportWarning(DiagnosticMessage warning) {
        // TODO(johnniwinther): Support pointing to individual parameters on
        // assignability warnings.
        List<DiagnosticMessage> infos = <DiagnosticMessage>[];
        Element declaration = element;
        if (declaration == null) {
          declaration = type.element;
        } else if (type.isTypedef) {
          infos.add(reporter.createMessage(declaration,
              MessageKind.THIS_IS_THE_DECLARATION, {'name': element.name}));
          declaration = type.element;
        }
        if (declaration != null) {
          infos.add(reporter.createMessage(
              declaration, MessageKind.THIS_IS_THE_METHOD));
        }
        reporter.reportWarning(warning, infos);
      }

      /// Report a warning on [node] if [argumentType] is not assignable to
      /// [parameterType].
      void checkAssignable(Spannable node, ResolutionDartType argumentType,
          ResolutionDartType parameterType) {
        if (!types.isAssignable(argumentType, parameterType)) {
          reportWarning(reporter.createMessage(node, MessageKind.NOT_ASSIGNABLE,
              {'fromType': argumentType, 'toType': parameterType}));
        }
      }

      ResolutionFunctionType funType = unaliasedType;
      Iterator<ResolutionDartType> parameterTypes =
          funType.parameterTypes.iterator;
      Iterator<ResolutionDartType> optionalParameterTypes =
          funType.optionalParameterTypes.iterator;
      while (!arguments.isEmpty) {
        Node argument = arguments.head;
        NamedArgument namedArgument = argument.asNamedArgument();
        if (namedArgument != null) {
          argument = namedArgument.expression;
          String argumentName = namedArgument.name.source;
          ResolutionDartType namedParameterType =
              funType.getNamedParameterType(argumentName);
          if (namedParameterType == null) {
            // TODO(johnniwinther): Provide better information on the called
            // function.
            reportWarning(reporter.createMessage(
                argument,
                MessageKind.NAMED_ARGUMENT_NOT_FOUND,
                {'argumentName': argumentName}));

            ResolutionDartType argumentType = analyze(argument);
            if (argumentTypes != null) argumentTypes.addLast(argumentType);
          } else {
            ResolutionDartType argumentType = analyze(argument);
            if (argumentTypes != null) argumentTypes.addLast(argumentType);
            checkAssignable(argument, argumentType, namedParameterType);
          }
        } else {
          if (!parameterTypes.moveNext()) {
            if (!optionalParameterTypes.moveNext()) {
              // TODO(johnniwinther): Provide better information on the
              // called function.
              reportWarning(reporter.createMessage(
                  argument, MessageKind.ADDITIONAL_ARGUMENT));

              ResolutionDartType argumentType = analyze(argument);
              if (argumentTypes != null) argumentTypes.addLast(argumentType);
            } else {
              ResolutionDartType argumentType = analyze(argument);
              if (argumentTypes != null) argumentTypes.addLast(argumentType);
              checkAssignable(
                  argument, argumentType, optionalParameterTypes.current);
            }
          } else {
            ResolutionDartType argumentType = analyze(argument);
            if (argumentTypes != null) argumentTypes.addLast(argumentType);
            checkAssignable(argument, argumentType, parameterTypes.current);
          }
        }
        arguments = arguments.tail;
      }
      if (parameterTypes.moveNext()) {
        // TODO(johnniwinther): Provide better information on the called
        // function.
        reportWarning(reporter.createMessage(send, MessageKind.MISSING_ARGUMENT,
            {'argumentType': parameterTypes.current}));
      }
    } else {
      while (!arguments.isEmpty) {
        ResolutionDartType argumentType = analyze(arguments.head);
        if (argumentTypes != null) argumentTypes.addLast(argumentType);
        arguments = arguments.tail;
      }
    }
  }

  // Analyze the invocation [node] of [elementAccess].
  //
  // If provided [argumentTypes] is filled with the argument types during
  // analysis.
  ResolutionDartType analyzeInvocation(Send node, ElementAccess elementAccess,
      [LinkBuilder<ResolutionDartType> argumentTypes]) {
    ResolutionDartType type = elementAccess.computeType(resolution);
    if (elementAccess.isCallable(compiler)) {
      analyzeArguments(node, elementAccess.element, type, argumentTypes);
    } else {
      reportTypeWarning(
          node, MessageKind.NOT_CALLABLE, {'elementName': elementAccess.name});
      analyzeArguments(node, elementAccess.element,
          const ResolutionDynamicType(), argumentTypes);
    }
    type.computeUnaliased(resolution);
    type = type.unaliased;
    if (type.isFunctionType) {
      ResolutionFunctionType funType = type;
      return funType.returnType;
    } else {
      return const ResolutionDynamicType();
    }
  }

  /**
   * Computes the [ElementAccess] for [name] on the [node] possibly using the
   * [element] provided for [node] by the resolver.
   */
  ElementAccess computeAccess(
      Send node, String name, Element element, MemberKind memberKind,
      {bool lookupClassMember: false}) {
    if (Elements.isMalformed(element)) {
      return const DynamicAccess();
    }
    if (node.receiver != null) {
      Element receiverElement = elements[node.receiver];
      if (receiverElement != null) {
        if (receiverElement.isPrefix) {
          if (node.isConditional) {
            // Skip cases like `prefix?.topLevel`.
            return const DynamicAccess();
          }
          assert(
              element != null, failedAt(node, 'Prefixed node has no element.'));
          return computeResolvedAccess(node, name, element, memberKind);
        }
      }
      // e.foo() for some expression e.
      ResolutionDartType receiverType = analyze(node.receiver);
      if (receiverType.treatAsDynamic || receiverType.isVoid) {
        return const DynamicAccess();
      }
      return lookupMember(
          node, receiverType, name, memberKind, elements[node.receiver],
          lookupClassMember:
              lookupClassMember || element != null && element.isStatic);
    } else {
      return computeResolvedAccess(node, name, element, memberKind);
    }
  }

  /**
   * Computes the [ElementAccess] for [name] on the [node] using the [element]
   * provided for [node] by the resolver.
   */
  ElementAccess computeResolvedAccess(
      Send node, String name, Element element, MemberKind memberKind) {
    if (element == null) {
      // foo() where foo is unresolved.
      return lookupMember(node, thisType, name, memberKind, null);
    } else if (element.isMalformed) {
      // foo() where foo is erroneous.
      return const DynamicAccess();
    } else if (element.impliesType) {
      // The literal `Foo` where Foo is a class, a typedef, or a type variable.
      if (elements.isTypeLiteral(node)) {
        return new TypeLiteralAccess(elements.getTypeLiteralType(node));
      }
      return createResolvedAccess(node, name, element);
    } else if (element.isClassMember) {
      // foo() where foo is a member.
      return lookupMember(node, thisType, name, memberKind, null,
          lookupClassMember: element.isStatic);
    } else if (element.isFunction) {
      // foo() where foo is a method in the same class.
      return createResolvedAccess(node, name, element);
    } else if (element.isVariable ||
        element.isRegularParameter ||
        element.isField ||
        element.isInitializingFormal) {
      // foo() where foo is a field in the same class.
      return createResolvedAccess(node, name, element);
    } else if (element.isGetter || element.isSetter) {
      return createResolvedAccess(node, name, element);
    } else {
      reporter.internalError(
          element, 'Unexpected element kind ${element.kind}.');
      return null;
    }
  }

  ElementAccess createResolvedAccess(Send node, String name, Element element) {
    checkPrivateAccess(node, element, name);
    return createPromotedAccess(element);
  }

  ElementAccess createPromotedAccess(Element element) {
    if (element.isVariable || element.isParameter) {
      TypePromotion typePromotion = getKnownTypePromotion(element);
      if (typePromotion != null) {
        return new PromotedAccess(element, typePromotion.type);
      }
    }
    return new ResolvedAccess(element);
  }

  /**
   * Computes the type of the access of [name] on the [node] possibly using the
   * [element] provided for [node] by the resolver.
   */
  ResolutionDartType computeAccessType(
      Send node, String name, Element element, MemberKind memberKind,
      {bool lookupClassMember: false}) {
    ResolutionDartType type = computeAccess(node, name, element, memberKind,
            lookupClassMember: lookupClassMember)
        .computeType(resolution);
    if (type == null) {
      reporter.internalError(node, 'Type is null on access of $name on $node.');
    }
    return type;
  }

  /// Compute a version of [shownType] that is more specific that [knownType].
  /// This is used to provided better hints when trying to promote a supertype
  /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List`
  /// we suggest the use of `List<int>`, which would make promotion valid.
  ResolutionDartType computeMoreSpecificType(
      ResolutionDartType shownType, ResolutionDartType knownType) {
    if (knownType.isInterfaceType &&
        shownType.isInterfaceType &&
        types.isSubtype(shownType.asRaw(), knownType)) {
      // For the comments in the block, assume the hierarchy:
      //     class A<T, V> {}
      //     class B<S, U> extends A<S, int> {}
      // and a promotion from a [knownType] of `A<double, int>` to a
      // [shownType] of `B`.
      ResolutionInterfaceType knownInterfaceType = knownType;
      ClassElement shownClass = shownType.element;

      // Compute `B<double, dynamic>` as the subtype of `A<double, int>` using
      // the relation between `A<S, int>` and `A<double, int>`.
      MoreSpecificSubtypeVisitor visitor =
          new MoreSpecificSubtypeVisitor(types);
      ResolutionInterfaceType shownTypeGeneric =
          visitor.computeMoreSpecific(shownClass, knownInterfaceType);

      if (shownTypeGeneric != null &&
          types.isMoreSpecific(shownTypeGeneric, knownType)) {
        // This should be the case but we double-check.
        // TODO(johnniwinther): Ensure that we don't suggest malbounded types.
        return shownTypeGeneric;
      }
    }
    return null;
  }

  ResolutionDartType visitSend(Send node) {
    Element element = elements[node];

    if (element != null && element.isConstructor) {
      ResolutionDartType receiverType;
      if (node.receiver != null) {
        receiverType = analyze(node.receiver);
      } else if (node.selector.isSuper()) {
        // TODO(johnniwinther): Lookup super-member in class members.
        receiverType = superType;
      } else {
        assert(node.selector.isThis());
        receiverType = thisType;
      }
      ResolutionDartType constructorType =
          computeConstructorType(element, receiverType);
      analyzeArguments(node, element, constructorType);
      return const ResolutionDynamicType();
    }

    Identifier selector = node.selector.asIdentifier();
    if (Elements.isClosureSend(node, element)) {
      if (element != null) {
        if (element.isError) {
          // foo() where foo is erroneous
          return analyzeInvocation(node, const DynamicAccess());
        } else {
          assert(element.isLocal,
              failedAt(node, "Unexpected element $element in closure send."));
          // foo() where foo is a local or a parameter.
          return analyzeInvocation(node, createPromotedAccess(element));
        }
      } else {
        // exp() where exp is some complex expression like (o) or foo().
        ResolutionDartType type = analyze(node.selector);
        return analyzeInvocation(node, new TypeAccess(type));
      }
    } else if (Elements.isMalformed(element) && selector == null) {
      // exp() where exp is an erroneous construct like `new Unresolved()`.
      ResolutionDartType type = analyze(node.selector);
      return analyzeInvocation(node, new TypeAccess(type));
    }

    String name = selector.source;

    if (node.isOperator && identical(name, 'is')) {
      analyze(node.receiver);
      if (!node.isIsNotCheck) {
        Element variable = elements[node.receiver];
        if (variable == null) {
          // Look for the variable element within parenthesized expressions.
          ParenthesizedExpression parentheses =
              node.receiver.asParenthesizedExpression();
          while (parentheses != null) {
            variable = elements[parentheses.expression];
            if (variable != null) break;
            parentheses = parentheses.expression.asParenthesizedExpression();
          }
        }

        if (variable != null && (variable.isVariable || variable.isParameter)) {
          ResolutionDartType knownType = getKnownType(variable);
          if (!knownType.isDynamic) {
            ResolutionDartType shownType =
                elements.getType(node.arguments.head);
            TypePromotion typePromotion =
                new TypePromotion(node, variable, shownType);
            if (!types.isMoreSpecific(shownType, knownType)) {
              String variableName = variable.name;
              if (!types.isSubtype(shownType, knownType)) {
                typePromotion.addHint(reporter.createMessage(
                    node, MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, {
                  'variableName': variableName,
                  'shownType': shownType,
                  'knownType': knownType
                }));
              } else {
                ResolutionDartType shownTypeSuggestion =
                    computeMoreSpecificType(shownType, knownType);
                if (shownTypeSuggestion != null) {
                  typePromotion.addHint(reporter.createMessage(
                      node, MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, {
                    'variableName': variableName,
                    'shownType': shownType,
                    'shownTypeSuggestion': shownTypeSuggestion,
                    'knownType': knownType
                  }));
                } else {
                  typePromotion.addHint(reporter.createMessage(
                      node, MessageKind.NOT_MORE_SPECIFIC, {
                    'variableName': variableName,
                    'shownType': shownType,
                    'knownType': knownType
                  }));
                }
              }
            }
            showTypePromotion(node, typePromotion);
          }
        }
      }
      return boolType;
    }
    if (node.isOperator && identical(name, 'as')) {
      analyze(node.receiver);
      return elements.getType(node.arguments.head);
    } else if (node.isOperator) {
      final Node receiver = node.receiver;
      final ResolutionDartType receiverType = analyze(receiver);
      if (identical(name, '==') ||
          identical(name, '!=')
          // TODO(johnniwinther): Remove these.
          ||
          identical(name, '===') ||
          identical(name, '!==')) {
        // Analyze argument.
        analyze(node.arguments.head);
        return boolType;
      } else if (identical(name, '||')) {
        checkAssignable(receiver, receiverType, boolType);
        final Node argument = node.arguments.head;
        final ResolutionDartType argumentType = analyze(argument);
        checkAssignable(argument, argumentType, boolType);
        return boolType;
      } else if (identical(name, '&&')) {
        checkAssignable(receiver, receiverType, boolType);
        final Node argument = node.arguments.head;

        final ResolutionDartType argumentType =
            analyzeInPromotedContext(receiver, argument);

        reshowTypePromotions(node, receiver, argument);

        checkAssignable(argument, argumentType, boolType);
        return boolType;
      } else if (identical(name, '!')) {
        checkAssignable(receiver, receiverType, boolType);
        return boolType;
      } else if (identical(name, '?')) {
        return boolType;
      } else if (identical(name, '??')) {
        final Node argument = node.arguments.head;
        final ResolutionDartType argumentType = analyze(argument);
        return types.computeLeastUpperBound(receiverType, argumentType);
      }
      String operatorName = selector.source;
      if (identical(name, '-') && node.arguments.isEmpty) {
        operatorName = 'unary-';
      }
      assert(
          identical(name, '+') ||
              identical(name, '=') ||
              identical(name, '-') ||
              identical(name, '*') ||
              identical(name, '/') ||
              identical(name, '%') ||
              identical(name, '~/') ||
              identical(name, '|') ||
              identical(name, '&') ||
              identical(name, '^') ||
              identical(name, '~') ||
              identical(name, '<<') ||
              identical(name, '>>') ||
              identical(name, '<') ||
              identical(name, '>') ||
              identical(name, '<=') ||
              identical(name, '>=') ||
              identical(name, '[]'),
          failedAt(node, 'Unexpected operator $name'));

      // TODO(karlklose): handle `void` in expression context by calling
      // [analyzeNonVoid] instead of [analyze].
      ElementAccess access = receiverType.isVoid
          ? const DynamicAccess()
          : lookupMember(
              node, receiverType, operatorName, MemberKind.OPERATOR, null);
      LinkBuilder<ResolutionDartType> argumentTypesBuilder =
          new LinkBuilder<ResolutionDartType>();
      ResolutionDartType resultType =
          analyzeInvocation(node, access, argumentTypesBuilder);
      if (receiverType == intType) {
        if (identical(name, '+') ||
            identical(operatorName, '-') ||
            identical(name, '*') ||
            identical(name, '%')) {
          ResolutionDartType argumentType = argumentTypesBuilder.toLink().head;
          if (argumentType == intType) {
            return intType;
          } else if (argumentType == doubleType) {
            return doubleType;
          }
        }
      }
      return resultType;
    } else if (node.isPropertyAccess) {
      ElementAccess access =
          computeAccess(node, selector.source, element, MemberKind.GETTER);
      return access.computeType(resolution);
    } else if (node.isFunctionObjectInvocation) {
      return unhandledExpression();
    } else {
      ElementAccess access =
          computeAccess(node, selector.source, element, MemberKind.METHOD);
      return analyzeInvocation(node, access);
    }
  }

  /// Returns the first type in the list or [:dynamic:] if the list is empty.
  ResolutionDartType firstType(List<ResolutionDartType> list) {
    return list.isEmpty ? const ResolutionDynamicType() : list.first;
  }

  /**
   * Returns the second type in the list or [:dynamic:] if the list is too
   * short.
   */
  ResolutionDartType secondType(List<ResolutionDartType> list) {
    return list.length < 2 ? const ResolutionDynamicType() : list[1];
  }

  /**
   * Checks [: target o= value :] for some operator o, and returns the type
   * of the result. This method also handles increment/decrement expressions
   * like [: target++ :].
   */
  ResolutionDartType checkAssignmentOperator(SendSet node, String operatorName,
      Node valueNode, ResolutionDartType value) {
    assert(!node.isIndex, failedAt(node));
    Element setterElement = elements[node];
    Element getterElement = elements[node.selector];
    Identifier selector = node.selector;
    ResolutionDartType getter = computeAccessType(
        node, selector.source, getterElement, MemberKind.GETTER);
    ResolutionDartType setter = computeAccessType(
        node, selector.source, setterElement, MemberKind.SETTER);
    // [operator] is the type of operator+ or operator- on [target].
    ResolutionDartType operator =
        lookupMemberType(node, getter, operatorName, MemberKind.OPERATOR);
    if (operator is ResolutionFunctionType) {
      ResolutionFunctionType operatorType = operator;
      // [result] is the type of target o value.
      ResolutionDartType result = operatorType.returnType;
      ResolutionDartType operatorArgument =
          firstType(operatorType.parameterTypes);
      // Check target o value.
      bool validValue = checkAssignable(valueNode, value, operatorArgument);
      if (validValue || !(node.isPrefix || node.isPostfix)) {
        // Check target = result.
        checkAssignable(node.assignmentOperator, result, setter);
      }
      return node.isPostfix ? getter : result;
    }
    return const ResolutionDynamicType();
  }

  /**
   * Checks [: base[key] o= value :] for some operator o, and returns the type
   * of the result. This method also handles increment/decrement expressions
   * like [: base[key]++ :].
   */
  ResolutionDartType checkIndexAssignmentOperator(SendSet node,
      String operatorName, Node valueNode, ResolutionDartType value) {
    assert(node.isIndex, failedAt(node));
    final ResolutionDartType base = analyze(node.receiver);
    final Node keyNode = node.arguments.head;
    final ResolutionDartType key = analyze(keyNode);

    // [indexGet] is the type of operator[] on [base].
    ResolutionDartType indexGet =
        lookupMemberType(node, base, '[]', MemberKind.OPERATOR);
    if (indexGet is ResolutionFunctionType) {
      ResolutionFunctionType indexGetType = indexGet;
      ResolutionDartType indexGetKey = firstType(indexGetType.parameterTypes);
      // Check base[key].
      bool validKey = checkAssignable(keyNode, key, indexGetKey);

      // [element] is the type of base[key].
      ResolutionDartType element = indexGetType.returnType;
      // [operator] is the type of operator o on [element].
      ResolutionDartType operator =
          lookupMemberType(node, element, operatorName, MemberKind.OPERATOR);
      if (operator is ResolutionFunctionType) {
        ResolutionFunctionType operatorType = operator;

        // Check base[key] o value.
        ResolutionDartType operatorArgument =
            firstType(operatorType.parameterTypes);
        bool validValue = checkAssignable(valueNode, value, operatorArgument);

        // [result] is the type of base[key] o value.
        ResolutionDartType result = operatorType.returnType;

        // [indexSet] is the type of operator[]= on [base].
        ResolutionDartType indexSet =
            lookupMemberType(node, base, '[]=', MemberKind.OPERATOR);
        if (indexSet is ResolutionFunctionType) {
          ResolutionFunctionType indexSetType = indexSet;
          ResolutionDartType indexSetKey =
              firstType(indexSetType.parameterTypes);
          ResolutionDartType indexSetValue =
              secondType(indexSetType.parameterTypes);

          if (validKey || indexGetKey != indexSetKey) {
            // Only check base[key] on []= if base[key] was valid for [] or
            // if the key types differ.
            checkAssignable(keyNode, key, indexSetKey);
          }
          // Check base[key] = result
          if (validValue || !(node.isPrefix || node.isPostfix)) {
            checkAssignable(node.assignmentOperator, result, indexSetValue);
          }
        }
        return node.isPostfix ? element : result;
      }
    }
    return const ResolutionDynamicType();
  }

  visitSendSet(SendSet node) {
    Element element = elements[node];
    Identifier selector = node.selector;
    final name = node.assignmentOperator.source;
    if (identical(name, '=') || identical(name, '??=')) {
      // e1 = value
      if (node.isIndex) {
        // base[key] = value
        final ResolutionDartType base = analyze(node.receiver);
        final Node keyNode = node.arguments.head;
        final ResolutionDartType key = analyze(keyNode);
        final Node valueNode = node.arguments.tail.head;
        final ResolutionDartType value = analyze(valueNode);
        ResolutionDartType indexSet =
            lookupMemberType(node, base, '[]=', MemberKind.OPERATOR);
        ResolutionDartType indexSetValue = const ResolutionDynamicType();
        if (indexSet is ResolutionFunctionType) {
          ResolutionFunctionType indexSetType = indexSet;
          ResolutionDartType indexSetKey =
              firstType(indexSetType.parameterTypes);
          checkAssignable(keyNode, key, indexSetKey);
          indexSetValue = secondType(indexSetType.parameterTypes);
          checkAssignable(node.assignmentOperator, value, indexSetValue);
        }
        return identical(name, '=')
            ? value
            : types.computeLeastUpperBound(value, indexSetValue);
      } else {
        // target = value
        ResolutionDartType target;
        if (analyzingInitializer) {
          // Field declaration `Foo target = value;` or initializer
          // `this.target = value`. Lookup the getter `target` in the class
          // members.
          target = computeAccessType(
              node, selector.source, element, MemberKind.GETTER,
              lookupClassMember: true);
        } else {
          // Normal assignment `target = value`.
          target = computeAccessType(
              node, selector.source, element, MemberKind.SETTER);
        }
        final Node valueNode = node.arguments.head;
        final ResolutionDartType value = analyze(valueNode);
        checkAssignable(node.assignmentOperator, value, target);
        return identical(name, '=')
            ? value
            : types.computeLeastUpperBound(value, target);
      }
    } else if (identical(name, '++') || identical(name, '--')) {
      // e++ or e--
      String operatorName = identical(name, '++') ? '+' : '-';
      if (node.isIndex) {
        // base[key]++, base[key]--, ++base[key], or --base[key]
        return checkIndexAssignmentOperator(
            node, operatorName, node.assignmentOperator, intType);
      } else {
        // target++, target--, ++target, or --target
        return checkAssignmentOperator(
            node, operatorName, node.assignmentOperator, intType);
      }
    } else {
      // e1 o= e2 for some operator o.
      String operatorName;
      switch (name) {
        case '+=':
          operatorName = '+';
          break;
        case '-=':
          operatorName = '-';
          break;
        case '*=':
          operatorName = '*';
          break;
        case '/=':
          operatorName = '/';
          break;
        case '%=':
          operatorName = '%';
          break;
        case '~/=':
          operatorName = '~/';
          break;
        case '&=':
          operatorName = '&';
          break;
        case '|=':
          operatorName = '|';
          break;
        case '^=':
          operatorName = '^';
          break;
        case '<<=':
          operatorName = '<<';
          break;
        case '>>=':
          operatorName = '>>';
          break;
        default:
          reporter.internalError(node, 'Unexpected assignment operator $name.');
      }
      if (node.isIndex) {
        // base[key] o= value for some operator o.
        final Node valueNode = node.arguments.tail.head;
        final ResolutionDartType value = analyze(valueNode);
        return checkIndexAssignmentOperator(
            node, operatorName, valueNode, value);
      } else {
        // target o= value for some operator o.
        final Node valueNode = node.arguments.head;
        final ResolutionDartType value = analyze(valueNode);
        return checkAssignmentOperator(node, operatorName, valueNode, value);
      }
    }
  }

  ResolutionDartType visitLiteralInt(LiteralInt node) {
    return intType;
  }

  ResolutionDartType visitLiteralDouble(LiteralDouble node) {
    return doubleType;
  }

  ResolutionDartType visitLiteralBool(LiteralBool node) {
    return boolType;
  }

  ResolutionDartType visitLiteralString(LiteralString node) {
    return stringType;
  }

  ResolutionDartType visitStringJuxtaposition(StringJuxtaposition node) {
    analyze(node.first);
    analyze(node.second);
    return stringType;
  }

  ResolutionDartType visitLiteralNull(LiteralNull node) {
    return const ResolutionDynamicType();
  }

  ResolutionInterfaceType visitLiteralSymbol(LiteralSymbol node) {
    return commonElements.symbolType;
  }

  ResolutionDartType computeConstructorType(
      ConstructorElement constructor, ResolutionDartType type) {
    if (Elements.isUnresolved(constructor))
      return const ResolutionDynamicType();
    ResolutionDartType constructorType = constructor.computeType(resolution);
    if (identical(type.kind, ResolutionTypeKind.INTERFACE)) {
      if (constructor.isSynthesized) {
        // TODO(johnniwinther): Remove this when synthesized constructors handle
        // type variables correctly.
        ResolutionInterfaceType interfaceType = type;
        ClassElement receiverElement = interfaceType.element;
        while (receiverElement.isMixinApplication) {
          receiverElement = receiverElement.supertype.element;
        }
        constructorType = constructorType
            .substByContext(interfaceType.asInstanceOf(receiverElement));
      } else {
        constructorType = constructorType.substByContext(type);
      }
    }
    return constructorType;
  }

  ResolutionDartType visitNewExpression(NewExpression node) {
    Element element = elements[node.send];
    if (Elements.isUnresolved(element)) return const ResolutionDynamicType();

    checkPrivateAccess(node, element, element.name);

    ResolutionDartType newType = elements.getType(node);
    assert(newType != null,
        failedAt(node, "No new type registered in $elements."));
    ResolutionDartType constructorType =
        computeConstructorType(element, newType);
    analyzeArguments(node.send, element, constructorType);
    return newType;
  }

  ResolutionDartType visitLiteralList(LiteralList node) {
    ResolutionInterfaceType listType = elements.getType(node);
    ResolutionDartType listElementType = firstType(listType.typeArguments);
    for (Link<Node> link = node.elements.nodes;
        !link.isEmpty;
        link = link.tail) {
      Node element = link.head;
      ResolutionDartType elementType = analyze(element);
      checkAssignable(element, elementType, listElementType,
          isConst: node.isConst);
    }
    return listType;
  }

  visitNodeList(NodeList node) {
    for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
      analyzeUntyped(link.head, inInitializer: analyzingInitializer);
    }
  }

  visitRedirectingFactoryBody(RedirectingFactoryBody node) {
    // TODO(lrn): Typecheck the body. It must refer to the constructor
    // of a subtype.
  }

  visitRethrow(Rethrow node) {
    // Nothing to do here.
  }

  /** Dart Programming Language Specification: 11.10 Return */
  visitReturn(Return node) {
    if (identical(node.beginToken.stringValue, 'native')) {
      return;
    }

    final Node expression = node.expression;

    // Executing a return statement return e; [...] It is a static type warning
    // if the type of e may not be assigned to the declared return type of the
    // immediately enclosing function.
    if (expression != null) {
      ResolutionDartType expressionType = analyze(expression);
      if (executableContext.isGenerativeConstructor) {
        // The resolver already emitted an error for this expression.
      } else {
        if (currentAsyncMarker == AsyncMarker.ASYNC) {
          ResolutionInterfaceType futureOfFlattenedType =
              commonElements.futureType(types.flatten(expressionType));
          expressionType = futureOfFlattenedType;
        }
        if (expectedReturnType.isVoid &&
            !types.isAssignable(expressionType, const ResolutionVoidType())) {
          // In `void f(...) => e`, `e` can have any type.
          if (!node.isArrowBody) {
            reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID);
          }
        } else {
          checkAssignable(expression, expressionType, expectedReturnType);
        }
      }
    } else if (currentAsyncMarker != AsyncMarker.SYNC) {
      // `return;` is allowed.
    } else if (!types.isAssignable(
        expectedReturnType, const ResolutionVoidType())) {
      // Let f be the function immediately enclosing a return statement of the
      // form 'return;' It is a static warning if both of the following
      // conditions hold:
      // - f is not a generative constructor.
      // - The return type of f may not be assigned to void.
      reportTypeWarning(
          node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType});
    }
  }

  ResolutionDartType visitThrow(Throw node) {
    // TODO(johnniwinther): Handle reachability.
    analyze(node.expression);
    return const ResolutionDynamicType();
  }

  ResolutionDartType visitAwait(Await node) {
    ResolutionDartType expressionType = analyze(node.expression);
    if (resolution.target.supportsAsyncAwait) {
      return types.flatten(expressionType);
    } else {
      return const ResolutionDynamicType();
    }
  }

  visitYield(Yield node) {
    ResolutionDartType resultType = analyze(node.expression);
    if (!node.hasStar) {
      if (currentAsyncMarker.isAsync) {
        ResolutionInterfaceType streamOfResultType =
            commonElements.streamType(resultType);
        resultType = streamOfResultType;
      } else {
        ResolutionInterfaceType iterableOfResultType =
            commonElements.iterableType(resultType);
        resultType = iterableOfResultType;
      }
    } else {
      if (currentAsyncMarker.isAsync) {
        // The static type of expression must be assignable to Stream.
        ResolutionInterfaceType streamType = commonElements.streamType();
        checkAssignable(node, resultType, streamType);
      } else {
        // The static type of expression must be assignable to Iterable.
        ResolutionInterfaceType iterableType = commonElements.iterableType();
        checkAssignable(node, resultType, iterableType);
      }
    }
    // The static type of the result must be assignable to the declared type.
    checkAssignable(node, resultType, expectedReturnType);
  }

  ResolutionDartType visitTypeAnnotation(TypeAnnotation node) {
    return elements.getType(node);
  }

  ResolutionDartType analyzeVariableTypeAnnotation(VariableDefinitions node) {
    ResolutionDartType type =
        analyzeWithDefault(node.type, const ResolutionDynamicType());
    if (type.isVoid) {
      reportTypeWarning(node.type, MessageKind.VOID_VARIABLE);
      type = const ResolutionDynamicType();
    }
    return type;
  }

  void analyzeVariableInitializer(
      Spannable spannable, ResolutionDartType declaredType, Node initializer) {
    if (initializer == null) return;

    ResolutionDartType expressionType = analyzeNonVoid(initializer);
    checkAssignable(spannable, expressionType, declaredType);
  }

  visitVariableDefinitions(VariableDefinitions node) {
    ResolutionDartType type = analyzeVariableTypeAnnotation(node);
    for (Link<Node> link = node.definitions.nodes;
        !link.isEmpty;
        link = link.tail) {
      Node definition = link.head;
      assert(definition is Identifier || definition is SendSet,
          failedAt(definition, 'expected identifier or initialization'));
      if (definition is SendSet) {
        SendSet initialization = definition;
        analyzeVariableInitializer(initialization.assignmentOperator, type,
            initialization.arguments.head);
        // TODO(sigmund): explore inferring a type for `var` using the RHS (like
        // DDC does), for example:
        // if (node.type == null && node.modifiers.isVar &&
        //     !initializer.isDynamic) {
        //   var variable = elements[definition];
        //   if (variable != null) {
        //     var typePromotion = new TypePromotion(
        //         node, variable, initializer);
        //     registerKnownTypePromotion(typePromotion);
        //   }
        // }
      }
    }
  }

  visitWhile(While node) {
    checkCondition(node.condition);
    analyzeUntyped(node.body);
  }

  ResolutionDartType visitParenthesizedExpression(
      ParenthesizedExpression node) {
    Expression expression = node.expression;
    ResolutionDartType type = analyze(expression);
    for (TypePromotion typePromotion in getShownTypePromotionsFor(expression)) {
      showTypePromotion(node, typePromotion);
    }
    return type;
  }

  ResolutionDartType visitConditional(Conditional node) {
    Expression condition = node.condition;
    Expression thenExpression = node.thenExpression;

    checkCondition(condition);

    ResolutionDartType thenType =
        analyzeInPromotedContext(condition, thenExpression);

    ResolutionDartType elseType = analyze(node.elseExpression);
    return types.computeLeastUpperBound(thenType, elseType);
  }

  visitStringInterpolation(StringInterpolation node) {
    node.visitChildren(this);
    return stringType;
  }

  visitStringInterpolationPart(StringInterpolationPart node) {
    node.visitChildren(this);
    return stringType;
  }

  visitEmptyStatement(EmptyStatement node) {
    // Nothing to do here.
  }

  visitBreakStatement(BreakStatement node) {
    // Nothing to do here.
  }

  visitContinueStatement(ContinueStatement node) {
    // Nothing to do here.
  }

  ResolutionDartType computeForInElementType(ForIn node) {
    VariableDefinitions declaredIdentifier =
        node.declaredIdentifier.asVariableDefinitions();
    if (declaredIdentifier != null) {
      return analyzeWithDefault(
          declaredIdentifier.type, const ResolutionDynamicType());
    } else {
      return analyze(node.declaredIdentifier);
    }
  }

  visitAsyncForIn(AsyncForIn node) {
    ResolutionDartType elementType = computeForInElementType(node);
    ResolutionDartType expressionType = analyze(node.expression);
    if (resolution.target.supportsAsyncAwait) {
      ResolutionInterfaceType streamOfDynamic = commonElements.streamType();
      if (!types.isAssignable(expressionType, streamOfDynamic)) {
        reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE,
            {'fromType': expressionType, 'toType': streamOfDynamic},
            isHint: true);
      } else {
        ResolutionInterfaceType interfaceType =
            Types.computeInterfaceType(resolution, expressionType);
        if (interfaceType != null) {
          ResolutionInterfaceType streamType =
              interfaceType.asInstanceOf(streamOfDynamic.element);
          if (streamType != null) {
            ResolutionDartType streamElementType =
                streamType.typeArguments.first;
            if (!types.isAssignable(streamElementType, elementType)) {
              reportMessage(
                  node.expression,
                  MessageKind.FORIN_NOT_ASSIGNABLE,
                  {
                    'currentType': streamElementType,
                    'expressionType': expressionType,
                    'elementType': elementType
                  },
                  isHint: true);
            }
          }
        }
      }
    }
    analyzeUntyped(node.body);
  }

  visitSyncForIn(SyncForIn node) {
    ResolutionDartType elementType = computeForInElementType(node);
    ResolutionDartType expressionType = analyze(node.expression);
    ResolutionDartType iteratorType = lookupMemberType(node.expression,
        expressionType, Identifiers.iterator, MemberKind.GETTER);
    ResolutionDartType currentType = lookupMemberType(
        node.expression, iteratorType, Identifiers.current, MemberKind.GETTER,
        isHint: true);
    if (!types.isAssignable(currentType, elementType)) {
      reportMessage(
          node.expression,
          MessageKind.FORIN_NOT_ASSIGNABLE,
          {
            'currentType': currentType,
            'expressionType': expressionType,
            'elementType': elementType
          },
          isHint: true);
    }
    analyzeUntyped(node.body);
  }

  visitLabeledStatement(LabeledStatement node) {
    analyzeUntyped(node.statement);
  }

  visitLiteralMap(LiteralMap node) {
    ResolutionInterfaceType mapType = elements.getType(node);
    ResolutionDartType mapKeyType = firstType(mapType.typeArguments);
    ResolutionDartType mapValueType = secondType(mapType.typeArguments);
    bool isConst = node.isConst;
    for (Link<Node> link = node.entries.nodes;
        !link.isEmpty;
        link = link.tail) {
      LiteralMapEntry entry = link.head;
      ResolutionDartType keyType = analyze(entry.key);
      checkAssignable(entry.key, keyType, mapKeyType, isConst: isConst);
      ResolutionDartType valueType = analyze(entry.value);
      checkAssignable(entry.value, valueType, mapValueType, isConst: isConst);
    }
    return mapType;
  }

  visitNamedArgument(NamedArgument node) {
    // Named arguments are visited as part of analyzing invocations of
    // unresolved methods. For instance [: foo(a: 42); :] where 'foo' is neither
    // found in the enclosing scope nor through lookup on 'this' or
    // [: x.foo(b: 42); :] where 'foo' cannot be not found through lookup on
    // the static type of 'x'.
    return analyze(node.expression);
  }

  visitSwitchStatement(SwitchStatement node) {
    // TODO(johnniwinther): Handle reachability based on reachability of
    // switch cases.
    // TODO(johnniwinther): Provide hint of duplicate case constants.

    ResolutionDartType expressionType = analyze(node.expression);

    // Check that all the case expressions are assignable to the expression.
    bool hasDefaultCase = false;
    for (SwitchCase switchCase in node.cases) {
      if (switchCase.isDefaultCase) {
        hasDefaultCase = true;
      }
      for (Node labelOrCase in switchCase.labelsAndCases) {
        CaseMatch caseMatch = labelOrCase.asCaseMatch();
        if (caseMatch == null) continue;

        ResolutionDartType caseType = analyze(caseMatch.expression);
        checkAssignable(caseMatch, expressionType, caseType);
      }

      analyzeUntyped(switchCase);
    }

    if (!hasDefaultCase && expressionType.isEnumType) {
      compiler.enqueuer.resolution
          .addDeferredAction(new DeferredAction(executableContext, () {
        Map<ConstantValue, FieldElement> enumValues =
            <ConstantValue, FieldElement>{};
        List<FieldElement> unreferencedFields = <FieldElement>[];
        EnumClassElement enumClass = expressionType.element;
        enumClass.enumValues.forEach((EnumConstantElement field) {
          // TODO(johnniwinther): Ensure that the enum constant is computed at
          // this point.
          ConstantValue constantValue = compiler.resolver.constantCompiler
              .getConstantValueForVariable(field);
          if (constantValue == null) {
            // The field might not have been resolved.
            unreferencedFields.add(field);
          } else {
            enumValues[constantValue] = field;
          }
        });

        for (SwitchCase switchCase in node.cases) {
          for (Node labelOrCase in switchCase.labelsAndCases) {
            CaseMatch caseMatch = labelOrCase.asCaseMatch();
            if (caseMatch != null) {
              ConstantExpression caseConstant = compiler
                  .resolver.constantCompiler
                  .compileNode(caseMatch.expression, elements);
              enumValues
                  .remove(compiler.constants.getConstantValue(caseConstant));
            }
          }
        }
        unreferencedFields.addAll(enumValues.values);
        if (!unreferencedFields.isEmpty) {
          reporter.reportWarningMessage(node, MessageKind.MISSING_ENUM_CASES, {
            'enumType': expressionType,
            'enumValues': unreferencedFields.map((e) => e.name).join(', ')
          });
        }
      }));
    }
  }

  visitSwitchCase(SwitchCase node) {
    analyzeUntyped(node.statements);
  }

  visitTryStatement(TryStatement node) {
    // TODO(johnniwinther): Use reachability information of try-block,
    // catch-blocks and finally-block to compute the whether the try statement
    // is returning.
    analyzeUntyped(node.tryBlock);
    for (CatchBlock catchBlock in node.catchBlocks) {
      analyzeUntyped(catchBlock);
    }
    analyzeUntyped(node.finallyBlock);
  }

  visitCatchBlock(CatchBlock node) {
    analyzeUntyped(node.block);
  }

  visitTypedef(Typedef node) {
    // Do not typecheck [Typedef] nodes.
  }

  visitNode(Node node) {
    reporter.internalError(node,
        'Unexpected node ${node.getObjectDescription()} in the type checker.');
  }
}
