// 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/token.dart';
import 'package:analyzer/src/dart/ast/ast_factory.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(
      atSign: Tokens.AT,
      name: name,
      period: Tokens.PERIOD,
      constructorName: constructorName,
      arguments: 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,
    );
    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,
    );

    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,
      AstTestFactory.emptyFunctionBody(),
    );

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

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

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

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

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

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

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

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

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

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

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

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

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

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