// 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 'dart:typed_data';

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/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.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/unlinked_token_type.dart';

/// Deserializer of ASTs.
class AstBinaryReader {
  static final _noDocumentationComment = Uint32List(0);

  final UnitReader _unitReader;
  final bool _withInformative;

  AstBinaryReader({
    required UnitReader reader,
  })   : _unitReader = reader,
        _withInformative = reader.withInformative;

  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.Class:
        return _readClassDeclaration();
      case Tag.ClassTypeAlias:
        return _readClassTypeAlias();
      case Tag.ConditionalExpression:
        return _readConditionalExpression();
      case Tag.Configuration:
        return _readConfiguration();
      case Tag.ConstructorDeclaration:
        return _readConstructorDeclaration();
      case Tag.ConstructorFieldInitializer:
        return _readConstructorFieldInitializer();
      case Tag.ConstructorName:
        return _readConstructorName();
      case Tag.DeclaredIdentifier:
        return _readDeclaredIdentifier();
      case Tag.DefaultFormalParameter:
        return _readDefaultFormalParameter();
      case Tag.DottedName:
        return _readDottedName();
      case Tag.DoubleLiteral:
        return _readDoubleLiteral();
      case Tag.EnumConstantDeclaration:
        return _readEnumConstantDeclaration();
      case Tag.EnumDeclaration:
        return _readEnumDeclaration();
      case Tag.ExportDirective:
        return _readExportDirective();
      case Tag.ExtendsClause:
        return _readExtendsClause();
      case Tag.ExtensionDeclaration:
        return _readExtensionDeclaration();
      case Tag.ExtensionOverride:
        return _readExtensionOverride();
      case Tag.FieldDeclaration:
        return _readFieldDeclaration();
      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.FunctionDeclaration:
        return _readFunctionDeclaration();
      case Tag.FunctionExpression:
        return _readFunctionExpression();
      case Tag.FunctionExpressionInvocation:
        return _readFunctionExpressionInvocation();
      case Tag.FunctionTypeAlias:
        return _readFunctionTypeAlias();
      case Tag.FunctionTypedFormalParameter:
        return _readFunctionTypedFormalParameter();
      case Tag.GenericFunctionType:
        return _readGenericFunctionType();
      case Tag.GenericTypeAlias:
        return _readGenericTypeAlias();
      case Tag.HideCombinator:
        return _readHideCombinator();
      case Tag.IfElement:
        return _readIfElement();
      case Tag.ImplementsClause:
        return _readImplementsClause();
      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.LibraryDirective:
        return _readLibraryDirective();
      case Tag.LibraryIdentifier:
        return _readLibraryIdentifier();
      case Tag.ListLiteral:
        return _readListLiteral();
      case Tag.MapLiteralEntry:
        return _readMapLiteralEntry();
      case Tag.MethodDeclaration:
        return _readMethodDeclaration();
      case Tag.MixinDeclaration:
        return _readMixinDeclaration();
      case Tag.MethodInvocation:
        return _readMethodInvocation();
      case Tag.NamedExpression:
        return _readNamedExpression();
      case Tag.NativeClause:
        return _readNativeClause();
      case Tag.NullLiteral:
        return _readNullLiteral();
      case Tag.OnClause:
        return _readOnClause();
      case Tag.ImportDirective:
        return _readImportDirective();
      case Tag.InstanceCreationExpression:
        return _readInstanceCreationExpression();
      case Tag.ParenthesizedExpression:
        return _readParenthesizedExpression();
      case Tag.PartDirective:
        return _readPartDirective();
      case Tag.PartOfDirective:
        return _readPartOfDirective();
      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.ShowCombinator:
        return _readShowCombinator();
      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.TypeName:
        return _readTypeName();
      case Tag.TypeParameter:
        return _readTypeParameter();
      case Tag.TypeParameterList:
        return _readTypeParameterList();
      case Tag.TopLevelVariableDeclaration:
        return _readTopLevelVariableDeclaration();
      case Tag.VariableDeclaration:
        return _readVariableDeclaration();
      case Tag.VariableDeclarationList:
        return _readVariableDeclarationList();
      case Tag.WithClause:
        return _readWithClause();
      default:
        throw UnimplementedError('Unexpected tag: $tag');
    }
  }

  IntegerLiteral _createIntegerLiteral(int value) {
    // TODO(scheglov) Write token?
    return astFactory.integerLiteral(
      TokenFactory.tokenFromTypeAndString(TokenType.INT, '$value'),
      value,
    );
  }

  FunctionBody _functionBodyForFlags(int flags) {
    if (AstBinaryFlags.isNative(flags)) {
      return AstTestFactory.nativeFunctionBody('');
    } else if (AstBinaryFlags.isAbstract(flags)) {
      return AstTestFactory.emptyFunctionBody();
    } else {
      return astFactory.blockFunctionBody(
        AstBinaryFlags.isAsync(flags) ? Tokens.ASYNC : null,
        AstBinaryFlags.isGenerator(flags) ? Tokens.STAR : null,
        astFactory.block(
          Tokens.OPEN_CURLY_BRACKET,
          const <Statement>[],
          Tokens.CLOSE_CURLY_BRACKET,
        ),
      );
    }
  }

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

  Annotation _readAnnotation() {
    var name = readNode() as Identifier;
    var constructorName = _readOptionalNode() as SimpleIdentifier?;
    var arguments = _readOptionalNode() as ArgumentList?;
    return astFactory.annotation(
      Tokens.AT,
      name,
      Tokens.PERIOD,
      constructorName,
      arguments,
    );
  }

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

    return astFactory.argumentList(
      Tokens.OPEN_PAREN,
      arguments,
      Tokens.CLOSE_PAREN,
    );
  }

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

  AssertInitializer _readAssertInitializer() {
    var condition = readNode() as Expression;
    var message = _readOptionalNode() as Expression?;
    return astFactory.assertInitializer(
      Tokens.ASSERT,
      Tokens.OPEN_PAREN,
      condition,
      Tokens.COMMA,
      message,
      Tokens.CLOSE_PAREN,
    );
  }

  AssignmentExpression _readAssignmentExpression() {
    var leftHandSide = readNode() as Expression;
    var rightHandSide = readNode() as Expression;
    var operatorType = UnlinkedTokenType.values[_readByte()];
    return astFactory.assignmentExpression(
      leftHandSide,
      Tokens.fromType(operatorType),
      rightHandSide,
    );
  }

  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()];
    return astFactory.binaryExpression(
      leftOperand,
      Tokens.fromType(operatorType),
      rightOperand,
    );
  }

  BooleanLiteral _readBooleanLiteral() {
    var value = _readByte() == 1;
    // TODO(scheglov) type?
    return AstTestFactory.booleanLiteral(value);
  }

  int _readByte() {
    return _unitReader.astReader.readByte();
  }

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

  ClassDeclaration _readClassDeclaration() {
    var flags = _readByte();

    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var extendsClause = _readOptionalNode() as ExtendsClause?;
    var withClause = _readOptionalNode() as WithClause?;
    var implementsClause = _readOptionalNode() as ImplementsClause?;
    var nativeClause = _readOptionalNode() as NativeClause?;
    var name = readNode() as SimpleIdentifier;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.classDeclaration(
      null,
      metadata,
      AstBinaryFlags.isAbstract(flags) ? Tokens.ABSTRACT : null,
      Tokens.CLASS,
      name,
      typeParameters,
      extendsClause,
      withClause,
      implementsClause,
      Tokens.OPEN_CURLY_BRACKET,
      const <ClassMember>[],
      Tokens.CLOSE_CURLY_BRACKET,
    ) as ClassDeclarationImpl;
    node.nativeClause = nativeClause;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      isClassWithConstConstructor: AstBinaryFlags.hasConstConstructor(flags),
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  ClassTypeAlias _readClassTypeAlias() {
    var flags = _readByte();

    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();

    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var superClass = readNode() as TypeName;
    var withClause = readNode() as WithClause;
    var implementsClause = _readOptionalNode() as ImplementsClause?;
    var name = readNode() as SimpleIdentifier;
    var metadata = _readNodeList<Annotation>();
    var documentationTokenIndexList = _readUint30List();

    var node = astFactory.classTypeAlias(
      null,
      metadata,
      Tokens.CLASS,
      name,
      typeParameters,
      Tokens.EQ,
      AstBinaryFlags.isAbstract(flags) ? Tokens.ABSTRACT : null,
      superClass,
      withClause,
      implementsClause,
      Tokens.SEMICOLON,
    ) as ClassTypeAliasImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  ConditionalExpression _readConditionalExpression() {
    var condition = readNode() as Expression;
    var thenExpression = readNode() as Expression;
    var elseExpression = readNode() as Expression;
    return astFactory.conditionalExpression(
      condition,
      Tokens.QUESTION,
      thenExpression,
      Tokens.COLON,
      elseExpression,
    );
  }

  Configuration _readConfiguration() {
    var flags = _readByte();
    var name = readNode() as DottedName;
    var value = _readOptionalNode() as StringLiteral?;
    var uri = readNode() as StringLiteral;
    return astFactory.configuration(
      Tokens.IF,
      Tokens.OPEN_PAREN,
      name,
      AstBinaryFlags.hasEqual(flags) ? Tokens.EQ : null,
      value,
      Tokens.CLOSE_PAREN,
      uri,
    );
  }

  ConstructorDeclaration _readConstructorDeclaration() {
    var flags = _readByte();

    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    var returnType = readNode() as SimpleIdentifier;

    Token? period;
    SimpleIdentifier? name;
    if (AstBinaryFlags.hasName(flags)) {
      var periodOffset = _readInformativeUint30();
      period = Token(TokenType.PERIOD, periodOffset);
      name = readNode() as SimpleIdentifier;
    }

    var parameters = readNode() as FormalParameterList;
    var initializers = _readNodeList<ConstructorInitializer>();
    var redirectedConstructor = _readOptionalNode() as ConstructorName?;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.constructorDeclaration(
      null,
      metadata,
      AstBinaryFlags.isExternal(flags) ? Tokens.EXTERNAL : null,
      AstBinaryFlags.isConst(flags) ? Tokens.CONST : null,
      AstBinaryFlags.isFactory(flags) ? Tokens.FACTORY : null,
      returnType,
      period,
      name,
      parameters,
      Tokens.choose(
        AstBinaryFlags.hasSeparatorColon(flags),
        Tokens.COLON,
        AstBinaryFlags.hasSeparatorEquals(flags),
        Tokens.EQ,
      ),
      initializers,
      redirectedConstructor,
      null,
    ) as ConstructorDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    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?;

    return astFactory.constructorName(
      type,
      name != null ? Tokens.PERIOD : null,
      name,
    );
  }

  DeclaredIdentifier _readDeclaredIdentifier() {
    var flags = _readByte();
    var type = _readOptionalNode() as TypeAnnotation?;
    var identifier = readNode() as SimpleIdentifier;
    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 codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    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,
    ) as DefaultFormalParameterImpl;
    node.summaryData = SummaryDataForFormalParameter(
      codeOffset: codeOffset,
      codeLength: codeLength,
    );

    return node;
  }

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

  DoubleLiteral _readDoubleLiteral() {
    var value = _unitReader.astReader.readDouble();
    return AstTestFactory.doubleLiteral(value);
  }

  EnumConstantDeclaration _readEnumConstantDeclaration() {
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    var name = readNode() as SimpleIdentifier;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.enumConstantDeclaration(null, metadata, name)
        as EnumConstantDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: -1,
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  EnumDeclaration _readEnumDeclaration() {
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    var constants = _readNodeList<EnumConstantDeclaration>();
    var name = readNode() as SimpleIdentifier;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.enumDeclaration(
      null,
      metadata,
      Tokens.ENUM,
      name,
      Tokens.OPEN_CURLY_BRACKET,
      constants,
      Tokens.CLOSE_CURLY_BRACKET,
    ) as EnumDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  ExportDirective _readExportDirective() {
    var combinators = _readNodeList<Combinator>();
    var configurations = _readNodeList<Configuration>();
    var uri = readNode() as StringLiteral;
    var keywordOffset = _readInformativeUint30();
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.exportDirective(
      null,
      metadata,
      KeywordToken(Keyword.EXPORT, keywordOffset),
      uri,
      configurations,
      combinators,
      Tokens.SEMICOLON,
    ) as ExportDirectiveImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: -1,
      codeLength: 0,
      documentationTokenIndexList: _noDocumentationComment,
      resolutionIndex: _readUInt30(),
    );

    return node;
  }

  ExtendsClause _readExtendsClause() {
    var type = readNode() as TypeName;
    return astFactory.extendsClause(Tokens.EXTENDS, type);
  }

  ExtensionDeclaration _readExtensionDeclaration() {
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var extendedType = readNode() as TypeAnnotation;
    var name = _readOptionalNode() as SimpleIdentifier?;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.extensionDeclaration(
      comment: null,
      metadata: metadata,
      extensionKeyword: Tokens.EXTENSION,
      name: name,
      typeParameters: typeParameters,
      onKeyword: Tokens.ON,
      extendedType: extendedType,
      leftBracket: Tokens.OPEN_CURLY_BRACKET,
      members: const <ClassMember>[],
      rightBracket: Tokens.CLOSE_CURLY_BRACKET,
    ) as ExtensionDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

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

  FieldDeclaration _readFieldDeclaration() {
    var flags = _readByte();
    var codeOffsetLengthList = _readInformativeUint30List();
    var documentationTokenIndexList = _readUint30List();
    var fields = readNode() as VariableDeclarationList;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.fieldDeclaration2(
      comment: null,
      abstractKeyword:
          AstBinaryFlags.isAbstract(flags) ? Tokens.ABSTRACT : null,
      covariantKeyword:
          AstBinaryFlags.isCovariant(flags) ? Tokens.COVARIANT : null,
      externalKeyword:
          AstBinaryFlags.isExternal(flags) ? Tokens.EXTERNAL : null,
      fieldList: fields,
      metadata: metadata,
      semicolon: Tokens.SEMICOLON,
      staticKeyword: AstBinaryFlags.isStatic(flags) ? Tokens.STATIC : null,
    ) as FieldDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: -1,
      codeLength: 0,
      codeOffsetLengthList: codeOffsetLengthList,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  FieldFormalParameter _readFieldFormalParameter() {
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var type = _readOptionalNode() as TypeAnnotation?;
    var formalParameters = _readOptionalNode() as FormalParameterList?;
    var flags = _readByte();
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    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,
    ) as FieldFormalParameterImpl;
    node.summaryData = SummaryDataForFormalParameter(
      codeOffset: codeOffset,
      codeLength: codeLength,
    );
    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 body = readNode() as CollectionElement;
    var flags = _readByte();
    var forLoopParts = readNode() as ForLoopParts;
    return astFactory.forElement(
      awaitKeyword: AstBinaryFlags.hasAwait(flags) ? Tokens.AWAIT : null,
      body: body,
      forKeyword: Tokens.FOR,
      forLoopParts: forLoopParts,
      leftParenthesis: Tokens.OPEN_PAREN,
      rightParenthesis: Tokens.CLOSE_PAREN,
    );
  }

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

    return astFactory.formalParameterList(
      Tokens.OPEN_PAREN,
      parameters,
      Tokens.choose(
        AstBinaryFlags.isDelimiterCurly(flags),
        Tokens.OPEN_CURLY_BRACKET,
        AstBinaryFlags.isDelimiterSquare(flags),
        Tokens.OPEN_SQUARE_BRACKET,
      ),
      Tokens.choose(
        AstBinaryFlags.isDelimiterCurly(flags),
        Tokens.CLOSE_CURLY_BRACKET,
        AstBinaryFlags.isDelimiterSquare(flags),
        Tokens.CLOSE_SQUARE_BRACKET,
      ),
      Tokens.CLOSE_PAREN,
    );
  }

  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,
    );
  }

  FunctionDeclaration _readFunctionDeclaration() {
    var flags = _readByte();
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();
    var functionExpression = readNode() as FunctionExpression;
    var returnType = _readOptionalNode() as TypeAnnotation?;
    var name = readNode() as SimpleIdentifier;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.functionDeclaration(
      null,
      metadata,
      AstBinaryFlags.isExternal(flags) ? Tokens.EXTERNAL : null,
      returnType,
      Tokens.choose(
        AstBinaryFlags.isGet(flags),
        Tokens.GET,
        AstBinaryFlags.isSet(flags),
        Tokens.SET,
      ),
      name,
      functionExpression,
    ) as FunctionDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  FunctionExpression _readFunctionExpression() {
    var flags = _readByte();
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var formalParameters = _readOptionalNode() as FormalParameterList?;
    var body = _functionBodyForFlags(flags);

    return astFactory.functionExpression(
      typeParameters,
      formalParameters,
      body,
    );
  }

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

  FunctionTypeAlias _readFunctionTypeAlias() {
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var returnType = _readOptionalNode() as TypeAnnotation?;
    var formalParameters = readNode() as FormalParameterList;
    var name = readNode() as SimpleIdentifier;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.functionTypeAlias(
      null,
      metadata,
      Tokens.TYPEDEF,
      returnType,
      name,
      typeParameters,
      formalParameters,
      Tokens.SEMICOLON,
    ) as FunctionTypeAliasImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  FunctionTypedFormalParameter _readFunctionTypedFormalParameter() {
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var returnType = _readOptionalNode() as TypeAnnotation?;
    var formalParameters = readNode() as FormalParameterList;
    var flags = _readByte();
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    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,
    ) as FunctionTypedFormalParameterImpl;
    node.summaryData = SummaryDataForFormalParameter(
      codeOffset: codeOffset,
      codeLength: codeLength,
    );
    return node;
  }

  GenericFunctionType _readGenericFunctionType() {
    var flags = _readByte();
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var returnType = _readOptionalNode() as TypeAnnotation?;
    var formalParameters = readNode() as FormalParameterList;

    return astFactory.genericFunctionType(
      returnType,
      Tokens.FUNCTION,
      typeParameters,
      formalParameters,
      question: AstBinaryFlags.hasQuestion(flags) ? Tokens.QUESTION : null,
    );
  }

  GenericTypeAlias _readGenericTypeAlias() {
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var type = readNode() as TypeAnnotation;
    var name = readNode() as SimpleIdentifier;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.genericTypeAlias(
      null,
      metadata,
      Tokens.TYPEDEF,
      name,
      typeParameters,
      Tokens.EQ,
      type,
      Tokens.SEMICOLON,
    ) as GenericTypeAliasImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  HideCombinator _readHideCombinator() {
    var keywordOffset = _readInformativeUint30();
    return astFactory.hideCombinator(
      KeywordToken(Keyword.HIDE, keywordOffset),
      _readNodeList<SimpleIdentifier>(),
    );
  }

  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.OPEN_PAREN,
      rightParenthesis: Tokens.CLOSE_PAREN,
      thenElement: thenElement,
    );
  }

  ImplementsClause _readImplementsClause() {
    var interfaces = _readNodeList<TypeName>();
    return astFactory.implementsClause(Tokens.IMPLEMENTS, interfaces);
  }

  ImportDirective _readImportDirective() {
    var flags = _readByte();

    SimpleIdentifier? prefixIdentifier;
    if (AstBinaryFlags.hasPrefix(flags)) {
      var prefixName = _readStringReference();
      var prefixOffset = _readInformativeUint30();
      prefixIdentifier = astFactory.simpleIdentifier(
        StringToken(TokenType.STRING, prefixName, prefixOffset),
      );
    }

    var combinators = _readNodeList<Combinator>();
    var configurations = _readNodeList<Configuration>();
    var uri = readNode() as StringLiteral;
    var keywordOffset = _readInformativeUint30();
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.importDirective(
      null,
      metadata,
      KeywordToken(Keyword.IMPORT, keywordOffset),
      uri,
      configurations,
      AstBinaryFlags.isDeferred(flags) ? Tokens.DEFERRED : null,
      Tokens.AS,
      prefixIdentifier,
      combinators,
      Tokens.SEMICOLON,
    ) as ImportDirectiveImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: -1,
      codeLength: 0,
      documentationTokenIndexList: _noDocumentationComment,
      resolutionIndex: _readUInt30(),
    );

    return node;
  }

  IndexExpression _readIndexExpression() {
    var flags = _readByte();
    var target = _readOptionalNode() as Expression?;
    var index = readNode() as Expression;
    // TODO(scheglov) Is this clumsy?
    if (target != null) {
      return astFactory.indexExpressionForTarget2(
        target: target,
        question: AstBinaryFlags.hasQuestion(flags) ? Tokens.QUESTION : null,
        leftBracket: Tokens.OPEN_SQUARE_BRACKET,
        index: index,
        rightBracket: Tokens.CLOSE_SQUARE_BRACKET,
      )..period = AstBinaryFlags.hasPeriod(flags) ? Tokens.PERIOD_PERIOD : null;
    } else {
      return astFactory.indexExpressionForCascade2(
        period: Tokens.PERIOD_PERIOD,
        question: AstBinaryFlags.hasQuestion(flags) ? Tokens.QUESTION : null,
        leftBracket: Tokens.OPEN_SQUARE_BRACKET,
        index: index,
        rightBracket: Tokens.CLOSE_SQUARE_BRACKET,
      );
    }
  }

  int _readInformativeUint30() {
    if (_withInformative) {
      return _readUInt30();
    }
    return 0;
  }

  Uint32List? _readInformativeUint30List() {
    if (_withInformative) {
      return _readUint30List();
    }
    return null;
  }

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

    return astFactory.instanceCreationExpression(
      Tokens.choose(
        AstBinaryFlags.isConst(flags),
        Tokens.CONST,
        AstBinaryFlags.isNew(flags),
        Tokens.NEW,
      ),
      constructorName,
      argumentList,
    );
  }

  IntegerLiteral _readIntegerLiteralNegative() {
    var value = (_readUint32() << 32) | _readUint32();
    return _createIntegerLiteral(-value);
  }

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

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

  IntegerLiteral _readIntegerLiteralPositive() {
    var value = (_readUint32() << 32) | _readUint32();
    return _createIntegerLiteral(value);
  }

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

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

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

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

  LibraryDirective _readLibraryDirective() {
    var documentationTokenIndexList = _readUint30List();
    var name = readNode() as LibraryIdentifier;
    var keywordOffset = _readInformativeUint30();
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.libraryDirective(
      null,
      metadata,
      KeywordToken(Keyword.LIBRARY, keywordOffset),
      name,
      Tokens.SEMICOLON,
    ) as LibraryDirectiveImpl;
    SummaryDataForLibraryDirective(
      _unitReader,
      node,
      documentationTokenIndexList: documentationTokenIndexList,
    );
    return node;
  }

  LibraryIdentifier _readLibraryIdentifier() {
    var components = _readNodeList<SimpleIdentifier>();
    return astFactory.libraryIdentifier(
      components,
    );
  }

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

    return astFactory.listLiteral(
      AstBinaryFlags.isConst(flags) ? Tokens.CONST : null,
      typeArguments,
      Tokens.OPEN_SQUARE_BRACKET,
      elements,
      Tokens.CLOSE_SQUARE_BRACKET,
    );
  }

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

  MethodDeclaration _readMethodDeclaration() {
    var flags = _readUInt30();

    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    var name = readNode() as SimpleIdentifier;
    var typeParameters = _readOptionalNode() as TypeParameterList?;
    var returnType = _readOptionalNode() as TypeAnnotation?;
    var formalParameters = _readOptionalNode() as FormalParameterList?;
    var metadata = _readNodeList<Annotation>();
    var body = _functionBodyForFlags(flags);

    var node = astFactory.methodDeclaration(
      null,
      metadata,
      AstBinaryFlags.isExternal(flags) ? Tokens.EXTERNAL : null,
      AstBinaryFlags.isStatic(flags) ? Tokens.STATIC : null,
      returnType,
      Tokens.choose(
        AstBinaryFlags.isGet(flags),
        Tokens.GET,
        AstBinaryFlags.isSet(flags),
        Tokens.SET,
      ),
      AstBinaryFlags.isOperator(flags) ? Tokens.OPERATOR : null,
      name,
      typeParameters,
      formalParameters,
      body,
    ) as MethodDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  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;

    return astFactory.methodInvocation(
      target,
      Tokens.choose(
        AstBinaryFlags.hasPeriod(flags),
        Tokens.PERIOD,
        AstBinaryFlags.hasPeriod2(flags),
        Tokens.PERIOD_PERIOD,
      ),
      methodName,
      typeArguments,
      arguments,
    );
  }

  MixinDeclaration _readMixinDeclaration() {
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var documentationTokenIndexList = _readUint30List();

    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.OPEN_CURLY_BRACKET,
      const <ClassMember>[],
      Tokens.CLOSE_CURLY_BRACKET,
    ) as MixinDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: codeOffset,
      codeLength: codeLength,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

  NamedExpression _readNamedExpression() {
    var name = _readStringReference();
    var offset = _readInformativeUint30();
    var nameNode = astFactory.label(
      astFactory.simpleIdentifier(
        StringToken(TokenType.STRING, name, offset),
      ),
      Tokens.COLON,
    );

    var expression = readNode() as Expression;
    return astFactory.namedExpression(nameNode, expression);
  }

  NativeClause _readNativeClause() {
    var name = _readOptionalNode() as StringLiteral?;
    return astFactory.nativeClause(Tokens.NATIVE, name);
  }

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

  NullLiteral _readNullLiteral() {
    return astFactory.nullLiteral(
      Tokens.NULL,
    );
  }

  OnClause _readOnClause() {
    var superclassConstraints = _readNodeList<TypeName>();
    return astFactory.onClause(Tokens.ON, superclassConstraints);
  }

  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;
    return astFactory.parenthesizedExpression(
      Tokens.OPEN_PAREN,
      expression,
      Tokens.CLOSE_PAREN,
    );
  }

  PartDirective _readPartDirective() {
    var uri = readNode() as StringLiteral;
    var keywordOffset = _readInformativeUint30();
    var metadata = _readNodeList<Annotation>();

    return astFactory.partDirective(
      null,
      metadata,
      KeywordToken(Keyword.PART, keywordOffset),
      uri,
      Tokens.SEMICOLON,
    );
  }

  PartOfDirective _readPartOfDirective() {
    var libraryName = _readOptionalNode() as LibraryIdentifier?;
    var uri = _readOptionalNode() as StringLiteral?;
    var keywordOffset = _readInformativeUint30();
    var metadata = _readNodeList<Annotation>();

    return astFactory.partOfDirective(
      null,
      metadata,
      KeywordToken(Keyword.PART, keywordOffset),
      Tokens.OF,
      uri,
      libraryName,
      Tokens.SEMICOLON,
    );
  }

  PostfixExpression _readPostfixExpression() {
    var operand = readNode() as Expression;
    var operatorType = UnlinkedTokenType.values[_readByte()];
    return astFactory.postfixExpression(
      operand,
      Tokens.fromType(operatorType),
    );
  }

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

  PrefixExpression _readPrefixExpression() {
    var operatorType = UnlinkedTokenType.values[_readByte()];
    var operand = readNode() as Expression;
    return astFactory.prefixExpression(
      Tokens.fromType(operatorType),
      operand,
    );
  }

  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.QUESTION_PERIOD
          : Tokens.QUESTION_PERIOD_PERIOD;
    } else {
      operator = AstBinaryFlags.hasPeriod(flags)
          ? Tokens.PERIOD
          : Tokens.PERIOD_PERIOD;
    }

    return astFactory.propertyAccess(target, operator, propertyName);
  }

  RedirectingConstructorInvocation _readRedirectingConstructorInvocation() {
    var constructorName = _readOptionalNode() as SimpleIdentifier?;
    var argumentList = readNode() as ArgumentList;
    return astFactory.redirectingConstructorInvocation(
      Tokens.THIS,
      constructorName != null ? Tokens.PERIOD : null,
      constructorName,
      argumentList,
    );
  }

  SetOrMapLiteral _readSetOrMapLiteral() {
    var flags = _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.OPEN_CURLY_BRACKET,
      typeArguments: typeArguments,
      rightBracket: Tokens.CLOSE_CURLY_BRACKET,
    ) as SetOrMapLiteralImpl;
    return node;
  }

  ShowCombinator _readShowCombinator() {
    var keywordOffset = _readInformativeUint30();
    return astFactory.showCombinator(
      KeywordToken(Keyword.SHOW, keywordOffset),
      _readNodeList<SimpleIdentifier>(),
    );
  }

  SimpleFormalParameter _readSimpleFormalParameter() {
    var type = _readOptionalNode() as TypeAnnotation?;
    var flags = _readByte();
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var metadata = _readNodeList<Annotation>();
    var identifier =
        AstBinaryFlags.hasName(flags) ? readNode() as SimpleIdentifier : 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,
    ) as SimpleFormalParameterImpl;
    node.summaryData = SummaryDataForFormalParameter(
      codeOffset: codeOffset,
      codeLength: codeLength,
    );
    return node;
  }

  SimpleIdentifier _readSimpleIdentifier() {
    var name = _readStringReference();
    var offset = _readInformativeUint30();
    return astFactory.simpleIdentifier(
      StringToken(TokenType.STRING, name, offset),
    );
  }

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

    return astFactory.simpleStringLiteral(
      TokenFactory.tokenFromString(lexeme),
      value,
    );
  }

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

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

  String _readStringReference() {
    return _unitReader.astReader.readStringReference();
  }

  SuperConstructorInvocation _readSuperConstructorInvocation() {
    var constructorName = _readOptionalNode() as SimpleIdentifier?;
    var argumentList = readNode() as ArgumentList;
    return astFactory.superConstructorInvocation(
      Tokens.SUPER,
      Tokens.PERIOD,
      constructorName,
      argumentList,
    );
  }

  SuperExpression _readSuperExpression() {
    return astFactory.superExpression(Tokens.SUPER);
  }

  SymbolLiteral _readSymbolLiteral() {
    var components = <Token>[];
    var length = _readUInt30();
    for (var i = 0; i < length; i++) {
      var lexeme = _readStringReference();
      var token = TokenFactory.tokenFromString(lexeme);
      components.add(token);
    }
    return astFactory.symbolLiteral(Tokens.HASH, components);
  }

  ThisExpression _readThisExpression() {
    return astFactory.thisExpression(Tokens.THIS);
  }

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

  TopLevelVariableDeclaration _readTopLevelVariableDeclaration() {
    var flags = _readByte();
    var codeOffsetLengthList = _readInformativeUint30List();
    var documentationTokenIndexList = _readUint30List();
    var variableList = readNode() as VariableDeclarationList;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.topLevelVariableDeclaration(
      null,
      metadata,
      variableList,
      Tokens.SEMICOLON,
      externalKeyword:
          AstBinaryFlags.isExternal(flags) ? Tokens.EXTERNAL : null,
    ) as TopLevelVariableDeclarationImpl;

    node.linkedContext = LinkedContext(
      _unitReader,
      node,
      codeOffset: -1,
      codeLength: 0,
      codeOffsetLengthList: codeOffsetLengthList,
      resolutionIndex: _readUInt30(),
      documentationTokenIndexList: documentationTokenIndexList,
    );

    return node;
  }

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

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

    return astFactory.typeName(
      name,
      typeArguments,
      question: AstBinaryFlags.hasQuestion(flags) ? Tokens.QUESTION : null,
    );
  }

  TypeParameter _readTypeParameter() {
    var codeOffset = _readInformativeUint30();
    var codeLength = _readInformativeUint30();
    var name = readNode() as SimpleIdentifier;
    var bound = _readOptionalNode() as TypeAnnotation?;
    var metadata = _readNodeList<Annotation>();

    var node = astFactory.typeParameter(
      null,
      metadata,
      name,
      bound != null ? Tokens.EXTENDS : null,
      bound,
    ) as TypeParameterImpl;
    node.summaryData = SummaryDataForTypeParameter(
      codeOffset: codeOffset,
      codeLength: codeLength,
    );

    return node;
  }

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

  int _readUInt30() {
    var byte = _readByte();
    if (byte & 0x80 == 0) {
      // 0xxxxxxx
      return byte;
    } else if (byte & 0x40 == 0) {
      // 10xxxxxx
      return ((byte & 0x3F) << 8) | _readByte();
    } else {
      // 11xxxxxx
      return ((byte & 0x3F) << 24) |
          (_readByte() << 16) |
          (_readByte() << 8) |
          _readByte();
    }
  }

  Uint32List _readUint30List() {
    var length = _readUInt30();
    var result = Uint32List(length);
    for (var i = 0; i < length; ++i) {
      result[i] = _readUInt30();
    }
    return result;
  }

  int _readUint32() {
    return (_readByte() << 24) |
        (_readByte() << 16) |
        (_readByte() << 8) |
        _readByte();
  }

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

    var node = astFactory.variableDeclaration(
      name,
      Tokens.EQ,
      initializer,
    ) as VariableDeclarationImpl;

    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,
    );
  }

  WithClause _readWithClause() {
    var mixins = _readNodeList<TypeName>();
    return astFactory.withClause(Tokens.WITH, mixins);
  }
}
