// Copyright (c) 2019, 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/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/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary2/ast_binary_flags.dart';
import 'package:analyzer/src/summary2/ast_binary_tag.dart';
import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
import 'package:analyzer/src/summary2/bundle_reader.dart';
import 'package:analyzer/src/summary2/not_serializable_nodes.dart';
import 'package:analyzer/src/summary2/unlinked_token_type.dart';
import 'package:collection/collection.dart';

/// Deserializer of ASTs.
class AstBinaryReader {
  final ResolutionReader _reader;

  AstBinaryReader({
    required ResolutionReader reader,
  }) : _reader = reader;

  AstNode readNode() {
    var tag = _readByte();
    switch (tag) {
      case Tag.AdjacentStrings:
        return _readAdjacentStrings();
      case Tag.Annotation:
        return _readAnnotation();
      case Tag.ArgumentList:
        return _readArgumentList();
      case Tag.AsExpression:
        return _readAsExpression();
      case Tag.AssertInitializer:
        return _readAssertInitializer();
      case Tag.AssignmentExpression:
        return _readAssignmentExpression();
      case Tag.AwaitExpression:
        return _readAwaitExpression();
      case Tag.BinaryExpression:
        return _readBinaryExpression();
      case Tag.BooleanLiteral:
        return _readBooleanLiteral();
      case Tag.CascadeExpression:
        return _readCascadeExpression();
      case Tag.ConditionalExpression:
        return _readConditionalExpression();
      case Tag.ConstructorFieldInitializer:
        return _readConstructorFieldInitializer();
      case Tag.ConstructorName:
        return _readConstructorName();
      case Tag.ConstructorReference:
        return _readConstructorReference();
      case Tag.DeclaredIdentifier:
        return _readDeclaredIdentifier();
      case Tag.DefaultFormalParameter:
        return _readDefaultFormalParameter();
      case Tag.DottedName:
        return _readDottedName();
      case Tag.DoubleLiteral:
        return _readDoubleLiteral();
      case Tag.ExtensionOverride:
        return _readExtensionOverride();
      case Tag.ForEachPartsWithDeclaration:
        return _readForEachPartsWithDeclaration();
      case Tag.ForElement:
        return _readForElement();
      case Tag.ForPartsWithDeclarations:
        return _readForPartsWithDeclarations();
      case Tag.ForPartsWithExpression:
        return _readForPartsWithExpression();
      case Tag.FieldFormalParameter:
        return _readFieldFormalParameter();
      case Tag.FormalParameterList:
        return _readFormalParameterList();
      case Tag.FunctionExpressionStub:
        return _readFunctionExpression();
      case Tag.FunctionExpressionInvocation:
        return _readFunctionExpressionInvocation();
      case Tag.FunctionReference:
        return _readFunctionReference();
      case Tag.FunctionTypedFormalParameter:
        return _readFunctionTypedFormalParameter();
      case Tag.GenericFunctionType:
        return _readGenericFunctionType();
      case Tag.IfElement:
        return _readIfElement();
      case Tag.IndexExpression:
        return _readIndexExpression();
      case Tag.IntegerLiteralNegative1:
        return _readIntegerLiteralNegative1();
      case Tag.IntegerLiteralNull:
        return _readIntegerLiteralNull();
      case Tag.IntegerLiteralPositive1:
        return _readIntegerLiteralPositive1();
      case Tag.IntegerLiteralPositive:
        return _readIntegerLiteralPositive();
      case Tag.IntegerLiteralNegative:
        return _readIntegerLiteralNegative();
      case Tag.InterpolationExpression:
        return _readInterpolationExpression();
      case Tag.InterpolationString:
        return _readInterpolationString();
      case Tag.IsExpression:
        return _readIsExpression();
      case Tag.ListLiteral:
        return _readListLiteral();
      case Tag.MapLiteralEntry:
        return _readMapLiteralEntry();
      case Tag.MixinDeclaration:
        return _readMixinDeclaration();
      case Tag.MethodInvocation:
        return _readMethodInvocation();
      case Tag.NamedExpression:
        return _readNamedExpression();
      case Tag.NullLiteral:
        return _readNullLiteral();
      case Tag.InstanceCreationExpression:
        return _readInstanceCreationExpression();
      case Tag.ParenthesizedExpression:
        return _readParenthesizedExpression();
      case Tag.PostfixExpression:
        return _readPostfixExpression();
      case Tag.PrefixExpression:
        return _readPrefixExpression();
      case Tag.PrefixedIdentifier:
        return _readPrefixedIdentifier();
      case Tag.PropertyAccess:
        return _readPropertyAccess();
      case Tag.RedirectingConstructorInvocation:
        return _readRedirectingConstructorInvocation();
      case Tag.SetOrMapLiteral:
        return _readSetOrMapLiteral();
      case Tag.SimpleFormalParameter:
        return _readSimpleFormalParameter();
      case Tag.SimpleIdentifier:
        return _readSimpleIdentifier();
      case Tag.SimpleStringLiteral:
        return _readSimpleStringLiteral();
      case Tag.SpreadElement:
        return _readSpreadElement();
      case Tag.StringInterpolation:
        return _readStringInterpolation();
      case Tag.SuperConstructorInvocation:
        return _readSuperConstructorInvocation();
      case Tag.SuperExpression:
        return _readSuperExpression();
      case Tag.SymbolLiteral:
        return _readSymbolLiteral();
      case Tag.ThisExpression:
        return _readThisExpression();
      case Tag.ThrowExpression:
        return _readThrowExpression();
      case Tag.TypeArgumentList:
        return _readTypeArgumentList();
      case Tag.TypeLiteral:
        return _readTypeLiteral();
      case Tag.TypeName:
        return _readTypeName();
      case Tag.TypeParameter:
        return _readTypeParameter();
      case Tag.TypeParameterList:
        return _readTypeParameterList();
      case Tag.VariableDeclaration:
        return _readVariableDeclaration();
      case Tag.VariableDeclarationList:
        return _readVariableDeclarationList();
      default:
        throw UnimplementedError('Unexpected tag: $tag');
    }
  }

