// 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);
      _resolveNamedArguments(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);
    var data = _get(entity);
    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);
    _resolveNamedArguments(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;
      }
      if (elementForParameters is FunctionTypedElement) {
        List<ParameterElement> parameters = elementForParameters.parameters;
        _resolveNamedArguments(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);
    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);
      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);
    _resolveNamedArguments(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);
    _resolveNamedArguments(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 {
      throw new StateError(
          'Unexpected LHS (${leftHandSide.runtimeType}) $leftHandSide');
    }
  }

  /// Apply resolution to named arguments of the [argumentList].
  void _resolveNamedArguments(
      ArgumentList argumentList, List<ParameterElement> parameters) {
    if (parameters != null) {
      for (var argument in argumentList.arguments) {
        if (argument is NamedExpression) {
          SimpleIdentifier identifier = argument.name.label;
          for (var parameter in parameters) {
            if (parameter.name == identifier.name) {
              identifier.staticElement = parameter;
              break;
            }
          }
        }
      }
    }
  }

  /// 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,
        isWriteReference: data.isWriteReference,
        isTypeReference: data.isTypeReference,
        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 isWriteReference = false,
      bool isTypeReference = 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;
  }
}
