// Copyright (c) 2018, 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/token.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/element/element.dart';
import 'package:analyzer/src/generated/resolver.dart' show AstRewriteVisitor;
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/resynthesize.dart';

/**
 * Builder of [Expression]s from [UnlinkedExpr]s.
 */
class ExprBuilder {
  static const ARGUMENT_LIST = 'ARGUMENT_LIST';

  final UnitResynthesizer resynthesizer;
  final ElementImpl context;
  final UnlinkedExpr _uc;
  final bool requireValidConst;

  int intPtr = 0;
  int doublePtr = 0;
  int stringPtr = 0;
  int refPtr = 0;
  int assignmentOperatorPtr = 0;
  final List<Expression> stack = <Expression>[];

  final List<UnlinkedExecutable> localFunctions;

  final Map<String, ParameterElement> parametersInScope;

  ExprBuilder(this.resynthesizer, this.context, this._uc,
      {this.requireValidConst: true,
      this.localFunctions,
      Map<String, ParameterElement> parametersInScope})
      : this.parametersInScope =
            parametersInScope ?? _parametersInScope(context);

  bool get hasNonEmptyExpr => _uc != null && _uc.operations.isNotEmpty;

  Expression build() {
    if (requireValidConst && !_uc.isValidConst) {
      return null;
    }
    for (UnlinkedExprOperation operation in _uc.operations) {
      switch (operation) {
        case UnlinkedExprOperation.pushNull:
          _push(AstTestFactory.nullLiteral());
          break;
        // bool
        case UnlinkedExprOperation.pushFalse:
          _push(AstTestFactory.booleanLiteral(false));
          break;
        case UnlinkedExprOperation.pushTrue:
          _push(AstTestFactory.booleanLiteral(true));
          break;
        // literals
        case UnlinkedExprOperation.pushInt:
          int value = _uc.ints[intPtr++];
          _push(AstTestFactory.integer(value));
          break;
        case UnlinkedExprOperation.pushLongInt:
          int value = 0;
          int count = _uc.ints[intPtr++];
          for (int i = 0; i < count; i++) {
            int next = _uc.ints[intPtr++];
            value = value << 32 | next;
          }
          _push(AstTestFactory.integer(value));
          break;
        case UnlinkedExprOperation.pushDouble:
          double value = _uc.doubles[doublePtr++];
          _push(AstTestFactory.doubleLiteral(value));
          break;
        case UnlinkedExprOperation.makeSymbol:
          String component = _uc.strings[stringPtr++];
          _push(AstTestFactory.symbolLiteral([component]));
          break;
        // String
        case UnlinkedExprOperation.pushString:
          String value = _uc.strings[stringPtr++];
          _push(AstTestFactory.string2(value));
          break;
        case UnlinkedExprOperation.concatenate:
          int count = _uc.ints[intPtr++];
          List<InterpolationElement> elements = <InterpolationElement>[];
          for (int i = 0; i < count; i++) {
            Expression expr = _pop();
            InterpolationElement element = _newInterpolationElement(expr);
            elements.insert(0, element);
          }
          _push(AstTestFactory.string(elements));
          break;
        // binary
        case UnlinkedExprOperation.equal:
          _pushBinary(TokenType.EQ_EQ);
          break;
        case UnlinkedExprOperation.notEqual:
          _pushBinary(TokenType.BANG_EQ);
          break;
        case UnlinkedExprOperation.and:
          _pushBinary(TokenType.AMPERSAND_AMPERSAND);
          break;
        case UnlinkedExprOperation.or:
          _pushBinary(TokenType.BAR_BAR);
          break;
        case UnlinkedExprOperation.bitXor:
          _pushBinary(TokenType.CARET);
          break;
        case UnlinkedExprOperation.bitAnd:
          _pushBinary(TokenType.AMPERSAND);
          break;
        case UnlinkedExprOperation.bitOr:
          _pushBinary(TokenType.BAR);
          break;
        case UnlinkedExprOperation.bitShiftLeft:
          _pushBinary(TokenType.LT_LT);
          break;
        case UnlinkedExprOperation.bitShiftRight:
          _pushBinary(TokenType.GT_GT);
          break;
        case UnlinkedExprOperation.add:
          _pushBinary(TokenType.PLUS);
          break;
        case UnlinkedExprOperation.subtract:
          _pushBinary(TokenType.MINUS);
          break;
        case UnlinkedExprOperation.multiply:
          _pushBinary(TokenType.STAR);
          break;
        case UnlinkedExprOperation.divide:
          _pushBinary(TokenType.SLASH);
          break;
        case UnlinkedExprOperation.floorDivide:
          _pushBinary(TokenType.TILDE_SLASH);
          break;
        case UnlinkedExprOperation.modulo:
          _pushBinary(TokenType.PERCENT);
          break;
        case UnlinkedExprOperation.greater:
          _pushBinary(TokenType.GT);
          break;
        case UnlinkedExprOperation.greaterEqual:
          _pushBinary(TokenType.GT_EQ);
          break;
        case UnlinkedExprOperation.less:
          _pushBinary(TokenType.LT);
          break;
        case UnlinkedExprOperation.lessEqual:
          _pushBinary(TokenType.LT_EQ);
          break;
        // prefix
        case UnlinkedExprOperation.complement:
          _pushPrefix(TokenType.TILDE);
          break;
        case UnlinkedExprOperation.negate:
          _pushPrefix(TokenType.MINUS);
          break;
        case UnlinkedExprOperation.not:
          _pushPrefix(TokenType.BANG);
          break;
        // conditional
        case UnlinkedExprOperation.conditional:
          Expression elseExpr = _pop();
          Expression thenExpr = _pop();
          Expression condition = _pop();
          _push(AstTestFactory.conditionalExpression(
              condition, thenExpr, elseExpr));
          break;
        case UnlinkedExprOperation.invokeMethodRef:
          _pushInvokeMethodRef();
          break;
        case UnlinkedExprOperation.invokeMethod:
          List<Expression> arguments = _buildArguments();
          TypeArgumentList typeArguments = _buildTypeArguments();
          Expression target = _pop();
          String name = _uc.strings[stringPtr++];
          _push(AstTestFactory.methodInvocation3(
              target, name, typeArguments, arguments));
          break;
        // containers
        case UnlinkedExprOperation.makeUntypedList:
          _pushList(null);
          break;
        case UnlinkedExprOperation.makeTypedList:
          TypeAnnotation itemType = _newTypeName();
          _pushList(
              AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
          break;
        case UnlinkedExprOperation.makeUntypedMap:
          _pushMap(null);
          break;
        case UnlinkedExprOperation.makeTypedMap:
          TypeAnnotation keyType = _newTypeName();
          TypeAnnotation valueType = _newTypeName();
          _pushMap(AstTestFactory.typeArgumentList(
              <TypeAnnotation>[keyType, valueType]));
          break;
        case UnlinkedExprOperation.makeUntypedSet:
          _pushSet(null);
          break;
        case UnlinkedExprOperation.makeTypedSet:
          TypeAnnotation itemType = _newTypeName();
          _pushSet(AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
          break;
        case UnlinkedExprOperation.pushReference:
          _pushReference();
          break;
        case UnlinkedExprOperation.extractProperty:
          _pushExtractProperty();
          break;
        case UnlinkedExprOperation.invokeConstructor:
          _pushInstanceCreation();
          break;
        case UnlinkedExprOperation.pushParameter:
          String name = _uc.strings[stringPtr++];
          SimpleIdentifier identifier = AstTestFactory.identifier3(name);
          identifier.staticElement = parametersInScope[name];
          _push(identifier);
          break;
        case UnlinkedExprOperation.ifNull:
          _pushBinary(TokenType.QUESTION_QUESTION);
          break;
        case UnlinkedExprOperation.await:
          Expression expression = _pop();
          _push(AstTestFactory.awaitExpression(expression));
          break;
        case UnlinkedExprOperation.pushLocalFunctionReference:
          _pushLocalFunctionReference();
          break;
        case UnlinkedExprOperation.assignToRef:
          var ref = _createReference();
          _push(_createAssignment(ref));
          break;
        case UnlinkedExprOperation.typeCast:
          Expression expression = _pop();
          TypeAnnotation type = _newTypeName();
          _push(AstTestFactory.asExpression(expression, type));
          break;
        case UnlinkedExprOperation.typeCheck:
          Expression expression = _pop();
          TypeAnnotation type = _newTypeName();
          _push(AstTestFactory.isExpression(expression, false, type));
          break;
        case UnlinkedExprOperation.throwException:
          Expression expression = _pop();
          _push(AstTestFactory.throwExpression2(expression));
          break;
        case UnlinkedExprOperation.assignToProperty:
          Expression target = _pop();
          String name = _uc.strings[stringPtr++];
          SimpleIdentifier propertyNode = AstTestFactory.identifier3(name);
          PropertyAccess propertyAccess =
              AstTestFactory.propertyAccess(target, propertyNode);
          _push(_createAssignment(propertyAccess));
          break;
        case UnlinkedExprOperation.assignToIndex:
          Expression index = _pop();
          Expression target = _pop();
          IndexExpression indexExpression =
              AstTestFactory.indexExpression(target, index);
          _push(_createAssignment(indexExpression));
          break;
        case UnlinkedExprOperation.extractIndex:
          Expression index = _pop();
          Expression target = _pop();
          _push(AstTestFactory.indexExpression(target, index));
          break;
        case UnlinkedExprOperation.pushSuper:
          _push(AstTestFactory.superExpression());
          break;
        case UnlinkedExprOperation.pushThis:
          _push(AstTestFactory.thisExpression());
          break;
        case UnlinkedExprOperation.cascadeSectionBegin:
        case UnlinkedExprOperation.cascadeSectionEnd:
        case UnlinkedExprOperation.pushLocalFunctionReference:
        case UnlinkedExprOperation.pushError:
        case UnlinkedExprOperation.pushTypedAbstract:
        case UnlinkedExprOperation.pushUntypedAbstract:
          throw new UnimplementedError(
              'Unexpected $operation in a constant expression.');
      }
    }
    return stack.single;
  }

  List<Expression> _buildArguments() {
    List<Expression> arguments;
    {
      int numNamedArgs = _uc.ints[intPtr++];
      int numPositionalArgs = _uc.ints[intPtr++];
      int numArgs = numNamedArgs + numPositionalArgs;
      arguments = _removeTopItems(numArgs);
      // add names to the named arguments
      for (int i = 0; i < numNamedArgs; i++) {
        String name = _uc.strings[stringPtr++];
        int index = numPositionalArgs + i;
        arguments[index] =
            AstTestFactory.namedExpression2(name, arguments[index]);
      }
    }
    return arguments;
  }

  /// Given the sequence of identifiers in [node], and the [classElement] or
  /// [constructorElement] to which this sequence resolves, build the
  /// [InstanceCreationExpression].
  InstanceCreationExpression _buildCreation(
    Expression node,
    TypeArgumentList typeArguments,
    ArgumentList argumentList, {
    ClassElement classElement,
    ConstructorElement constructorElement,
  }) {
    InstanceCreationExpression composeCreation(
        DartType type,
        ConstructorName constructorName,
        ConstructorElement constructorElement,
        ArgumentList argumentList) {
      TypeName typeName = constructorName.type;
      typeName.type = type;

      constructorName.name?.staticElement = constructorElement;

      var creation = astFactory.instanceCreationExpression(
          _uc.isValidConst
              ? TokenFactory.tokenFromKeyword(Keyword.CONST)
              : TokenFactory.tokenFromKeyword(Keyword.NEW),
          constructorName,
          argumentList);

      creation.staticElement = constructorElement;
      creation.staticType = type;
      return creation;
    }

    classElement ??= constructorElement?.enclosingElement;
    var type = AstRewriteVisitor.getType(
        resynthesizer.typeSystem, classElement, typeArguments);

    // C()
    if (node is SimpleIdentifier && classElement != null) {
      constructorElement = type.lookUpConstructor('', resynthesizer.library);
      node.staticType = type;
      return composeCreation(
        type,
        astFactory.constructorName(
          astFactory.typeName(node, typeArguments),
          null,
          null,
        ),
        constructorElement,
        argumentList,
      );
    }
    if (node is PrefixedIdentifier) {
      // C.n()
      if (constructorElement != null) {
        constructorElement =
            type.lookUpConstructor(node.identifier.name, resynthesizer.library);
        node.prefix.staticType = type;
        return composeCreation(
          type,
          astFactory.constructorName(
            astFactory.typeName(node.prefix, typeArguments),
            TokenFactory.tokenFromType(TokenType.PERIOD),
            node.identifier,
          ),
          constructorElement,
          argumentList,
        );
      }
      // p.C()
      if (classElement != null) {
        constructorElement = type.lookUpConstructor('', resynthesizer.library);
        node.identifier.staticType = type;
        return composeCreation(
          type,
          astFactory.constructorName(
            astFactory.typeName(node.identifier, typeArguments),
            null,
            null,
          ),
          constructorElement,
          argumentList,
        );
      }
    }
    // p.C.n()
    if (node is PropertyAccess && constructorElement != null) {
      constructorElement =
          type.lookUpConstructor(node.propertyName.name, resynthesizer.library);
      var typeIdentifier = (node.target as PrefixedIdentifier).identifier;
      typeIdentifier.staticType = type;
      return composeCreation(
        type,
        astFactory.constructorName(
          astFactory.typeName(typeIdentifier, typeArguments),
          TokenFactory.tokenFromType(TokenType.PERIOD),
          node.propertyName,
        ),
        constructorElement,
        argumentList,
      );
    }

    throw new UnimplementedError('For ${node?.runtimeType}: $node; '
        'class: $classElement;  constructor: $constructorElement');
  }

  /**
   * Build the identifier sequence (a single or prefixed identifier, or a
   * property access) corresponding to the given reference [info].
   */
  Expression _buildIdentifierSequence(ReferenceInfo info) {
    Expression enclosing;
    if (info.enclosing != null) {
      enclosing = _buildIdentifierSequence(info.enclosing);
    }
    Element element = info.element;
    if (element == null && info.name == 'length') {
      element = _getStringLengthElement();
    }
    if (enclosing == null) {
      return AstTestFactory.identifier3(info.name)..staticElement = element;
    }
    if (enclosing is SimpleIdentifier) {
      SimpleIdentifier identifier = AstTestFactory.identifier3(info.name)
        ..staticElement = element;
      return AstTestFactory.identifier(enclosing, identifier);
    }
    SimpleIdentifier property = AstTestFactory.identifier3(info.name)
      ..staticElement = element;
    return AstTestFactory.propertyAccess(enclosing, property);
  }

  TypeArgumentList _buildTypeArguments() {
    int numTypeArguments = _uc.ints[intPtr++];
    if (numTypeArguments == 0) {
      return null;
    }

    var typeNames = new List<TypeAnnotation>(numTypeArguments);
    for (int i = 0; i < numTypeArguments; i++) {
      typeNames[i] = _newTypeName();
    }
    return AstTestFactory.typeArgumentList(typeNames);
  }

  TypeAnnotation _buildTypeAst(DartType type) {
    List<TypeAnnotation> argumentNodes;
    if (type is ParameterizedType) {
      if (!resynthesizer.doesTypeHaveImplicitArguments(type)) {
        List<DartType> typeArguments = type.typeArguments;
        argumentNodes = typeArguments.every((a) => a.isDynamic)
            ? null
            : typeArguments.map(_buildTypeAst).toList();
      }
    }
    TypeName node = AstTestFactory.typeName4(type.name, argumentNodes);
    node.type = type;
    (node.name as SimpleIdentifier).staticElement = type.element;
    return node;
  }

  Expression _createAssignment(Expression lhs) {
    Expression binary(TokenType tokenType) {
      return AstTestFactory.assignmentExpression(lhs, tokenType, _pop());
    }

    Expression prefix(TokenType tokenType) {
      return AstTestFactory.prefixExpression(tokenType, lhs);
    }

    Expression postfix(TokenType tokenType) {
      return AstTestFactory.postfixExpression(lhs, tokenType);
    }

    switch (_uc.assignmentOperators[assignmentOperatorPtr++]) {
      case UnlinkedExprAssignOperator.assign:
        return binary(TokenType.EQ);
      case UnlinkedExprAssignOperator.ifNull:
        return binary(TokenType.QUESTION_QUESTION_EQ);
      case UnlinkedExprAssignOperator.multiply:
        return binary(TokenType.STAR_EQ);
      case UnlinkedExprAssignOperator.divide:
        return binary(TokenType.SLASH_EQ);
      case UnlinkedExprAssignOperator.floorDivide:
        return binary(TokenType.TILDE_SLASH_EQ);
      case UnlinkedExprAssignOperator.modulo:
        return binary(TokenType.PERCENT_EQ);
      case UnlinkedExprAssignOperator.plus:
        return binary(TokenType.PLUS_EQ);
      case UnlinkedExprAssignOperator.minus:
        return binary(TokenType.MINUS_EQ);
      case UnlinkedExprAssignOperator.shiftLeft:
        return binary(TokenType.LT_LT_EQ);
      case UnlinkedExprAssignOperator.shiftRight:
        return binary(TokenType.GT_GT_EQ);
      case UnlinkedExprAssignOperator.bitAnd:
        return binary(TokenType.AMPERSAND_EQ);
      case UnlinkedExprAssignOperator.bitXor:
        return binary(TokenType.CARET_EQ);
      case UnlinkedExprAssignOperator.bitOr:
        return binary(TokenType.BAR_EQ);
      case UnlinkedExprAssignOperator.prefixIncrement:
        return prefix(TokenType.PLUS_PLUS);
      case UnlinkedExprAssignOperator.prefixDecrement:
        return prefix(TokenType.MINUS_MINUS);
      case UnlinkedExprAssignOperator.postfixIncrement:
        return postfix(TokenType.PLUS_PLUS);
      case UnlinkedExprAssignOperator.postfixDecrement:
        return postfix(TokenType.MINUS_MINUS);
      default:
        throw new UnimplementedError('Unexpected UnlinkedExprAssignOperator');
    }
  }

  Expression _createReference() {
    EntityRef ref = _uc.references[refPtr++];
    if (ref.paramReference != 0) {
      // This is a reference to a type parameter.  For type inference purposes
      // we don't actually need to know which type parameter it's a reference
      // to; we just need to know that it represents a type.  So map it to
      // `Object`.
      return AstTestFactory.identifier3('Object')
        ..staticElement = resynthesizer.typeProvider.objectType.element;
    }
    ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    return _buildIdentifierSequence(info);
  }

  PropertyAccessorElement _getStringLengthElement() =>
      resynthesizer.typeProvider.stringType.getGetter('length');

  FormalParameter _makeParameter(ParameterElement param) {
    SimpleFormalParameterImpl simpleParam =
        AstTestFactory.simpleFormalParameter(null, param.name);
    simpleParam.identifier.staticElement = param;
    simpleParam.declaredElement = param;
    var unlinkedParam = (param as ParameterElementImpl).unlinkedParam;
    if (unlinkedParam.kind == UnlinkedParamKind.positional) {
      return AstTestFactory.positionalFormalParameter(simpleParam, null);
    } else if (unlinkedParam.kind == UnlinkedParamKind.named) {
      return AstTestFactory.namedFormalParameter(simpleParam, null);
    } else {
      return simpleParam;
    }
  }

  InterpolationElement _newInterpolationElement(Expression expr) {
    if (expr is SimpleStringLiteral) {
      return astFactory.interpolationString(expr.literal, expr.value);
    } else {
      return astFactory.interpolationExpression(
          TokenFactory.tokenFromType(TokenType.STRING_INTERPOLATION_EXPRESSION),
          expr,
          TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
    }
  }

  /**
   * Convert the next reference to the [DartType] and return the AST
   * corresponding to this type.
   */
  TypeAnnotation _newTypeName() {
    EntityRef typeRef = _uc.references[refPtr++];
    DartType type = resynthesizer.buildType(context, typeRef);
    return _buildTypeAst(type);
  }

  Expression _pop() => stack.removeLast();

  void _push(Expression expr) {
    stack.add(expr);
  }

  void _pushBinary(TokenType operator) {
    Expression right = _pop();
    Expression left = _pop();
    _push(AstTestFactory.binaryExpression(left, operator, right));
  }

  void _pushExtractProperty() {
    Expression target = _pop();
    String name = _uc.strings[stringPtr++];
    SimpleIdentifier propertyNode = AstTestFactory.identifier3(name);
    // Only String.length property access can be potentially resolved.
    if (name == 'length') {
      propertyNode.staticElement = _getStringLengthElement();
    }
    _push(AstTestFactory.propertyAccess(target, propertyNode));
  }

  void _pushInstanceCreation() {
    EntityRef ref = _uc.references[refPtr++];
    ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    // prepare ConstructorElement
    TypeName typeNode;
    String constructorName;
    ConstructorElement constructorElement;
    if (info.element != null) {
      if (info.element is ConstructorElement) {
        constructorName = info.name;
      } else if (info.element is ClassElement) {
        constructorName = null;
      } else {
        // Unexpected element, consider it unresolved.
        _buildArguments();
        var identifier = AstTestFactory.identifier3('__unresolved__')
          ..staticType = resynthesizer.typeProvider.dynamicType;
        _push(identifier);
        return;
      }
      InterfaceType definingType = resynthesizer.createConstructorDefiningType(
          context, info, ref.typeArguments);
      constructorElement =
          resynthesizer.getConstructorForInfo(definingType, info);
      typeNode = _buildTypeAst(definingType);
    } else {
      if (info.enclosing != null) {
        if (info.enclosing.enclosing != null) {
          PrefixedIdentifier typeName = AstTestFactory.identifier5(
              info.enclosing.enclosing.name, info.enclosing.name);
          typeName.prefix.staticElement = info.enclosing.enclosing.element;
          typeName.identifier.staticElement = info.enclosing.element;
          typeName.identifier.staticType = info.enclosing.type;
          typeNode = AstTestFactory.typeName3(typeName);
          typeNode.type = info.enclosing.type;
          constructorName = info.name;
        } else if (info.enclosing.element != null) {
          SimpleIdentifier typeName =
              AstTestFactory.identifier3(info.enclosing.name);
          typeName.staticElement = info.enclosing.element;
          typeName.staticType = info.enclosing.type;
          typeNode = AstTestFactory.typeName3(typeName);
          typeNode.type = info.enclosing.type;
          constructorName = info.name;
        } else {
          typeNode = AstTestFactory.typeName3(
              AstTestFactory.identifier5(info.enclosing.name, info.name));
          constructorName = null;
        }
      } else {
        typeNode = AstTestFactory.typeName4(info.name);
      }
    }
    // prepare arguments
    List<Expression> arguments = _buildArguments();
    // create ConstructorName
    ConstructorName constructorNode;
    if (constructorName != null) {
      constructorNode =
          AstTestFactory.constructorName(typeNode, constructorName);
      constructorNode.name.staticElement = constructorElement;
    } else {
      constructorNode = AstTestFactory.constructorName(typeNode, null);
    }
    constructorNode.staticElement = constructorElement;
    // create InstanceCreationExpression
    InstanceCreationExpression instanceCreation =
        AstTestFactory.instanceCreationExpression(
            requireValidConst ? Keyword.CONST : Keyword.NEW,
            constructorNode,
            arguments);
    instanceCreation.staticElement = constructorElement;
    _push(instanceCreation);
  }

  void _pushInvokeMethodRef() {
    List<Expression> arguments = _buildArguments();
    EntityRef ref = _uc.references[refPtr++];
    ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    Expression node = _buildIdentifierSequence(info);
    TypeArgumentList typeArguments = _buildTypeArguments();
    var period = TokenFactory.tokenFromType(TokenType.PERIOD);
    var argumentList = AstTestFactory.argumentList(arguments);

    // Check for optional new/const.
    if (info.element is ClassElement) {
      _push(_buildCreation(node, typeArguments, argumentList,
          classElement: info.element));
      return;
    }
    if (info.element is ConstructorElement) {
      _push(_buildCreation(node, typeArguments, argumentList,
          constructorElement: info.element));
      return;
    }

    if (node is SimpleIdentifier) {
      _push(astFactory.methodInvocation(
          null, period, node, typeArguments, argumentList));
    } else if (node is PropertyAccess) {
      _push(astFactory.methodInvocation(
          node.target, period, node.propertyName, typeArguments, argumentList));
    } else if (node is PrefixedIdentifier) {
      _push(astFactory.methodInvocation(
          node.prefix, period, node.identifier, typeArguments, argumentList));
    } else {
      throw new UnimplementedError('For ${node?.runtimeType}: $node');
    }
  }

  void _pushList(TypeArgumentList typeArguments) {
    int count = _uc.ints[intPtr++];
    List<Expression> elements = <Expression>[];
    for (int i = 0; i < count; i++) {
      elements.insert(0, _pop());
    }
    var typeArg = typeArguments == null
        ? resynthesizer.typeProvider.dynamicType
        : typeArguments.arguments[0].type;
    var staticType = resynthesizer.typeProvider.listType.instantiate([typeArg]);
    _push(AstTestFactory.listLiteral2(Keyword.CONST, typeArguments, elements)
      ..staticType = staticType);
  }

  void _pushLocalFunctionReference() {
    int popCount = _uc.ints[intPtr++];
    // Note: nonzero popCount is no longer used.
    assert(popCount == 0);
    int functionIndex = _uc.ints[intPtr++];
    var localFunction = localFunctions[functionIndex];
    var parametersInScope =
        new Map<String, ParameterElement>.from(this.parametersInScope);
    var functionElement =
        new FunctionElementImpl.forSerialized(localFunction, context);
    for (ParameterElementImpl parameter in functionElement.parameters) {
      parametersInScope[parameter.name] = parameter;
      if (parameter.unlinkedParam.type == null) {
        // Store a type of `dynamic` for the parameter; this prevents
        // resynthesis from trying to read a type out of the summary (which
        // wouldn't work anyway, since nested functions don't have their
        // parameter types stored in the summary anyhow).
        parameter.type = resynthesizer.typeProvider.dynamicType;
      }
    }
    var parameters = functionElement.parameters.map(_makeParameter).toList();
    var asyncKeyword = localFunction.isAsynchronous
        ? TokenFactory.tokenFromKeyword(Keyword.ASYNC)
        : null;
    FunctionBody functionBody;
    if (localFunction.bodyExpr == null) {
      // Most likely the original source code contained a block function body
      // here.  Block function bodies aren't supported by the summary mechanism.
      // But they are tolerated when their presence doesn't affect inferred
      // types.
      functionBody = AstTestFactory.blockFunctionBody(AstTestFactory.block());
    } else {
      var bodyExpr = new ExprBuilder(
              resynthesizer, functionElement, localFunction.bodyExpr,
              requireValidConst: requireValidConst,
              parametersInScope: parametersInScope,
              localFunctions: localFunction.localFunctions)
          .build();
      functionBody = astFactory.expressionFunctionBody(asyncKeyword,
          TokenFactory.tokenFromType(TokenType.FUNCTION), bodyExpr, null);
    }
    FunctionExpressionImpl functionExpression = astFactory.functionExpression(
        null, AstTestFactory.formalParameterList(parameters), functionBody);
    functionExpression.declaredElement = functionElement;
    _push(functionExpression);
  }

  void _pushMap(TypeArgumentList typeArguments) {
    int count = _uc.ints[intPtr++];
    List<MapLiteralEntry> entries = <MapLiteralEntry>[];
    for (int i = 0; i < count; i++) {
      Expression value = _pop();
      Expression key = _pop();
      entries.insert(0, AstTestFactory.mapLiteralEntry2(key, value));
    }
    var keyType = typeArguments == null
        ? resynthesizer.typeProvider.dynamicType
        : typeArguments.arguments[0].type;
    var valueType = typeArguments == null
        ? resynthesizer.typeProvider.dynamicType
        : typeArguments.arguments[1].type;
    var staticType =
        resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
    _push(AstTestFactory.mapLiteral(Keyword.CONST, typeArguments, entries)
      ..staticType = staticType);
  }

  void _pushPrefix(TokenType operator) {
    Expression operand = _pop();
    _push(AstTestFactory.prefixExpression(operator, operand));
  }

  void _pushReference() {
    _push(_createReference());
  }

  void _pushSet(TypeArgumentList typeArguments) {
    int count = _uc.ints[intPtr++];
    List<Expression> elements = <Expression>[];
    for (int i = 0; i < count; i++) {
      elements.insert(0, _pop());
    }
    _push(AstTestFactory.setLiteral(Keyword.CONST, typeArguments, elements));
  }

  List<Expression> _removeTopItems(int count) {
    int start = stack.length - count;
    int end = stack.length;
    List<Expression> items = stack.getRange(start, end).toList();
    stack.removeRange(start, end);
    return items;
  }

  /// Figures out the default value of [parametersInScope] based on [context].
  ///
  /// If [context] is (or contains) a constructor, then its parameters are used.
  /// Otherwise, no parameters are considered to be in scope.
  static Map<String, ParameterElement> _parametersInScope(Element context) {
    var result = <String, ParameterElement>{};
    for (Element e = context; e != null; e = e.enclosingElement) {
      if (e is ConstructorElement) {
        for (var parameter in e.parameters) {
          result[parameter.name] = parameter;
        }
        return result;
      }
    }
    return result;
  }
}