  IntegerLiteral _createIntegerLiteral(String lexeme, int value) {
    var node = astFactory.integerLiteral(
      TokenFactory.tokenFromTypeAndString(TokenType.INT, lexeme),
      value,
    );
    _readExpressionResolution(node);
    return node;
  }

  AdjacentStrings _readAdjacentStrings() {
    var components = _readNodeList<StringLiteral>();
    var node = astFactory.adjacentStrings(components);
    _readExpressionResolution(node);
    return node;
  }

  Annotation _readAnnotation() {
    var name = readNode() as Identifier;
    var typeArguments = _readOptionalNode() as TypeArgumentList?;
    var constructorName = _readOptionalNode() as SimpleIdentifier?;
    var arguments = _readOptionalNode() as ArgumentList?;
    var node = astFactory.annotation(
      atSign: Tokens.at(),
      name: name,
      typeArguments: typeArguments,
      period: Tokens.period(),
      constructorName: constructorName,
      arguments: arguments,
    );
    node.element = _reader.readElement();
    return node;
  }

  ArgumentList _readArgumentList() {
    var arguments = _readNodeList<Expression>();

    return astFactory.argumentList(
      Tokens.openParenthesis(),
      arguments,
      Tokens.closeParenthesis(),
    );
  }

  AsExpression _readAsExpression() {
    var expression = readNode() as Expression;
    var type = readNode() as TypeAnnotation;
    var node = astFactory.asExpression(expression, Tokens.as_(), type);
    _readExpressionResolution(node);
    return node;
  }

  AssertInitializer _readAssertInitializer() {
    var condition = readNode() as Expression;
    var message = _readOptionalNode() as Expression?;
    return astFactory.assertInitializer(
      Tokens.assert_(),
      Tokens.openParenthesis(),
      condition,
      Tokens.comma(),
      message,
      Tokens.closeParenthesis(),
    );
  }

  AssignmentExpression _readAssignmentExpression() {
    var leftHandSide = readNode() as Expression;
    var rightHandSide = readNode() as Expression;
    var operatorType = UnlinkedTokenType.values[_readByte()];
    var node = astFactory.assignmentExpression(
      leftHandSide,
      Tokens.fromType(operatorType),
      rightHandSide,
    );
    node.staticElement = _reader.readElement() as MethodElement?;
    node.readElement = _reader.readElement();
    node.readType = _reader.readType();
    node.writeElement = _reader.readElement();
    node.writeType = _reader.readType();
    _readExpressionResolution(node);
    return node;
  }

  AwaitExpression _readAwaitExpression() {
    var expression = readNode() as Expression;
    return astFactory.awaitExpression(Tokens.await_(), expression);
  }

  BinaryExpression _readBinaryExpression() {
    var leftOperand = readNode() as Expression;
    var rightOperand = readNode() as Expression;
    var operatorType = UnlinkedTokenType.values[_readByte()];
    var node = astFactory.binaryExpression(
      leftOperand,
      Tokens.fromType(operatorType),
      rightOperand,
    );
    node.staticElement = _reader.readElement() as MethodElement?;
    node.staticInvokeType = _reader.readOptionalFunctionType();
    _readExpressionResolution(node);
    return node;
  }

  BooleanLiteral _readBooleanLiteral() {
    var value = _readByte() == 1;
    var node = AstTestFactory.booleanLiteral(value);
    _readExpressionResolution(node);
    return node;
  }

  int _readByte() {
    return _reader.readByte();
  }

  CascadeExpression _readCascadeExpression() {
    var target = readNode() as Expression;
    var sections = _readNodeList<Expression>();
    var node = astFactory.cascadeExpression(target, sections);
    node.staticType = target.staticType;
    return node;
  }

