// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/fasta/resolution_storer.dart';
import 'package:front_end/src/base/syntactic_entity.dart';
import 'package:front_end/src/scanner/token.dart';
import 'package:kernel/kernel.dart' as kernel;

/// Visitor that applies resolution data from the front end (obtained via
/// [ResolutionStorer]) to an analyzer AST.
class ResolutionApplier extends GeneralizingAstVisitor {
  final LibraryElement _enclosingLibraryElement;
  final TypeContext _typeContext;

  final Map<int, ResolutionData> _data;

  /// The current label scope. Each [Block] adds a new one.
  _LabelScope _labelScope = new _LabelScope(null);

  ResolutionApplier(
      this._enclosingLibraryElement, this._typeContext, this._data);

  /// Apply resolution to annotations of the given [node].
  void applyToAnnotations(AnnotatedNode node) {
    node.metadata.accept(this);
  }

  @override
  void visitAdjacentStrings(AdjacentStrings node) {
    node.strings.accept(this);
    node.staticType = _typeContext.stringType;
  }

  @override
  void visitAnnotation(Annotation node) {
    Identifier name = node.name;
    ArgumentList argumentList = node.arguments;

    SimpleIdentifier fieldName;
    SimpleIdentifier constructorName;

    var data = _get(name);
    if (name is SimpleIdentifier) {
      var translatedReference = _translateReference(data);
      name.staticElement = translatedReference;
      name.staticType = _translateType(data.inferredType);
      node.element = translatedReference;
    } else if (name is PrefixedIdentifier) {
      if (data.prefixInfo != null) {
        name.prefix.staticElement = _translatePrefixInfo(data.prefixInfo);

        data = _get(name.identifier);
        name.identifier.staticElement = _translateReference(data);
        name.identifier.staticType = _translateType(data.inferredType);

        if (argumentList == null) {
          fieldName = node.constructorName;
        } else {
          constructorName = node.constructorName;
        }
      } else {
        name.prefix.staticElement = _translateReference(data);
        name.prefix.staticType = _translateType(data.inferredType);

        if (argumentList == null) {
          fieldName = name.identifier;
        } else {
          constructorName = name.identifier;
        }
      }
    }

    if (fieldName != null) {
      data = _get(fieldName);
      var translatedReference = _translateReference(data);
      node.element = translatedReference;
      fieldName.staticElement = translatedReference;
      fieldName.staticType = _translateType(data.inferredType);
    }

    if (argumentList != null) {
      var data = _get(argumentList);
      ConstructorElement element = _translateReference(data);
      node.element = element;

      if (constructorName != null) {
        constructorName.staticElement = element;
        constructorName.staticType = element.type;
      }

      argumentList.accept(this);
      _resolveArgumentsToParameters(argumentList, element.parameters);
    }
  }

  @override
  void visitArgumentList(ArgumentList node) {
    for (var argument in node.arguments) {
      if (argument is NamedExpression) {
        argument.expression.accept(this);
        argument.staticType = argument.expression.staticType;
      } else {
        argument.accept(this);
      }
    }
  }

  @override
  void visitAsExpression(AsExpression node) {
    node.expression.accept(this);
    node.type.accept(this);
    var data = _get(node.asOperator);
    node.staticType = _translateType(data.inferredType);
  }

  @override
  void visitAssignmentExpression(AssignmentExpression node) {
    node.leftHandSide.accept(this);
    node.rightHandSide.accept(this);

    SyntacticEntity entity =
        _getAssignmentEntity(node.leftHandSide) ?? node.operator;
    var data = _get(entity,
        isSynthetic: entity is SimpleIdentifier && entity.isSynthetic);
    node.staticElement = _translateAuxiliaryReference(data.combiner);
    node.staticType = _translateType(data.inferredType);
  }

  @override
  void visitBinaryExpression(BinaryExpression node) {
    node.leftOperand.accept(this);

    var data = _get(node.operator);
    TokenType operatorType = node.operator.type;
    if (operatorType != TokenType.QUESTION_QUESTION &&
        operatorType != TokenType.AMPERSAND_AMPERSAND &&
        operatorType != TokenType.BAR_BAR) {
      node.staticElement = _translateReference(data);
    }

    // Record the return type of the expression.
    node.staticType = _translateType(data.inferredType);

    node.rightOperand.accept(this);
  }

