// 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.resolution.members;

import '../common.dart';
import '../common/names.dart' show
    Selectors;
import '../common/resolution.dart' show
    Feature;
import '../compiler.dart' show
    Compiler;
import '../constants/constructors.dart' show
    RedirectingFactoryConstantConstructor;
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../core_types.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart' show
    ConstructorElementX,
    ErroneousElementX,
    FunctionElementX,
    JumpTargetX,
    LocalFunctionElementX,
    LocalParameterElementX,
    LocalVariableElementX,
    MethodElementX,
    ParameterElementX,
    VariableElementX,
    VariableList;
import '../tokens/token.dart' show
    isUserDefinableOperator;
import '../tree/tree.dart';
import '../util/util.dart' show
    Link;
import '../universe/call_structure.dart' show
    CallStructure;
import '../universe/selector.dart' show
    Selector;
import '../universe/use.dart' show
    DynamicUse,
    StaticUse,
    TypeUse;

import 'access_semantics.dart';
import 'class_members.dart' show MembersCreator;
import 'operators.dart';
import 'send_structure.dart';

import 'constructors.dart' show
    ConstructorResolver,
    ConstructorResult,
    ConstructorResultKind;
import 'label_scope.dart' show
    StatementScope;
import 'registry.dart' show
    ResolutionRegistry;
import 'resolution.dart' show
    ResolverTask;
import 'resolution_common.dart' show
    MappingVisitor;
import 'resolution_result.dart';
import 'scope.dart' show
    BlockScope,
    MethodScope,
    Scope;
import 'signatures.dart' show
    SignatureResolver;
import 'variables.dart' show
    VariableDefinitionsVisitor;

/// The state of constants in resolutions.
enum ConstantState {
  /// Expressions are not required to be constants.
  NON_CONSTANT,

  /// Expressions are required to be constants.
  ///
  /// For instance the values of a constant list literal.
  CONSTANT,

  /// Expressions are required to be constants and parameter references are
  /// also considered constant.
  ///
  /// This is used for resolving constructor initializers of constant
  /// constructors.
  CONSTANT_INITIALIZER,
}

/**
 * Core implementation of resolution.
 *
 * Do not subclass or instantiate this class outside this library
 * except for testing.
 */
class ResolverVisitor extends MappingVisitor<ResolutionResult> {
  /**
   * The current enclosing element for the visited AST nodes.
   *
   * This field is updated when nested closures are visited.
   */
  Element enclosingElement;

  /// Whether we are in a context where `this` is accessible (this will be false
  /// in static contexts, factory methods, and field initializers).
  bool inInstanceContext;
  bool inCheckContext;
  bool inCatchBlock;
  ConstantState constantState;

  Scope scope;
  ClassElement currentClass;
  ExpressionStatement currentExpressionStatement;

  /// `true` if a [Send] or [SendSet] is visited as the prefix of member access.
  /// For instance `Class` in `Class.staticField` or `prefix.Class` in
  /// `prefix.Class.staticMethod()`.
  bool sendIsMemberAccess = false;

  StatementScope statementScope;
  int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
      | ElementCategory.IMPLIES_TYPE;

  /// When visiting the type declaration of the variable in a [ForIn] loop,
  /// the initializer of the variable is implicit and we should not emit an
  /// error when verifying that all final variables are initialized.
  bool inLoopVariable = false;

  /// The nodes for which variable access and mutation must be registered in
  /// order to determine when the static type of variables types is promoted.
  Link<Node> promotionScope = const Link<Node>();

  bool isPotentiallyMutableTarget(Element target) {
    if (target == null) return false;
    return (target.isVariable || target.isParameter) &&
      !(target.isFinal || target.isConst);
  }

  // TODO(ahe): Find a way to share this with runtime implementation.
  static final RegExp symbolValidationPattern =
      new RegExp(r'^(?:[a-zA-Z$][a-zA-Z$0-9_]*\.)*(?:[a-zA-Z$][a-zA-Z$0-9_]*=?|'
                 r'-|'
                 r'unary-|'
                 r'\[\]=|'
                 r'~|'
                 r'==|'
                 r'\[\]|'
                 r'\*|'
                 r'/|'
                 r'%|'
                 r'~/|'
                 r'\+|'
                 r'<<|'
                 r'>>|'
                 r'>=|'
                 r'>|'
                 r'<=|'
                 r'<|'
                 r'&|'
                 r'\^|'
                 r'\|'
                 r')$');

  ResolverVisitor(Compiler compiler,
                  Element element,
                  ResolutionRegistry registry,
                  {bool useEnclosingScope: false})
    : this.enclosingElement = element,
      // When the element is a field, we are actually resolving its
      // initial value, which should not have access to instance
      // fields.
      inInstanceContext = (element.isInstanceMember && !element.isField)
          || element.isGenerativeConstructor,
      this.currentClass = element.isClassMember ? element.enclosingClass
                                             : null,
      this.statementScope = new StatementScope(),
      scope = useEnclosingScope
          ? Scope.buildEnclosingScope(element) : element.buildScope(),
      // The type annotations on a typedef do not imply type checks.
      // TODO(karlklose): clean this up (dartbug.com/8870).
      inCheckContext = compiler.options.enableTypeAssertions &&
          !element.isLibrary &&
          !element.isTypedef &&
          !element.enclosingElement.isTypedef,
      inCatchBlock = false,
      constantState = element.isConst
          ? ConstantState.CONSTANT : ConstantState.NON_CONSTANT,
      super(compiler, registry);

  CoreClasses get coreClasses => compiler.coreClasses;

  CoreTypes get coreTypes => compiler.coreTypes;

  AsyncMarker get currentAsyncMarker {
    if (enclosingElement is FunctionElement) {
      FunctionElement function = enclosingElement;
      return function.asyncMarker;
    }
    return AsyncMarker.SYNC;
  }