  ConditionalExpression _readConditionalExpression() {
    var condition = readNode() as Expression;
    var thenExpression = readNode() as Expression;
    var elseExpression = readNode() as Expression;
    var node = astFactory.conditionalExpression(
      condition,
      Tokens.question(),
      thenExpression,
      Tokens.colon(),
      elseExpression,
    );
    _readExpressionResolution(node);
    return node;
  }

  ConstructorFieldInitializer _readConstructorFieldInitializer() {
    var flags = _readByte();
    var fieldName = readNode() as SimpleIdentifier;
    var expression = readNode() as Expression;
    var hasThis = AstBinaryFlags.hasThis(flags);
    return astFactory.constructorFieldInitializer(
      hasThis ? Tokens.this_() : null,
      hasThis ? Tokens.period() : null,
      fieldName,
      Tokens.eq(),
      expression,
    );
  }

  ConstructorName _readConstructorName() {
    var type = readNode() as TypeName;
    var name = _readOptionalNode() as SimpleIdentifier?;

    var node = astFactory.constructorName(
      type,
      name != null ? Tokens.period() : null,
      name,
    );
    node.staticElement = _reader.readElement() as ConstructorElement?;
    return node;
  }

  ConstructorReference _readConstructorReference() {
    var constructorName = readNode() as ConstructorName;
    var node = astFactory.constructorReference(
      constructorName: constructorName,
    );
    _readExpressionResolution(node);
    return node;
  }

  SimpleIdentifierImpl _readDeclarationName() {
    var name = _reader.readStringReference();
    return astFactory.simpleIdentifier(
      StringToken(TokenType.STRING, name, -1),
    );
  }

  DeclaredIdentifier _readDeclaredIdentifier() {
    var flags = _readByte();
    var type = _readOptionalNode() as TypeAnnotation?;
    var identifier = _readDeclarationName();
    var metadata = _readNodeList<Annotation>();
    return astFactory.declaredIdentifier(
      null,
      metadata,
      Tokens.choose(
        AstBinaryFlags.isConst(flags),
        Tokens.const_(),
        AstBinaryFlags.isFinal(flags),
        Tokens.final_(),
        AstBinaryFlags.isVar(flags),
        Tokens.var_(),
      ),
      type,
      identifier,
    );
  }

  DefaultFormalParameter _readDefaultFormalParameter() {
    var flags = _readByte();
    var parameter = readNode() as NormalFormalParameter;
    var defaultValue = _readOptionalNode() as Expression?;

    ParameterKind kind;
    if (AstBinaryFlags.isPositional(flags)) {
      kind = AstBinaryFlags.isRequired(flags)
          ? ParameterKind.REQUIRED
          : ParameterKind.POSITIONAL;
    } else {
      kind = AstBinaryFlags.isRequired(flags)
          ? ParameterKind.NAMED_REQUIRED
          : ParameterKind.NAMED;
    }

    var node = astFactory.defaultFormalParameter(
      parameter,
      kind,
      AstBinaryFlags.hasInitializer(flags) ? Tokens.colon() : null,
      defaultValue,
    );

    var nonDefaultElement = parameter.declaredElement!;
    var element = DefaultParameterElementImpl(
      name: nonDefaultElement.name,
      nameOffset: nonDefaultElement.nameOffset,
      parameterKind: kind,
    );
    if (parameter is SimpleFormalParameterImpl) {
      parameter.declaredElement = element;
    }
    node.identifier?.staticElement = element;
    element.type = nonDefaultElement.type;

    return node;
  }

  DottedName _readDottedName() {
    var components = _readNodeList<SimpleIdentifier>();
    return astFactory.dottedName(components);
  }

  DoubleLiteral _readDoubleLiteral() {
    var value = _reader.readDouble();
    var node = AstTestFactory.doubleLiteral(value);
    _readExpressionResolution(node);
    return node;
  }

  void _readExpressionResolution(ExpressionImpl node) {
    node.staticType = _reader.readType();
  }

  ExtensionOverride _readExtensionOverride() {
    var extensionName = readNode() as Identifier;
    var typeArguments = _readOptionalNode() as TypeArgumentList?;
    var argumentList = readNode() as ArgumentList;
    var node = astFactory.extensionOverride(
      extensionName: extensionName,
      argumentList: argumentList,
      typeArguments: typeArguments,
    );
    _readExpressionResolution(node);
    return node;
  }

  FieldFormalParameter _readFieldFormalParameter() {
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var type = _readOptionalNode() as TypeAnnotation?;
    var formalParameters = _readOptionalNode() as FormalParameterList?;
    var flags = _readByte();
    var metadata = _readNodeList<Annotation>();
    var identifier = readNode() as SimpleIdentifier;
    var node = astFactory.fieldFormalParameter2(
      identifier: identifier,
      period: Tokens.period(),
      thisKeyword: Tokens.this_(),
      covariantKeyword:
          AstBinaryFlags.isCovariant(flags) ? Tokens.covariant_() : null,
      typeParameters: typeParameters,
      keyword: Tokens.choose(
        AstBinaryFlags.isConst(flags),
        Tokens.const_(),
        AstBinaryFlags.isFinal(flags),
        Tokens.final_(),
        AstBinaryFlags.isVar(flags),
        Tokens.var_(),
      ),
      metadata: metadata,
      comment: null,
      type: type,
      parameters: formalParameters,
      question: AstBinaryFlags.hasQuestion(flags) ? Tokens.question() : null,
      requiredKeyword:
          AstBinaryFlags.isRequired(flags) ? Tokens.required_() : null,
    );
    return node;
  }