  @override
  void visitBlock(Block node) {
    _labelScope = new _LabelScope(_labelScope);
    super.visitBlock(node);
    _labelScope = _labelScope.parent;
  }

  @override
  void visitBreakStatement(BreakStatement node) {
    SimpleIdentifier label = node.label;
    if (label != null) {
      LabelElement labelElement = _labelScope[label.name];
      label.staticElement = labelElement;
    }
  }

  @override
  void visitCascadeExpression(CascadeExpression node) {
    visitNode(node);
    node.staticType = node.target.staticType;
  }

  @override
  void visitCatchClause(CatchClause node) {
    node.exceptionType?.accept(this);
    SimpleIdentifier exception = node.exceptionParameter;
    if (exception != null) {
      LocalVariableElementImpl element = exception.staticElement;
      DartType type = _translateType(
          _get(exception, isSynthetic: exception.isSynthetic).inferredType);
      element.type = type;
      exception.staticType = type;
    }

    SimpleIdentifier stackTrace = node.stackTraceParameter;
    if (stackTrace != null) {
      LocalVariableElementImpl element = stackTrace.staticElement;
      DartType type = _translateType(_get(stackTrace).inferredType);
      element.type = type;
      stackTrace.staticType = type;
    }

    node.body.accept(this);
  }

  @override
  void visitConditionalExpression(ConditionalExpression node) {
    node.condition.accept(this);
    node.thenExpression.accept(this);
    node.elseExpression.accept(this);
    node.staticType = _translateType(_get(node.question).inferredType);
  }

  @override
  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
    var element = _translateReference(_get(node.equals));
    if (element is PropertyAccessorElement) {
      node.fieldName.staticElement = element.variable;
    } else {
      node.fieldName.staticElement = element;
    }