  Element reportLookupErrorIfAny(Element result, Node node, String name) {
    if (!Elements.isUnresolved(result)) {
      if (!inInstanceContext && result.isInstanceMember) {
        reporter.reportErrorMessage(
            node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name});
        return new ErroneousElementX(MessageKind.NO_INSTANCE_AVAILABLE,
                                     {'name': name},
                                     name, enclosingElement);
      } else if (result.isAmbiguous) {
        AmbiguousElement ambiguous = result;
        return reportAndCreateErroneousElement(
              node,
              name,
              ambiguous.messageKind,
              ambiguous.messageArguments,
              infos: ambiguous.computeInfos(enclosingElement, reporter),
              isError: true);
      }
    }
    return result;
  }

  // Create, or reuse an already created, target element for a statement.
  JumpTarget getOrDefineTarget(Node statement) {
    JumpTarget element = registry.getTargetDefinition(statement);
    if (element == null) {
      element = new JumpTargetX(statement,
                                   statementScope.nestingLevel,
                                   enclosingElement);
      registry.defineTarget(statement, element);
    }
    return element;
  }

  doInPromotionScope(Node node, action()) {
    promotionScope = promotionScope.prepend(node);
    var result = action();
    promotionScope = promotionScope.tail;
    return result;
  }

  inStaticContext(action(),
                  {bool inConstantInitializer: false}) {
    bool wasInstanceContext = inInstanceContext;
    ConstantState oldConstantState = constantState;
    constantState = inConstantInitializer
        ? ConstantState.CONSTANT_INITIALIZER
        : constantState;
    inInstanceContext = false;
    var result = action();
    inInstanceContext = wasInstanceContext;
    constantState = oldConstantState;
    return result;
  }

  ResolutionResult visitInStaticContext(Node node,
                                        {bool inConstantInitializer: false}) {
    return inStaticContext(
        () => visit(node),
        inConstantInitializer: inConstantInitializer);
  }

  /// Execute [action] where the constant state is `ConstantState.CONSTANT` if
  /// not already `ConstantState.CONSTANT_INITIALIZER`.
  inConstantContext(action()) {
    ConstantState oldConstantState = constantState;
    if (constantState != ConstantState.CONSTANT_INITIALIZER) {
      constantState = ConstantState.CONSTANT;
    }
    var result = action();
    constantState = oldConstantState;
    return result;
  }

  /// Visit [node] where the constant state is `ConstantState.CONSTANT` if
  /// not already `ConstantState.CONSTANT_INITIALIZER`.
  ResolutionResult visitInConstantContext(Node node) {
    ResolutionResult result = inConstantContext(() => visit(node));
    assert(invariant(node, result != null,
        message: "No resolution result for $node."));

    return result;
  }

  ErroneousElement reportAndCreateErroneousElement(
      Node node,
      String name,
      MessageKind kind,
      Map arguments,
      {List<DiagnosticMessage> infos: const <DiagnosticMessage>[],
       bool isError: false}) {
    if (isError) {
      reporter.reportError(
          reporter.createMessage(node, kind, arguments), infos);
    } else {
      reporter.reportWarning(
          reporter.createMessage(node, kind, arguments), infos);
    }
    // TODO(ahe): Use [allowedCategory] to synthesize a more precise subclass
    // of [ErroneousElementX]. For example, [ErroneousFieldElementX],
    // [ErroneousConstructorElementX], etc.
    return new ErroneousElementX(kind, arguments, name, enclosingElement);
  }

  /// Report a warning or error on an unresolved access in non-instance context.
  ///
  /// The [ErroneousElement] corresponding to the message is returned.
  ErroneousElement reportCannotResolve(Node node, String name) {
    assert(invariant(node, !inInstanceContext,
        message: "ResolverVisitor.reportCannotResolve must not be called in "
                 "instance context."));

    // We report an error within initializers because `this` is implicitly
    // accessed when unqualified identifiers are not resolved.  For
    // details, see section 16.14.3 of the spec (2nd edition):
    //   An unqualified invocation `i` of the form `id(a1, ...)`
    //   ...
    //   If `i` does not occur inside a top level or static function, `i`
    //   is equivalent to `this.id(a1 , ...)`.
    bool inInitializer =
        enclosingElement.isGenerativeConstructor ||
        (enclosingElement.isInstanceMember && enclosingElement.isField);
    MessageKind kind;
    Map arguments = {'name': name};
    if (inInitializer) {
      kind = MessageKind.CANNOT_RESOLVE_IN_INITIALIZER;
    } else if (name == 'await') {
      var functionName = enclosingElement.name;
      if (functionName == '') {
        kind = MessageKind.CANNOT_RESOLVE_AWAIT_IN_CLOSURE;
      } else {
        kind = MessageKind.CANNOT_RESOLVE_AWAIT;
        arguments['functionName'] = functionName;
      }
    } else {
      kind = MessageKind.CANNOT_RESOLVE;
    }
    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    return reportAndCreateErroneousElement(
        node, name, kind, arguments, isError: inInitializer);
  }

  ResolutionResult visitIdentifier(Identifier node) {
    if (node.isThis()) {
      if (!inInstanceContext) {
        reporter.reportErrorMessage(
            node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node});
      }
      return const NoneResult();
    } else if (node.isSuper()) {
      if (!inInstanceContext) {
        reporter.reportErrorMessage(
            node, MessageKind.NO_SUPER_IN_STATIC);
      }
      if ((ElementCategory.SUPER & allowedCategory) == 0) {
        reporter.reportErrorMessage(
            node, MessageKind.INVALID_USE_OF_SUPER);
      }
      return const NoneResult();
    } else {
      String name = node.source;
      Element element = lookupInScope(reporter, node, scope, name);
      if (Elements.isUnresolved(element) && name == 'dynamic') {
        // TODO(johnniwinther): Remove this hack when we can return more complex
        // objects than [Element] from this method.
        element = coreClasses.typeClass;
        // Set the type to be `dynamic` to mark that this is a type literal.
        registry.setType(node, const DynamicType());
      }
      element = reportLookupErrorIfAny(element, node, name);
      if (element == null) {
        if (!inInstanceContext) {
          element = reportCannotResolve(node, name);
        }
      } else if (element.isMalformed) {
        // Use the malformed element.
      } else {
        if ((element.kind.category & allowedCategory) == 0) {
          element = reportAndCreateErroneousElement(
              node, name, MessageKind.GENERIC,
              // TODO(ahe): Improve error message. Need UX input.
              {'text': "is not an expression $element"});
        }
      }
      if (!Elements.isUnresolved(element) && element.isClass) {
        ClassElement classElement = element;
        classElement.ensureResolved(resolution);
      }
      if (element != null) {
        registry.useElement(node, element);
        if (element.isPrefix) {
          return new PrefixResult(element, null);
        } else if (element.isClass && sendIsMemberAccess) {
          return new PrefixResult(null, element);
        }
        return new ElementResult(element);
      }
      return const NoneResult();
    }
  }

  TypeResult visitTypeAnnotation(TypeAnnotation node) {
    DartType type = resolveTypeAnnotation(node);
    if (inCheckContext) {
      registry.registerTypeUse(new TypeUse.checkedModeCheck(type));
    }
    return new TypeResult(type);
  }

  bool isNamedConstructor(Send node) => node.receiver != null;

  Name getRedirectingThisOrSuperConstructorName(Send node) {
    if (isNamedConstructor(node)) {
      String constructorName = node.selector.asIdentifier().source;
      return new Name(constructorName, enclosingElement.library);
    } else {
      return const PublicName('');
    }
  }

  FunctionElement resolveConstructorRedirection(FunctionElementX constructor) {
    FunctionExpression node = constructor.parseNode(resolution.parsing);

    // A synthetic constructor does not have a node.
    if (node == null) return null;
    if (node.initializers == null) return null;
    Link<Node> initializers = node.initializers.nodes;
    if (!initializers.isEmpty &&
        Initializers.isConstructorRedirect(initializers.head)) {
      Name name =
          getRedirectingThisOrSuperConstructorName(initializers.head);
      final ClassElement classElement = constructor.enclosingClass;
      return classElement.lookupConstructor(name.text);
    }
    return null;
  }

  void setupFunction(FunctionExpression node, FunctionElement function) {
    Element enclosingElement = function.enclosingElement;
    if (node.modifiers.isStatic &&
        enclosingElement.kind != ElementKind.CLASS) {
      reporter.reportErrorMessage(node, MessageKind.ILLEGAL_STATIC);
    }

    scope = new MethodScope(scope, function);
    // Put the parameters in scope.
    FunctionSignature functionParameters = function.functionSignature;
    Link<Node> parameterNodes = (node.parameters == null)
        ? const Link<Node>() : node.parameters.nodes;
    functionParameters.forEachParameter((ParameterElementX element) {
      // TODO(karlklose): should be a list of [FormalElement]s, but the actual
      // implementation uses [Element].
      List<Element> optionals = functionParameters.optionalParameters;
      if (!optionals.isEmpty && element == optionals.first) {
        NodeList nodes = parameterNodes.head;
        parameterNodes = nodes.nodes;
      }
      if (element.isOptional) {
        if (element.initializer != null) {
          ResolutionResult result = visitInConstantContext(element.initializer);
          if (result.isConstant) {
            element.constant = result.constant;
          }
        } else {
          element.constant = new NullConstantExpression();
        }
      }
      VariableDefinitions variableDefinitions = parameterNodes.head;
      Node parameterNode = variableDefinitions.definitions.nodes.head;
      // Field parameters (this.x) are not visible inside the constructor. The
      // fields they reference are visible, but must be resolved independently.
      if (element.isInitializingFormal) {
        registry.useElement(parameterNode, element);
      } else {
        LocalParameterElementX parameterElement = element;
        defineLocalVariable(parameterNode, parameterElement);
        addToScope(parameterElement);
      }
      parameterNodes = parameterNodes.tail;
    });
    addDeferredAction(enclosingElement, () {
      functionParameters.forEachOptionalParameter(
          (ParameterElementX parameter) {
        parameter.constant =
            compiler.resolver.constantCompiler.compileConstant(parameter);
      });
    });
    if (inCheckContext) {
      functionParameters.forEachParameter((ParameterElement element) {
        registry.registerTypeUse(new TypeUse.checkedModeCheck(element.type));
      });
    }
  }

  ResolutionResult visitAssert(Assert node) {
    if (!compiler.options.enableAssertMessage) {
      if (node.hasMessage) {
        reporter.reportErrorMessage(
            node, MessageKind.EXPERIMENTAL_ASSERT_MESSAGE);
      }
    }
    // TODO(sra): We could completely ignore the assert in production mode if we
    // didn't need it to be resolved for type checking.
    registry.registerFeature(
        node.hasMessage ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT);
    visit(node.condition);
    visit(node.message);
    return const NoneResult();
  }

  ResolutionResult visitCascade(Cascade node) {
    visit(node.expression);
    return const NoneResult();
  }

  ResolutionResult visitCascadeReceiver(CascadeReceiver node) {
    visit(node.expression);
    return const NoneResult();
  }

  ResolutionResult visitIn(Node node, Scope nestedScope) {
    Scope oldScope = scope;
    scope = nestedScope;
    ResolutionResult result = visit(node);
    scope = oldScope;
    return result;
  }

  /**
   * Introduces new default targets for break and continue
   * before visiting the body of the loop
   */
  void visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) {
    JumpTarget element = getOrDefineTarget(loop);
    statementScope.enterLoop(element);
    visitIn(body, bodyScope);
    statementScope.exitLoop();
    if (!element.isTarget) {
      registry.undefineTarget(loop);
    }
  }

  ResolutionResult visitBlock(Block node) {
    visitIn(node.statements, new BlockScope(scope));
    return const NoneResult();
  }

  ResolutionResult visitDoWhile(DoWhile node) {
    visitLoopBodyIn(node, node.body, new BlockScope(scope));
    visit(node.condition);
    return const NoneResult();
  }

  ResolutionResult visitEmptyStatement(EmptyStatement node) {
    return const NoneResult();
  }

  ResolutionResult visitExpressionStatement(ExpressionStatement node) {
    ExpressionStatement oldExpressionStatement = currentExpressionStatement;
    currentExpressionStatement = node;
    visit(node.expression);
    currentExpressionStatement = oldExpressionStatement;
    return const NoneResult();
  }

  ResolutionResult visitFor(For node) {
    Scope blockScope = new BlockScope(scope);
    visitIn(node.initializer, blockScope);
    visitIn(node.condition, blockScope);
    visitIn(node.update, blockScope);
    visitLoopBodyIn(node, node.body, blockScope);
    return const NoneResult();
  }

  ResolutionResult visitFunctionDeclaration(FunctionDeclaration node) {
    assert(node.function.name != null);
    visitFunctionExpression(node.function, inFunctionDeclaration: true);
    return const NoneResult();
  }


  /// Process a local function declaration or an anonymous function expression.
  ///
  /// [inFunctionDeclaration] is `true` when the current node is the immediate
  /// child of a function declaration.
  ///
  /// This is used to distinguish local function declarations from anonymous
  /// function expressions.
  ResolutionResult visitFunctionExpression(
      FunctionExpression node,
      {bool inFunctionDeclaration: false}) {
    bool doAddToScope = inFunctionDeclaration;
    if (!inFunctionDeclaration && node.name != null) {
      reporter.reportErrorMessage(
          node.name,
          MessageKind.NAMED_FUNCTION_EXPRESSION,
          {'name': node.name});
    }
    visit(node.returnType);
    String name;
    if (node.name == null) {
      name = "";
    } else {
      name = node.name.asIdentifier().source;
    }
    LocalFunctionElementX function = new LocalFunctionElementX(
        name, node, ElementKind.FUNCTION, Modifiers.EMPTY,
        enclosingElement);
    ResolverTask.processAsyncMarker(compiler, function, registry);
    function.functionSignature = SignatureResolver.analyze(
        compiler,
        node.parameters,
        node.returnType,
        function,
        registry,
        createRealParameters: true,
        isFunctionExpression: !inFunctionDeclaration);
    checkLocalDefinitionName(node, function);
    registry.defineFunction(node, function);
    if (doAddToScope) {
      addToScope(function);
    }
    Scope oldScope = scope; // The scope is modified by [setupFunction].
    setupFunction(node, function);

    Element previousEnclosingElement = enclosingElement;
    enclosingElement = function;
    // Run the body in a fresh statement scope.
    StatementScope oldStatementScope = statementScope;
    statementScope = new StatementScope();
    visit(node.body);
    statementScope = oldStatementScope;

    scope = oldScope;
    enclosingElement = previousEnclosingElement;

    registry.registerStaticUse(new StaticUse.closure(function));
    return const NoneResult();
  }

  ResolutionResult visitIf(If node) {
    doInPromotionScope(node.condition.expression, () => visit(node.condition));
    doInPromotionScope(node.thenPart,
        () => visitIn(node.thenPart, new BlockScope(scope)));
    visitIn(node.elsePart, new BlockScope(scope));
    return const NoneResult();
  }

  static Selector computeSendSelector(Send node,
                                      LibraryElement library,
                                      Element element) {
    // First determine if this is part of an assignment.
    bool isSet = node.asSendSet() != null;

    if (node.isIndex) {
      return isSet ? new Selector.indexSet() : new Selector.index();
    }

    if (node.isOperator) {
      String source = node.selector.asOperator().source;
      String string = source;
      if (identical(string, '!') ||
          identical(string, '&&') || identical(string, '||') ||
          identical(string, 'is') || identical(string, 'as') ||
          identical(string, '?') || identical(string, '??')) {
        return null;
      }
      String op = source;
      if (!isUserDefinableOperator(source)) {
        op = Elements.mapToUserOperatorOrNull(source);
      }
      if (op == null) {
        // Unsupported operator. An error has been reported during parsing.
        return new Selector.call(
            new Name(source, library),
            new CallStructure.unnamed(node.argumentsNode.slowLength()));
      }
      return node.arguments.isEmpty
          ? new Selector.unaryOperator(op)
          : new Selector.binaryOperator(op);
    }

    Identifier identifier = node.selector.asIdentifier();
    if (node.isPropertyAccess) {
      assert(!isSet);
      return new Selector.getter(
          new Name(identifier.source, library));
    } else if (isSet) {
      return new Selector.setter(
          new Name(identifier.source, library, isSetter: true));
    }

    // Compute the arity and the list of named arguments.
    int arity = 0;
    List<String> named = <String>[];
    for (Link<Node> link = node.argumentsNode.nodes;
        !link.isEmpty;
        link = link.tail) {
      Expression argument = link.head;
      NamedArgument namedArgument = argument.asNamedArgument();
      if (namedArgument != null) {
        named.add(namedArgument.name.source);
      }
      arity++;
    }

    if (element != null && element.isConstructor) {
      return new Selector.callConstructor(
          new Name(element.name, library), arity, named);
    }

    // If we're invoking a closure, we do not have an identifier.
    return (identifier == null)
        ? new Selector.callClosure(arity, named)
        : new Selector.call(new Name(identifier.source, library),
                            new CallStructure(arity, named));
  }

  Selector resolveSelector(Send node, Element element) {
    LibraryElement library = enclosingElement.library;
    Selector selector = computeSendSelector(node, library, element);
    if (selector != null) registry.setSelector(node, selector);
    return selector;
  }

  ArgumentsResult resolveArguments(NodeList list) {
    if (list == null) return null;
    bool isValidAsConstant = true;
    List<ResolutionResult> argumentResults = <ResolutionResult>[];
    bool oldSendIsMemberAccess = sendIsMemberAccess;
    sendIsMemberAccess = false;
    Map<String, Node> seenNamedArguments = new Map<String, Node>();
    int argumentCount = 0;
    List<String> namedArguments = <String>[];
    for (Link<Node> link = list.nodes; !link.isEmpty; link = link.tail) {
      Expression argument = link.head;
      ResolutionResult result = visit(argument);
      if (!result.isConstant) {
        isValidAsConstant = false;
      }
      argumentResults.add(result);

      NamedArgument namedArgument = argument.asNamedArgument();
      if (namedArgument != null) {
        String source = namedArgument.name.source;
        namedArguments.add(source);
        if (seenNamedArguments.containsKey(source)) {
          reportDuplicateDefinition(
              source,
              argument,
              seenNamedArguments[source]);
          isValidAsConstant = false;
        } else {
          seenNamedArguments[source] = namedArgument;
        }
      } else if (!seenNamedArguments.isEmpty) {
        reporter.reportErrorMessage(
            argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED);
        isValidAsConstant = false;
      }
      argumentCount++;
    }
    sendIsMemberAccess = oldSendIsMemberAccess;
    return new ArgumentsResult(
        new CallStructure(argumentCount, namedArguments),
        argumentResults,
        isValidAsConstant: isValidAsConstant);
  }

  /// Check that access to `super` is currently allowed. Returns an
  /// [AccessSemantics] in case of an error, `null` otherwise.
  AccessSemantics checkSuperAccess(Send node) {
    if (!inInstanceContext) {
      ErroneousElement error = reportAndCreateErroneousElement(
          node, 'super',
          MessageKind.NO_SUPER_IN_STATIC, {},
          isError: true);
      registry.registerFeature(Feature.COMPILE_TIME_ERROR);
      return new StaticAccess.invalid(error);
    }
    if (node.isConditional) {
      // `super?.foo` is not allowed.
      ErroneousElement error = reportAndCreateErroneousElement(
          node, 'super',
          MessageKind.INVALID_USE_OF_SUPER, {},
          isError: true);
      registry.registerFeature(Feature.COMPILE_TIME_ERROR);
      return new StaticAccess.invalid(error);
    }
    if (currentClass.supertype == null) {
      // This is just to guard against internal errors, so no need
      // for a real error message.
      ErroneousElement error = reportAndCreateErroneousElement(
          node, 'super',
          MessageKind.GENERIC,
          {'text': "Object has no superclass"},
          isError: true);
      registry.registerFeature(Feature.COMPILE_TIME_ERROR);
      return new StaticAccess.invalid(error);
    }
    registry.registerSuperUse(reporter.spanFromSpannable(node));
    return null;
  }

  /// Check that access to `this` is currently allowed. Returns an
  /// [AccessSemantics] in case of an error, `null` otherwise.
  AccessSemantics checkThisAccess(Send node) {
    if (!inInstanceContext) {
      ErroneousElement error = reportAndCreateErroneousElement(
          node, 'this',
          MessageKind.NO_THIS_AVAILABLE, const {},
          isError: true);
      registry.registerFeature(Feature.COMPILE_TIME_ERROR);
      return new StaticAccess.invalid(error);
    }
    return null;
  }

  /// Compute the [AccessSemantics] corresponding to a super access of [target].
  AccessSemantics computeSuperAccessSemantics(Spannable node, Element target) {
    if (target.isMalformed) {
      return new StaticAccess.unresolvedSuper(target);
    } else if (target.isGetter) {
      return new StaticAccess.superGetter(target);
    } else if (target.isSetter) {
      return new StaticAccess.superSetter(target);
    } else if (target.isField) {
      if (target.isFinal) {
        return new StaticAccess.superFinalField(target);
      } else {
        return new StaticAccess.superField(target);
      }
    } else {
      assert(invariant(node, target.isFunction,
          message: "Unexpected super target '$target'."));
      return new StaticAccess.superMethod(target);
    }
  }

  /// Compute the [AccessSemantics] corresponding to a compound super access
  /// reading from [getter] and writing to [setter].
  AccessSemantics computeCompoundSuperAccessSemantics(
      Spannable node,
      Element getter,
      Element setter,
      {bool isIndex: false}) {
    if (getter.isMalformed) {
      if (setter.isMalformed) {
        return new StaticAccess.unresolvedSuper(getter);
      } else if (setter.isFunction) {
        assert(invariant(node, setter.name == '[]=',
            message: "Unexpected super setter '$setter'."));
        return new CompoundAccessSemantics(
                    CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, setter);
      } else {
        assert(invariant(node, setter.isSetter,
            message: "Unexpected super setter '$setter'."));
        return new CompoundAccessSemantics(
            CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, setter);
      }
    } else if (getter.isField) {
      if (setter.isMalformed) {
        assert(invariant(node, getter.isFinal,
            message: "Unexpected super setter '$setter' for getter '$getter."));
        return new StaticAccess.superFinalField(getter);
      } else if (setter.isField) {
        if (getter == setter) {
          return new StaticAccess.superField(getter);
        } else {
          return new CompoundAccessSemantics(
              CompoundAccessKind.SUPER_FIELD_FIELD, getter, setter);
        }
      } else {
        // Either the field is accessible directly, or a setter shadows the
        // setter access. If there was another instance member it would shadow
        // the field.
        assert(invariant(node, setter.isSetter,
            message: "Unexpected super setter '$setter'."));
        return new CompoundAccessSemantics(
            CompoundAccessKind.SUPER_FIELD_SETTER, getter, setter);
      }
    } else if (getter.isGetter) {
      if (setter.isMalformed) {
        return new CompoundAccessSemantics(
            CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, setter);
      } else if (setter.isField) {
        return new CompoundAccessSemantics(
            CompoundAccessKind.SUPER_GETTER_FIELD, getter, setter);
      } else {
        assert(invariant(node, setter.isSetter,
            message: "Unexpected super setter '$setter'."));
        return new CompoundAccessSemantics(
            CompoundAccessKind.SUPER_GETTER_SETTER, getter, setter);
      }
    } else {
      assert(invariant(node, getter.isFunction,
          message: "Unexpected super getter '$getter'."));
      if (setter.isMalformed) {
        if (isIndex) {
          return new CompoundAccessSemantics(
              CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, setter);
        } else {
          return new StaticAccess.superMethod(getter);
        }
      } else if (setter.isFunction) {
        assert(invariant(node, setter.name == '[]=',
            message: "Unexpected super setter '$setter'."));
        assert(invariant(node, getter.name == '[]',
            message: "Unexpected super getter '$getter'."));
        return new CompoundAccessSemantics(
                    CompoundAccessKind.SUPER_GETTER_SETTER, getter, setter);
      } else {
        assert(invariant(node, setter.isSetter,
            message: "Unexpected super setter '$setter'."));
        return new CompoundAccessSemantics(
            CompoundAccessKind.SUPER_METHOD_SETTER, getter, setter);
      }
    }
  }

  /// Compute the [AccessSemantics] corresponding to a local access of [target].
  AccessSemantics computeLocalAccessSemantics(Spannable node,
                                              LocalElement target) {
    if (target.isParameter) {
      if (target.isFinal || target.isConst) {
        return new StaticAccess.finalParameter(target);
      } else {
        return new StaticAccess.parameter(target);
      }
    } else if (target.isVariable) {
      if (target.isFinal || target.isConst) {
        return new StaticAccess.finalLocalVariable(target);
      } else {
        return new StaticAccess.localVariable(target);
      }
    } else {
      assert(invariant(node, target.isFunction,
          message: "Unexpected local target '$target'."));
      return new StaticAccess.localFunction(target);
    }
  }

  /// Compute the [AccessSemantics] corresponding to a static or toplevel access
  /// of [target].
  AccessSemantics computeStaticOrTopLevelAccessSemantics(
      Spannable node,
      Element target) {

    target = target.declaration;
    if (target.isMalformed) {
      // This handles elements with parser errors.
      return new StaticAccess.unresolved(target);
    }
    if (target.isStatic) {
      if (target.isGetter) {
        return new StaticAccess.staticGetter(target);
      } else if (target.isSetter) {
        return new StaticAccess.staticSetter(target);
      } else if (target.isField) {
        if (target.isFinal || target.isConst) {
          return new StaticAccess.finalStaticField(target);
        } else {
          return new StaticAccess.staticField(target);
        }
      } else {
        assert(invariant(node, target.isFunction,
            message: "Unexpected static target '$target'."));
        return new StaticAccess.staticMethod(target);
      }
     } else {
       assert(invariant(node, target.isTopLevel,
           message: "Unexpected statically resolved target '$target'."));
       if (target.isGetter) {
         return new StaticAccess.topLevelGetter(target);
       } else if (target.isSetter) {
         return new StaticAccess.topLevelSetter(target);
       } else if (target.isField) {
         if (target.isFinal) {
           return new StaticAccess.finalTopLevelField(target);
         } else {
           return new StaticAccess.topLevelField(target);
         }
       } else {
         assert(invariant(node, target.isFunction,
             message: "Unexpected top level target '$target'."));
         return new StaticAccess.topLevelMethod(target);
       }
     }
  }

  /// Compute the [AccessSemantics] for accessing the name of [selector] on the
  /// super class.
  ///
  /// If no matching super member is found and error is reported and
  /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName]
  /// is provided, the [AccessSemantics] corresponding to the alternate name is
  /// returned. For instance, the access of a super setter for an unresolved
  /// getter:
  ///
  ///     class Super {
  ///       set name(_) {}
  ///     }
  ///     class Sub extends Super {
  ///       foo => super.name; // Access to the setter.
  ///     }
  ///
  AccessSemantics computeSuperAccessSemanticsForSelector(
      Spannable node,
      Selector selector,
      {Name alternateName}) {

    Name name = selector.memberName;
    // TODO(johnniwinther): Ensure correct behavior if currentClass is a
    // patch.
    Element target = currentClass.lookupSuperByName(name);
    // [target] may be null which means invoking noSuchMethod on super.
    if (target == null) {
      if (alternateName != null) {
        target = currentClass.lookupSuperByName(alternateName);
      }
      Element error;
      if (selector.isSetter) {
        error = reportAndCreateErroneousElement(
          node, name.text, MessageKind.UNDEFINED_SUPER_SETTER,
          {'className': currentClass.name, 'memberName': name});
      } else {
        error = reportAndCreateErroneousElement(
          node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER,
          {'className': currentClass.name, 'memberName': name});
      }
      if (target == null) {
        // If a setter wasn't resolved, use the [ErroneousElement].
        target = error;
      }
      // We still need to register the invocation, because we might
      // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn].
      registry.registerDynamicUse(new DynamicUse(selector, null));
      registry.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
    }
    return computeSuperAccessSemantics(node, target);
  }

  /// Compute the [AccessSemantics] for accessing the name of [selector] on the
  /// super class.
  ///
  /// If no matching super member is found and error is reported and
  /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName]
  /// is provided, the [AccessSemantics] corresponding to the alternate name is
  /// returned. For instance, the access of a super setter for an unresolved
  /// getter:
  ///
  ///     class Super {
  ///       set name(_) {}
  ///     }
  ///     class Sub extends Super {
  ///       foo => super.name; // Access to the setter.
  ///     }
  ///
  AccessSemantics computeSuperAccessSemanticsForSelectors(
      Spannable node,
      Selector getterSelector,
      Selector setterSelector,
      {bool isIndex: false}) {
    bool getterError = false;
    bool setterError = false;

    // TODO(johnniwinther): Ensure correct behavior if currentClass is a
    // patch.
    Element getter = currentClass.lookupSuperByName(getterSelector.memberName);
    // [target] may be null which means invoking noSuchMethod on super.
    if (getter == null) {
      getter = reportAndCreateErroneousElement(
          node, getterSelector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
          {'className': currentClass.name, 'memberName': getterSelector.name});
      getterError = true;
    }
    Element setter = currentClass.lookupSuperByName(setterSelector.memberName);
    // [target] may be null which means invoking noSuchMethod on super.
    if (setter == null) {
      setter = reportAndCreateErroneousElement(
          node, setterSelector.name, MessageKind.NO_SUCH_SUPER_MEMBER,
          {'className': currentClass.name, 'memberName': setterSelector.name});
      setterError = true;
    } else if (getter == setter) {
      if (setter.isFunction) {
        setter = reportAndCreateErroneousElement(
            node, setterSelector.name,
            MessageKind.ASSIGNING_METHOD_IN_SUPER,
            {'superclassName': setter.enclosingClass.name,
             'name': setterSelector.name});
        setterError = true;
      } else if (setter.isField && setter.isFinal) {
        setter = reportAndCreateErroneousElement(
            node, setterSelector.name,
            MessageKind.ASSIGNING_FINAL_FIELD_IN_SUPER,
            {'superclassName': setter.enclosingClass.name,
             'name': setterSelector.name});
        setterError = true;
      }
    }
    if (getterError) {
      // We still need to register the invocation, because we might
      // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn].
      registry.registerDynamicUse(
          new DynamicUse(getterSelector, null));
    }
    if (setterError) {
      // We still need to register the invocation, because we might
      // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn].
      registry.registerDynamicUse(
          new DynamicUse(setterSelector, null));
    }
    if (getterError || setterError) {
      registry.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
    }
    return computeCompoundSuperAccessSemantics(
        node, getter, setter, isIndex: isIndex);
  }

  /// Resolve [node] as a subexpression that is _not_ the prefix of a member
  /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`.
  ResolutionResult visitExpression(Node node) {
    bool oldSendIsMemberAccess = sendIsMemberAccess;
    sendIsMemberAccess = false;
    ResolutionResult result = visit(node);
    sendIsMemberAccess = oldSendIsMemberAccess;
    return result;
  }

  /// Resolve [node] as a subexpression that _is_ the prefix of a member access.
  /// For instance `a` in `a.b`, as opposed to `a` in `a + b`.
  ResolutionResult visitExpressionPrefix(Node node) {
    int oldAllowedCategory = allowedCategory;
    bool oldSendIsMemberAccess = sendIsMemberAccess;
    allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER;
    sendIsMemberAccess = true;
    ResolutionResult result = visit(node);
    sendIsMemberAccess = oldSendIsMemberAccess;
    allowedCategory = oldAllowedCategory;
    return result;
  }

  /// Handle a type test expression, like `a is T` and `a is! T`.
  ResolutionResult handleIs(Send node) {
    Node expression = node.receiver;
    visitExpression(expression);

    // TODO(johnniwinther): Use seen type tests to avoid registration of
    // mutation/access to unpromoted variables.

    Send notTypeNode = node.arguments.head.asSend();
    DartType type;
    SendStructure sendStructure;
    if (notTypeNode != null) {
      // `e is! T`.
      Node typeNode = notTypeNode.receiver;
      type = resolveTypeAnnotation(typeNode);
      sendStructure = new IsNotStructure(type);
    } else {
      // `e is T`.
      Node typeNode = node.arguments.head;
      type = resolveTypeAnnotation(typeNode);
      sendStructure = new IsStructure(type);
    }
    registry.registerTypeUse(new TypeUse.isCheck(type));
    registry.registerSendStructure(node, sendStructure);
    return const NoneResult();
  }

  /// Handle a type cast expression, like `a as T`.
  ResolutionResult handleAs(Send node) {
    Node expression = node.receiver;
    visitExpression(expression);

    Node typeNode = node.arguments.head;
    DartType type = resolveTypeAnnotation(typeNode);
    registry.registerTypeUse(new TypeUse.asCast(type));
    registry.registerSendStructure(node, new AsStructure(type));
    return const NoneResult();
  }

  /// Handle the unary expression of an unresolved unary operator [text], like
  /// the no longer supported `+a`.
  ResolutionResult handleUnresolvedUnary(Send node, String text) {
    Node expression = node.receiver;
    if (node.isSuperCall) {
      checkSuperAccess(node);
    } else {
      visitExpression(expression);
    }

    registry.registerSendStructure(node, const InvalidUnaryStructure());
    return const NoneResult();
  }

  /// Handle the unary expression of a user definable unary [operator], like
  /// `-a`, and `-super`.
  ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) {
    ResolutionResult result = const NoneResult();
    Node expression = node.receiver;
    Selector selector = operator.selector;
    // TODO(23998): Remove this when all information goes through the
    // [SendStructure].
    registry.setSelector(node, selector);

    AccessSemantics semantics;
    if (node.isSuperCall) {
      semantics = checkSuperAccess(node);
      if (semantics == null) {
        semantics = computeSuperAccessSemanticsForSelector(node, selector);
        // TODO(johnniwinther): Add information to [AccessSemantics] about
        // whether it is erroneous.
        if (semantics.kind == AccessKind.SUPER_METHOD) {
          registry.registerStaticUse(
              new StaticUse.superInvoke(
                  semantics.element.declaration,
                  selector.callStructure));
        }
        // TODO(23998): Remove this when all information goes through
        // the [SendStructure].
        registry.useElement(node, semantics.element);
      }
    } else {
      ResolutionResult expressionResult = visitExpression(expression);
      semantics = const DynamicAccess.expression();
      registry.registerDynamicUse(new DynamicUse(selector, null));

      if (expressionResult.isConstant) {
        bool isValidConstant;
        ConstantExpression expressionConstant = expressionResult.constant;
        DartType knownExpressionType =
            expressionConstant.getKnownType(coreTypes);
        switch (operator.kind) {
          case UnaryOperatorKind.COMPLEMENT:
            isValidConstant =
                knownExpressionType == coreTypes.intType;
            break;
          case UnaryOperatorKind.NEGATE:
            isValidConstant =
                knownExpressionType == coreTypes.intType ||
                knownExpressionType == coreTypes.doubleType;
            break;
          case UnaryOperatorKind.NOT:
            reporter.internalError(node,
                "Unexpected user definable unary operator: $operator");
        }
        if (isValidConstant) {
          // TODO(johnniwinther): Handle potentially invalid constant
          // expressions.
          ConstantExpression constant =
              new UnaryConstantExpression(operator, expressionConstant);
          registry.setConstant(node, constant);
          result = new ConstantResult(node, constant);
        }
      }
    }
    if (semantics != null) {
      registry.registerSendStructure(node,
          new UnaryStructure(semantics, operator));
    }
    return result;
  }

  /// Handle a not expression, like `!a`.
  ResolutionResult handleNot(Send node, UnaryOperator operator) {
    assert(invariant(node, operator.kind == UnaryOperatorKind.NOT));

    Node expression = node.receiver;
    ResolutionResult result = visitExpression(expression);
    registry.registerSendStructure(node, const NotStructure());

    if (result.isConstant) {
      ConstantExpression expressionConstant = result.constant;
      if (expressionConstant.getKnownType(coreTypes) == coreTypes.boolType) {
        // TODO(johnniwinther): Handle potentially invalid constant expressions.
        ConstantExpression constant =
            new UnaryConstantExpression(operator, expressionConstant);
        registry.setConstant(node, constant);
        return new ConstantResult(node, constant);
      }
    }

    return const NoneResult();
  }

  /// Handle a logical and expression, like `a && b`.
  ResolutionResult handleLogicalAnd(Send node) {
    Node left = node.receiver;
    Node right = node.arguments.head;
    ResolutionResult leftResult =
        doInPromotionScope(left, () => visitExpression(left));
    ResolutionResult rightResult =
        doInPromotionScope(right, () => visitExpression(right));
    registry.registerSendStructure(node, const LogicalAndStructure());

    if (leftResult.isConstant && rightResult.isConstant) {
      ConstantExpression leftConstant = leftResult.constant;
      ConstantExpression rightConstant = rightResult.constant;
      if (leftConstant.getKnownType(coreTypes) == coreTypes.boolType &&
          rightConstant.getKnownType(coreTypes) == coreTypes.boolType) {
        // TODO(johnniwinther): Handle potentially invalid constant expressions.
        ConstantExpression constant = new BinaryConstantExpression(
            leftConstant,
            BinaryOperator.LOGICAL_AND,
            rightConstant);
        registry.setConstant(node, constant);
        return new ConstantResult(node, constant);
      }
    }

    return const NoneResult();
  }

  /// Handle a logical or expression, like `a || b`.
  ResolutionResult handleLogicalOr(Send node) {
    Node left = node.receiver;
    Node right = node.arguments.head;
    ResolutionResult leftResult = visitExpression(left);
    ResolutionResult rightResult = visitExpression(right);
    registry.registerSendStructure(node, const LogicalOrStructure());

    if (leftResult.isConstant && rightResult.isConstant) {
      ConstantExpression leftConstant = leftResult.constant;
      ConstantExpression rightConstant = rightResult.constant;
      if (leftConstant.getKnownType(coreTypes) == coreTypes.boolType &&
          rightConstant.getKnownType(coreTypes) == coreTypes.boolType) {
        // TODO(johnniwinther): Handle potentially invalid constant expressions.
        ConstantExpression constant = new BinaryConstantExpression(
            leftConstant,
            BinaryOperator.LOGICAL_OR,
            rightConstant);
        registry.setConstant(node, constant);
        return new ConstantResult(node, constant);
      }
    }
    return const NoneResult();
  }

  /// Handle an if-null expression, like `a ?? b`.
  ResolutionResult handleIfNull(Send node) {
    Node left = node.receiver;
    Node right = node.arguments.head;
    visitExpression(left);
    visitExpression(right);
    registry.registerSendStructure(node, const IfNullStructure());
    return const NoneResult();
  }

  /// Handle the binary expression of an unresolved binary operator [text], like
  /// the no longer supported `a === b`.
  ResolutionResult handleUnresolvedBinary(Send node, String text) {
    Node left = node.receiver;
    Node right = node.arguments.head;
    if (node.isSuperCall) {
      checkSuperAccess(node);
    } else {
      visitExpression(left);
    }
    visitExpression(right);
    registry.registerSendStructure(node, const InvalidBinaryStructure());
    return const NoneResult();
  }

  /// Handle the binary expression of a user definable binary [operator], like
  /// `a + b`, `super + b`, `a == b` and `a != b`.
  ResolutionResult handleUserDefinableBinary(Send node,
                                             BinaryOperator operator) {
    ResolutionResult result = const NoneResult();
    Node left = node.receiver;
    Node right = node.arguments.head;
    AccessSemantics semantics;
    Selector selector;
    if (operator.kind == BinaryOperatorKind.INDEX) {
      selector = new Selector.index();
    } else {
      selector = new Selector.binaryOperator(operator.selectorName);
    }
    // TODO(23998): Remove this when all information goes through the
    // [SendStructure].
    registry.setSelector(node, selector);

    if (node.isSuperCall) {
      semantics = checkSuperAccess(node);
      if (semantics == null) {
        semantics = computeSuperAccessSemanticsForSelector(node, selector);
        // TODO(johnniwinther): Add information to [AccessSemantics] about
        // whether it is erroneous.
        if (semantics.kind == AccessKind.SUPER_METHOD) {
          registry.registerStaticUse(
              new StaticUse.superInvoke(
                  semantics.element.declaration,
                  selector.callStructure));
        }
        // TODO(23998): Remove this when all information goes through
        // the [SendStructure].
        registry.useElement(node, semantics.element);
      }
      visitExpression(right);
    } else {
      ResolutionResult leftResult = visitExpression(left);
      ResolutionResult rightResult = visitExpression(right);
      registry.registerDynamicUse(new DynamicUse(selector, null));
      semantics = const DynamicAccess.expression();

      if (leftResult.isConstant && rightResult.isConstant) {
        bool isValidConstant;
        ConstantExpression leftConstant = leftResult.constant;
        ConstantExpression rightConstant = rightResult.constant;
        DartType knownLeftType = leftConstant.getKnownType(coreTypes);
        DartType knownRightType = rightConstant.getKnownType(coreTypes);
        switch (operator.kind) {
          case BinaryOperatorKind.EQ:
          case BinaryOperatorKind.NOT_EQ:
            isValidConstant =
                (knownLeftType == coreTypes.intType ||
                 knownLeftType == coreTypes.doubleType ||
                 knownLeftType == coreTypes.stringType ||
                 knownLeftType == coreTypes.boolType ||
                 knownLeftType == coreTypes.nullType) &&
                (knownRightType == coreTypes.intType ||
                 knownRightType == coreTypes.doubleType ||
                 knownRightType == coreTypes.stringType ||
                 knownRightType == coreTypes.boolType ||
                 knownRightType == coreTypes.nullType);
            break;
          case BinaryOperatorKind.ADD:
            isValidConstant =
                (knownLeftType == coreTypes.intType ||
                 knownLeftType == coreTypes.doubleType ||
                 knownLeftType == coreTypes.stringType) &&
                (knownRightType == coreTypes.intType ||
                 knownRightType == coreTypes.doubleType ||
                 knownRightType == coreTypes.stringType);
            break;
          case BinaryOperatorKind.SUB:
          case BinaryOperatorKind.MUL:
          case BinaryOperatorKind.DIV:
          case BinaryOperatorKind.IDIV:
          case BinaryOperatorKind.MOD:
          case BinaryOperatorKind.GTEQ:
          case BinaryOperatorKind.GT:
          case BinaryOperatorKind.LTEQ:
          case BinaryOperatorKind.LT:
            isValidConstant =
                (knownLeftType == coreTypes.intType ||
                 knownLeftType == coreTypes.doubleType) &&
                (knownRightType == coreTypes.intType ||
                 knownRightType == coreTypes.doubleType);
            break;
          case BinaryOperatorKind.SHL:
          case BinaryOperatorKind.SHR:
          case BinaryOperatorKind.AND:
          case BinaryOperatorKind.OR:
          case BinaryOperatorKind.XOR:
            isValidConstant =
                knownLeftType == coreTypes.intType &&
                knownRightType == coreTypes.intType;
            break;
          case BinaryOperatorKind.INDEX:
            isValidConstant = false;
            break;
          case BinaryOperatorKind.LOGICAL_AND:
          case BinaryOperatorKind.LOGICAL_OR:
          case BinaryOperatorKind.IF_NULL:
            reporter.internalError(
                node, "Unexpected binary operator '${operator}'.");
            break;
        }
        if (isValidConstant) {
          // TODO(johnniwinther): Handle potentially invalid constant
          // expressions.
          ConstantExpression constant = new BinaryConstantExpression(
              leftResult.constant,
              operator,
              rightResult.constant);
          registry.setConstant(node, constant);
          result = new ConstantResult(node, constant);
        }
      }
    }

    if (semantics != null) {
      // TODO(johnniwinther): Support invalid super access as an
      // [AccessSemantics].
      SendStructure sendStructure;
      switch (operator.kind) {
        case BinaryOperatorKind.EQ:
          sendStructure = new EqualsStructure(semantics);
          break;
        case BinaryOperatorKind.NOT_EQ:
          sendStructure = new NotEqualsStructure(semantics);
          break;
        case BinaryOperatorKind.INDEX:
          sendStructure = new IndexStructure(semantics);
          break;
        case BinaryOperatorKind.ADD:
        case BinaryOperatorKind.SUB:
        case BinaryOperatorKind.MUL:
        case BinaryOperatorKind.DIV:
        case BinaryOperatorKind.IDIV:
        case BinaryOperatorKind.MOD:
        case BinaryOperatorKind.SHL:
        case BinaryOperatorKind.SHR:
        case BinaryOperatorKind.GTEQ:
        case BinaryOperatorKind.GT:
        case BinaryOperatorKind.LTEQ:
        case BinaryOperatorKind.LT:
        case BinaryOperatorKind.AND:
        case BinaryOperatorKind.OR:
        case BinaryOperatorKind.XOR:
          sendStructure = new BinaryStructure(semantics, operator);
          break;
        case BinaryOperatorKind.LOGICAL_AND:
        case BinaryOperatorKind.LOGICAL_OR:
        case BinaryOperatorKind.IF_NULL:
          reporter.internalError(
              node, "Unexpected binary operator '${operator}'.");
          break;
      }
      registry.registerSendStructure(node, sendStructure);
    }
    return result;
  }

  /// Handle an invocation of an expression, like `(){}()` or `(foo)()`.
  ResolutionResult handleExpressionInvoke(Send node) {
    assert(invariant(node, node.isCall,
        message: "Unexpected expression: $node"));
    Node expression = node.selector;
    visitExpression(expression);
    CallStructure callStructure =
        resolveArguments(node.argumentsNode).callStructure;
    Selector selector = callStructure.callSelector;
    // TODO(23998): Remove this when all information goes through the
    // [SendStructure].
    registry.setSelector(node, selector);
    registry.registerDynamicUse(new DynamicUse(selector, null));
    registry.registerSendStructure(node,
        new InvokeStructure(const DynamicAccess.expression(), selector));
    return const NoneResult();
  }

  /// Handle access of a property of [name] on `this`, like `this.name` and
  /// `this.name()`, or `name` and `name()` in instance context.
  ResolutionResult handleThisPropertyAccess(Send node, Name name) {
    AccessSemantics semantics = new DynamicAccess.thisProperty(name);
    return handleDynamicAccessSemantics(node, name, semantics);
  }

  /// Handle update of a property of [name] on `this`, like `this.name = b` and
  /// `this.name++`, or `name = b` and `name++` in instance context.
  ResolutionResult handleThisPropertyUpdate(
      SendSet node, Name name, Element element) {
    AccessSemantics semantics = new DynamicAccess.thisProperty(name);
    return handleDynamicUpdateSemantics(node, name, element, semantics);
  }

  /// Handle access on `this`, like `this()` and `this` when it is parsed as a
  /// [Send] node.
  ResolutionResult handleThisAccess(Send node) {
    if (node.isCall) {
      CallStructure callStructure =
          resolveArguments(node.argumentsNode).callStructure;
      Selector selector = callStructure.callSelector;
      // TODO(johnniwinther): Handle invalid this access as an
      // [AccessSemantics].
      AccessSemantics accessSemantics = checkThisAccess(node);
      if (accessSemantics == null) {
        accessSemantics = const DynamicAccess.thisAccess();
        registry.registerDynamicUse(
            new DynamicUse(selector, null));
      }
      registry.registerSendStructure(node,
          new InvokeStructure(accessSemantics, selector));
      // TODO(23998): Remove this when all information goes through
      // the [SendStructure].
      registry.setSelector(node, selector);
      return const NoneResult();
    } else {
      // TODO(johnniwinther): Handle get of `this` when it is a [Send] node.
      reporter.internalError(
          node, "Unexpected node '$node'.");
    }
    return const NoneResult();
  }

  /// Handle access of a super property, like `super.foo` and `super.foo()`.
  ResolutionResult handleSuperPropertyAccess(Send node, Name name) {
    Element target;
    Selector selector;
    CallStructure callStructure;
    if (node.isCall) {
      callStructure = resolveArguments(node.argumentsNode).callStructure;
      selector = new Selector.call(name, callStructure);
    } else {
      selector = new Selector.getter(name);
    }
    AccessSemantics semantics = checkSuperAccess(node);
    if (semantics == null) {
      semantics = computeSuperAccessSemanticsForSelector(
          node, selector, alternateName: name.setter);
    }
    if (node.isCall) {
      bool isIncompatibleInvoke = false;
      switch (semantics.kind) {
        case AccessKind.SUPER_METHOD:
          MethodElementX superMethod = semantics.element;
          superMethod.computeType(resolution);
          if (!callStructure.signatureApplies(
                  superMethod.functionSignature)) {
            registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
            registry.registerDynamicUse(
                new DynamicUse(selector, null));
            registry.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
            isIncompatibleInvoke = true;
          } else {
            registry.registerStaticUse(
                new StaticUse.superInvoke(semantics.element, callStructure));
          }
          break;
        case AccessKind.SUPER_FIELD:
        case AccessKind.SUPER_FINAL_FIELD:
        case AccessKind.SUPER_GETTER:
          registry.registerStaticUse(
              new StaticUse.superGet(semantics.element));
          selector = callStructure.callSelector;
          registry.registerDynamicUse(
              new DynamicUse(selector, null));
          break;
        case AccessKind.SUPER_SETTER:
        case AccessKind.UNRESOLVED_SUPER:
          // NoSuchMethod registered in [computeSuperSemantics].
          break;
        case AccessKind.INVALID:
          // 'super' is not allowed.
          break;
        default:
          reporter.internalError(
              node, "Unexpected super property access $semantics.");
          break;
      }
      registry.registerSendStructure(node,
          isIncompatibleInvoke
              ? new IncompatibleInvokeStructure(semantics, selector)
              : new InvokeStructure(semantics, selector));
    } else {
      switch (semantics.kind) {
        case AccessKind.SUPER_METHOD:
          // TODO(johnniwinther): Method this should be registered as a
          // closurization.
          registry.registerStaticUse(
              new StaticUse.superTearOff(semantics.element));
          break;
        case AccessKind.SUPER_FIELD:
        case AccessKind.SUPER_FINAL_FIELD:
        case AccessKind.SUPER_GETTER:
          registry.registerStaticUse(
              new StaticUse.superGet(semantics.element));
          break;
        case AccessKind.SUPER_SETTER:
        case AccessKind.UNRESOLVED_SUPER:
          // NoSuchMethod registered in [computeSuperSemantics].
          break;
        case AccessKind.INVALID:
          // 'super' is not allowed.
          break;
        default:
          reporter.internalError(
              node, "Unexpected super property access $semantics.");
          break;
      }
      registry.registerSendStructure(node, new GetStructure(semantics));
    }
    target = semantics.element;

    // TODO(23998): Remove these when all information goes through
    // the [SendStructure].
    registry.useElement(node, target);
    registry.setSelector(node, selector);
    return const NoneResult();
  }

  /// Handle a [Send] whose selector is an [Operator], like `a && b`, `a is T`,
  /// `a + b`, and `~a`.
  ResolutionResult handleOperatorSend(Send node) {
    String operatorText = node.selector.asOperator().source;
    if (operatorText == 'is') {
      return handleIs(node);
    } else if (operatorText  == 'as') {
      return handleAs(node);
    } else if (node.arguments.isEmpty) {
      UnaryOperator operator = UnaryOperator.parse(operatorText);
      if (operator == null) {
        return handleUnresolvedUnary(node, operatorText);
      } else {
        switch (operator.kind) {
          case UnaryOperatorKind.NOT:
            return handleNot(node, operator);
          case UnaryOperatorKind.COMPLEMENT:
          case UnaryOperatorKind.NEGATE:
            assert(invariant(node, operator.isUserDefinable,
                message: "Unexpected unary operator '${operator}'."));
            return handleUserDefinableUnary(node, operator);
        }
      }
    } else {
      BinaryOperator operator = BinaryOperator.parse(operatorText);
      if (operator == null) {
        return handleUnresolvedBinary(node, operatorText);
      } else {
        switch (operator.kind) {
          case BinaryOperatorKind.LOGICAL_AND:
            return handleLogicalAnd(node);
          case BinaryOperatorKind.LOGICAL_OR:
            return handleLogicalOr(node);
          case BinaryOperatorKind.IF_NULL:
            return handleIfNull(node);
          case BinaryOperatorKind.EQ:
          case BinaryOperatorKind.NOT_EQ:
          case BinaryOperatorKind.INDEX:
          case BinaryOperatorKind.ADD:
          case BinaryOperatorKind.SUB:
          case BinaryOperatorKind.MUL:
          case BinaryOperatorKind.DIV:
          case BinaryOperatorKind.IDIV:
          case BinaryOperatorKind.MOD:
          case BinaryOperatorKind.SHL:
          case BinaryOperatorKind.SHR:
          case BinaryOperatorKind.GTEQ:
          case BinaryOperatorKind.GT:
          case BinaryOperatorKind.LTEQ:
          case BinaryOperatorKind.LT:
          case BinaryOperatorKind.AND:
          case BinaryOperatorKind.OR:
          case BinaryOperatorKind.XOR:
            return handleUserDefinableBinary(node, operator);
        }
      }
    }
  }

  /// Handle qualified access to an unresolved static class member, like `a.b`
  /// or `a.b()` where `a` is a class and `b` is unresolved.
  ResolutionResult handleUnresolvedStaticMemberAccess(
      Send node, Name name, ClassElement receiverClass) {
    // TODO(johnniwinther): Share code with [handleStaticInstanceMemberAccess]
    // and [handlePrivateStaticMemberAccess].
    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    // TODO(johnniwinther): Produce a different error if [name] is resolves to
    // a constructor.

    // TODO(johnniwinther): With the simplified [TreeElements] invariant,
    // try to resolve injected elements if [currentClass] is in the patch
    // library of [receiverClass].

    // TODO(karlklose): this should be reported by the caller of
    // [resolveSend] to select better warning messages for getters and
    // setters.
    ErroneousElement error = reportAndCreateErroneousElement(
        node, name.text, MessageKind.UNDEFINED_GETTER,
        {'className': receiverClass.name, 'memberName': name.text});
    // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
    // member access.
    return handleErroneousAccess(
        node, name, new StaticAccess.unresolved(error));
  }

  /// Handle qualified update to an unresolved static class member, like
  /// `a.b = c` or `a.b++` where `a` is a class and `b` is unresolved.
  ResolutionResult handleUnresolvedStaticMemberUpdate(
      SendSet node, Name name, ClassElement receiverClass) {
    // TODO(johnniwinther): Share code with [handleStaticInstanceMemberUpdate]
    // and [handlePrivateStaticMemberUpdate].
    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    // TODO(johnniwinther): Produce a different error if [name] is resolves to
    // a constructor.

    // TODO(johnniwinther): With the simplified [TreeElements] invariant,
    // try to resolve injected elements if [currentClass] is in the patch
    // library of [receiverClass].

    // TODO(johnniwinther): Produce a different error for complex update.
    ErroneousElement error = reportAndCreateErroneousElement(
        node, name.text, MessageKind.UNDEFINED_GETTER,
        {'className': receiverClass.name, 'memberName': name.text});
    // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
    // member access.
    return handleUpdate(node, name, new StaticAccess.unresolved(error));
  }

  /// Handle qualified access of an instance member, like `a.b` or `a.b()` where
  /// `a` is a class and `b` is a non-static member.
  ResolutionResult handleStaticInstanceMemberAccess(
      Send node, Name name, ClassElement receiverClass, Element member) {

    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    // TODO(johnniwinther): With the simplified [TreeElements] invariant,
    // try to resolve injected elements if [currentClass] is in the patch
    // library of [receiverClass].

    // TODO(karlklose): this should be reported by the caller of
    // [resolveSend] to select better warning messages for getters and
    // setters.
    ErroneousElement error = reportAndCreateErroneousElement(
        node, name.text, MessageKind.MEMBER_NOT_STATIC,
        {'className': receiverClass.name, 'memberName': name});

    // TODO(johnniwinther): Add an [AccessSemantics] for statically accessed
    // instance members.
    return handleErroneousAccess(
        node, name, new StaticAccess.unresolved(error));
  }

  /// Handle qualified update of an instance member, like `a.b = c` or `a.b++`
  /// where `a` is a class and `b` is a non-static member.
  ResolutionResult handleStaticInstanceMemberUpdate(
      SendSet node, Name name, ClassElement receiverClass, Element member) {

    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    // TODO(johnniwinther): With the simplified [TreeElements] invariant,
    // try to resolve injected elements if [currentClass] is in the patch
    // library of [receiverClass].

    // TODO(johnniwinther): Produce a different error for complex update.
    ErroneousElement error = reportAndCreateErroneousElement(
        node, name.text, MessageKind.MEMBER_NOT_STATIC,
        {'className': receiverClass.name, 'memberName': name});

    // TODO(johnniwinther): Add an [AccessSemantics] for statically accessed
    // instance members.
    return handleUpdate(node, name, new StaticAccess.unresolved(error));
  }

  /// Handle qualified access of an inaccessible private static class member,
  /// like `a._b` or `a._b()` where `a` is class, `_b` is static member of `a`
  /// but `a` is not defined in the current library.
  ResolutionResult handlePrivateStaticMemberAccess(
      Send node, Name name, ClassElement receiverClass, Element member) {
    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    ErroneousElement error = reportAndCreateErroneousElement(
        node, name.text, MessageKind.PRIVATE_ACCESS,
        {'libraryName': member.library.libraryOrScriptName,
         'name': name});
    // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
    // member access.
    return handleErroneousAccess(
        node, name, new StaticAccess.unresolved(error));
  }

  /// Handle qualified update of an inaccessible private static class member,
  /// like `a._b = c` or `a._b++` where `a` is class, `_b` is static member of
  /// `a` but `a` is not defined in the current library.
  ResolutionResult handlePrivateStaticMemberUpdate(
      SendSet node, Name name, ClassElement receiverClass, Element member) {
    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    ErroneousElement error = reportAndCreateErroneousElement(
        node, name.text, MessageKind.PRIVATE_ACCESS,
        {'libraryName': member.library.libraryOrScriptName,
         'name': name});
    // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static
    // member access.
    return handleUpdate(node, name, new StaticAccess.unresolved(error));
  }

  /// Handle qualified access to a static member, like `a.b` or `a.b()` where
  /// `a` is a class and `b` is a static member of `a`.
  ResolutionResult handleStaticMemberAccess(
      Send node, Name memberName, ClassElement receiverClass) {
    String name = memberName.text;
    receiverClass.ensureResolved(resolution);
    if (node.isOperator) {
      // When the resolved receiver is a class, we can have two cases:
      //  1) a static send: C.foo, or
      //  2) an operator send, where the receiver is a class literal: 'C + 1'.
      // The following code that looks up the selector on the resolved
      // receiver will treat the second as the invocation of a static operator
      // if the resolved receiver is not null.
      return const NoneResult();
    }
    MembersCreator.computeClassMembersByName(
        compiler, receiverClass.declaration, name);
    Element member = receiverClass.lookupLocalMember(name);
    if (member == null) {
      return handleUnresolvedStaticMemberAccess(
          node, memberName, receiverClass);
    } else if (member.isAmbiguous) {
      return handleAmbiguousSend(node, memberName, member);
    } else if (member.isInstanceMember) {
      return handleStaticInstanceMemberAccess(
          node, memberName, receiverClass, member);
    } else if (memberName.isPrivate && memberName.library != member.library) {
      return handlePrivateStaticMemberAccess(
          node, memberName, receiverClass, member);
    } else {
      return handleStaticOrTopLevelAccess(node, memberName, member);
    }
  }

  /// Handle qualified update to a static member, like `a.b = c` or `a.b++`
  /// where `a` is a class and `b` is a static member of `a`.
  ResolutionResult handleStaticMemberUpdate(
      Send node, Name memberName, ClassElement receiverClass) {
    String name = memberName.text;
    receiverClass.ensureResolved(resolution);
    MembersCreator.computeClassMembersByName(
        compiler, receiverClass.declaration, name);
    Element member = receiverClass.lookupLocalMember(name);
    if (member == null) {
      return handleUnresolvedStaticMemberUpdate(
          node, memberName, receiverClass);
    } else if (member.isAmbiguous) {
      return handleAmbiguousUpdate(node, memberName, member);
    } else if (member.isInstanceMember) {
      return handleStaticInstanceMemberUpdate(
          node, memberName, receiverClass, member);
    } else if (memberName.isPrivate && memberName.library != member.library) {
      return handlePrivateStaticMemberUpdate(
          node, memberName, receiverClass, member);
    } else {
      return handleStaticOrTopLevelUpdate(node, memberName, member);
    }
  }

  /// Handle access to a type literal of type variable [element]. Like `T` or
  /// `T()` where 'T' is type variable.
  // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
  // the [GetStructure].
  // TODO(johnniwinther): Remove [element] when it is no longer needed for
  // evaluating constants.
  ResolutionResult handleTypeVariableTypeLiteralAccess(
      Send node,
      Name name,
      TypeVariableElement element) {
    AccessSemantics semantics;
    if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
      // TODO(johnniwinther): Add another access semantics for this.
      ErroneousElement error = reportAndCreateErroneousElement(
          node, name.text,
          MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
          {'typeVariableName': name},
          isError: true);
      registry.registerFeature(Feature.COMPILE_TIME_ERROR);
      semantics = new StaticAccess.invalid(error);
      // TODO(johnniwinther): Clean up registration of elements and selectors
      // for this case.
    } else {
      semantics = new StaticAccess.typeParameterTypeLiteral(element);
    }

    registry.useElement(node, element);
    registry.registerTypeLiteral(node, element.type);

    if (node.isCall) {
      CallStructure callStructure =
          resolveArguments(node.argumentsNode).callStructure;
      Selector selector = callStructure.callSelector;
      // TODO(23998): Remove this when all information goes through
      // the [SendStructure].
      registry.setSelector(node, selector);

      registry.registerSendStructure(node,
          new InvokeStructure(semantics, selector));
    } else {
      // TODO(johnniwinther): Avoid the need for a [Selector] here.
      registry.registerSendStructure(node, new GetStructure(semantics));
    }
    return const NoneResult();
  }

  /// Handle access to a type literal of type variable [element]. Like `T = b`,
  /// `T++` or `T += b` where 'T' is type variable.
  ResolutionResult handleTypeVariableTypeLiteralUpdate(
      SendSet node,
      Name name,
      TypeVariableElement element) {
    AccessSemantics semantics;
    if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
      // TODO(johnniwinther): Add another access semantics for this.
      ErroneousElement error = reportAndCreateErroneousElement(
          node, name.text,
          MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
          {'typeVariableName': name},
          isError: true);
      registry.registerFeature(Feature.COMPILE_TIME_ERROR);
      semantics = new StaticAccess.invalid(error);
    } else {
      ErroneousElement error;
      if (node.isIfNullAssignment) {
        error = reportAndCreateErroneousElement(
            node.selector, name.text,
            MessageKind.IF_NULL_ASSIGNING_TYPE, const {});
        // TODO(23998): Remove these when all information goes through
        // the [SendStructure].
        registry.useElement(node.selector, element);
      } else {
        error = reportAndCreateErroneousElement(
            node.selector, name.text,
            MessageKind.ASSIGNING_TYPE, const {});
      }

      // TODO(23998): Remove this when all information goes through
      // the [SendStructure].
      registry.useElement(node, error);
      // TODO(johnniwinther): Register only on read?
      registry.registerTypeLiteral(node, element.type);
      registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
      semantics = new StaticAccess.typeParameterTypeLiteral(element);
    }
    return handleUpdate(node, name, semantics);
  }

  /// Handle access to a constant type literal of [type].
  // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
  // the [GetStructure].
  // TODO(johnniwinther): Remove [element] when it is no longer needed for
  // evaluating constants.
  ResolutionResult handleConstantTypeLiteralAccess(
      Send node,
      Name name,
      TypeDeclarationElement element,
      DartType type,
      ConstantAccess semantics) {
    registry.useElement(node, element);
    registry.registerTypeLiteral(node, type);

    if (node.isCall) {
      CallStructure callStructure =
          resolveArguments(node.argumentsNode).callStructure;
      Selector selector = callStructure.callSelector;
      // TODO(23998): Remove this when all information goes through
      // the [SendStructure].
      registry.setSelector(node, selector);

      // The node itself is not a constant but we register the selector (the
      // identifier that refers to the class/typedef) as a constant.
      registry.useElement(node.selector, element);
      analyzeConstantDeferred(node.selector, enforceConst: false);

      registry.registerSendStructure(node,
          new InvokeStructure(semantics, selector));
      return const NoneResult();
    } else {
      analyzeConstantDeferred(node, enforceConst: false);

      registry.setConstant(node, semantics.constant);
      registry.registerSendStructure(node, new GetStructure(semantics));
      return new ConstantResult(node, semantics.constant);
    }
  }

  /// Handle access to a constant type literal of [type].
  // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
  // the [GetStructure].
  // TODO(johnniwinther): Remove [element] when it is no longer needed for
  // evaluating constants.
  ResolutionResult handleConstantTypeLiteralUpdate(
      SendSet node,
      Name name,
      TypeDeclarationElement element,
      DartType type,
      ConstantAccess semantics) {

    // TODO(johnniwinther): Remove this when all constants are evaluated.
    compiler.resolver.constantCompiler.evaluate(semantics.constant);

    ErroneousElement error;
    if (node.isIfNullAssignment) {
      error = reportAndCreateErroneousElement(
          node.selector, name.text,
          MessageKind.IF_NULL_ASSIGNING_TYPE, const {});
      // TODO(23998): Remove these when all information goes through
      // the [SendStructure].
      registry.setConstant(node.selector, semantics.constant);
      registry.useElement(node.selector, element);
    } else {
      error = reportAndCreateErroneousElement(
          node.selector, name.text,
          MessageKind.ASSIGNING_TYPE, const {});
    }

    // TODO(23998): Remove this when all information goes through
    // the [SendStructure].
    registry.useElement(node, error);
    registry.registerTypeLiteral(node, type);
    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);

    return handleUpdate(node, name, semantics);
  }

  /// Handle access to a type literal of a typedef. Like `F` or
  /// `F()` where 'F' is typedef.
  ResolutionResult handleTypedefTypeLiteralAccess(
      Send node,
      Name name,
      TypedefElement typdef) {
    typdef.ensureResolved(resolution);
    DartType type = typdef.rawType;
    ConstantExpression constant = new TypeConstantExpression(type);
    AccessSemantics semantics = new ConstantAccess.typedefTypeLiteral(constant);
    return handleConstantTypeLiteralAccess(node, name, typdef, type, semantics);
  }

  /// Handle access to a type literal of a typedef. Like `F = b`, `F++` or
  /// `F += b` where 'F' is typedef.
  ResolutionResult handleTypedefTypeLiteralUpdate(
      SendSet node,
      Name name,
      TypedefElement typdef) {
    typdef.ensureResolved(resolution);
    DartType type = typdef.rawType;
    ConstantExpression constant = new TypeConstantExpression(type);
    AccessSemantics semantics = new ConstantAccess.typedefTypeLiteral(constant);
    return handleConstantTypeLiteralUpdate(node, name, typdef, type, semantics);
  }

  /// Handle access to a type literal of the type 'dynamic'. Like `dynamic` or
  /// `dynamic()`.
  ResolutionResult handleDynamicTypeLiteralAccess(Send node) {
    DartType type = const DynamicType();
    ConstantExpression constant = new TypeConstantExpression(
        // TODO(johnniwinther): Use [type] when evaluation of constants is done
        // directly on the constant expressions.
        node.isCall ? coreTypes.typeType : type);
    AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant);
    return handleConstantTypeLiteralAccess(
        node, const PublicName('dynamic'),
        coreClasses.typeClass, type, semantics);
  }

  /// Handle update to a type literal of the type 'dynamic'. Like `dynamic++` or
  /// `dynamic = 0`.
  ResolutionResult handleDynamicTypeLiteralUpdate(SendSet node) {
    DartType type = const DynamicType();
    ConstantExpression constant =
        new TypeConstantExpression(const DynamicType());
    AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant);
    return handleConstantTypeLiteralUpdate(
        node, const PublicName('dynamic'),
        coreClasses.typeClass, type, semantics);
  }

  /// Handle access to a type literal of a class. Like `C` or
  /// `C()` where 'C' is class.
  ResolutionResult handleClassTypeLiteralAccess(
      Send node,
      Name name,
      ClassElement cls) {
    cls.ensureResolved(resolution);
    DartType type = cls.rawType;
    ConstantExpression constant = new TypeConstantExpression(type);
    AccessSemantics semantics = new ConstantAccess.classTypeLiteral(constant);
    return handleConstantTypeLiteralAccess(node, name, cls, type, semantics);
  }

  /// Handle access to a type literal of a class. Like `C = b`, `C++` or
  /// `C += b` where 'C' is class.
  ResolutionResult handleClassTypeLiteralUpdate(
      SendSet node,
      Name name,
      ClassElement cls) {
    cls.ensureResolved(resolution);
    DartType type = cls.rawType;
    ConstantExpression constant = new TypeConstantExpression(type);
    AccessSemantics semantics = new ConstantAccess.classTypeLiteral(constant);
    return handleConstantTypeLiteralUpdate(node, name, cls, type, semantics);
  }

  /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in
  /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time
  /// error.
  ResolutionResult handleClassSend(
      Send node,
      Name name,
      ClassElement cls) {
    cls.ensureResolved(resolution);
    if (sendIsMemberAccess) {
      registry.useElement(node, cls);
      return new PrefixResult(null, cls);
    } else {
      // `C` or `C()` where 'C' is a class.
      return handleClassTypeLiteralAccess(node, name, cls);
    }
  }

  /// Compute a [DeferredPrefixStructure] for [node].
  ResolutionResult handleDeferredAccess(
      Send node,
      PrefixElement prefix,
      ResolutionResult result) {
    assert(invariant(node, prefix.isDeferred,
        message: "Prefix $prefix is not deferred."));
    SendStructure sendStructure = registry.getSendStructure(node);
    assert(invariant(node, sendStructure !=  null,
        message: "No SendStructure for $node."));
    registry.registerSendStructure(node,
        new DeferredPrefixStructure(prefix, sendStructure));
    if (result.isConstant) {
      ConstantExpression constant =
          new DeferredConstantExpression(result.constant, prefix);
      registry.setConstant(node, constant);
      result = new ConstantResult(node, constant);
    }
    return result;
  }

  /// Handle qualified [Send] where the receiver resolves to a [prefix],
  /// like `prefix.toplevelFunction()` or `prefix.Class.staticField` where
  /// `prefix` is a library prefix.
  ResolutionResult handleLibraryPrefixSend(
      Send node, Name name, PrefixElement prefix) {
    ResolutionResult result;
    Element member = prefix.lookupLocalMember(name.text);
    if (member == null) {
      registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
      Element error = reportAndCreateErroneousElement(
          node, name.text, MessageKind.NO_SUCH_LIBRARY_MEMBER,
          {'libraryName': prefix.name, 'memberName': name});
      result = handleUnresolvedAccess(node, name, error);
    } else {
      result = handleResolvedSend(node, name, member);
    }
    if (result.kind == ResultKind.PREFIX) {
      // [member] is a class prefix of a static access like `prefix.Class` of
      // `prefix.Class.foo`. No need to call [handleDeferredAccess]; it will
      // called on the parent `prefix.Class.foo` node.
      result = new PrefixResult(prefix, result.element);
    } else if (prefix.isDeferred &&
               (member == null || !member.isDeferredLoaderGetter)) {
      result = handleDeferredAccess(node, prefix, result);
    }
    return result;
  }

  /// Handle qualified [SendSet] where the receiver resolves to a [prefix],
  /// like `prefix.toplevelField = b` or `prefix.Class.staticField++` where
  /// `prefix` is a library prefix.
  ResolutionResult handleLibraryPrefixSendSet(
      SendSet node, Name name, PrefixElement prefix) {
    ResolutionResult result;
    Element member = prefix.lookupLocalMember(name.text);
    if (member == null) {
      registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
      Element error = reportAndCreateErroneousElement(
          node, name.text, MessageKind.NO_SUCH_LIBRARY_MEMBER,
          {'libraryName': prefix.name, 'memberName': name});
      return handleUpdate(node, name, new StaticAccess.unresolved(error));
    } else {
      result = handleResolvedSendSet(node, name, member);
    }
    if (result.kind == ResultKind.PREFIX) {
      // [member] is a class prefix of a static access like `prefix.Class` of
      // `prefix.Class.foo`. No need to call [handleDeferredAccess]; it will
      // called on the parent `prefix.Class.foo` node.
      result = new PrefixResult(prefix, result.element);
    } else if (prefix.isDeferred &&
               (member == null || !member.isDeferredLoaderGetter)) {
      result = handleDeferredAccess(node, prefix, result);
    }
    return result;
  }

  /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in
  /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time
  /// error.
  ResolutionResult handleLibraryPrefix(
      Send node,
      Name name,
      PrefixElement prefix) {
    if ((ElementCategory.PREFIX & allowedCategory) == 0) {
      ErroneousElement error = reportAndCreateErroneousElement(
          node,
          name.text,
          MessageKind.PREFIX_AS_EXPRESSION,
          {'prefix': name},
          isError: true);
      registry.registerFeature(Feature.COMPILE_TIME_ERROR);
      return handleErroneousAccess(
          node, name, new StaticAccess.invalid(error));
    }
    if (prefix.isDeferred) {
      // TODO(23998): Remove this when deferred access is detected
      // through a [SendStructure].
      registry.useElement(node.selector, prefix);
    }
    registry.useElement(node, prefix);
    return new PrefixResult(prefix, null);
  }

  /// Handle qualified [Send] where the receiver resolves to an [Element], like
  /// `a.b` where `a` is a prefix or a class.
  ResolutionResult handlePrefixSend(
      Send node, Name name, PrefixResult prefixResult) {
    Element element = prefixResult.element;
    if (element.isPrefix) {
      if (node.isConditional) {
        return handleLibraryPrefix(node, name, element);
      } else {
        return handleLibraryPrefixSend(node, name, element);
      }
    } else {
      assert(element.isClass);
      ResolutionResult result = handleStaticMemberAccess(node, name, element);
      if (prefixResult.isDeferred) {
        result = handleDeferredAccess(node, prefixResult.prefix, result);
      }
      return result;
    }
  }

  /// Handle qualified [SendSet] where the receiver resolves to an [Element],
  /// like `a.b = c` where `a` is a prefix or a class.
  ResolutionResult handlePrefixSendSet(
      SendSet node, Name name, PrefixResult prefixResult) {
    Element element = prefixResult.element;
    if (element.isPrefix) {
      if (node.isConditional) {
        return handleLibraryPrefix(node, name, element);
      } else {
        return handleLibraryPrefixSendSet(node, name, element);
      }
    } else {
      assert(element.isClass);
      ResolutionResult result = handleStaticMemberUpdate(node, name, element);
      if (prefixResult.isDeferred) {
        result = handleDeferredAccess(node, prefixResult.prefix, result);
      }
      return result;
    }
  }

  /// Handle dynamic access of [semantics].
  ResolutionResult handleDynamicAccessSemantics(
      Send node, Name name, AccessSemantics semantics) {
    SendStructure sendStructure;
    Selector selector;
    if (node.isCall) {
      CallStructure callStructure =
          resolveArguments(node.argumentsNode).callStructure;
      selector = new Selector.call(name, callStructure);
      registry.registerDynamicUse(
          new DynamicUse(selector, null));
      sendStructure = new InvokeStructure(semantics, selector);
    } else {
      assert(invariant(node, node.isPropertyAccess));
      selector = new Selector.getter(name);
      registry.registerDynamicUse(
          new DynamicUse(selector, null));
      sendStructure = new GetStructure(semantics);
    }
    registry.registerSendStructure(node, sendStructure);
    // TODO(23998): Remove this when all information goes through
    // the [SendStructure].
    registry.setSelector(node, selector);
    return const NoneResult();
  }

  /// Handle dynamic update of [semantics].
  ResolutionResult handleDynamicUpdateSemantics(
      SendSet node, Name name, Element element, AccessSemantics semantics) {
    Selector getterSelector = new Selector.getter(name);
    Selector setterSelector = new Selector.setter(name.setter);
    registry.registerDynamicUse(
        new DynamicUse(setterSelector, null));
    if (node.isComplex) {
      registry.registerDynamicUse(
          new DynamicUse(getterSelector, null));
    }

    // TODO(23998): Remove these when elements are only accessed through the
    // send structure.
    Element getter = element;
    Element setter = element;
    if (element != null && element.isAbstractField) {
      AbstractFieldElement abstractField = element;
      getter = abstractField.getter;
      setter = abstractField.setter;
    }
    if (setter != null) {
      registry.useElement(node, setter);
      if (getter != null && node.isComplex) {
        registry.useElement(node.selector, getter);
      }
    }

    return handleUpdate(node, name, semantics);
  }

  /// Handle `this` as a qualified property, like `a.this`.
  ResolutionResult handleQualifiedThisAccess(Send node, Name name) {
    ErroneousElement error = reportAndCreateErroneousElement(
        node.selector,
        name.text,
        MessageKind.THIS_PROPERTY, {},
        isError: true);
    registry.registerFeature(Feature.COMPILE_TIME_ERROR);
    AccessSemantics accessSemantics = new StaticAccess.invalid(error);
    return handleErroneousAccess(node, name, accessSemantics);
  }

  /// Handle a qualified [Send], that is where the receiver is non-null, like
  /// `a.b`, `a.b()`, `this.a()` and `super.a()`.
  ResolutionResult handleQualifiedSend(Send node) {
    Identifier selector = node.selector.asIdentifier();
    String text = selector.source;
    Name name = new Name(text, enclosingElement.library);
    if (text == 'this') {
      return handleQualifiedThisAccess(node, name);
    } else if (node.isSuperCall) {
      return handleSuperPropertyAccess(node, name);
    } else if (node.receiver.isThis()) {
      AccessSemantics semantics = checkThisAccess(node);
      if (semantics == null) {
        return handleThisPropertyAccess(node, name);
      } else {
        // TODO(johnniwinther): Handle invalid this access as an
        // [AccessSemantics].
        return handleErroneousAccess(node, name, semantics);
      }
    }
    ResolutionResult result = visitExpressionPrefix(node.receiver);
    if (result.kind == ResultKind.PREFIX) {
      return handlePrefixSend(node, name, result);
    } else if (node.isConditional) {
      return handleDynamicAccessSemantics(
          node, name, new DynamicAccess.ifNotNullProperty(name));
    } else {
      // Handle dynamic property access, like `a.b` or `a.b()` where `a` is not
      // a prefix or class.
      // TODO(johnniwinther): Use the `element` of [result].
      return handleDynamicAccessSemantics(
          node, name, new DynamicAccess.dynamicProperty(name));
    }
  }

  /// Handle a qualified [SendSet], that is where the receiver is non-null, like
  /// `a.b = c`, `a.b++`, and `a.b += c`.
  ResolutionResult handleQualifiedSendSet(SendSet node) {
    Identifier selector = node.selector.asIdentifier();
    String text = selector.source;
    Name name = new Name(text, enclosingElement.library);
    if (text == 'this') {
      return handleQualifiedThisAccess(node, name);
    } else if (node.receiver.isThis()) {
      AccessSemantics semantics = checkThisAccess(node);
      if (semantics == null) {
        return handleThisPropertyUpdate(node, name, null);
      } else {
        // TODO(johnniwinther): Handle invalid this access as an
        // [AccessSemantics].
        return handleUpdate(node, name, semantics);
      }
    }
    ResolutionResult result = visitExpressionPrefix(node.receiver);
    if (result.kind == ResultKind.PREFIX) {
      return handlePrefixSendSet(node, name, result);
    } else if (node.isConditional) {
      return handleDynamicUpdateSemantics(
          node, name, null, new DynamicAccess.ifNotNullProperty(name));
    } else {
      // Handle dynamic property access, like `a.b = c`, `a.b++` or `a.b += c`
      // where `a` is not a prefix or class.
      // TODO(johnniwinther): Use the `element` of [result].
      return handleDynamicUpdateSemantics(
          node, name, null, new DynamicAccess.dynamicProperty(name));
    }
  }

  /// Handle access unresolved access to [name] in a non-instance context.
  ResolutionResult handleUnresolvedAccess(
        Send node, Name name, Element element) {
    // TODO(johnniwinther): Support unresolved top level access as an
    // [AccessSemantics].
    AccessSemantics semantics = new StaticAccess.unresolved(element);
    return handleErroneousAccess(node, name, semantics);
  }

  /// Handle erroneous access of [element] of the given [semantics].
  ResolutionResult handleErroneousAccess(
      Send node, Name name, AccessSemantics semantics) {
    SendStructure sendStructure;
    Selector selector;
    if (node.isCall) {
      CallStructure callStructure =
          resolveArguments(node.argumentsNode).callStructure;
      selector = new Selector.call(name, callStructure);
      registry.registerDynamicUse(new DynamicUse(selector, null));
      sendStructure = new InvokeStructure(semantics, selector);
    } else {
      assert(invariant(node, node.isPropertyAccess));
      selector = new Selector.getter(name);
      registry.registerDynamicUse(new DynamicUse(selector, null));
      sendStructure = new GetStructure(semantics);
    }
    // TODO(23998): Remove this when all information goes through
    // the [SendStructure].
    registry.setSelector(node, selector);
    registry.useElement(node, semantics.element);
    registry.registerSendStructure(node, sendStructure);
    return const NoneResult();
  }

  /// Handle access to an ambiguous element, that is, a name imported twice.
  ResolutionResult handleAmbiguousSend(
      Send node,
      Name name,
      AmbiguousElement element) {

    ErroneousElement error = reportAndCreateErroneousElement(
        node,
        name.text,
        element.messageKind,
        element.messageArguments,
        infos: element.computeInfos(enclosingElement, reporter));
    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);

    // TODO(johnniwinther): Support ambiguous access as an [AccessSemantics].
    AccessSemantics semantics = new StaticAccess.unresolved(error);
    return handleErroneousAccess(node, name, semantics);
  }

  /// Handle update to an ambiguous element, that is, a name imported twice.
  ResolutionResult handleAmbiguousUpdate(
      SendSet node,
      Name name,
      AmbiguousElement element) {

    ErroneousElement error = reportAndCreateErroneousElement(
        node,
        name.text,
        element.messageKind,
        element.messageArguments,
        infos: element.computeInfos(enclosingElement, reporter));
    registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);

    // TODO(johnniwinther): Support ambiguous access as an [AccessSemantics].
    AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
    return handleUpdate(node, name, accessSemantics);
  }

  /// Report access of an instance [member] from a non-instance context.
  AccessSemantics reportStaticInstanceAccess(Send node, Name name) {
    ErroneousElement error = reportAndCreateErroneousElement(
        node, name.text,
        MessageKind.NO_INSTANCE_AVAILABLE, {'name': name},
        isError: true);
    // TODO(johnniwinther): Support static instance access as an
    // [AccessSemantics].
    registry.registerFeature(Feature.COMPILE_TIME_ERROR);
    return new StaticAccess.invalid(error);
  }

  /// Handle access of a parameter, local variable or local function.
  ResolutionResult handleLocalAccess(Send node, Name name, Element element) {
    ResolutionResult result = const NoneResult();
    AccessSemantics semantics = computeLocalAccessSemantics(node, element);
    Selector selector;
    if (node.isCall) {
      CallStructure callStructure =
          resolveArguments(node.argumentsNode).callStructure;
      selector = new Selector.call(name, callStructure);
      bool isIncompatibleInvoke = false;
      switch (semantics.kind) {
        case AccessKind.LOCAL_FUNCTION:
          LocalFunctionElementX function = semantics.element;
          function.computeType(resolution);
          if (!callStructure.signatureApplies(function.functionSignature)) {
            registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
            registry.registerDynamicUse(
                new DynamicUse(selector, null));
            isIncompatibleInvoke = true;
          }
          break;
        case AccessKind.PARAMETER:
        case AccessKind.FINAL_PARAMETER:
        case AccessKind.LOCAL_VARIABLE:
        case AccessKind.FINAL_LOCAL_VARIABLE:
          selector = callStructure.callSelector;
          registry.registerDynamicUse(
              new DynamicUse(selector, null));
          break;
        default:
          reporter.internalError(node,
              "Unexpected local access $semantics.");
          break;
      }
      registry.registerSendStructure(node,
          isIncompatibleInvoke
              ? new IncompatibleInvokeStructure(semantics, selector)
              : new InvokeStructure(semantics, selector));
    } else {
      switch (semantics.kind) {
        case AccessKind.LOCAL_VARIABLE:
        case AccessKind.LOCAL_FUNCTION:
          result = new ElementResult(element);
          break;
        case AccessKind.PARAMETER:
        case AccessKind.FINAL_PARAMETER:
          if (constantState == ConstantState.CONSTANT_INITIALIZER) {
            ParameterElement parameter = element;
            if (parameter.isNamed) {
              result = new ConstantResult(
                  node,
                  new NamedArgumentReference(parameter.name),
                  element: element);
            } else {
              result = new ConstantResult(
                  node,
                  new PositionalArgumentReference(
                      parameter.functionDeclaration.parameters.indexOf(
                          parameter)),
                  element: element);
            }
          } else {
            result = new ElementResult(element);
          }
          break;
        case AccessKind.FINAL_LOCAL_VARIABLE:
          if (element.isConst) {
            result = new ConstantResult(
                node,
                new VariableConstantExpression(element),
                element: element);
          } else {
            result = new ElementResult(element);
          }
          break;
        default:
          reporter.internalError(node,
              "Unexpected local access $semantics.");
          break;
      }
      selector = new Selector.getter(name);
      registry.registerSendStructure(node, new GetStructure(semantics));
    }

    // TODO(23998): Remove these when all information goes through
    // the [SendStructure].
    registry.useElement(node, element);
    registry.setSelector(node, selector);

    registerPotentialAccessInClosure(node, element);

    return result;
  }

  /// Handle update of a parameter, local variable or local function.
  ResolutionResult handleLocalUpdate(Send node, Name name, Element element) {
    AccessSemantics semantics;
    ErroneousElement error;
    if (element.isParameter) {
      if (element.isFinal) {
        error = reportAndCreateErroneousElement(
            node.selector, name.text,
            MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER,
            {'name': name});
        semantics = new StaticAccess.finalParameter(element);
      } else {
        semantics = new StaticAccess.parameter(element);
      }
    } else if (element.isVariable) {
      if (element.isFinal || element.isConst) {
        error = reportAndCreateErroneousElement(
            node.selector, name.text,
            MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER,
            {'name': name});
        semantics = new StaticAccess.finalLocalVariable(element);
      } else {
        semantics = new StaticAccess.localVariable(element);
      }
    } else {
      assert(invariant(node, element.isFunction,
          message: "Unexpected local $element."));
      error = reportAndCreateErroneousElement(
          node.selector, name.text,
          MessageKind.ASSIGNING_METHOD, const {});
      semantics = new StaticAccess.localFunction(element);
    }
    if (isPotentiallyMutableTarget(element)) {
      registry.registerPotentialMutation(element, node);
      if (enclosingElement != element.enclosingElement) {
        registry.registerPotentialMutationInClosure(element, node);
      }
      for (Node scope in promotionScope) {
        registry.registerPotentialMutationIn(scope, element, node);
      }
    }

    ResolutionResult result = handleUpdate(node, name, semantics);
    if (error != null) {
      registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
      // TODO(23998): Remove this when all information goes through
      // the [SendStructure].
      registry.useElement(node, error);
    }
    return result;
  }

  /// Handle access of a static or top level [element].
  ResolutionResult handleStaticOrTopLevelAccess(
        Send node, Name name, Element element) {
    ResolutionResult result = const NoneResult();
    MemberElement member;
    if (element.isAbstractField) {
      AbstractFieldElement abstractField = element;
      if (abstractField.getter != null) {
        member = abstractField.getter;
      } else {
        member = abstractField.setter;
      }
    } else {
      member = element;
    }
    // TODO(johnniwinther): Needed to provoke a parsing and with it discovery
    // of parse errors to make [element] erroneous. Fix this!
    member.computeType(resolution);


    if (member == compiler.mirrorSystemGetNameFunction &&
        !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
      reporter.reportHintMessage(
          node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
          {'class': compiler.mirrorSystemClass.name,
           'name': compiler.mirrorSystemGetNameFunction.name});
    }

    Selector selector;
    AccessSemantics semantics =
        computeStaticOrTopLevelAccessSemantics(node, member);
    if (node.isCall) {
      ArgumentsResult argumentsResult =
          resolveArguments(node.argumentsNode);
      CallStructure callStructure = argumentsResult.callStructure;
      selector = new Selector.call(name, callStructure);

      bool isIncompatibleInvoke = false;
      switch (semantics.kind) {
        case AccessKind.STATIC_METHOD:
        case AccessKind.TOPLEVEL_METHOD:
          MethodElement method = semantics.element;
          method.computeType(resolution);
          if (!callStructure.signatureApplies(method.functionSignature)) {
            registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
            registry.registerDynamicUse(
                new DynamicUse(selector, null));
            isIncompatibleInvoke = true;
          } else {
            registry.registerStaticUse(
                new StaticUse.staticInvoke(semantics.element, callStructure));
            handleForeignCall(node, semantics.element, callStructure);
            if (method == compiler.identicalFunction &&
                argumentsResult.isValidAsConstant) {
              result = new ConstantResult(node,
                  new IdenticalConstantExpression(
                      argumentsResult.argumentResults[0].constant,
                      argumentsResult.argumentResults[1].constant));
            }
          }
          break;
        case AccessKind.STATIC_FIELD:
        case AccessKind.FINAL_STATIC_FIELD:
        case AccessKind.STATIC_GETTER:
        case AccessKind.TOPLEVEL_FIELD:
        case AccessKind.FINAL_TOPLEVEL_FIELD:
        case AccessKind.TOPLEVEL_GETTER:
          registry.registerStaticUse(
              new StaticUse.staticGet(semantics.element));
          selector = callStructure.callSelector;
          registry.registerDynamicUse(
              new DynamicUse(selector, null));
          break;
        case AccessKind.STATIC_SETTER:
        case AccessKind.TOPLEVEL_SETTER:
        case AccessKind.UNRESOLVED:
          registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
          member = reportAndCreateErroneousElement(
              node.selector, name.text,
              MessageKind.UNDEFINED_STATIC_GETTER_BUT_SETTER,
              {'name': name});
          break;
        default:
          reporter.internalError(node,
              "Unexpected statically resolved access $semantics.");
          break;
      }
      registry.registerSendStructure(node,
          isIncompatibleInvoke
              ? new IncompatibleInvokeStructure(semantics, selector)
              : new InvokeStructure(semantics, selector));
    } else {
      selector = new Selector.getter(name);
      switch (semantics.kind) {
        case AccessKind.STATIC_METHOD:
        case AccessKind.TOPLEVEL_METHOD:
          registry.registerStaticUse(
              new StaticUse.staticTearOff(semantics.element));
          break;
        case AccessKind.STATIC_FIELD:
        case AccessKind.FINAL_STATIC_FIELD:
        case AccessKind.STATIC_GETTER:
        case AccessKind.TOPLEVEL_FIELD:
        case AccessKind.FINAL_TOPLEVEL_FIELD:
        case AccessKind.TOPLEVEL_GETTER:
          registry.registerStaticUse(
              new StaticUse.staticGet(semantics.element));
          break;
        case AccessKind.STATIC_SETTER:
        case AccessKind.TOPLEVEL_SETTER:
        case AccessKind.UNRESOLVED:
          registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
          member = reportAndCreateErroneousElement(
              node.selector, name.text,
              MessageKind.UNDEFINED_STATIC_GETTER_BUT_SETTER,
              {'name': name});
          break;
        default:
          reporter.internalError(node,
              "Unexpected statically resolved access $semantics.");
          break;
      }
      registry.registerSendStructure(node, new GetStructure(semantics));
      if (member.isConst) {
        FieldElement field = member;
        result = new ConstantResult(
            node, new VariableConstantExpression(field), element: field);
      } else {
        result = new ElementResult(member);
      }
    }

    // TODO(23998): Remove these when all information goes through
    // the [SendStructure].
    registry.useElement(node, member);
    registry.setSelector(node, selector);

    return result;
  }

  /// Handle update of a static or top level [element].
  ResolutionResult handleStaticOrTopLevelUpdate(
        SendSet node, Name name, Element element) {
    AccessSemantics semantics;
    if (element.isAbstractField) {
      AbstractFieldElement abstractField = element;
      if (abstractField.setter == null) {
        ErroneousElement error = reportAndCreateErroneousElement(
            node.selector, name.text,
            MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER,
            {'name': name});
        registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);

        if (node.isComplex) {
          // `a++` or `a += b` where `a` has no setter.
          semantics = new CompoundAccessSemantics(
              element.isTopLevel
                  ? CompoundAccessKind.UNRESOLVED_TOPLEVEL_SETTER
                  : CompoundAccessKind.UNRESOLVED_STATIC_SETTER,
              abstractField.getter,
              error);
        } else {
          // `a = b` where `a` has no setter.
          semantics = element.isTopLevel
              ? new StaticAccess.topLevelGetter(abstractField.getter)
              : new StaticAccess.staticGetter(abstractField.getter);
        }
        registry.registerStaticUse(
            new StaticUse.staticGet(abstractField.getter));
      } else if (node.isComplex) {
        if (abstractField.getter == null) {
          ErroneousElement error = reportAndCreateErroneousElement(
              node.selector, name.text,
              MessageKind.UNDEFINED_STATIC_GETTER_BUT_SETTER,
              {'name': name});
          registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
          // `a++` or `a += b` where `a` has no getter.
          semantics = new CompoundAccessSemantics(
              element.isTopLevel
                  ? CompoundAccessKind.UNRESOLVED_TOPLEVEL_GETTER
                  : CompoundAccessKind.UNRESOLVED_STATIC_GETTER,
              error,
              abstractField.setter);
          registry.registerStaticUse(
              new StaticUse.staticSet(abstractField.setter));
        } else {
          // `a++` or `a += b` where `a` has both a getter and a setter.
          semantics = new CompoundAccessSemantics(
              element.isTopLevel
                  ? CompoundAccessKind.TOPLEVEL_GETTER_SETTER
                  : CompoundAccessKind.STATIC_GETTER_SETTER,
              abstractField.getter,
              abstractField.setter);
          registry.registerStaticUse(
              new StaticUse.staticGet(abstractField.getter));
          registry.registerStaticUse(
              new StaticUse.staticSet(abstractField.setter));
        }
      } else {
        // `a = b` where `a` has a setter.
        semantics = element.isTopLevel
            ? new StaticAccess.topLevelSetter(abstractField.setter)
            : new StaticAccess.staticSetter(abstractField.setter);
        registry.registerStaticUse(
            new StaticUse.staticSet(abstractField.setter));
      }
    } else {
      MemberElement member = element;
      // TODO(johnniwinther): Needed to provoke a parsing and with it discovery
      // of parse errors to make [element] erroneous. Fix this!
      member.computeType(resolution);
      if (member.isMalformed) {
        // [member] has parse errors.
        semantics = new StaticAccess.unresolved(member);
      } else if (member.isFunction) {
        // `a = b`, `a++` or `a += b` where `a` is a function.
        ErroneousElement error = reportAndCreateErroneousElement(
            node.selector, name.text,
            MessageKind.ASSIGNING_METHOD, const {});
        registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
        if (node.isComplex) {
          // `a++` or `a += b` where `a` is a function.
          registry.registerStaticUse(
              new StaticUse.staticTearOff(element));
        }
        semantics = member.isTopLevel
            ? new StaticAccess.topLevelMethod(member)
            : new StaticAccess.staticMethod(member);
      } else {
        // `a = b`, `a++` or `a += b` where `a` is a field.
        assert(invariant(node, member.isField,
            message: "Unexpected element: $member."));
        if (node.isComplex) {
          // `a++` or `a += b` where `a` is a field.
          registry.registerStaticUse(new StaticUse.staticGet(member));
        }
        if (member.isFinal || member.isConst) {
          ErroneousElement error = reportAndCreateErroneousElement(
               node.selector, name.text,
               MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER,
               {'name': name});
          registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
          semantics = member.isTopLevel
              ? new StaticAccess.finalTopLevelField(member)
              : new StaticAccess.finalStaticField(member);
        } else {
          registry.registerStaticUse(new StaticUse.staticSet(member));
          semantics = member.isTopLevel
              ? new StaticAccess.topLevelField(member)
              : new StaticAccess.staticField(member);
        }
      }
    }
    return handleUpdate(node, name, semantics);
  }

  /// Handle access to resolved [element].
  ResolutionResult handleResolvedSend(Send node, Name name, Element element) {
    if (element.isAmbiguous) {
      return handleAmbiguousSend(node, name, element);
    }
    if (element.isMalformed) {
      // This handles elements with parser errors.
      assert(invariant(node, element is! ErroneousElement,
          message: "Unexpected erroneous element $element."));
      return handleErroneousAccess(node, name,
          new StaticAccess.unresolved(element));
    }
    if (element.isInstanceMember) {
      if (inInstanceContext) {
        // TODO(johnniwinther): Maybe use the found [element].
        return handleThisPropertyAccess(node, name);
      } else {
        return handleErroneousAccess(
            node, name, reportStaticInstanceAccess(node, name));
      }
    }
    if (element.isClass) {
      // `C`, `C()`, or 'C.b` where 'C' is a class.
      return handleClassSend(node, name, element);
    } else if (element.isTypedef) {
      // `F` or `F()` where 'F' is a typedef.
      return handleTypedefTypeLiteralAccess(node, name, element);
    } else if (element.isTypeVariable) {
      return handleTypeVariableTypeLiteralAccess(node, name, element);
    } else if (element.isPrefix) {
      return handleLibraryPrefix(node, name, element);
    } else if (element.isLocal) {
      return handleLocalAccess(node, name, element);
    } else if (element.isStatic || element.isTopLevel) {
      return handleStaticOrTopLevelAccess(node, name, element);
    }
    return reporter.internalError(node, "Unexpected resolved send: $element");
  }

  /// Handle update to resolved [element].
  ResolutionResult handleResolvedSendSet(
      SendSet node, Name name, Element element) {
    if (element.isAmbiguous) {
      return handleAmbiguousUpdate(node, name, element);
    }
    if (element.isMalformed) {
      // This handles elements with parser errors..
      assert(invariant(node, element is! ErroneousElement,
          message: "Unexpected erroneous element $element."));
      return handleUpdate(node, name,new StaticAccess.unresolved(element));
    }
    if (element.isInstanceMember) {
      if (inInstanceContext) {
        return handleThisPropertyUpdate(node, name, element);
      } else {
        return handleUpdate(node, name, reportStaticInstanceAccess(node, name));
      }
    }
    if (element.isClass) {
      // `C = b`, `C++`, or 'C += b` where 'C' is a class.
      return handleClassTypeLiteralUpdate(node, name, element);
    } else if (element.isTypedef) {
      // `C = b`, `C++`, or 'C += b` where 'F' is a typedef.
      return handleTypedefTypeLiteralUpdate(node, name, element);
    } else if (element.isTypeVariable) {
      // `T = b`, `T++`, or 'T += b` where 'T' is a type variable.
      return handleTypeVariableTypeLiteralUpdate(node, name, element);
    } else if (element.isPrefix) {
      // `p = b` where `p` is a prefix.
      ErroneousElement error = reportAndCreateErroneousElement(
           node,
           name.text,
           MessageKind.PREFIX_AS_EXPRESSION,
           {'prefix': name},
           isError: true);
      registry.registerFeature(Feature.COMPILE_TIME_ERROR);
      return handleUpdate(
          node, name, new StaticAccess.invalid(error));
    } else if (element.isLocal) {
      return handleLocalUpdate(node, name, element);
    } else if (element.isStatic || element.isTopLevel) {
      return handleStaticOrTopLevelUpdate(node, name, element);
    }
    return reporter.internalError(node, "Unexpected resolved send: $element");
  }

  /// Handle an unqualified [Send], that is where the `node.receiver` is null,
  /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`.
  ResolutionResult handleUnqualifiedSend(Send node) {
    Identifier selector = node.selector.asIdentifier();
    if (selector == null) {
      // `(){}()` and `(foo)()`.
      return handleExpressionInvoke(node);
    }
    String text = selector.source;
    if (text == 'this') {
      // `this()`.
      return handleThisAccess(node);
    }
    // `name` or `name()`
    Name name = new Name(text, enclosingElement.library);
    Element element = lookupInScope(reporter, node, scope, text);
    if (element == null) {
      if (text == 'dynamic') {
        // `dynamic` or `dynamic()` where 'dynamic' is not declared in the
        // current scope.
        return handleDynamicTypeLiteralAccess(node);
      } else if (inInstanceContext) {
        // Implicitly `this.name`.
        return handleThisPropertyAccess(node, name);
      } else {
        // Create [ErroneousElement] for unresolved access.
        ErroneousElement error = reportCannotResolve(node, text);
        return handleUnresolvedAccess(node, name, error);
      }
    } else {
      return handleResolvedSend(node, name, element);
    }
  }

  /// Handle an unqualified [SendSet], that is where the `node.receiver` is
  /// null, like `a = b`, `a++`, and `a += b`.
  ResolutionResult handleUnqualifiedSendSet(SendSet node) {
    Identifier selector = node.selector.asIdentifier();
    String text = selector.source;
    Name name = new Name(text, enclosingElement.library);
    Element element = lookupInScope(reporter, node, scope, text);
    if (element == null) {
      if (text == 'dynamic') {
        // `dynamic = b`, `dynamic++`, or `dynamic += b` where 'dynamic' is not
        // declared in the current scope.
        return handleDynamicTypeLiteralUpdate(node);
      } else if (inInstanceContext) {
        // Left-hand side is implicitly `this.name`.
        return handleThisPropertyUpdate(node, name, null);
      } else {
        // Create [ErroneousElement] for unresolved access.
        ErroneousElement error = reportCannotResolve(node, text);
        return handleUpdate(node, name, new StaticAccess.unresolved(error));
      }
    } else {
      return handleResolvedSendSet(node, name, element);
    }
  }

  ResolutionResult visitSend(Send node) {
    if (node.isOperator) {
      // `a && b`, `a + b`, `-a`, or `a is T`.
      return handleOperatorSend(node);
    } else if (node.receiver != null) {
      // `a.b`.
      return handleQualifiedSend(node);
    } else {
      // `a`.
      return handleUnqualifiedSend(node);
    }
  }

  /// Register read access of [target] inside a closure.
  void registerPotentialAccessInClosure(Send node, Element target) {
    if (isPotentiallyMutableTarget(target)) {
      if (enclosingElement != target.enclosingElement) {
        for (Node scope in promotionScope) {
          registry.setAccessedByClosureIn(scope, target, node);
        }
      }
    }
  }

  // TODO(johnniwinther): Move this to the backend resolution callbacks.
  void handleForeignCall(Send node,
                         Element target,
                         CallStructure callStructure) {
    if (target != null && compiler.backend.isForeign(target)) {
      registry.registerForeignCall(node, target, callStructure, this);
    }
  }

  /// Callback for native enqueuer to parse a type.  Returns [:null:] on error.
  DartType resolveTypeFromString(Node node, String typeName) {
    Element element = lookupInScope(reporter, node, scope, typeName);
    if (element == null) return null;
    if (element is! ClassElement) return null;
    ClassElement cls = element;
    cls.ensureResolved(resolution);
    return cls.computeType(resolution);
  }

  /// Handle index operations like `a[b] = c`, `a[b] += c`, and `a[b]++`.
  ResolutionResult handleIndexSendSet(SendSet node) {
    String operatorText = node.assignmentOperator.source;
    Node receiver = node.receiver;
    Node index = node.arguments.head;
    visitExpression(receiver);
    visitExpression(index);
    AccessSemantics semantics = const DynamicAccess.expression();
    if (node.isPrefix || node.isPostfix) {
      // `a[b]++` or `++a[b]`.
      IncDecOperator operator = IncDecOperator.parse(operatorText);
      Selector getterSelector = new Selector.index();
      Selector setterSelector = new Selector.indexSet();
      Selector operatorSelector =
          new Selector.binaryOperator(operator.selectorName);

      // TODO(23998): Remove these when selectors are only accessed
      // through the send structure.
      registry.setGetterSelectorInComplexSendSet(node, getterSelector);
      registry.setSelector(node, setterSelector);
      registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);

      registry.registerDynamicUse(
          new DynamicUse(getterSelector, null));
      registry.registerDynamicUse(
          new DynamicUse(setterSelector, null));
      registry.registerDynamicUse(
          new DynamicUse(operatorSelector, null));

      SendStructure sendStructure = node.isPrefix
          ? new IndexPrefixStructure(semantics, operator)
          : new IndexPostfixStructure(semantics, operator);
      registry.registerSendStructure(node, sendStructure);
      return const NoneResult();
    } else {
      Node rhs = node.arguments.tail.head;
      visitExpression(rhs);

      AssignmentOperator operator = AssignmentOperator.parse(operatorText);
      if (operator.kind == AssignmentOperatorKind.ASSIGN) {
        // `a[b] = c`.
        Selector setterSelector = new Selector.indexSet();

        // TODO(23998): Remove this when selectors are only accessed
        // through the send structure.
        registry.setSelector(node, setterSelector);
        registry.registerDynamicUse(
            new DynamicUse(setterSelector, null));

        SendStructure sendStructure = new IndexSetStructure(semantics);
        registry.registerSendStructure(node, sendStructure);
        return const NoneResult();
      } else {
        // `a[b] += c`.
        Selector getterSelector = new Selector.index();
        Selector setterSelector = new Selector.indexSet();
        Selector operatorSelector =
            new Selector.binaryOperator(operator.selectorName);

        // TODO(23998): Remove these when selectors are only accessed
        // through the send structure.
        registry.setGetterSelectorInComplexSendSet(node, getterSelector);
        registry.setSelector(node, setterSelector);
        registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);

        registry.registerDynamicUse(
            new DynamicUse(getterSelector, null));
        registry.registerDynamicUse(
            new DynamicUse(setterSelector, null));
        registry.registerDynamicUse(
            new DynamicUse(operatorSelector, null));

        SendStructure sendStructure;
        if (operator.kind == AssignmentOperatorKind.IF_NULL) {
          sendStructure = new IndexSetIfNullStructure(semantics);
        } else {
          sendStructure = new CompoundIndexSetStructure(semantics, operator);
        }
        registry.registerSendStructure(node, sendStructure);
        return const NoneResult();
      }
    }
  }

  /// Handle super index operations like `super[a] = b`, `super[a] += b`, and
  /// `super[a]++`.
  // TODO(johnniwinther): Share code with [handleIndexSendSet].
  ResolutionResult handleSuperIndexSendSet(SendSet node) {
    String operatorText = node.assignmentOperator.source;
    Node index = node.arguments.head;
    visitExpression(index);

    AccessSemantics semantics = checkSuperAccess(node);
    if (node.isPrefix || node.isPostfix) {
      // `super[a]++` or `++super[a]`.
      IncDecOperator operator = IncDecOperator.parse(operatorText);
      Selector getterSelector = new Selector.index();
      Selector setterSelector = new Selector.indexSet();
      Selector operatorSelector =
          new Selector.binaryOperator(operator.selectorName);

      // TODO(23998): Remove these when selectors are only accessed
      // through the send structure.
      registry.setGetterSelectorInComplexSendSet(node, getterSelector);
      registry.setSelector(node, setterSelector);
      registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);

      if (semantics == null) {
        semantics = computeSuperAccessSemanticsForSelectors(
            node, getterSelector, setterSelector, isIndex: true);

        if (!semantics.getter.isError) {
          registry.registerStaticUse(
              new StaticUse.superInvoke(
                  semantics.getter, getterSelector.callStructure));
        }
        if (!semantics.setter.isError) {
          registry.registerStaticUse(
              new StaticUse.superInvoke(
                  semantics.setter, setterSelector.callStructure));
        }

        // TODO(23998): Remove these when elements are only accessed
        // through the send structure.
        registry.useElement(node, semantics.setter);
        registry.useElement(node.selector, semantics.getter);
      }
      registry.registerDynamicUse(
          new DynamicUse(operatorSelector, null));

      SendStructure sendStructure = node.isPrefix
          ? new IndexPrefixStructure(semantics, operator)
          : new IndexPostfixStructure(semantics, operator);
      registry.registerSendStructure(node, sendStructure);
      return const NoneResult();
    } else {
      Node rhs = node.arguments.tail.head;
      visitExpression(rhs);

      AssignmentOperator operator = AssignmentOperator.parse(operatorText);
      if (operator.kind == AssignmentOperatorKind.ASSIGN) {
        // `super[a] = b`.
        Selector setterSelector = new Selector.indexSet();
        if (semantics == null) {
          semantics =
              computeSuperAccessSemanticsForSelector(node, setterSelector);

          // TODO(23998): Remove these when elements are only accessed
          // through the send structure.
          registry.useElement(node, semantics.setter);
        }

        // TODO(23998): Remove this when selectors are only accessed
        // through the send structure.
        registry.setSelector(node, setterSelector);
        if (!semantics.setter.isError) {
          registry.registerStaticUse(
              new StaticUse.superInvoke(
                  semantics.setter, setterSelector.callStructure));
        }

        SendStructure sendStructure = new IndexSetStructure(semantics);
        registry.registerSendStructure(node, sendStructure);
        return const NoneResult();
      } else {
        // `super[a] += b`.
        Selector getterSelector = new Selector.index();
        Selector setterSelector = new Selector.indexSet();
        Selector operatorSelector =
            new Selector.binaryOperator(operator.selectorName);
        if (semantics == null) {
          semantics = computeSuperAccessSemanticsForSelectors(
              node, getterSelector, setterSelector, isIndex: true);

          if (!semantics.getter.isError) {
            registry.registerStaticUse(
                new StaticUse.superInvoke(
                    semantics.getter, getterSelector.callStructure));
          }
          if (!semantics.setter.isError) {
            registry.registerStaticUse(
                new StaticUse.superInvoke(
                    semantics.setter, setterSelector.callStructure));
          }

          // TODO(23998): Remove these when elements are only accessed
          // through the send structure.
          registry.useElement(node, semantics.setter);
          registry.useElement(node.selector, semantics.getter);
        }

        // TODO(23998): Remove these when selectors are only accessed
        // through the send structure.
        registry.setGetterSelectorInComplexSendSet(node, getterSelector);
        registry.setSelector(node, setterSelector);
        registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);

        registry.registerDynamicUse(
            new DynamicUse(operatorSelector, null));

        SendStructure sendStructure;
        if (operator.kind == AssignmentOperatorKind.IF_NULL) {
          sendStructure = new IndexSetIfNullStructure(semantics);
        } else {
          sendStructure = new CompoundIndexSetStructure(semantics, operator);
        }
        registry.registerSendStructure(node, sendStructure);
        return const NoneResult();
      }
    }
  }

  /// Handle super index operations like `super.a = b`, `super.a += b`, and
  /// `super.a++`.
  // TODO(johnniwinther): Share code with [handleSuperIndexSendSet].
  ResolutionResult handleSuperSendSet(SendSet node) {
    Identifier selector = node.selector.asIdentifier();
    String text = selector.source;
    Name name = new Name(text, enclosingElement.library);
    String operatorText = node.assignmentOperator.source;
    Selector getterSelector = new Selector.getter(name);
    Selector setterSelector = new Selector.setter(name);

    void registerStaticUses(AccessSemantics semantics) {
      switch (semantics.kind) {
        case AccessKind.SUPER_METHOD:
          registry.registerStaticUse(
              new StaticUse.superTearOff(semantics.element));
          break;
        case AccessKind.SUPER_GETTER:
          registry.registerStaticUse(new StaticUse.superGet(semantics.getter));
          break;
        case AccessKind.SUPER_SETTER:
          registry.registerStaticUse(
              new StaticUse.superSetterSet(semantics.setter));
          break;
        case AccessKind.SUPER_FIELD:
          registry.registerStaticUse(
              new StaticUse.superGet(semantics.element));
          registry.registerStaticUse(
              new StaticUse.superFieldSet(semantics.element));
          break;
        case AccessKind.SUPER_FINAL_FIELD:
          registry.registerStaticUse(
              new StaticUse.superGet(semantics.element));
          break;
        case AccessKind.COMPOUND:
          CompoundAccessSemantics compoundSemantics = semantics;
          switch (compoundSemantics.compoundAccessKind) {
            case CompoundAccessKind.SUPER_GETTER_FIELD:
            case CompoundAccessKind.SUPER_FIELD_FIELD:
              registry.registerStaticUse(
                  new StaticUse.superGet(semantics.getter));
              registry.registerStaticUse(
                  new StaticUse.superFieldSet(semantics.setter));
              break;
            case CompoundAccessKind.SUPER_FIELD_SETTER:
            case CompoundAccessKind.SUPER_GETTER_SETTER:
              registry.registerStaticUse(
                  new StaticUse.superGet(semantics.getter));
              registry.registerStaticUse(
                  new StaticUse.superSetterSet(semantics.setter));
              break;
            case CompoundAccessKind.SUPER_METHOD_SETTER:
              registry.registerStaticUse(
                  new StaticUse.superSetterSet(semantics.setter));
              break;
            case CompoundAccessKind.UNRESOLVED_SUPER_GETTER:
              registry.registerStaticUse(
                  new StaticUse.superSetterSet(semantics.setter));
              break;
            case CompoundAccessKind.UNRESOLVED_SUPER_SETTER:
              registry.registerStaticUse(
                  new StaticUse.superGet(semantics.getter));
              break;
            default:
              break;
          }
          break;
        default:
          break;
      }
    }

    AccessSemantics semantics = checkSuperAccess(node);
    if (node.isPrefix || node.isPostfix) {
      // `super.a++` or `++super.a`.
      if (semantics == null) {
        semantics = computeSuperAccessSemanticsForSelectors(
            node, getterSelector, setterSelector);
        registerStaticUses(semantics);
      }
      return handleUpdate(node, name, semantics);
    } else {
      AssignmentOperator operator = AssignmentOperator.parse(operatorText);
      if (operator.kind == AssignmentOperatorKind.ASSIGN) {
        // `super.a = b`.
        if (semantics == null) {
          semantics =
              computeSuperAccessSemanticsForSelector(
                  node, setterSelector, alternateName: name);
          switch (semantics.kind) {
            case AccessKind.SUPER_FINAL_FIELD:
              reporter.reportWarningMessage(
                  node,
                  MessageKind.ASSIGNING_FINAL_FIELD_IN_SUPER,
                  {'name': name,
                   'superclassName': semantics.setter.enclosingClass.name});
              // TODO(johnniwinther): This shouldn't be needed.
              registry.registerDynamicUse(
                  new DynamicUse(setterSelector, null));
              registry.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
              break;
            case AccessKind.SUPER_METHOD:
              reporter.reportWarningMessage(
                  node, MessageKind.ASSIGNING_METHOD_IN_SUPER,
                  {'name': name,
                   'superclassName': semantics.setter.enclosingClass.name});
              // TODO(johnniwinther): This shouldn't be needed.
              registry.registerDynamicUse(
                  new DynamicUse(setterSelector, null));
              registry.registerFeature(Feature.SUPER_NO_SUCH_METHOD);
              break;
            case AccessKind.SUPER_FIELD:
              registry.registerStaticUse(
                  new StaticUse.superFieldSet(semantics.setter));
              break;
            case AccessKind.SUPER_SETTER:
              registry.registerStaticUse(
                  new StaticUse.superSetterSet(semantics.setter));
              break;
            default:
              break;
          }
        }
        return handleUpdate(node, name, semantics);
      } else {
        // `super.a += b`.
        if (semantics == null) {
          semantics = computeSuperAccessSemanticsForSelectors(
              node, getterSelector, setterSelector);
          registerStaticUses(semantics);
        }
        return handleUpdate(node, name, semantics);
      }
    }
  }

  /// Handle update of an entity defined by [semantics]. For instance `a = b`,
  /// `a++` or `a += b` where [semantics] describe `a`.
  ResolutionResult handleUpdate(
      SendSet node,
      Name name,
      AccessSemantics semantics) {
    SendStructure sendStructure;
    String operatorText = node.assignmentOperator.source;
    Selector getterSelector = new Selector.getter(name);
    Selector setterSelector = new Selector.setter(name);
    if (node.isPrefix || node.isPostfix) {
      // `e++` or `++e`.
      IncDecOperator operator = IncDecOperator.parse(operatorText);
      Selector operatorSelector =
          new Selector.binaryOperator(operator.selectorName);

      // TODO(23998): Remove these when selectors are only accessed
      // through the send structure.
      registry.setGetterSelectorInComplexSendSet(node, getterSelector);
      registry.setSelector(node, setterSelector);
      registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);

      // TODO(23998): Remove these when elements are only accessed
      // through the send structure.
      registry.useElement(node, semantics.setter);
      registry.useElement(node.selector, semantics.getter);

      registry.registerDynamicUse(
          new DynamicUse(operatorSelector, null));

      SendStructure sendStructure = node.isPrefix
          ? new PrefixStructure(semantics, operator)
          : new PostfixStructure(semantics, operator);
      registry.registerSendStructure(node, sendStructure);
      registry.registerFeature(Feature.INC_DEC_OPERATION);
    } else {
      Node rhs = node.arguments.head;
      visitExpression(rhs);

      AssignmentOperator operator = AssignmentOperator.parse(operatorText);
      if (operator.kind == AssignmentOperatorKind.ASSIGN) {
        // `e1 = e2`.

        // TODO(23998): Remove these when elements are only accessed
        // through the send structure.
        registry.useElement(node, semantics.setter);

        // TODO(23998): Remove this when selectors are only accessed
        // through the send structure.
        registry.setSelector(node, setterSelector);

        SendStructure sendStructure = new SetStructure(semantics);
        registry.registerSendStructure(node, sendStructure);
      } else {
        // `e1 += e2`.
        Selector operatorSelector =
            new Selector.binaryOperator(operator.selectorName);

        // TODO(23998): Remove these when elements are only accessed
        // through the send structure.
        registry.useElement(node, semantics.setter);
        registry.useElement(node.selector, semantics.getter);

        // TODO(23998): Remove these when selectors are only accessed
        // through the send structure.
        registry.setGetterSelectorInComplexSendSet(node, getterSelector);
        registry.setSelector(node, setterSelector);
        registry.setOperatorSelectorInComplexSendSet(node, operatorSelector);

        registry.registerDynamicUse(
            new DynamicUse(operatorSelector, null));

        SendStructure sendStructure;
        if (operator.kind == AssignmentOperatorKind.IF_NULL) {
          sendStructure = new SetIfNullStructure(semantics);
        } else {
          sendStructure = new CompoundStructure(semantics, operator);
        }
        registry.registerSendStructure(node, sendStructure);
      }
    }
    return new ResolutionResult.forElement(semantics.setter);
  }

  ResolutionResult visitSendSet(SendSet node) {
    if (node.isIndex) {
      // `a[b] = c`
      if (node.isSuperCall) {
        // `super[b] = c`
        return handleSuperIndexSendSet(node);
      } else {
        return handleIndexSendSet(node);
      }
    } else if (node.isSuperCall) {
      // `super.a = c`
      return handleSuperSendSet(node);
    } else if (node.receiver == null) {
      // `a = c`
      return handleUnqualifiedSendSet(node);
    } else {
      // `a.b = c`
      return handleQualifiedSendSet(node);
    }
  }

  ConstantResult visitLiteralInt(LiteralInt node) {
    ConstantExpression constant = new IntConstantExpression(node.value);
    registry.registerConstantLiteral(constant);
    registry.setConstant(node, constant);
    return new ConstantResult(node, constant);
  }

  ConstantResult visitLiteralDouble(LiteralDouble node) {
    ConstantExpression constant = new DoubleConstantExpression(node.value);
    registry.registerConstantLiteral(constant);
    registry.setConstant(node, constant);
    return new ConstantResult(node, constant);
  }

  ConstantResult visitLiteralBool(LiteralBool node) {
    ConstantExpression constant = new BoolConstantExpression(node.value);
    registry.registerConstantLiteral(constant);
    registry.setConstant(node, constant);
    return new ConstantResult(node, constant);
  }

  ResolutionResult visitLiteralString(LiteralString node) {
    if (node.dartString != null) {
      // [dartString] might be null on parser errors.
      ConstantExpression constant =
          new StringConstantExpression(node.dartString.slowToString());
      registry.registerConstantLiteral(constant);
      registry.setConstant(node, constant);
      return new ConstantResult(node, constant);
    }
    return const NoneResult();
  }

  ConstantResult visitLiteralNull(LiteralNull node) {
    ConstantExpression constant = new NullConstantExpression();
    registry.registerConstantLiteral(constant);
    registry.setConstant(node, constant);
    return new ConstantResult(node, constant);
  }

  ConstantResult visitLiteralSymbol(LiteralSymbol node) {
    String name = node.slowNameString;
    // TODO(johnniwinther): Use [registerConstantLiteral] instead.
    registry.registerConstSymbol(name);
    if (!validateSymbol(node, name, reportError: false)) {
      reporter.reportErrorMessage(
          node,
          MessageKind.UNSUPPORTED_LITERAL_SYMBOL,
          {'value': name});
    }
    analyzeConstantDeferred(node);
    ConstantExpression constant = new SymbolConstantExpression(name);
    registry.setConstant(node, constant);
    return new ConstantResult(node, constant);
  }

  ResolutionResult visitStringJuxtaposition(StringJuxtaposition node) {
    registry.registerFeature(Feature.STRING_JUXTAPOSITION);
    ResolutionResult first = visit(node.first);
    ResolutionResult second = visit(node.second);
    if (first.isConstant && second.isConstant) {
      ConstantExpression constant = new ConcatenateConstantExpression(
          <ConstantExpression>[first.constant, second.constant]);
      registry.setConstant(node, constant);
      return new ConstantResult(node, constant);
    }
    return const NoneResult();
  }

  ResolutionResult visitNodeList(NodeList node) {
    for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
      visit(link.head);
    }
    return const NoneResult();
  }

  ResolutionResult visitRethrow(Rethrow node) {
    if (!inCatchBlock && node.throwToken.stringValue == 'rethrow') {
      reporter.reportErrorMessage(
          node, MessageKind.RETHROW_OUTSIDE_CATCH);
    }
    return const NoneResult();
  }

  ResolutionResult visitReturn(Return node) {
    Node expression = node.expression;
    if (expression != null) {
      if (enclosingElement.isGenerativeConstructor) {
        // It is a compile-time error if a return statement of the form
        // `return e;` appears in a generative constructor.  (Dart Language
        // Specification 13.12.)
        reporter.reportErrorMessage(
            expression,
            MessageKind.RETURN_IN_GENERATIVE_CONSTRUCTOR);
      } else if (!node.isArrowBody && currentAsyncMarker.isYielding) {
        reporter.reportErrorMessage(
            node,
            MessageKind.RETURN_IN_GENERATOR,
            {'modifier': currentAsyncMarker});
      }
    }
    visit(node.expression);
    return const NoneResult();
  }

  ResolutionResult visitYield(Yield node) {
    if (!currentAsyncMarker.isYielding) {
      reporter.reportErrorMessage(node, MessageKind.INVALID_YIELD);
    }
    if (currentAsyncMarker.isAsync) {
      coreClasses.streamClass.ensureResolved(resolution);
    } else {
      coreClasses.iterableClass.ensureResolved(resolution);
    }
    visit(node.expression);
    return const NoneResult();
  }

  ResolutionResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
    if (!enclosingElement.isFactoryConstructor) {
      reporter.reportErrorMessage(
          node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY);
      reporter.reportHintMessage(
          enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD);
    }

    ConstructorElementX constructor = enclosingElement;
    bool isConstConstructor = constructor.isConst;
    bool isValidAsConstant = isConstConstructor;
    ConstructorResult result = resolveRedirectingFactory(
        node, inConstContext: isConstConstructor);
    ConstructorElement redirectionTarget = result.element;
    constructor.immediateRedirectionTarget = redirectionTarget;

    Node constructorReference = node.constructorReference;
    if (result.isDeferred) {
      constructor.redirectionDeferredPrefix = result.prefix;
    }

    registry.setRedirectingTargetConstructor(node, redirectionTarget);
    switch (result.kind) {
      case ConstructorResultKind.GENERATIVE:
      case ConstructorResultKind.FACTORY:
        // Register a post process to check for cycles in the redirection chain
        // and set the actual generative constructor at the end of the chain.
        addDeferredAction(constructor, () {
          compiler.resolver.resolveRedirectionChain(constructor, node);
        });
        break;
      case ConstructorResultKind.ABSTRACT:
      case ConstructorResultKind.INVALID_TYPE:
      case ConstructorResultKind.UNRESOLVED_CONSTRUCTOR:
      case ConstructorResultKind.NON_CONSTANT:
        isValidAsConstant = false;
        constructor.setEffectiveTarget(
            result.element, result.type, isMalformed: true);
        break;
    }
    if (Elements.isUnresolved(redirectionTarget)) {
      registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
      return const NoneResult();
    } else {
      if (isConstConstructor &&
          !redirectionTarget.isConst) {
        reporter.reportErrorMessage(
            node, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
        isValidAsConstant = false;
      }
      if (redirectionTarget == constructor) {
        reporter.reportErrorMessage(
            node, MessageKind.CYCLIC_REDIRECTING_FACTORY);
        // TODO(johnniwinther): Create constant constructor for this case and
        // let evaluation detect the cyclicity.
        isValidAsConstant = false;
      }
    }

    // Check that the target constructor is type compatible with the
    // redirecting constructor.
    ClassElement targetClass = redirectionTarget.enclosingClass;
    InterfaceType type = registry.getType(node);
    FunctionType targetConstructorType =
        redirectionTarget.computeType(resolution)
            .subst(type.typeArguments, targetClass.typeVariables);
    FunctionType constructorType = constructor.computeType(resolution);
    bool isSubtype = compiler.types.isSubtype(
        targetConstructorType, constructorType);
    if (!isSubtype) {
      reporter.reportWarningMessage(
          node,
          MessageKind.NOT_ASSIGNABLE,
          {'fromType': targetConstructorType, 'toType': constructorType});
      // TODO(johnniwinther): Handle this (potentially) erroneous case.
      isValidAsConstant = false;
    }

    redirectionTarget.computeType(resolution);
    FunctionSignature targetSignature = redirectionTarget.functionSignature;
    constructor.computeType(resolution);
    FunctionSignature constructorSignature = constructor.functionSignature;
    if (!targetSignature.isCompatibleWith(constructorSignature)) {
      assert(!isSubtype);
      registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
      isValidAsConstant = false;
    }

    registry.registerStaticUse(
        new StaticUse.constructorRedirect(redirectionTarget));
    // TODO(johnniwinther): Register the effective target type as part of the
    // static use instead.
    registry.registerTypeUse(new TypeUse.instantiation(
        redirectionTarget.enclosingClass.thisType
            .subst(type.typeArguments, targetClass.typeVariables)));
    if (enclosingElement == compiler.symbolConstructor) {
      registry.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
    }
    if (isValidAsConstant) {
      List<String> names = <String>[];
      List<ConstantExpression> arguments = <ConstantExpression>[];
      int index = 0;
      constructorSignature.forEachParameter((ParameterElement parameter) {
        if (parameter.isNamed) {
          String name = parameter.name;
          names.add(name);
          arguments.add(new NamedArgumentReference(name));
        } else {
          arguments.add(new PositionalArgumentReference(index));
        }
        index++;
      });
      CallStructure callStructure =
          new CallStructure(constructorSignature.parameterCount, names);
      constructor.constantConstructor =
          new RedirectingFactoryConstantConstructor(
              new ConstructedConstantExpression(
                  type,
                  redirectionTarget,
                  callStructure,
                  arguments));
    }
    return const NoneResult();
  }

  ResolutionResult visitThrow(Throw node) {
    registry.registerFeature(Feature.THROW_EXPRESSION);
    visit(node.expression);
    return const NoneResult();
  }

  ResolutionResult visitAwait(Await node) {
    if (!currentAsyncMarker.isAsync) {
      reporter.reportErrorMessage(node, MessageKind.INVALID_AWAIT);
    }
    coreClasses.futureClass.ensureResolved(resolution);
    visit(node.expression);
    return const NoneResult();
  }

  ResolutionResult visitVariableDefinitions(VariableDefinitions node) {
    DartType type;
    if (node.type != null) {
      type = resolveTypeAnnotation(node.type);
    } else {
      type = const DynamicType();
    }
    VariableList variables = new VariableList.node(node, type);
    VariableDefinitionsVisitor visitor =
        new VariableDefinitionsVisitor(compiler, node, this, variables);

    Modifiers modifiers = node.modifiers;
    void reportExtraModifier(String modifier) {
      Node modifierNode;
      for (Link<Node> nodes = modifiers.nodes.nodes;
           !nodes.isEmpty;
           nodes = nodes.tail) {
        if (modifier == nodes.head.asIdentifier().source) {
          modifierNode = nodes.head;
          break;
        }
      }
      assert(modifierNode != null);
      reporter.reportErrorMessage(
          modifierNode, MessageKind.EXTRANEOUS_MODIFIER,
          {'modifier': modifier});
    }
    if (modifiers.isFinal && (modifiers.isConst || modifiers.isVar)) {
      reportExtraModifier('final');
    }
    if (modifiers.isVar && (modifiers.isConst || node.type != null)) {
      reportExtraModifier('var');
    }
    if (enclosingElement.isFunction || enclosingElement.isConstructor) {
      if (modifiers.isAbstract) {
        reportExtraModifier('abstract');
      }
      if (modifiers.isStatic) {
        reportExtraModifier('static');
      }
    }
    if (node.metadata != null) {
      variables.metadataInternal =
          compiler.resolver.resolveMetadata(enclosingElement, node);
    }
    visitor.visit(node.definitions);
    return const NoneResult();
  }

  ResolutionResult visitWhile(While node) {
    visit(node.condition);
    visitLoopBodyIn(node, node.body, new BlockScope(scope));
    return const NoneResult();
  }

  ResolutionResult visitParenthesizedExpression(ParenthesizedExpression node) {
    bool oldSendIsMemberAccess = sendIsMemberAccess;
    sendIsMemberAccess = false;
    var oldCategory = allowedCategory;
    allowedCategory =
        ElementCategory.VARIABLE |
        ElementCategory.FUNCTION |
        ElementCategory.IMPLIES_TYPE;
    ResolutionResult result = visit(node.expression);
    allowedCategory = oldCategory;
    sendIsMemberAccess = oldSendIsMemberAccess;
    if (result.kind == ResultKind.CONSTANT) {
      return result;
    }
    return const NoneResult();
  }

  ResolutionResult visitNewExpression(NewExpression node) {
    ConstructorResult result = resolveConstructor(node);
    ConstructorElement constructor = result.element;
    ArgumentsResult argumentsResult;
    if (node.isConst) {
      argumentsResult =
          inConstantContext(() => resolveArguments(node.send.argumentsNode));
    } else {
      argumentsResult = resolveArguments(node.send.argumentsNode);
    }
    // TODO(johnniwinther): Avoid the need for a [Selector].
    Selector selector = resolveSelector(node.send, constructor);
    CallStructure callStructure = selector.callStructure;
    registry.useElement(node.send, constructor);

    DartType type = result.type;
    ConstructorAccessKind kind;
    NewStructure newStructure;
    bool isInvalid = false;
    switch (result.kind) {
      case ConstructorResultKind.GENERATIVE:
        // Ensure that the signature of [constructor] has been computed.
        constructor.computeType(resolution);
        if (!callStructure.signatureApplies(constructor.functionSignature)) {
          isInvalid = true;
          kind = ConstructorAccessKind.INCOMPATIBLE;
          registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
        } else {
          kind = ConstructorAccessKind.GENERATIVE;
        }
        break;
      case ConstructorResultKind.FACTORY:
        // Ensure that the signature of [constructor] has been computed.
        constructor.computeType(resolution);
        if (!callStructure.signatureApplies(constructor.functionSignature)) {
          // The effective target might still be valid(!) so the is not an
          // invalid case in itself. For instance
          //
          //    class A {
          //       factory A() = A.a;
          //       A.a(a);
          //    }
          //    m() => new A(0); // This creates a warning but works at runtime.
          //
          registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
        }
        kind = ConstructorAccessKind.FACTORY;
        break;
      case ConstructorResultKind.ABSTRACT:
        isInvalid = true;
        kind = ConstructorAccessKind.ABSTRACT;
        break;
      case ConstructorResultKind.INVALID_TYPE:
        isInvalid = true;
        kind = ConstructorAccessKind.UNRESOLVED_TYPE;
        break;
      case ConstructorResultKind.UNRESOLVED_CONSTRUCTOR:
        // TODO(johnniwinther): Unify codepaths to only have one return.
        registry.registerNewStructure(node,
            new NewInvokeStructure(
                new ConstructorAccessSemantics(
                    ConstructorAccessKind.UNRESOLVED_CONSTRUCTOR,
                    constructor,
                    type),
                selector));
        return new ResolutionResult.forElement(constructor);
      case ConstructorResultKind.NON_CONSTANT:
        registry.registerNewStructure(node,
            new NewInvokeStructure(
                new ConstructorAccessSemantics(
                    ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR,
                    constructor,
                    type),
                selector));
        return new ResolutionResult.forElement(constructor);
    }

    if (!isInvalid) {
      // [constructor] might be the implementation element
      // and only declaration elements may be registered.
      registry.registerStaticUse(
          new StaticUse.constructorInvoke(
              constructor.declaration, callStructure));
      // TODO(johniwinther): Avoid registration of `type` in face of redirecting
      // factory constructors.
      registry.registerTypeUse(new TypeUse.instantiation(type));
    }

    if (node.isConst) {
      bool isValidAsConstant = !isInvalid && constructor.isConst;

      if (constructor == compiler.symbolConstructor) {
        Node argumentNode = node.send.arguments.head;
        ConstantExpression constant =
            compiler.resolver.constantCompiler.compileNode(
                argumentNode, registry.mapping);
        ConstantValue name = compiler.constants.getConstantValue(constant);
        if (!name.isString) {
          DartType type = name.getType(coreTypes);
          reporter.reportErrorMessage(
              argumentNode,
              MessageKind.STRING_EXPECTED,
              {'type': type});
        } else {
          StringConstantValue stringConstant = name;
          String nameString = stringConstant.toDartString().slowToString();
          if (validateSymbol(argumentNode, nameString)) {
            registry.registerConstSymbol(nameString);
          }
        }
      } else if (constructor == compiler.mirrorsUsedConstructor) {
        compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping);
      }

      analyzeConstantDeferred(node);

      if (type.containsTypeVariables) {
        reporter.reportErrorMessage(
            node.send.selector,
            MessageKind.TYPE_VARIABLE_IN_CONSTANT);
        isValidAsConstant = false;
        isInvalid = true;
      }

      if (result.isDeferred) {
        isValidAsConstant = false;
      }

      if (isValidAsConstant &&
          argumentsResult.isValidAsConstant &&
          // TODO(johnniwinther): Remove this when all constants are computed
          // in resolution.
          !constructor.isFromEnvironmentConstructor) {
        CallStructure callStructure = argumentsResult.callStructure;
        List<ConstantExpression> arguments = argumentsResult.constantArguments;

        ConstructedConstantExpression constant =
            new ConstructedConstantExpression(
                type,
                constructor,
                callStructure,
                arguments);
        registry.registerNewStructure(node,
            new ConstInvokeStructure(ConstantInvokeKind.CONSTRUCTED, constant));
        return new ConstantResult(node, constant);
      } else if (isInvalid) {
        // Known to be non-constant.
        kind == ConstructorAccessKind.NON_CONSTANT_CONSTRUCTOR;
        registry.registerNewStructure(node,
            new NewInvokeStructure(
                new ConstructorAccessSemantics(kind, constructor, type),
                selector));
      } else {
        // Might be valid but we don't know for sure. The compile-time constant
        // evaluator will compute the actual constant as a deferred action.
        registry.registerNewStructure(node,
            new LateConstInvokeStructure(registry.mapping));
      }

    } else {
      // Not constant.
      if (constructor == compiler.symbolConstructor &&
          !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
          reporter.reportHintMessage(
              node.newToken, MessageKind.NON_CONST_BLOAT,
              {'name': coreClasses.symbolClass.name});
      }
      registry.registerNewStructure(node,
          new NewInvokeStructure(
              new ConstructorAccessSemantics(kind, constructor, type),
              selector));
    }

    return const NoneResult();
  }

  void checkConstMapKeysDontOverrideEquals(Spannable spannable,
                                           MapConstantValue map) {
    for (ConstantValue key in map.keys) {
      if (!key.isObject) continue;
      ObjectConstantValue objectConstant = key;
      DartType keyType = objectConstant.type;
      ClassElement cls = keyType.element;
      if (cls == coreClasses.stringClass) continue;
      Element equals = cls.lookupMember('==');
      if (equals.enclosingClass != coreClasses.objectClass) {
        reporter.reportErrorMessage(
            spannable,
            MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS,
            {'type': keyType});
      }
    }
  }

  void analyzeConstant(Node node, {enforceConst: true}) {
    ConstantExpression constant =
        compiler.resolver.constantCompiler.compileNode(
            node, registry.mapping, enforceConst: enforceConst);

    if (constant == null) {
      assert(invariant(node, compiler.compilationFailed));
      return;
    }

    ConstantValue value = compiler.constants.getConstantValue(constant);
    if (value.isMap) {
      checkConstMapKeysDontOverrideEquals(node, value);
    }
  }

  void analyzeConstantDeferred(Node node, {bool enforceConst: true}) {
    addDeferredAction(enclosingElement, () {
      analyzeConstant(node, enforceConst: enforceConst);
    });
  }

  bool validateSymbol(Node node, String name, {bool reportError: true}) {
    if (name.isEmpty) return true;
    if (name.startsWith('_')) {
      if (reportError) {
        reporter.reportErrorMessage(
            node, MessageKind.PRIVATE_IDENTIFIER, {'value': name});
      }
      return false;
    }
    if (!symbolValidationPattern.hasMatch(name)) {
      if (reportError) {
        reporter.reportErrorMessage(
            node, MessageKind.INVALID_SYMBOL, {'value': name});
      }
      return false;
    }
    return true;
  }

  /**
   * Try to resolve the constructor that is referred to by [node].
   * Note: this function may return an ErroneousFunctionElement instead of
   * [:null:], if there is no corresponding constructor, class or library.
   */
  ConstructorResult resolveConstructor(NewExpression node) {
    return node.accept(new ConstructorResolver(
        compiler, this, inConstContext: node.isConst));
  }

  ConstructorResult resolveRedirectingFactory(RedirectingFactoryBody node,
                                               {bool inConstContext: false}) {
    return node.accept(new ConstructorResolver(
        compiler, this, inConstContext: inConstContext));
  }

  DartType resolveTypeAnnotation(TypeAnnotation node,
                                 {bool malformedIsError: false,
                                  bool deferredIsMalformed: true}) {
    DartType type = typeResolver.resolveTypeAnnotation(
        this, node, malformedIsError: malformedIsError,
        deferredIsMalformed: deferredIsMalformed);
    if (inCheckContext) {
      registry.registerTypeUse(new TypeUse.checkedModeCheck(type));
    }
    return type;
  }

  ResolutionResult visitLiteralList(LiteralList node) {
    bool isValidAsConstant = true;
    sendIsMemberAccess = false;

    NodeList arguments = node.typeArguments;
    DartType typeArgument;
    if (arguments != null) {
      Link<Node> nodes = arguments.nodes;
      if (nodes.isEmpty) {
        // The syntax [: <>[] :] is not allowed.
        reporter.reportErrorMessage(
            arguments, MessageKind.MISSING_TYPE_ARGUMENT);
        isValidAsConstant = false;
      } else {
        typeArgument = resolveTypeAnnotation(nodes.head);
        for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) {
          reporter.reportWarningMessage(
              nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
          resolveTypeAnnotation(nodes.head);
        }
      }
    }
    DartType listType;
    if (typeArgument != null) {
      if (node.isConst && typeArgument.containsTypeVariables) {
        reporter.reportErrorMessage(
            arguments.nodes.head,
            MessageKind.TYPE_VARIABLE_IN_CONSTANT);
        isValidAsConstant = false;
      }
      listType = coreTypes.listType(typeArgument);
    } else {
      listType = coreTypes.listType();
    }
    registry.registerLiteralList(
        node,
        listType,
        isConstant: node.isConst,
        isEmpty: node.elements.isEmpty);
    if (node.isConst) {
      List<ConstantExpression> constantExpressions = <ConstantExpression>[];
      inConstantContext(() {
        for (Node element in node.elements) {
          ResolutionResult elementResult = visit(element);
          if (isValidAsConstant && elementResult.isConstant) {
            constantExpressions.add(elementResult.constant);
          } else {
            isValidAsConstant = false;
          }
        }
      });
      analyzeConstantDeferred(node);
      sendIsMemberAccess = false;
      if (isValidAsConstant) {
        ConstantExpression constant =
            new ListConstantExpression(listType, constantExpressions);
        registry.setConstant(node, constant);
        return new ConstantResult(node, constant);
      }
    } else {
      visit(node.elements);
      sendIsMemberAccess = false;
    }
    return const NoneResult();

  }

  ResolutionResult visitConditional(Conditional node) {
    ResolutionResult conditionResult =
        doInPromotionScope(node.condition, () => visit(node.condition));
    ResolutionResult thenResult =
        doInPromotionScope(node.thenExpression, () => visit(node.thenExpression));
    ResolutionResult elseResult = visit(node.elseExpression);
    if (conditionResult.isConstant &&
        thenResult.isConstant &&
        elseResult.isConstant) {
      ConstantExpression constant = new ConditionalConstantExpression(
          conditionResult.constant,
          thenResult.constant,
          elseResult.constant);
      registry.setConstant(node, constant);
      return new ConstantResult(node, constant);
    }
    return const NoneResult();
  }

  ResolutionResult visitStringInterpolation(StringInterpolation node) {
    // TODO(johnniwinther): This should be a consequence of the registration
    // of [registerStringInterpolation].
    registry.registerTypeUse(new TypeUse.instantiation(coreTypes.stringType));
    registry.registerFeature(Feature.STRING_INTERPOLATION);
    registerImplicitInvocation(Selectors.toString_);

    bool isValidAsConstant = true;
    List<ConstantExpression> parts = <ConstantExpression>[];

    void resolvePart(Node subnode) {
      ResolutionResult result = visit(subnode);
      if (isValidAsConstant && result.isConstant) {
        parts.add(result.constant);
      } else {
        isValidAsConstant = false;
      }
    }

    resolvePart(node.string);
    for (StringInterpolationPart part in node.parts) {
      resolvePart(part.expression);
      resolvePart(part.string);
    }

    if (isValidAsConstant) {
      ConstantExpression constant = new ConcatenateConstantExpression(parts);
      registry.setConstant(node, constant);
      return new ConstantResult(node, constant);
    }
    return const NoneResult();
  }

  ResolutionResult visitBreakStatement(BreakStatement node) {
    JumpTarget target;
    if (node.target == null) {
      target = statementScope.currentBreakTarget();
      if (target == null) {
        reporter.reportErrorMessage(
            node, MessageKind.NO_BREAK_TARGET);
        return const NoneResult();
      }
      target.isBreakTarget = true;
    } else {
      String labelName = node.target.source;
      LabelDefinition label = statementScope.lookupLabel(labelName);
      if (label == null) {
        reporter.reportErrorMessage(
            node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
        return const NoneResult();
      }
      target = label.target;
      if (!target.statement.isValidBreakTarget()) {
        reporter.reportErrorMessage(
            node.target, MessageKind.INVALID_BREAK);
        return const NoneResult();
      }
      label.setBreakTarget();
      registry.useLabel(node, label);
    }
    registry.registerTargetOf(node, target);
    return const NoneResult();
  }

  ResolutionResult visitContinueStatement(ContinueStatement node) {
    JumpTarget target;
    if (node.target == null) {
      target = statementScope.currentContinueTarget();
      if (target == null) {
        reporter.reportErrorMessage(
            node, MessageKind.NO_CONTINUE_TARGET);
        return const NoneResult();
      }
      target.isContinueTarget = true;
    } else {
      String labelName = node.target.source;
      LabelDefinition label = statementScope.lookupLabel(labelName);
      if (label == null) {
        reporter.reportErrorMessage(
            node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
        return const NoneResult();
      }
      target = label.target;
      if (!target.statement.isValidContinueTarget()) {
        reporter.reportErrorMessage(
            node.target, MessageKind.INVALID_CONTINUE);
      }
      label.setContinueTarget();
      registry.useLabel(node, label);
    }
    registry.registerTargetOf(node, target);
    return const NoneResult();
  }

  registerImplicitInvocation(Selector selector) {
    registry.registerDynamicUse(new DynamicUse(selector, null));
  }

  ResolutionResult visitAsyncForIn(AsyncForIn node) {
    if (!currentAsyncMarker.isAsync) {
      reporter.reportErrorMessage(
          node.awaitToken, MessageKind.INVALID_AWAIT_FOR_IN);
    }
    registry.registerFeature(Feature.ASYNC_FOR_IN);
    registry.registerDynamicUse(
        new DynamicUse(Selectors.current, null));
    registry.registerDynamicUse(
        new DynamicUse(Selectors.moveNext, null));

    visit(node.expression);

    Scope blockScope = new BlockScope(scope);
    visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope);
    visitLoopBodyIn(node, node.body, blockScope);
    return const NoneResult();
  }

  ResolutionResult visitSyncForIn(SyncForIn node) {
    registry.registerFeature(Feature.SYNC_FOR_IN);
    registry.registerDynamicUse(
        new DynamicUse(Selectors.iterator, null));
    registry.registerDynamicUse(
        new DynamicUse(Selectors.current, null));
    registry.registerDynamicUse(
        new DynamicUse(Selectors.moveNext, null));

    visit(node.expression);

    Scope blockScope = new BlockScope(scope);
    visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope);
    visitLoopBodyIn(node, node.body, blockScope);
    return const NoneResult();
  }

  void visitForInDeclaredIdentifierIn(
      Node declaration,
      ForIn node,
      Scope blockScope) {
    LibraryElement library = enclosingElement.library;

    bool oldAllowFinalWithoutInitializer = inLoopVariable;
    inLoopVariable = true;
    visitIn(declaration, blockScope);
    inLoopVariable = oldAllowFinalWithoutInitializer;

    Send send = declaration.asSend();
    VariableDefinitions variableDefinitions =
        declaration.asVariableDefinitions();
    Element loopVariable;
    Selector loopVariableSelector;
    if (send != null) {
      loopVariable = registry.getDefinition(send);
      Identifier identifier = send.selector.asIdentifier();
      if (identifier == null) {
        reporter.reportErrorMessage(
            send.selector, MessageKind.INVALID_FOR_IN);
      } else {
        loopVariableSelector = new Selector.setter(
            new Name(identifier.source, library));
      }
      if (send.receiver != null) {
        reporter.reportErrorMessage(
            send.receiver, MessageKind.INVALID_FOR_IN);
      }
    } else if (variableDefinitions != null) {
      Link<Node> nodes = variableDefinitions.definitions.nodes;
      if (!nodes.tail.isEmpty) {
        reporter.reportErrorMessage(
            nodes.tail.head, MessageKind.INVALID_FOR_IN);
      }
      Node first = nodes.head;
      Identifier identifier = first.asIdentifier();
      if (identifier == null) {
        reporter.reportErrorMessage(
            first, MessageKind.INVALID_FOR_IN);
      } else {
        loopVariableSelector = new Selector.setter(
            new Name(identifier.source, library));
        loopVariable = registry.getDefinition(identifier);
      }
    } else {
      reporter.reportErrorMessage(
          declaration, MessageKind.INVALID_FOR_IN);
    }
    if (loopVariableSelector != null) {
      registry.setSelector(declaration, loopVariableSelector);
      if (loopVariable == null || loopVariable.isInstanceMember) {
        registry.registerDynamicUse(
            new DynamicUse(loopVariableSelector, null));
      } else if (loopVariable.isStatic || loopVariable.isTopLevel) {
        registry.registerStaticUse(
            new StaticUse.staticSet(loopVariable.declaration));
      }
    } else {
      // The selector may only be null if we reported an error.
      assert(invariant(declaration, compiler.compilationFailed));
    }
    if (loopVariable != null) {
      // loopVariable may be null if it could not be resolved.
      registry.setForInVariable(node, loopVariable);
    }
  }

  visitLabel(Label node) {
    // Labels are handled by their containing statements/cases.
  }

  ResolutionResult visitLabeledStatement(LabeledStatement node) {
    Statement body = node.statement;
    JumpTarget targetElement = getOrDefineTarget(body);
    Map<String, LabelDefinition> labelElements = <String, LabelDefinition>{};
    for (Label label in node.labels) {
      String labelName = label.labelName;
      if (labelElements.containsKey(labelName)) continue;
      LabelDefinition element = targetElement.addLabel(label, labelName);
      labelElements[labelName] = element;
    }
    statementScope.enterLabelScope(labelElements);
    visit(node.statement);
    statementScope.exitLabelScope();
    labelElements.forEach((String labelName, LabelDefinition element) {
      if (element.isTarget) {
        registry.defineLabel(element.label, element);
      } else {
        reporter.reportWarningMessage(
            element.label,
            MessageKind.UNUSED_LABEL,
            {'labelName': labelName});
      }
    });
    if (!targetElement.isTarget) {
      registry.undefineTarget(body);
    }
    return const NoneResult();
  }

  ResolutionResult visitLiteralMap(LiteralMap node) {
    bool isValidAsConstant = true;
    sendIsMemberAccess = false;

    NodeList arguments = node.typeArguments;
    DartType keyTypeArgument;
    DartType valueTypeArgument;
    if (arguments != null) {
      Link<Node> nodes = arguments.nodes;
      if (nodes.isEmpty) {
        // The syntax [: <>{} :] is not allowed.
        reporter.reportErrorMessage(
            arguments, MessageKind.MISSING_TYPE_ARGUMENT);
        isValidAsConstant = false;
      } else {
        keyTypeArgument = resolveTypeAnnotation(nodes.head);
        nodes = nodes.tail;
        if (nodes.isEmpty) {
          reporter.reportWarningMessage(
              arguments, MessageKind.MISSING_TYPE_ARGUMENT);
        } else {
          valueTypeArgument = resolveTypeAnnotation(nodes.head);
          for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) {
            reporter.reportWarningMessage(
                nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
            resolveTypeAnnotation(nodes.head);
          }
        }
      }
    }
    DartType mapType;
    if (valueTypeArgument != null) {
      mapType = coreTypes.mapType(keyTypeArgument, valueTypeArgument);
    } else {
      mapType = coreTypes.mapType();
    }
    if (node.isConst && mapType.containsTypeVariables) {
      reporter.reportErrorMessage(
          arguments,
          MessageKind.TYPE_VARIABLE_IN_CONSTANT);
      isValidAsConstant = false;
    }
    registry.registerMapLiteral(
        node,
        mapType,
        isConstant: node.isConst,
        isEmpty: node.entries.isEmpty);

    if (node.isConst) {
      List<ConstantExpression> keyExpressions = <ConstantExpression>[];
      List<ConstantExpression> valueExpressions = <ConstantExpression>[];
      inConstantContext(() {
        for (LiteralMapEntry entry in node.entries) {
          ResolutionResult keyResult = visit(entry.key);
          ResolutionResult valueResult = visit(entry.value);
          if (isValidAsConstant &&
              keyResult.isConstant &&
              valueResult.isConstant) {
            keyExpressions.add(keyResult.constant);
            valueExpressions.add(valueResult.constant);
          } else {
            isValidAsConstant = false;
          }
        }
      });
      analyzeConstantDeferred(node);
      sendIsMemberAccess = false;
      if (isValidAsConstant) {
        ConstantExpression constant = new MapConstantExpression(
            mapType, keyExpressions, valueExpressions);
        registry.setConstant(node, constant);
        return new ConstantResult(node, constant);
      }
    } else {
      node.visitChildren(this);
      sendIsMemberAccess = false;
    }
    return const NoneResult();
  }

  ResolutionResult visitLiteralMapEntry(LiteralMapEntry node) {
    node.visitChildren(this);
    return const NoneResult();
  }

  ResolutionResult visitNamedArgument(NamedArgument node) {
    return visit(node.expression);
  }

  DartType typeOfConstant(ConstantValue constant) {
    if (constant.isInt) return coreTypes.intType;
    if (constant.isBool) return coreTypes.boolType;
    if (constant.isDouble) return coreTypes.doubleType;
    if (constant.isString) return coreTypes.stringType;
    if (constant.isNull) return coreTypes.nullType;
    if (constant.isFunction) return coreTypes.functionType;
    assert(constant.isObject);
    ObjectConstantValue objectConstant = constant;
    return objectConstant.type;
  }

  bool overridesEquals(DartType type) {
    ClassElement cls = type.element;
    Element equals = cls.lookupMember('==');
    return equals.enclosingClass != coreClasses.objectClass;
  }

  void checkCaseExpressions(SwitchStatement node) {
    CaseMatch firstCase = null;
    DartType firstCaseType = null;
    DiagnosticMessage error;
    List<DiagnosticMessage> infos = <DiagnosticMessage>[];

    for (Link<Node> cases = node.cases.nodes;
         !cases.isEmpty;
         cases = cases.tail) {
      SwitchCase switchCase = cases.head;

      for (Node labelOrCase in switchCase.labelsAndCases) {
        CaseMatch caseMatch = labelOrCase.asCaseMatch();
        if (caseMatch == null) continue;

        // Analyze the constant.
        ConstantExpression constant =
            registry.getConstant(caseMatch.expression);
        assert(invariant(node, constant != null,
            message: 'No constant computed for $node'));

        ConstantValue value = compiler.constants.getConstantValue(constant);
        DartType caseType = value.getType(coreTypes);//typeOfConstant(value);

        if (firstCaseType == null) {
          firstCase = caseMatch;
          firstCaseType = caseType;

          // We only report the bad type on the first class element. All others
          // get a "type differs" error.
          if (caseType == coreTypes.doubleType) {
            reporter.reportErrorMessage(
                node,
                MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
                {'type': "double"});
          } else if (caseType == coreTypes.functionType) {
            reporter.reportErrorMessage(
                node, MessageKind.SWITCH_CASE_FORBIDDEN,
                {'type': "Function"});
          } else if (value.isObject && overridesEquals(caseType)) {
            reporter.reportErrorMessage(
                firstCase.expression,
                MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
                {'type': caseType});
          }
        } else {
          if (caseType != firstCaseType) {
            if (error == null) {
              error = reporter.createMessage(
                  node,
                  MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL,
                  {'type': firstCaseType});
              infos.add(reporter.createMessage(
                  firstCase.expression,
                  MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
                  {'type': firstCaseType}));
            }
            infos.add(reporter.createMessage(
                caseMatch.expression,
                MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
                {'type': caseType}));
          }
        }
      }
    }
    if (error != null) {
      reporter.reportError(error, infos);
    }
  }

  ResolutionResult visitSwitchStatement(SwitchStatement node) {
    node.expression.accept(this);

    JumpTarget breakElement = getOrDefineTarget(node);
    Map<String, LabelDefinition> continueLabels = <String, LabelDefinition>{};
    Link<Node> cases = node.cases.nodes;
    while (!cases.isEmpty) {
      SwitchCase switchCase = cases.head;
      for (Node labelOrCase in switchCase.labelsAndCases) {
        CaseMatch caseMatch = labelOrCase.asCaseMatch();
        if (caseMatch != null) {
          analyzeConstantDeferred(caseMatch.expression);
          continue;
        }
        Label label = labelOrCase;
        String labelName = label.labelName;

        LabelDefinition existingElement = continueLabels[labelName];
        if (existingElement != null) {
          // It's an error if the same label occurs twice in the same switch.
          reporter.reportError(
              reporter.createMessage(
                  label,
                  MessageKind.DUPLICATE_LABEL,
                  {'labelName': labelName}),
              <DiagnosticMessage>[
                  reporter.createMessage(
                    existingElement.label,
                    MessageKind.EXISTING_LABEL,
                    {'labelName': labelName}),
              ]);
        } else {
          // It's only a warning if it shadows another label.
          existingElement = statementScope.lookupLabel(labelName);
          if (existingElement != null) {
            reporter.reportWarning(
                reporter.createMessage(
                    label,
                    MessageKind.DUPLICATE_LABEL,
                    {'labelName': labelName}),
                <DiagnosticMessage>[
                    reporter.createMessage(
                        existingElement.label,
                        MessageKind.EXISTING_LABEL,
                        {'labelName': labelName}),
                ]);
          }
        }

        JumpTarget targetElement = getOrDefineTarget(switchCase);
        LabelDefinition labelElement = targetElement.addLabel(label, labelName);
        registry.defineLabel(label, labelElement);
        continueLabels[labelName] = labelElement;
      }
      cases = cases.tail;
      // Test that only the last case, if any, is a default case.
      if (switchCase.defaultKeyword != null && !cases.isEmpty) {
        reporter.reportErrorMessage(
            switchCase, MessageKind.INVALID_CASE_DEFAULT);
      }
    }

    addDeferredAction(enclosingElement, () {
      checkCaseExpressions(node);
    });

    statementScope.enterSwitch(breakElement, continueLabels);
    node.cases.accept(this);
    statementScope.exitSwitch();

    // Clean-up unused labels.
    continueLabels.forEach((String key, LabelDefinition label) {
      if (!label.isContinueTarget) {
        JumpTarget targetElement = label.target;
        SwitchCase switchCase = targetElement.statement;
        registry.undefineTarget(switchCase);
        registry.undefineLabel(label.label);
      }
    });
    // TODO(15575): We should warn if we can detect a fall through
    // error.
    registry.registerFeature(Feature.FALL_THROUGH_ERROR);
    return const NoneResult();
  }

  ResolutionResult visitSwitchCase(SwitchCase node) {
    node.labelsAndCases.accept(this);
    visitIn(node.statements, new BlockScope(scope));
    return const NoneResult();
  }

  ResolutionResult visitCaseMatch(CaseMatch node) {
    visit(node.expression);
    return const NoneResult();
  }

  ResolutionResult visitTryStatement(TryStatement node) {
    // TODO(karlklose): also track the information about mutated variables,
    // catch, and finally-block.
    registry.registerTryStatement();

    visit(node.tryBlock);
    if (node.catchBlocks.isEmpty && node.finallyBlock == null) {
      reporter.reportErrorMessage(
          node.getEndToken().next, MessageKind.NO_CATCH_NOR_FINALLY);
    }
    visit(node.catchBlocks);
    visit(node.finallyBlock);
    return const NoneResult();
  }

  ResolutionResult visitCatchBlock(CatchBlock node) {
    registry.registerFeature(Feature.CATCH_STATEMENT);
    // Check that if catch part is present, then
    // it has one or two formal parameters.
    VariableDefinitions exceptionDefinition;
    VariableDefinitions stackTraceDefinition;
    if (node.formals != null) {
      Link<Node> formalsToProcess = node.formals.nodes;
      if (formalsToProcess.isEmpty) {
        reporter.reportErrorMessage(
            node, MessageKind.EMPTY_CATCH_DECLARATION);
      } else {
        exceptionDefinition = formalsToProcess.head.asVariableDefinitions();
        formalsToProcess = formalsToProcess.tail;
        if (!formalsToProcess.isEmpty) {
          stackTraceDefinition = formalsToProcess.head.asVariableDefinitions();
          formalsToProcess = formalsToProcess.tail;
          if (!formalsToProcess.isEmpty) {
            for (Node extra in formalsToProcess) {
              reporter.reportErrorMessage(
                  extra, MessageKind.EXTRA_CATCH_DECLARATION);
            }
          }
          registry.registerFeature(Feature.STACK_TRACE_IN_CATCH);
        }
      }

      // Check that the formals aren't optional and that they have no
      // modifiers or type.
      for (Link<Node> link = node.formals.nodes;
           !link.isEmpty;
           link = link.tail) {
        // If the formal parameter is a node list, it means that it is a
        // sequence of optional parameters.
        NodeList nodeList = link.head.asNodeList();
        if (nodeList != null) {
          reporter.reportErrorMessage(
              nodeList, MessageKind.OPTIONAL_PARAMETER_IN_CATCH);
        } else {
          VariableDefinitions declaration = link.head;
          for (Node modifier in declaration.modifiers.nodes) {
            reporter.reportErrorMessage(
                modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH);
          }
          TypeAnnotation type = declaration.type;
          if (type != null) {
            reporter.reportErrorMessage(
                type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH);
          }
        }
      }
    }

    Scope blockScope = new BlockScope(scope);
    TypeResult exceptionTypeResult = visitIn(node.type, blockScope);
    visitIn(node.formals, blockScope);
    var oldInCatchBlock = inCatchBlock;
    inCatchBlock = true;
    visitIn(node.block, blockScope);
    inCatchBlock = oldInCatchBlock;

    if (exceptionTypeResult != null) {
      DartType exceptionType = exceptionTypeResult.type;
      if (exceptionDefinition != null) {
        Node exceptionVariable = exceptionDefinition.definitions.nodes.head;
        VariableElementX exceptionElement =
            registry.getDefinition(exceptionVariable);
        exceptionElement.variables.type = exceptionType;
      }
      registry.registerTypeUse(new TypeUse.catchType(exceptionType));
    }
    if (stackTraceDefinition != null) {
      Node stackTraceVariable = stackTraceDefinition.definitions.nodes.head;
      VariableElementX stackTraceElement =
          registry.getDefinition(stackTraceVariable);
      InterfaceType stackTraceType = coreTypes.stackTraceType;
      stackTraceElement.variables.type = stackTraceType;
    }
    return const NoneResult();
  }
}

/// Looks up [name] in [scope] and unwraps the result.
Element lookupInScope(DiagnosticReporter reporter, Node node,
                      Scope scope, String name) {
  return Elements.unwrap(scope.lookup(name), reporter, node);
}