  ForEachPartsWithDeclaration _readForEachPartsWithDeclaration() {
    var loopVariable = readNode() as DeclaredIdentifier;
    var iterable = readNode() as Expression;
    return astFactory.forEachPartsWithDeclaration(
      inKeyword: Tokens.in_(),
      iterable: iterable,
      loopVariable: loopVariable,
    );
  }

  ForElement _readForElement() {
    var flags = _readByte();
    var forLoopParts = readNode() as ForLoopParts;
    var body = readNode() as CollectionElement;
    return astFactory.forElement(
      awaitKeyword: AstBinaryFlags.hasAwait(flags) ? Tokens.await_() : null,
      body: body,
      forKeyword: Tokens.for_(),
      forLoopParts: forLoopParts,
      leftParenthesis: Tokens.openParenthesis(),
      rightParenthesis: Tokens.closeParenthesis(),
    );
  }

  FormalParameterList _readFormalParameterList() {
    var flags = _readByte();
    var parameters = _readNodeList<FormalParameter>();

    return astFactory.formalParameterList(
      Tokens.openParenthesis(),
      parameters,
      Tokens.choose(
        AstBinaryFlags.isDelimiterCurly(flags),
        Tokens.openCurlyBracket(),
        AstBinaryFlags.isDelimiterSquare(flags),
        Tokens.openSquareBracket(),
      ),
      Tokens.choose(
        AstBinaryFlags.isDelimiterCurly(flags),
        Tokens.closeCurlyBracket(),
        AstBinaryFlags.isDelimiterSquare(flags),
        Tokens.closeSquareBracket(),
      ),
      Tokens.closeParenthesis(),
    );
  }

  ForPartsWithDeclarations _readForPartsWithDeclarations() {
    var variables = readNode() as VariableDeclarationList;
    var condition = _readOptionalNode() as Expression?;
    var updaters = _readNodeList<Expression>();
    return astFactory.forPartsWithDeclarations(
      condition: condition,
      leftSeparator: Tokens.semicolon(),
      rightSeparator: Tokens.semicolon(),
      updaters: updaters,
      variables: variables,
    );
  }

  ForPartsWithExpression _readForPartsWithExpression() {
    var initialization = _readOptionalNode() as Expression?;
    var condition = _readOptionalNode() as Expression?;
    var updaters = _readNodeList<Expression>();
    return astFactory.forPartsWithExpression(
      condition: condition,
      initialization: initialization,
      leftSeparator: Tokens.semicolon(),
      rightSeparator: Tokens.semicolon(),
      updaters: updaters,
    );
  }

  FunctionExpression _readFunctionExpression() {
    return emptyFunctionExpression();
  }

  FunctionExpressionInvocation _readFunctionExpressionInvocation() {
    var function = readNode() as Expression;
    var typeArguments = _readOptionalNode() as TypeArgumentList?;
    var arguments = readNode() as ArgumentList;
    var node = astFactory.functionExpressionInvocation(
      function,
      typeArguments,
      arguments,
    );
    _readInvocationExpression(node);
    return node;
  }

  FunctionReference _readFunctionReference() {
    var function = readNode() as Expression;
    var typeArguments = _readOptionalNode() as TypeArgumentList?;

    var node = astFactory.functionReference(
      function: function,
      typeArguments: typeArguments,
    );
    node.typeArgumentTypes = _reader.readOptionalTypeList();
    _readExpressionResolution(node);
    return node;
  }

  FunctionTypedFormalParameter _readFunctionTypedFormalParameter() {
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var returnType = _readOptionalNode() as TypeAnnotation?;
    var formalParameters = readNode() as FormalParameterList;
    var flags = _readByte();
    var metadata = _readNodeList<Annotation>();
    var identifier = readNode() as SimpleIdentifier;
    var node = astFactory.functionTypedFormalParameter2(
      comment: null,
      covariantKeyword:
          AstBinaryFlags.isCovariant(flags) ? Tokens.covariant_() : null,
      identifier: identifier,
      metadata: metadata,
      parameters: formalParameters,
      requiredKeyword:
          AstBinaryFlags.isRequired(flags) ? Tokens.required_() : null,
      returnType: returnType,
      typeParameters: typeParameters,
    );
    return node;
  }