    node.expression.accept(this);
  }

  @override
  void visitContinueStatement(ContinueStatement node) {
    SimpleIdentifier label = node.label;
    if (label != null) {
      LabelElement labelElement = _labelScope[label.name];
      label.staticElement = labelElement;
    }
  }

  @override
  void visitExpression(Expression node) {
    visitNode(node);
    node.staticType = _translateType(_get(node).inferredType);
  }

  @override
  void visitForEachStatement(ForEachStatement node) {
    DeclaredIdentifier loopVariable = node.loopVariable;
    if (loopVariable != null) {
      loopVariable.type?.accept(this);
      SimpleIdentifier identifier = loopVariable.identifier;

      DartType type = _translateType(_get(identifier).inferredType);
      identifier.staticType = type;

      VariableElementImpl element = identifier.staticElement;
      if (element != null) {
        _typeContext.encloseVariable(element);
        identifier.staticElement = element;
        element.type = type;
      }
    } else {
      node.identifier.accept(this);
    }
    node.iterable.accept(this);
    node.body.accept(this);
  }

  @override
  void visitFormalParameterList(FormalParameterList parameterList) {
    for (var parameter in parameterList.parameters) {
      parameter.metadata?.accept(this);
      NormalFormalParameter normalParameter;
      if (parameter is DefaultFormalParameter) {
        parameter.defaultValue?.accept(this);
        normalParameter = parameter.parameter;
      } else if (parameter is NormalFormalParameter) {
        normalParameter = parameter;
      } else {
        // All parameters should either be DefaultFormalParameter or
        // NormalFormalParameter.
        throw new UnimplementedError('${parameter.runtimeType}');
      }
      if (normalParameter is SimpleFormalParameter) {
        normalParameter.type?.accept(this);
      } else if (normalParameter is FieldFormalParameter) {
        normalParameter.type?.accept(this);
      } else if (normalParameter is FunctionTypedFormalParameter) {
        normalParameter.returnType?.accept(this);
        normalParameter.typeParameters?.accept(this);
        normalParameter.parameters?.accept(this);
        var data = _get(normalParameter.identifier);
        normalParameter.identifier.staticType =
            _translateType(data.inferredType);
      } else {
        // Now that DefaultFormalParameter has been handled, all parameters
        // should be SimpleFormalParameter, FieldFormalParameter, or
        // FunctionTypedFormalParameter.
        throw new UnimplementedError('${normalParameter.runtimeType}');
      }
    }
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    FunctionElementImpl element = node.declaredElement;
    _typeContext.enterLocalFunction(element);

    node.returnType?.accept(this);
    FunctionExpression functionExpression = node.functionExpression;
    FormalParameterList parameterList = functionExpression.parameters;

    // Apply resolution to default values.
    parameterList.accept(this);

    functionExpression.body?.accept(this);
    _storeFunctionType(_translateType(_get(node.name).inferredType), element);

    // Associate the elements with the nodes.
    if (element != null) {
      functionExpression.element = element;

      node.name.staticElement = element;
      node.name.staticType = element.type;

      TypeParameterList typeParameterList = functionExpression.typeParameters;
      if (typeParameterList != null) {
        List<TypeParameter> typeParameters = typeParameterList.typeParameters;
        for (var i = 0; i < typeParameters.length; i++) {
          TypeParameter typeParameter = typeParameters[i];
          typeParameter.name.staticElement = element.typeParameters[i];
          typeParameter.name.staticType = _typeContext.typeType;
        }
      }
    }

    _typeContext.exitLocalFunction(element);
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    FormalParameterList parameterList = node.parameters;

    FunctionElementImpl element = node.declaredElement;
    _typeContext.enterLocalFunction(element);

    // Apply resolution to default values.
    parameterList.accept(this);

    node.body.accept(this);
    _storeFunctionType(
        _translateType(_get(node.parameters).inferredType), element);

    // Associate the elements with the nodes.
    if (element != null) {
      node.element = element;
      node.staticType = element.type;
    }

    _typeContext.exitLocalFunction(element);
  }

  @override
  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
    node.function.accept(this);
    node.typeArguments?.accept(this);

    var data = _get(node.argumentList);
    DartType invokeType = _translateType(data.invokeType);
    node.staticInvokeType = invokeType;

    DartType resultType = _translateType(data.inferredType);
    node.staticType = resultType;

    node.argumentList.accept(this);
  }

  @override
  void visitGenericFunctionType(covariant GenericFunctionTypeImpl node) {
    var data = _get(node.functionKeyword);
    FunctionType type = _translateType(data.inferredType);
    node.type = type;
    _typeContext.enterLocalFunction(type.element);
    super.visitGenericFunctionType(node);
    _typeContext.exitLocalFunction(type.element);
  }

  @override
  void visitIndexExpression(IndexExpression node) {
    node.target?.accept(this);

    var data = _get(node.leftBracket);
    node.staticElement = _translateReference(data);
    node.staticType = _translateType(data.inferredType);

    node.index.accept(this);
  }

  @override
  void visitInstanceCreationExpression(InstanceCreationExpression node) {
    ConstructorName constructorName = node.constructorName;
    Identifier typeIdentifier = constructorName.type.name;
    SimpleIdentifier classIdentifier;
    SimpleIdentifier constructorIdentifier;

    constructorName.type.typeArguments?.accept(this);
    var data = _get(typeIdentifier);
    TypeName newTypeName;
    if (typeIdentifier is SimpleIdentifier) {
      classIdentifier = typeIdentifier;
      constructorIdentifier = constructorName.name;
    } else if (typeIdentifier is PrefixedIdentifier) {
      if (data.isPrefixReference) {
        typeIdentifier.prefix.staticElement =
            _translatePrefixInfo(data.prefixInfo);

        classIdentifier = typeIdentifier.identifier;
        constructorIdentifier = node.constructorName.name;

        data = _get(classIdentifier);
      } else {
        classIdentifier = typeIdentifier.prefix;
        constructorIdentifier = typeIdentifier.identifier;

        TypeArgumentList typeArguments = constructorName.type.typeArguments;
        newTypeName = astFactory.typeName(classIdentifier, typeArguments);
        constructorName.type = newTypeName;
        constructorName.period = typeIdentifier.period;
        constructorName.name = constructorIdentifier;
      }
    }
    classIdentifier.staticElement = _translateReference(data);

    data = _get(node.argumentList);

    ConstructorElement constructor = _translateReference(data);
    DartType type = _translateType(data.inferredType);

    node.staticElement = constructor;
    node.staticType = type;

    node.constructorName.staticElement = constructor;
    node.constructorName.type.type = type;

    typeIdentifier.staticType = type;
    classIdentifier.staticType = type;
    constructorIdentifier?.staticElement = constructor;

    ArgumentList argumentList = node.argumentList;
    argumentList.accept(this);
    _resolveArgumentsToParameters(argumentList, constructor?.parameters);
  }

  @override
  void visitIsExpression(IsExpression node) {
    node.expression.accept(this);
    node.type.accept(this);
    var data = _get(node.isOperator);
    node.staticType = _translateType(data.inferredType);
  }

  @override
  void visitLabel(Label node) {
    SimpleIdentifier label = node.label;
    String name = label.name;
    var element = new LabelElementImpl(name, label.offset, false, false);
    _labelScope.add(name, element);
    label.staticElement = element;
  }

  @override
  void visitListLiteral(ListLiteral node) {
    node.typeArguments?.accept(this);
    node.elements.accept(this);
    DartType type = _translateType(
        _get(node.constKeyword ?? node.leftBracket).inferredType);
    node.staticType = type;
  }

  @override
  void visitMapLiteral(MapLiteral node) {
    node.typeArguments?.accept(this);
    node.entries.accept(this);
    DartType type = _translateType(
        _get(node.constKeyword ?? node.leftBracket).inferredType);
    node.staticType = type;
  }

  @override
  void visitMethodInvocation(MethodInvocation node) {
    node.target?.accept(this);
    node.typeArguments?.accept(this);

    ArgumentList argumentList = node.argumentList;

    var data = _get(argumentList);
    Element invokeElement;
    if (data.loadLibrary != null) {
      LibraryElement libraryElement =
          _translateAuxiliaryReference(data.loadLibrary);
      invokeElement = libraryElement.loadLibraryFunction;
    } else if (data.isImplicitCall) {
      if (node.methodName != null) {
        node.methodName.accept(this);
        invokeElement = node.methodName.staticElement;
      }
    } else {
      invokeElement = _translateReference(data);
    }
    DartType invokeType = _translateType(data.invokeType);
    DartType resultType = _translateType(data.inferredType);

    if (invokeElement is PropertyInducingElement) {
      PropertyInducingElement property = invokeElement;
      invokeElement = property.getter;
    }

    node.staticInvokeType = invokeType;
    node.staticType = resultType;

    if (node.methodName.name == 'call' && invokeElement == null) {
      // Don't resolve explicit call() invocation of function types.
    } else if (_get(node.methodName.token,
            isSynthetic: node.methodName.isSynthetic, failIfAbsent: false) !=
        null) {
      node.methodName.accept(this);
    } else {
      node.methodName.staticElement = invokeElement;
      node.methodName.staticType = invokeType;
    }

    argumentList.accept(this);

    {
      var elementForParameters = invokeElement;
      if (elementForParameters is PropertyAccessorElement) {
        PropertyAccessorElement accessor = elementForParameters;
        elementForParameters = accessor.returnType.element;
      }
      List<ParameterElement> parameters;
      if (elementForParameters is FunctionTypedElement) {
        parameters = elementForParameters.parameters;
      } else if (elementForParameters is ParameterElement) {
        var type = elementForParameters.type;
        if (type is FunctionType) {
          parameters = type.parameters;
        }
      }
      _resolveArgumentsToParameters(argumentList, parameters);
    }

    if (invokeElement is ConstructorElement) {
      _rewriteIntoInstanceCreation(node, invokeElement, invokeType, resultType);
    }
  }

  @override
  void visitNativeFunctionBody(NativeFunctionBody node) {
    // nothing to resolve
  }

  @override
  void visitParenthesizedExpression(ParenthesizedExpression node) {
    node.visitChildren(this);
    node.staticType = node.expression.staticType;
  }

  @override
  void visitPostfixExpression(PostfixExpression node) {
    node.operand.accept(this);
    SyntacticEntity entity =
        _getAssignmentEntity(node.operand) ?? node.operator;
    var data = _get(entity);
    node.staticElement = _translateAuxiliaryReference(data.combiner);
    node.staticType = _translateType(data.inferredType);
  }

  @override
  void visitPrefixedIdentifier(PrefixedIdentifier node) {
    node.prefix.accept(this);
    node.identifier.accept(this);
    node.staticType = node.identifier.staticType;
  }

  @override
  void visitPrefixExpression(PrefixExpression node) {
    node.operand.accept(this);
    TokenType tokenType = node.operator.type;
    if (tokenType.isIncrementOperator) {
      // ++v;
      // This is an assignment, it is associated with the operand.
      SyntacticEntity entity =
          _getAssignmentEntity(node.operand) ?? node.operator;
      var data = _get(entity);
      node.staticElement = _translateAuxiliaryReference(data.combiner);
      node.staticType = _translateType(data.inferredType);
    } else if (tokenType == TokenType.BANG) {
      // !boolExpression;
      node.staticType = _translateType(_get(node).inferredType);
    } else {
      // ~v;
      // This is a method invocation, it is associated with the operator.
      SyntacticEntity entity = node.operator;
      var data = _get(entity);
      node.staticElement = _translateReference(data);
      node.staticType = _translateType(data.inferredType);
    }
  }

  @override
  void visitPropertyAccess(PropertyAccess node) {
    node.target?.accept(this);
    node.propertyName.accept(this);
    node.staticType = node.propertyName.staticType;
  }

  @override
  void visitRedirectingConstructorInvocation(
      RedirectingConstructorInvocation node) {
    SimpleIdentifier constructorName = node.constructorName;

    ConstructorElement element =
        _translateReference(_get(constructorName ?? node));
    node.staticElement = element;
    constructorName?.staticElement = element;

    ArgumentList argumentList = node.argumentList;
    argumentList.accept(this);
    _resolveArgumentsToParameters(argumentList, element?.parameters);
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    var data = _get(node, isSynthetic: node.token.isSynthetic);
    if (data.prefixInfo != null) {
      node.staticElement = _translatePrefixInfo(data.prefixInfo);
    } else if (data.declaration != null) {
      node.staticElement = _translateDeclaration(data.declaration);
    } else if (data.loadLibrary != null) {
      LibraryElement library = _translateAuxiliaryReference(data.loadLibrary);
      node.staticElement = library.loadLibraryFunction;
    } else {
      node.staticElement = _translateReference(data);
    }
    node.staticType = _translateType(
        data.isWriteReference ? data.writeContext : data.inferredType);
  }

  @override
  void visitStringInterpolation(StringInterpolation node) {
    for (var element in node.elements) {
      if (element is InterpolationExpression) {
        element.expression.accept(this);
      }
    }
    node.staticType = _typeContext.stringType;
  }

  @override
  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    SimpleIdentifier constructorName = node.constructorName;
    var superElement = _typeContext.enclosingClassElement.supertype.element;
    ConstructorElement element;
    if (constructorName == null) {
      element = superElement.unnamedConstructor;
    } else {
      String name = constructorName.name;
      element = superElement.getNamedConstructor(name);
      constructorName.staticElement = element;
    }
    node.staticElement = element;

    ArgumentList argumentList = node.argumentList;
    argumentList.accept(this);
    _resolveArgumentsToParameters(argumentList, element?.parameters);
  }

  @override
  void visitSuperExpression(SuperExpression node) {
    node.staticType = _typeContext.enclosingClassElement?.type;
  }

  @override
  void visitThisExpression(ThisExpression node) {
    node.staticType = _typeContext.enclosingClassElement?.type;
  }

  @override
  void visitTypeName(TypeName node) {
    super.visitTypeName(node);
    node.type = node.name.staticType;
  }

  @override
  visitTypeParameter(TypeParameter node) {
    node.bound?.accept(this);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    AstNode parent = node.parent;
    if (parent is VariableDeclarationList &&
        (parent.parent is TopLevelVariableDeclaration ||
            parent.parent is FieldDeclaration)) {
      // Don't visit the name; resolution for it will come from the outline.
    } else {
      DartType type = _translateType(
          _get(node.name, isSynthetic: node.name.isSynthetic).inferredType);
      node.name.staticType = type;

      VariableElementImpl element = node.name.staticElement;
      if (element != null) {
        _typeContext.encloseVariable(element);
        node.name.staticElement = element;
        element.type = type;
      }

      node.initializer?.accept(this);

      if (element is ConstVariableElement) {
        (element as ConstVariableElement).constantInitializer =
            node.initializer;
      }
    }
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    if (node.parent is TopLevelVariableDeclaration) {
      node.variables.accept(this);
    } else {
      node.type?.accept(this);
      node.metadata.accept(this);
      node.variables.accept(this);
    }
  }

  ResolutionData _get(SyntacticEntity entity,
      {bool failIfAbsent = true, bool isSynthetic = false}) {
    int entityOffset = entity.offset;
    var encodedLocation = 2 * entityOffset + (isSynthetic ? 1 : 0);
    var data = _data[encodedLocation];
    if (failIfAbsent && data == null) {
      String fileName = _enclosingLibraryElement.source.fullName;
      throw new StateError('No data for $entity at (offset=$entityOffset, '
          'isSynthetic=$isSynthetic) in $fileName');
    }
    return data;
  }

  /// Return the [SyntacticEntity] with which the front-end associates
  /// assignment to the given [leftHandSide].
  SyntacticEntity _getAssignmentEntity(Expression leftHandSide) {
    if (leftHandSide is SimpleIdentifier) {
      return leftHandSide;
    } else if (leftHandSide is PrefixedIdentifier) {
      return leftHandSide.identifier;
    } else if (leftHandSide is PropertyAccess) {
      return leftHandSide.propertyName;
    } else if (leftHandSide is IndexExpressionImpl) {
      return leftHandSide.leftBracket;
    } else if (leftHandSide is ParenthesizedExpression) {
      return leftHandSide.rightParenthesis;
    } else {
      return null;
    }
  }

  /// Resolve arguments of the [argumentList] to corresponding [parameters].
  void _resolveArgumentsToParameters(
      ArgumentList argumentList, List<ParameterElement> parameters) {
    if (parameters != null) {
      var numberOfPositionalParameters = 0;
      for (var parameter in parameters) {
        if (parameter.isPositional) {
          numberOfPositionalParameters++;
        }
      }

      var numberOfArguments = argumentList.arguments.length;
      if (numberOfArguments == numberOfPositionalParameters &&
          numberOfPositionalParameters == parameters.length) {
        argumentList.correspondingStaticParameters = parameters;
        return;
      }

      var resolvedParameters = new List<ParameterElement>(numberOfArguments);
      for (var i = 0; i < numberOfArguments; i++) {
        var argument = argumentList.arguments[i];
        ParameterElement argumentParameter;
        if (argument is NamedExpression) {
          SimpleIdentifier identifier = argument.name.label;
          for (var parameter in parameters) {
            if (parameter.name == identifier.name) {
              argumentParameter = parameter;
              identifier.staticElement = parameter;
              break;
            }
          }
        } else if (i < parameters.length && parameters[i].isPositional) {
          argumentParameter = parameters[i];
        }
        resolvedParameters[i] = argumentParameter;
      }

      argumentList.correspondingStaticParameters = resolvedParameters;
    }
  }

  /// Rewrite AST if the [node] represents an instance creation.
  void _rewriteIntoInstanceCreation(
      MethodInvocation node,
      ConstructorElement invokeElement,
      DartType invokeType,
      DartType resultType) {
    if (node.isCascaded) {
      return;
    }

    Identifier typeIdentifier;
    Token constructorIdentifierPeriod;
    SimpleIdentifier constructorIdentifier;
    var target = node.target;
    if (target == null) {
      SimpleIdentifier simpleTypeIdentifier = node.methodName;
      simpleTypeIdentifier.staticElement = resultType.element;
      simpleTypeIdentifier.staticType = resultType;

      typeIdentifier = simpleTypeIdentifier;
    } else if (target is SimpleIdentifier) {
      if (target.staticElement is PrefixElement) {
        SimpleIdentifier simpleTypeIdentifier = node.methodName;
        simpleTypeIdentifier.staticElement = resultType.element;
        simpleTypeIdentifier.staticType = resultType;

        typeIdentifier = astFactory.prefixedIdentifier(
            target, node.operator, simpleTypeIdentifier);
      } else {
        typeIdentifier = target;

        constructorIdentifierPeriod = node.operator;
        constructorIdentifier = node.methodName;
      }
    } else {
      PrefixedIdentifier prefixed = target;
      typeIdentifier = prefixed;

      constructorIdentifierPeriod = prefixed.period;
      constructorIdentifier = node.methodName;
    }

    var typeName = astFactory.typeName(typeIdentifier, node.typeArguments);
    typeName.type = resultType;

    var creation = astFactory.instanceCreationExpression(
      null,
      astFactory.constructorName(
        typeName,
        constructorIdentifierPeriod,
        constructorIdentifier,
      ),
      node.argumentList,
    );
    creation.staticElement = invokeElement;
    creation.staticType = resultType;
    NodeReplacer.replace(node, creation);
  }

  void _storeFunctionType(DartType type, FunctionTypedElementImpl element) {
    if (type is FunctionType && element != null) {
      DartType Function(DartType) substituteConstituentType;
      if (type.typeFormals.length == element.typeParameters.length &&
          type.typeFormals.length != 0) {
        var argumentTypes = element.typeParameters.map((e) => e.type).toList();
        var parameterTypes = type.typeFormals.map((e) {
          var type = e.type;
          var element = type.element;
          if (element is TypeParameterMember) {
            return element.baseElement.type;
          } else {
            return type;
          }
        }).toList();
        substituteConstituentType =
            (DartType t) => t.substitute2(argumentTypes, parameterTypes);
        for (int i = 0; i < type.typeFormals.length; i++) {
          (element.typeParameters[i] as TypeParameterElementImpl).bound =
              type.typeFormals[i].bound == null
                  ? null
                  : substituteConstituentType(type.typeFormals[i].bound);
        }
      } else {
        substituteConstituentType = (DartType t) => t;
      }
      element.returnType = substituteConstituentType(type.returnType);
      int normalParameterIndex = 0;
      int optionalParameterIndex = 0;
      for (ParameterElementImpl parameter in element.parameters) {
        if (parameter.isNamed) {
          parameter.type = substituteConstituentType(
              type.namedParameterTypes[parameter.name]);
        } else if (normalParameterIndex < type.normalParameterTypes.length) {
          parameter.type = substituteConstituentType(
              type.normalParameterTypes[normalParameterIndex++]);
        } else if (optionalParameterIndex <
            type.optionalParameterTypes.length) {
          parameter.type = substituteConstituentType(
              type.optionalParameterTypes[optionalParameterIndex++]);
        }
      }
    }
  }

  Element _translateAuxiliaryReference(kernel.Node reference) {
    return _typeContext.translateReference(reference);
  }

  Element _translateDeclaration(int declaration) {
    return _typeContext.translateDeclaration(declaration);
  }

  Element _translatePrefixInfo(int prefixInfo) {
    return _typeContext.translatePrefixInfo(prefixInfo);
  }

  Element _translateReference(ResolutionData data) {
    if (data.isPrefixReference) {
      return _translatePrefixInfo(data.prefixInfo);
    }
    return _typeContext.translateReference(data.reference,
        isNamespaceCombinatorReference: data.isNamespaceCombinatorReference,
        isTypeReference: data.isTypeReference,
        isWriteReference: data.isWriteReference,
        inferredType: data.inferredType,
        receiverType: data.receiverType);
  }

  DartType _translateType(kernel.DartType type) {
    return _typeContext.translateType(type);
  }
}