  GenericFunctionType _readGenericFunctionType() {
    var flags = _readByte();
    // TODO(scheglov) add type parameters to locals
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var returnType = _readOptionalNode() as TypeAnnotation?;
    var formalParameters = readNode() as FormalParameterList;
    var node = astFactory.genericFunctionType(
      returnType,
      Tokens.function(),
      typeParameters,
      formalParameters,
      question: AstBinaryFlags.hasQuestion(flags) ? Tokens.question() : null,
    );
    var type = _reader.readRequiredType() as FunctionType;
    node.type = type;

    var element = GenericFunctionTypeElementImpl.forOffset(-1);
    element.parameters = formalParameters.parameters
        .map((parameter) => parameter.declaredElement!)
        .toList();
    element.returnType = returnType?.type ?? DynamicTypeImpl.instance;
    element.type = type;
    node.declaredElement = element;

    return node;
  }

  IfElement _readIfElement() {
    var condition = readNode() as Expression;
    var thenElement = readNode() as CollectionElement;
    var elseElement = _readOptionalNode() as CollectionElement?;
    return astFactory.ifElement(
      condition: condition,
      elseElement: elseElement,
      elseKeyword: elseElement != null ? Tokens.else_() : null,
      ifKeyword: Tokens.if_(),
      leftParenthesis: Tokens.openParenthesis(),
      rightParenthesis: Tokens.closeParenthesis(),
      thenElement: thenElement,
    );
  }

  IndexExpression _readIndexExpression() {
    var flags = _readByte();
    var target = _readOptionalNode() as Expression?;
    var index = readNode() as Expression;
    // TODO(scheglov) Is this clumsy?
    IndexExpressionImpl node;
    if (target != null) {
      node = (astFactory.indexExpressionForTarget2(
        target: target,
        question: AstBinaryFlags.hasQuestion(flags) ? Tokens.question() : null,
        leftBracket: Tokens.openSquareBracket(),
        index: index,
        rightBracket: Tokens.closeSquareBracket(),
      ))
        ..period =
            AstBinaryFlags.hasPeriod(flags) ? Tokens.periodPeriod() : null;
    } else {
      node = astFactory.indexExpressionForCascade2(
        period: Tokens.periodPeriod(),
        question: AstBinaryFlags.hasQuestion(flags) ? Tokens.question() : null,
        leftBracket: Tokens.openSquareBracket(),
        index: index,
        rightBracket: Tokens.closeSquareBracket(),
      );
    }
    node.staticElement = _reader.readElement() as MethodElement?;
    _readExpressionResolution(node);
    return node;
  }

  InstanceCreationExpression _readInstanceCreationExpression() {
    var flags = _readByte();
    var constructorName = readNode() as ConstructorName;
    var argumentList = readNode() as ArgumentList;

    var node = astFactory.instanceCreationExpression(
      Tokens.choose(
        AstBinaryFlags.isConst(flags),
        Tokens.const_(),
        AstBinaryFlags.isNew(flags),
        Tokens.new_(),
      ),
      constructorName,
      argumentList,
    );
    _readExpressionResolution(node);
    _resolveNamedExpressions(
      node.constructorName.staticElement,
      node.argumentList,
    );
    return node;
  }

  IntegerLiteral _readIntegerLiteralNegative() {
    var lexeme = _readStringReference();
    var value = (_readUInt32() << 32) | _readUInt32();
    return _createIntegerLiteral(lexeme, -value);
  }

  IntegerLiteral _readIntegerLiteralNegative1() {
    var lexeme = _readStringReference();
    var value = _readByte();
    return _createIntegerLiteral(lexeme, -value);
  }

  IntegerLiteral _readIntegerLiteralNull() {
    var lexeme = _readStringReference();
    var node = astFactory.integerLiteral(
      TokenFactory.tokenFromTypeAndString(TokenType.INT, lexeme),
      null,
    );
    _readExpressionResolution(node);
    return node;
  }

  IntegerLiteral _readIntegerLiteralPositive() {
    var lexeme = _readStringReference();
    var value = (_readUInt32() << 32) | _readUInt32();
    return _createIntegerLiteral(lexeme, value);
  }

  IntegerLiteral _readIntegerLiteralPositive1() {
    var lexeme = _readStringReference();
    var value = _readByte();
    return _createIntegerLiteral(lexeme, value);
  }

  InterpolationExpression _readInterpolationExpression() {
    var flags = _readByte();
    var expression = readNode() as Expression;
    var isIdentifier = AstBinaryFlags.isStringInterpolationIdentifier(flags);
    return astFactory.interpolationExpression(
      isIdentifier
          ? Tokens.openCurlyBracket()
          : Tokens.stringInterpolationExpression(),
      expression,
      isIdentifier ? null : Tokens.closeCurlyBracket(),
    );
  }

  InterpolationString _readInterpolationString() {
    var lexeme = _readStringReference();
    var value = _readStringReference();
    return astFactory.interpolationString(
      TokenFactory.tokenFromString(lexeme),
      value,
    );
  }

  void _readInvocationExpression(InvocationExpressionImpl node) {
    node.staticInvokeType = _reader.readType();
    node.typeArgumentTypes = _reader.readOptionalTypeList();
    _readExpressionResolution(node);
  }

  IsExpression _readIsExpression() {
    var flags = _readByte();
    var expression = readNode() as Expression;
    var type = readNode() as TypeAnnotation;
    var node = astFactory.isExpression(
      expression,
      Tokens.is_(),
      AstBinaryFlags.hasNot(flags) ? Tokens.bang() : null,
      type,
    );
    _readExpressionResolution(node);
    return node;
  }

  ListLiteral _readListLiteral() {
    var flags = _readByte();
    var typeArguments = _readOptionalNode() as TypeArgumentList?;
    var elements = _readNodeList<CollectionElement>();

    var node = astFactory.listLiteral(
      AstBinaryFlags.isConst(flags) ? Tokens.const_() : null,
      typeArguments,
      Tokens.openSquareBracket(),
      elements,
      Tokens.closeSquareBracket(),
    );
    _readExpressionResolution(node);
    return node;
  }

  MapLiteralEntry _readMapLiteralEntry() {
    var key = readNode() as Expression;
    var value = readNode() as Expression;
    return astFactory.mapLiteralEntry(key, Tokens.colon(), value);
  }

  MethodInvocation _readMethodInvocation() {
    var flags = _readByte();
    var target = _readOptionalNode() as Expression?;
    var methodName = readNode() as SimpleIdentifier;
    var typeArguments = _readOptionalNode() as TypeArgumentList?;
    var arguments = readNode() as ArgumentList;

    Token? operator;
    if (AstBinaryFlags.hasQuestion(flags)) {
      operator = AstBinaryFlags.hasPeriod(flags)
          ? Tokens.questionPeriod()
          : Tokens.questionPeriodPeriod();
    } else if (AstBinaryFlags.hasPeriod(flags)) {
      operator = Tokens.period();
    } else if (AstBinaryFlags.hasPeriod2(flags)) {
      operator = Tokens.periodPeriod();
    }

    var node = astFactory.methodInvocation(
      target,
      operator,
      methodName,
      typeArguments,
      arguments,
    );
    _readInvocationExpression(node);
    return node;
  }

  MixinDeclaration _readMixinDeclaration() {
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var onClause = _readOptionalNode() as OnClause?;
    var implementsClause = _readOptionalNode() as ImplementsClause?;
    var name = readNode() as SimpleIdentifier;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.mixinDeclaration(
      null,
      metadata,
      Tokens.mixin_(),
      name,
      typeParameters,
      onClause,
      implementsClause,
      Tokens.openCurlyBracket(),
      const <ClassMember>[],
      Tokens.closeCurlyBracket(),
    );

    return node;
  }

  NamedExpression _readNamedExpression() {
    var name = _readStringReference();
    var nameNode = astFactory.label(
      astFactory.simpleIdentifier(
        StringToken(TokenType.STRING, name, -1),
      ),
      Tokens.colon(),
    );
    var expression = readNode() as Expression;
    var node = astFactory.namedExpression(nameNode, expression);
    node.staticType = expression.staticType;
    return node;
  }

  List<T> _readNodeList<T>() {
    var length = _reader.readUInt30();
    return List.generate(length, (_) => readNode() as T);
  }

  NullLiteral _readNullLiteral() {
    var node = astFactory.nullLiteral(
      Tokens.null_(),
    );
    _readExpressionResolution(node);
    return node;
  }

  AstNode? _readOptionalNode() {
    if (_readOptionTag()) {
      return readNode();
    } else {
      return null;
    }
  }

  bool _readOptionTag() {
    var tag = _readByte();
    if (tag == Tag.Nothing) {
      return false;
    } else if (tag == Tag.Something) {
      return true;
    } else {
      throw UnimplementedError('Unexpected option tag: $tag');
    }
  }

  ParenthesizedExpression _readParenthesizedExpression() {
    var expression = readNode() as Expression;
    var node = astFactory.parenthesizedExpression(
      Tokens.openParenthesis(),
      expression,
      Tokens.closeParenthesis(),
    );
    _readExpressionResolution(node);
    return node;
  }

  PostfixExpression _readPostfixExpression() {
    var operand = readNode() as Expression;
    var operatorType = UnlinkedTokenType.values[_readByte()];
    var node = astFactory.postfixExpression(
      operand,
      Tokens.fromType(operatorType),
    );
    node.staticElement = _reader.readElement() as MethodElement?;
    if (node.operator.type.isIncrementOperator) {
      node.readElement = _reader.readElement();
      node.readType = _reader.readType();
      node.writeElement = _reader.readElement();
      node.writeType = _reader.readType();
    }
    _readExpressionResolution(node);
    return node;
  }