/// A container with [typeArguments].
class TypeArgumentsDartType implements ParameterizedType {
  @override
  final List<DartType> typeArguments;

  TypeArgumentsDartType(this.typeArguments);

  @override
  bool get isUndefined => false;

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);

  @override
  String toString() {
    return '<${typeArguments.join(', ')}>';
  }
}

/// Context for translating types.
abstract class TypeContext {
  /// The enclosing [ClassElement], or `null` if not in a class.
  ClassElement get enclosingClassElement;

  DartType get stringType;

  DartType get typeType;

  /// Attach the variable [element] to the current executable.
  void encloseVariable(ElementImpl element);

  /// Finalize the given function [element] - set all types for it.
  /// Then make it the current executable.
  void enterLocalFunction(FunctionTypedElementImpl element);

  /// Restore the current executable that was before the [element].
  void exitLocalFunction(FunctionTypedElementImpl element);

  /// Return the Analyzer [Element] for the local declaration having the given
  /// offset.
  Element translateDeclaration(int declarationOffset);

  /// Return the analyzer [Element] for the import prefix corresponding to the
  /// import having the given offset.
  PrefixElement translatePrefixInfo(int importIndex);

  /// Return the analyzer [Element] for the given kernel node.
  Element translateReference(kernel.Node referencedNode,
      {bool isNamespaceCombinatorReference = false,
      bool isTypeReference = false,
      bool isWriteReference = false,
      kernel.DartType inferredType,
      kernel.DartType receiverType});

  /// Return the Analyzer [DartType] for the given [kernelType].
  DartType translateType(kernel.DartType kernelType);
}

/// The hierarchical scope for labels.
class _LabelScope {
  final _LabelScope parent;
  final Map<String, LabelElement> elements = {};

  _LabelScope(this.parent);

  LabelElement operator [](String name) {
    var element = elements[name];
    if (element != null) {
      return element;
    }
    if (parent != null) {
      return parent[name];
    }
    return null;
  }

  void add(String name, LabelElement element) {
    elements[name] = element;
  }
}