  PrefixedIdentifier _readPrefixedIdentifier() {
    var prefix = readNode() as SimpleIdentifier;
    var identifier = readNode() as SimpleIdentifier;
    var node = astFactory.prefixedIdentifier(
      prefix,
      Tokens.period(),
      identifier,
    );
    _readExpressionResolution(node);
    return node;
  }

  PrefixExpression _readPrefixExpression() {
    var operatorType = UnlinkedTokenType.values[_readByte()];
    var operand = readNode() as Expression;
    var node = astFactory.prefixExpression(
      Tokens.fromType(operatorType),
      operand,
    );
    node.staticElement = _reader.readElement() as MethodElement?;
    if (node.operator.type.isIncrementOperator) {
      node.readElement = _reader.readElement();
      node.readType = _reader.readType();
      node.writeElement = _reader.readElement();
      node.writeType = _reader.readType();
    }
    _readExpressionResolution(node);
    return node;
  }

  PropertyAccess _readPropertyAccess() {
    var flags = _readByte();
    var target = _readOptionalNode() as Expression?;
    var propertyName = readNode() as SimpleIdentifier;

    Token operator;
    if (AstBinaryFlags.hasQuestion(flags)) {
      operator = AstBinaryFlags.hasPeriod(flags)
          ? Tokens.questionPeriod()
          : Tokens.questionPeriodPeriod();
    } else {
      operator = AstBinaryFlags.hasPeriod(flags)
          ? Tokens.period()
          : Tokens.periodPeriod();
    }

    var node = astFactory.propertyAccess(target, operator, propertyName);
    _readExpressionResolution(node);
    return node;
  }

  RedirectingConstructorInvocation _readRedirectingConstructorInvocation() {
    var constructorName = _readOptionalNode() as SimpleIdentifier?;
    var argumentList = readNode() as ArgumentList;
    var node = astFactory.redirectingConstructorInvocation(
      Tokens.this_(),
      constructorName != null ? Tokens.period() : null,
      constructorName,
      argumentList,
    );
    node.staticElement = _reader.readElement() as ConstructorElement?;
    _resolveNamedExpressions(node.staticElement, node.argumentList);
    return node;
  }

  SetOrMapLiteral _readSetOrMapLiteral() {
    var flags = _readByte();
    var isMapOrSetBits = _readByte();
    var typeArguments = _readOptionalNode() as TypeArgumentList?;
    var elements = _readNodeList<CollectionElement>();
    var node = astFactory.setOrMapLiteral(
      constKeyword: AstBinaryFlags.isConst(flags) ? Tokens.const_() : null,
      elements: elements,
      leftBracket: Tokens.openCurlyBracket(),
      typeArguments: typeArguments,
      rightBracket: Tokens.closeCurlyBracket(),
    );

    const isMapBit = 1 << 0;
    const isSetBit = 1 << 1;
    if ((isMapOrSetBits & isMapBit) != 0) {
      node.becomeMap();
    } else if ((isMapOrSetBits & isSetBit) != 0) {
      node.becomeSet();
    }

    _readExpressionResolution(node);
    return node;
  }

  SimpleFormalParameter _readSimpleFormalParameter() {
    var type = _readOptionalNode() as TypeAnnotation?;
    var flags = _readByte();
    var metadata = _readNodeList<Annotation>();
    var identifier =
        AstBinaryFlags.hasName(flags) ? _readDeclarationName() : null;

    var node = astFactory.simpleFormalParameter2(
      identifier: identifier,
      type: type,
      covariantKeyword:
          AstBinaryFlags.isCovariant(flags) ? Tokens.covariant_() : null,
      comment: null,
      metadata: metadata,
      keyword: Tokens.choose(
        AstBinaryFlags.isConst(flags),
        Tokens.const_(),
        AstBinaryFlags.isFinal(flags),
        Tokens.final_(),
        AstBinaryFlags.isVar(flags),
        Tokens.var_(),
      ),
      requiredKeyword:
          AstBinaryFlags.isRequired(flags) ? Tokens.required_() : null,
    );
    var actualType = _reader.readRequiredType();
    _reader.readByte(); // TODO(scheglov) inherits covariant

    var element = ParameterElementImpl(
      name: identifier?.name ?? '',
      nameOffset: -1,
      parameterKind: node.kind,
    );
    element.type = actualType;
    node.declaredElement = element;
    identifier?.staticElement = element;

    return node;
  }

  SimpleIdentifier _readSimpleIdentifier() {
    var name = _readStringReference();
    var node = astFactory.simpleIdentifier(
      StringToken(TokenType.STRING, name, -1),
    );
    node.staticElement = _reader.readElement();
    _readExpressionResolution(node);
    return node;
  }

  SimpleStringLiteral _readSimpleStringLiteral() {
    var lexeme = _readStringReference();
    var value = _readStringReference();

    var node = astFactory.simpleStringLiteral(
      TokenFactory.tokenFromString(lexeme),
      value,
    );
    _readExpressionResolution(node);
    return node;
  }

  SpreadElement _readSpreadElement() {
    var flags = _readByte();
    var expression = readNode() as Expression;
    return astFactory.spreadElement(
      spreadOperator: AstBinaryFlags.hasQuestion(flags)
          ? Tokens.periodPeriodPeriodQuestion()
          : Tokens.periodPeriodPeriod(),
      expression: expression,
    );
  }

  StringInterpolation _readStringInterpolation() {
    var elements = _readNodeList<InterpolationElement>();
    var node = astFactory.stringInterpolation(elements);
    _readExpressionResolution(node);
    return node;
  }

  String _readStringReference() {
    return _reader.readStringReference();
  }

  SuperConstructorInvocation _readSuperConstructorInvocation() {
    var constructorName = _readOptionalNode() as SimpleIdentifier?;
    var argumentList = readNode() as ArgumentList;
    var node = astFactory.superConstructorInvocation(
      Tokens.super_(),
      constructorName != null ? Tokens.period() : null,
      constructorName,
      argumentList,
    );
    node.staticElement = _reader.readElement() as ConstructorElement?;
    _resolveNamedExpressions(node.staticElement, node.argumentList);
    return node;
  }

  SuperExpression _readSuperExpression() {
    var node = astFactory.superExpression(Tokens.super_());
    _readExpressionResolution(node);
    return node;
  }

  SymbolLiteral _readSymbolLiteral() {
    var components = _reader
        .readStringReferenceList()
        .map(TokenFactory.tokenFromString)
        .toList();
    var node = astFactory.symbolLiteral(Tokens.hash(), components);
    _readExpressionResolution(node);
    return node;
  }

  ThisExpression _readThisExpression() {
    var node = astFactory.thisExpression(Tokens.this_());
    _readExpressionResolution(node);
    return node;
  }

  ThrowExpression _readThrowExpression() {
    var expression = readNode() as Expression;
    var node = astFactory.throwExpression(Tokens.throw_(), expression);
    _readExpressionResolution(node);
    return node;
  }

  TypeArgumentList _readTypeArgumentList() {
    var arguments = _readNodeList<TypeAnnotation>();
    return astFactory.typeArgumentList(Tokens.lt(), arguments, Tokens.gt());
  }

  TypeLiteral _readTypeLiteral() {
    var typeName = readNode() as TypeName;
    var node = astFactory.typeLiteral(typeName: typeName);
    _readExpressionResolution(node);
    return node;
  }

  TypeName _readTypeName() {
    var flags = _readByte();
    var name = readNode() as Identifier;
    var typeArguments = _readOptionalNode() as TypeArgumentList?;

    var node = astFactory.typeName(
      name,
      typeArguments,
      question: AstBinaryFlags.hasQuestion(flags) ? Tokens.question() : null,
    );
    node.type = _reader.readType();
    return node;
  }

  TypeParameter _readTypeParameter() {
    var name = _readDeclarationName();
    var bound = _readOptionalNode() as TypeAnnotation?;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.typeParameter(
      null,
      metadata,
      name,
      bound != null ? Tokens.extends_() : null,
      bound,
    );

    return node;
  }

  TypeParameterList _readTypeParameterList() {
    var typeParameters = _readNodeList<TypeParameter>();
    return astFactory.typeParameterList(
      Tokens.lt(),
      typeParameters,
      Tokens.gt(),
    );
  }

  int _readUInt32() {
    return _reader.readUInt32();
  }

  VariableDeclaration _readVariableDeclaration() {
    var flags = _readByte();
    var name = readNode() as SimpleIdentifier;
    var initializer = _readOptionalNode() as Expression?;

    var node = astFactory.variableDeclaration(
      name,
      Tokens.eq(),
      initializer,
    );

    node.hasInitializer = AstBinaryFlags.hasInitializer(flags);

    return node;
  }

  VariableDeclarationList _readVariableDeclarationList() {
    var flags = _readByte();
    var type = _readOptionalNode() as TypeAnnotation?;
    var variables = _readNodeList<VariableDeclaration>();
    var metadata = _readNodeList<Annotation>();

    return astFactory.variableDeclarationList2(
      comment: null,
      keyword: Tokens.choose(
        AstBinaryFlags.isConst(flags),
        Tokens.const_(),
        AstBinaryFlags.isFinal(flags),
        Tokens.final_(),
        AstBinaryFlags.isVar(flags),
        Tokens.var_(),
      ),
      lateKeyword: AstBinaryFlags.isLate(flags) ? Tokens.late_() : null,
      metadata: metadata,
      type: type,
      variables: variables,
    );
  }

  void _resolveNamedExpressions(
    Element? executable,
    ArgumentList argumentList,
  ) {
    for (var argument in argumentList.arguments) {
      if (argument is NamedExpressionImpl) {
        var nameNode = argument.name.label;
        if (executable is ExecutableElement) {
          var parameters = executable.parameters;
          var name = nameNode.name;
          nameNode.staticElement = parameters.firstWhereOrNull((e) {
            return e.name == name;
          });
        }
      }
    }
  }
}
