// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/summary2/ast_binary_flags.dart';
import 'package:analyzer/src/summary2/ast_binary_tag.dart';
import 'package:analyzer/src/summary2/bundle_writer.dart';
import 'package:analyzer/src/summary2/data_writer.dart';
import 'package:analyzer/src/summary2/tokens_writer.dart';
import 'package:analyzer/src/task/inference_error.dart';

/// Serializer of fully resolved ASTs.
class AstBinaryWriter extends ThrowingAstVisitor<void> {
  final bool _withInformative;
  final BufferedSink _sink;
  final StringIndexer _stringIndexer;
  final int Function() _getNextResolutionIndex;
  final ResolutionSink? _resolutionSink;

  /// TODO(scheglov) Keep it private, and write here, similarly as we do
  /// for [_classMemberIndexItems]?
  final List<_UnitMemberIndexItem> unitMemberIndexItems = [];
  final List<_ClassMemberIndexItem> _classMemberIndexItems = [];
  bool _shouldStoreVariableInitializers = false;
  bool _hasConstConstructor = false;
  int _nextUnnamedExtensionId = 0;

  AstBinaryWriter({
    required bool withInformative,
    required BufferedSink sink,
    required StringIndexer stringIndexer,
    required int Function() getNextResolutionIndex,
    required ResolutionSink? resolutionSink,
  })   : _withInformative = withInformative,
        _sink = sink,
        _stringIndexer = stringIndexer,
        _getNextResolutionIndex = getNextResolutionIndex,
        _resolutionSink = resolutionSink;

  @override
  void visitAdjacentStrings(AdjacentStrings node) {
    _writeByte(Tag.AdjacentStrings);
    _writeNodeList(node.strings);
  }

  @override
  void visitAnnotation(Annotation node) {
    _writeByte(Tag.Annotation);

    _writeMarker(MarkerTag.Annotation_name);
    _writeNode(node.name);
    _writeMarker(MarkerTag.Annotation_constructorName);
    _writeOptionalNode(node.constructorName);

    _writeMarker(MarkerTag.Annotation_arguments);
    var arguments = node.arguments;
    if (arguments != null) {
      if (!arguments.arguments.every(_isSerializableExpression)) {
        arguments = null;
      }
    }
    _writeOptionalNode(arguments);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.Annotation_element);
      resolutionSink.writeElement(node.element);
    }
  }

  @override
  void visitArgumentList(ArgumentList node) {
    _writeByte(Tag.ArgumentList);
    _writeMarker(MarkerTag.ArgumentList_arguments);
    _writeNodeList(node.arguments);
    _writeMarker(MarkerTag.ArgumentList_end);
  }

  @override
  void visitAsExpression(AsExpression node) {
    _writeByte(Tag.AsExpression);

    _writeMarker(MarkerTag.AsExpression_expression);
    _writeNode(node.expression);

    _writeMarker(MarkerTag.AsExpression_type);
    _writeNode(node.type);

    _writeMarker(MarkerTag.AsExpression_expression2);
    _storeExpression(node);

    _writeMarker(MarkerTag.AsExpression_end);
  }

  @override
  void visitAssertInitializer(AssertInitializer node) {
    _writeByte(Tag.AssertInitializer);
    _writeMarker(MarkerTag.AssertInitializer_condition);
    _writeNode(node.condition);
    _writeMarker(MarkerTag.AssertInitializer_message);
    _writeOptionalNode(node.message);
    _writeMarker(MarkerTag.AssertInitializer_end);
  }

  @override
  void visitAssignmentExpression(AssignmentExpression node) {
    _writeByte(Tag.AssignmentExpression);

    _writeMarker(MarkerTag.AssignmentExpression_leftHandSide);
    _writeNode(node.leftHandSide);
    _writeMarker(MarkerTag.AssignmentExpression_rightHandSide);
    _writeNode(node.rightHandSide);

    var operatorToken = node.operator.type;
    var binaryToken = TokensWriter.astToBinaryTokenType(operatorToken);
    _writeByte(binaryToken.index);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.AssignmentExpression_staticElement);
      resolutionSink.writeElement(node.staticElement);
      _writeMarker(MarkerTag.AssignmentExpression_readElement);
      resolutionSink.writeElement(node.readElement);
      _writeMarker(MarkerTag.AssignmentExpression_readType);
      resolutionSink.writeType(node.readType);
      _writeMarker(MarkerTag.AssignmentExpression_writeElement);
      resolutionSink.writeElement(node.writeElement);
      _writeMarker(MarkerTag.AssignmentExpression_writeType);
      resolutionSink.writeType(node.writeType);
    }
    _writeMarker(MarkerTag.AssignmentExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.AssignmentExpression_end);
  }

  @override
  void visitAwaitExpression(AwaitExpression node) {
    _writeByte(Tag.AwaitExpression);

    _writeMarker(MarkerTag.AwaitExpression_expression);
    _writeNode(node.expression);

    _writeMarker(MarkerTag.AsExpression_expression2);
    _storeExpression(node);

    _writeMarker(MarkerTag.AwaitExpression_end);
  }

  @override
  void visitBinaryExpression(BinaryExpression node) {
    _writeByte(Tag.BinaryExpression);

    _writeMarker(MarkerTag.BinaryExpression_leftOperand);
    _writeNode(node.leftOperand);
    _writeMarker(MarkerTag.BinaryExpression_rightOperand);
    _writeNode(node.rightOperand);

    var operatorToken = node.operator.type;
    var binaryToken = TokensWriter.astToBinaryTokenType(operatorToken);
    _writeByte(binaryToken.index);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.BinaryExpression_staticElement);
      resolutionSink.writeElement(node.staticElement);
    }
    _writeMarker(MarkerTag.BinaryExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.BinaryExpression_end);
  }

  @override
  void visitBooleanLiteral(BooleanLiteral node) {
    _writeByte(Tag.BooleanLiteral);
    _writeByte(node.value ? 1 : 0);
    _storeExpression(node);
  }

  @override
  void visitCascadeExpression(CascadeExpression node) {
    _writeByte(Tag.CascadeExpression);
    _writeMarker(MarkerTag.CascadeExpression_target);
    _writeNode(node.target);
    _writeMarker(MarkerTag.CascadeExpression_cascadeSections);
    _writeNodeList(node.cascadeSections);
    _writeMarker(MarkerTag.CascadeExpression_end);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    var classOffset = _sink.offset;
    var resolutionIndex = _getNextResolutionIndex();

    _hasConstConstructor = false;
    for (var member in node.members) {
      if (member is ConstructorDeclaration && member.constKeyword != null) {
        _hasConstConstructor = true;
        break;
      }
    }

    _writeByte(Tag.Class);
    _writeByte(
      AstBinaryFlags.encode(
        hasConstConstructor: _hasConstConstructor,
        isAbstract: node.abstractKeyword != null,
      ),
    );

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as ClassElementImpl;
      resolutionSink.writeByte(element.isSimplyBounded ? 1 : 0);
    }

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    _pushScopeTypeParameters(node.typeParameters);

    _writeMarker(MarkerTag.ClassDeclaration_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.ClassDeclaration_extendsClause);
    _writeOptionalNode(node.extendsClause);
    _writeMarker(MarkerTag.ClassDeclaration_withClause);
    _writeOptionalNode(node.withClause);
    _writeMarker(MarkerTag.ClassDeclaration_implementsClause);
    _writeOptionalNode(node.implementsClause);
    _writeMarker(MarkerTag.ClassDeclaration_nativeClause);
    _writeOptionalNode(node.nativeClause);
    _writeMarker(MarkerTag.ClassDeclaration_namedCompilationUnitMember);
    _storeNamedCompilationUnitMember(node);
    _writeMarker(MarkerTag.ClassDeclaration_end);
    _writeUInt30(resolutionIndex);

    _classMemberIndexItems.clear();
    _writeNodeList(node.members);
    _hasConstConstructor = false;

    if (resolutionSink != null) {
      resolutionSink.localElements.popScope();
    }

    // TODO(scheglov) write member index
    var classIndexOffset = _sink.offset;
    _writeClassMemberIndex();

    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: classOffset,
        tag: Tag.Class,
        name: node.name.name,
        classIndexOffset: classIndexOffset,
      ),
    );
  }

  @override
  void visitClassTypeAlias(ClassTypeAlias node) {
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.ClassTypeAlias,
        name: node.name.name,
      ),
    );

    var resolutionIndex = _getNextResolutionIndex();

    _writeByte(Tag.ClassTypeAlias);
    _writeByte(
      AstBinaryFlags.encode(
        isAbstract: node.abstractKeyword != null,
      ),
    );

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as ClassElementImpl;
      resolutionSink.writeByte(element.isSimplyBounded ? 1 : 0);
    }

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _pushScopeTypeParameters(node.typeParameters);
    _writeMarker(MarkerTag.ClassTypeAlias_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.ClassTypeAlias_superclass);
    _writeNode(node.superclass);
    _writeMarker(MarkerTag.ClassTypeAlias_withClause);
    _writeNode(node.withClause);
    _writeMarker(MarkerTag.ClassTypeAlias_implementsClause);
    _writeOptionalNode(node.implementsClause);
    _writeMarker(MarkerTag.ClassTypeAlias_typeAlias);
    _storeTypeAlias(node);
    _writeMarker(MarkerTag.ClassTypeAlias_end);
    _writeDocumentationCommentString(node.documentationComment);
    _writeUInt30(resolutionIndex);

    if (resolutionSink != null) {
      resolutionSink.localElements.popScope();
    }
  }

  @override
  void visitCompilationUnit(CompilationUnit node) {
    var nodeImpl = node as CompilationUnitImpl;
    _writeLanguageVersion(nodeImpl.languageVersion!);
    _writeFeatureSet(node.featureSet);
    _writeLineInfo(node.lineInfo!);
    _writeUInt30(_withInformative ? node.length : 0);
    _writeNodeList(node.directives);
    for (var declaration in node.declarations) {
      declaration.accept(this);
    }
  }

  @override
  void visitConditionalExpression(ConditionalExpression node) {
    _writeByte(Tag.ConditionalExpression);
    _writeMarker(MarkerTag.ConditionalExpression_condition);
    _writeNode(node.condition);
    _writeMarker(MarkerTag.ConditionalExpression_thenExpression);
    _writeNode(node.thenExpression);
    _writeMarker(MarkerTag.ConditionalExpression_elseExpression);
    _writeNode(node.elseExpression);
    _storeExpression(node);
  }

  @override
  void visitConfiguration(Configuration node) {
    _writeByte(Tag.Configuration);

    _writeByte(
      AstBinaryFlags.encode(
        hasEqual: node.equalToken != null,
      ),
    );

    _writeMarker(MarkerTag.Configuration_name);
    _writeNode(node.name);
    _writeMarker(MarkerTag.Configuration_value);
    _writeOptionalNode(node.value);
    _writeMarker(MarkerTag.Configuration_uri);
    _writeNode(node.uri);
    _writeMarker(MarkerTag.Configuration_end);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    _classMemberIndexItems.add(
      _ClassMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.ConstructorDeclaration,
        name: node.name?.name ?? '',
      ),
    );

    _writeByte(Tag.ConstructorDeclaration);

    _writeByte(
      AstBinaryFlags.encode(
        hasName: node.name != null,
        hasSeparatorColon: node.separator?.type == TokenType.COLON,
        hasSeparatorEquals: node.separator?.type == TokenType.EQ,
        isAbstract: node.body is EmptyFunctionBody,
        isConst: node.constKeyword != null,
        isExternal: node.externalKeyword != null,
        isFactory: node.factoryKeyword != null,
      ),
    );

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    var resolutionIndex = _getNextResolutionIndex();
    _writeMarker(MarkerTag.ConstructorDeclaration_returnType);
    _writeNode(node.returnType);

    var period = node.period;
    if (period != null) {
      _writeInformativeUint30(period.offset);
      _writeDeclarationName(node.name!);
    }

    _writeMarker(MarkerTag.ConstructorDeclaration_parameters);
    _writeNode(node.parameters);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      resolutionSink.localElements.pushScope();
      for (var parameter in node.parameters.parameters) {
        resolutionSink.localElements.declare(parameter.declaredElement!);
      }
    }

    // TODO(scheglov) Not nice, we skip both resolution and AST.
    // But eventually we want to store full AST, and partial resolution.
    _writeMarker(MarkerTag.ConstructorDeclaration_initializers);
    if (node.constKeyword != null) {
      _writeNodeList(node.initializers);
    } else {
      _writeNodeList(const <ConstructorInitializer>[]);
    }

    if (resolutionSink != null) {
      resolutionSink.localElements.popScope();
    }

    _writeMarker(MarkerTag.ConstructorDeclaration_redirectedConstructor);
    _writeOptionalNode(node.redirectedConstructor);
    _writeMarker(MarkerTag.ConstructorDeclaration_classMember);
    _storeClassMember(node);
    _writeMarker(MarkerTag.ConstructorDeclaration_end);
    _writeUInt30(resolutionIndex);
  }

  @override
  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
    _writeByte(Tag.ConstructorFieldInitializer);

    _writeByte(
      AstBinaryFlags.encode(
        hasThis: node.thisKeyword != null,
      ),
    );

    _writeMarker(MarkerTag.ConstructorFieldInitializer_fieldName);
    _writeNode(node.fieldName);
    _writeMarker(MarkerTag.ConstructorFieldInitializer_expression);
    _writeNode(node.expression);
    _writeMarker(MarkerTag.ConstructorFieldInitializer_end);
  }

  @override
  void visitConstructorName(ConstructorName node) {
    _writeByte(Tag.ConstructorName);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      // When we parse `C() = A.named` we don't know that `A` is a class name.
      // We parse it as a `TypeName(PrefixedIdentifier)`.
      // But when we resolve, we rewrite it.
      // We need to inform the applier about the right shape of the AST.
      resolutionSink.writeByte(node.name != null ? 1 : 0);
    }

    _writeMarker(MarkerTag.ConstructorName_type);
    _writeNode(node.type);
    _writeMarker(MarkerTag.ConstructorName_name);
    _writeOptionalNode(node.name);

    if (resolutionSink != null) {
      _writeMarker(MarkerTag.ConstructorName_staticElement);
      resolutionSink.writeElement(node.staticElement);
    }

    _writeMarker(MarkerTag.ConstructorName_end);
  }

  @override
  void visitDeclaredIdentifier(DeclaredIdentifier node) {
    _writeByte(Tag.DeclaredIdentifier);
    _writeByte(
      AstBinaryFlags.encode(
        isConst: node.keyword?.keyword == Keyword.CONST,
        isFinal: node.keyword?.keyword == Keyword.FINAL,
        isVar: node.keyword?.keyword == Keyword.VAR,
      ),
    );
    _writeMarker(MarkerTag.DeclaredIdentifier_type);
    _writeOptionalNode(node.type);
    _writeMarker(MarkerTag.DeclaredIdentifier_identifier);
    _writeDeclarationName(node.identifier);
    _writeMarker(MarkerTag.DeclaredIdentifier_declaration);
    _storeDeclaration(node);
    _writeMarker(MarkerTag.DeclaredIdentifier_end);
  }

  @override
  void visitDefaultFormalParameter(DefaultFormalParameter node) {
    _writeByte(Tag.DefaultFormalParameter);

    _writeByte(
      AstBinaryFlags.encode(
        hasInitializer: node.defaultValue != null,
        isPositional: node.isPositional,
        isRequired: node.isRequired,
      ),
    );

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);

    _writeMarker(MarkerTag.DefaultFormalParameter_parameter);
    _writeNode(node.parameter);

    var defaultValue = node.defaultValue;
    if (!_isSerializableExpression(defaultValue)) {
      defaultValue = null;
    }
    _writeMarker(MarkerTag.DefaultFormalParameter_defaultValue);
    _writeOptionalNode(defaultValue);
    _writeMarker(MarkerTag.DefaultFormalParameter_end);
  }

  @override
  void visitDottedName(DottedName node) {
    _writeByte(Tag.DottedName);
    _writeNodeList(node.components);
  }

  @override
  void visitDoubleLiteral(DoubleLiteral node) {
    _writeByte(Tag.DoubleLiteral);
    _writeDouble(node.value);
  }

  @override
  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
    _writeByte(Tag.EnumConstantDeclaration);

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    _writeMarker(MarkerTag.EnumConstantDeclaration_name);
    _writeDeclarationName(node.name);
    _writeMarker(MarkerTag.EnumConstantDeclaration_declaration);
    _storeDeclaration(node);
    _writeMarker(MarkerTag.EnumConstantDeclaration_end);
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    var resolutionIndex = _getNextResolutionIndex();
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.EnumDeclaration,
        name: node.name.name,
      ),
    );

    _writeByte(Tag.EnumDeclaration);

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    _writeMarker(MarkerTag.EnumDeclaration_constants);
    _writeNodeList(node.constants);
    _writeMarker(MarkerTag.EnumDeclaration_namedCompilationUnitMember);
    _storeNamedCompilationUnitMember(node);
    _writeMarker(MarkerTag.EnumDeclaration_end);
    _writeUInt30(resolutionIndex);
  }

  @override
  void visitExportDirective(ExportDirective node) {
    var resolutionIndex = _getNextResolutionIndex();

    _writeByte(Tag.ExportDirective);
    _writeMarker(MarkerTag.ExportDirective_namespaceDirective);
    _storeNamespaceDirective(node);
    _writeUInt30(resolutionIndex);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.ExportDirective_exportedLibrary);
      resolutionSink.writeElement(
        (node.element as ExportElementImpl).exportedLibrary,
      );
    }

    _writeMarker(MarkerTag.ExportDirective_end);
  }

  @override
  void visitExtendsClause(ExtendsClause node) {
    _writeByte(Tag.ExtendsClause);
    _writeMarker(MarkerTag.ExtendsClause_superclass);
    _writeNode(node.superclass);
    _writeMarker(MarkerTag.ExtendsClause_end);
  }

  @override
  void visitExtensionDeclaration(ExtensionDeclaration node) {
    var classOffset = _sink.offset;
    var resolutionIndex = _getNextResolutionIndex();

    _writeByte(Tag.ExtensionDeclaration);

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    _pushScopeTypeParameters(node.typeParameters);
    _writeMarker(MarkerTag.ExtensionDeclaration_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.ExtensionDeclaration_extendedType);
    _writeNode(node.extendedType);
    _writeOptionalDeclarationName(node.name);
    _writeMarker(MarkerTag.ExtensionDeclaration_compilationUnitMember);
    _storeCompilationUnitMember(node);
    _writeMarker(MarkerTag.ExtensionDeclaration_end);
    _writeUInt30(resolutionIndex);

    _classMemberIndexItems.clear();
    _writeNodeList(node.members);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      resolutionSink.localElements.popScope();
    }

    // TODO(scheglov) write member index
    var classIndexOffset = _sink.offset;
    _writeClassMemberIndex();

    var nameIdentifier = node.name;
    var indexName = nameIdentifier != null
        ? nameIdentifier.name
        : 'extension-${_nextUnnamedExtensionId++}';
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: classOffset,
        tag: Tag.ExtensionDeclaration,
        name: indexName,
        classIndexOffset: classIndexOffset,
      ),
    );
  }

  @override
  void visitExtensionOverride(ExtensionOverride node) {
    _writeByte(Tag.ExtensionOverride);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      resolutionSink.writeByte(MethodInvocationRewriteTag.extensionOverride);
    }

    _writeMarker(MarkerTag.ExtensionOverride_extensionName);
    _writeNode(node.extensionName);
    _writeMarker(MarkerTag.ExtensionOverride_typeArguments);
    _writeOptionalNode(node.typeArguments);
    _writeMarker(MarkerTag.ExtensionOverride_argumentList);
    _writeNode(node.argumentList);
    _writeMarker(MarkerTag.ExtensionOverride_extendedType);

    if (resolutionSink != null) {
      resolutionSink.writeType(node.extendedType);
    }

    _writeMarker(MarkerTag.ExtensionOverride_end);
    // TODO(scheglov) typeArgumentTypes?
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    _classMemberIndexItems.add(
      _ClassMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.FieldDeclaration,
        fieldNames: node.fields.variables.map((e) => e.name.name).toList(),
      ),
    );

    _writeByte(Tag.FieldDeclaration);
    _writeByte(
      AstBinaryFlags.encode(
        isAbstract: node.abstractKeyword != null,
        isCovariant: node.covariantKeyword != null,
        isExternal: node.externalKeyword != null,
        isStatic: node.staticKeyword != null,
      ),
    );

    _writeInformativeVariableCodeRanges(node.offset, node.fields);
    _writeDocumentationCommentString(node.documentationComment);

    var resolutionIndex = _getNextResolutionIndex();

    _shouldStoreVariableInitializers = node.fields.isConst ||
        _hasConstConstructor && node.fields.isFinal && !node.isStatic;
    try {
      _writeMarker(MarkerTag.FieldDeclaration_fields);
      _writeNode(node.fields);
    } finally {
      _shouldStoreVariableInitializers = false;
    }

    _writeMarker(MarkerTag.FieldDeclaration_classMember);
    _storeClassMember(node);
    _writeMarker(MarkerTag.FieldDeclaration_end);

    _writeUInt30(resolutionIndex);
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    _writeByte(Tag.FieldFormalParameter);

    _pushScopeTypeParameters(node.typeParameters);
    _writeMarker(MarkerTag.FieldFormalParameter_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.FieldFormalParameter_type);
    _writeOptionalNode(node.type);
    _writeMarker(MarkerTag.FieldFormalParameter_parameters);
    _writeOptionalNode(node.parameters);
    _writeMarker(MarkerTag.FieldFormalParameter_normalFormalParameter);
    _storeNormalFormalParameter(
      node,
      node.keyword,
      hasQuestion: node.question != null,
    );
    _writeMarker(MarkerTag.FieldFormalParameter_end);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      resolutionSink.localElements.popScope();
    }
  }

  @override
  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
    _writeByte(Tag.ForEachPartsWithDeclaration);
    _writeMarker(MarkerTag.ForEachPartsWithDeclaration_loopVariable);
    _writeNode(node.loopVariable);
    _writeMarker(MarkerTag.ForEachPartsWithDeclaration_forEachParts);
    _storeForEachParts(node);
    _writeMarker(MarkerTag.ForEachPartsWithDeclaration_end);
  }

  @override
  void visitForElement(ForElement node) {
    _writeByte(Tag.ForElement);
    _writeByte(
      AstBinaryFlags.encode(
        hasAwait: node.awaitKeyword != null,
      ),
    );
    _writeMarker(MarkerTag.ForElement_forLoopParts);
    _writeNode(node.forLoopParts);
    _writeMarker(MarkerTag.ForElement_body);
    _writeNode(node.body);
    _writeMarker(MarkerTag.ForElement_end);
  }

  @override
  void visitFormalParameterList(FormalParameterList node) {
    _writeByte(Tag.FormalParameterList);

    var leftDelimiter = node.leftDelimiter?.type;
    _writeByte(
      AstBinaryFlags.encode(
        isDelimiterCurly: leftDelimiter == TokenType.OPEN_CURLY_BRACKET,
        isDelimiterSquare: leftDelimiter == TokenType.OPEN_SQUARE_BRACKET,
      ),
    );

    _writeMarker(MarkerTag.FormalParameterList_parameters);
    _writeNodeList(node.parameters);
    _writeMarker(MarkerTag.FormalParameterList_end);
  }

  @override
  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
    _writeByte(Tag.ForPartsWithDeclarations);
    _writeMarker(MarkerTag.ForPartsWithDeclarations_variables);
    _writeNode(node.variables);
    _writeMarker(MarkerTag.ForPartsWithDeclarations_forParts);
    _storeForParts(node);
    _writeMarker(MarkerTag.ForPartsWithDeclarations_end);
  }

  @override
  void visitForPartsWithExpression(ForPartsWithExpression node) {
    _writeByte(Tag.ForPartsWithExpression);
    _writeMarker(MarkerTag.ForPartsWithExpression_initialization);
    _writeOptionalNode(node.initialization);
    _writeMarker(MarkerTag.ForPartsWithExpression_forParts);
    _storeForParts(node);
    _writeMarker(MarkerTag.ForPartsWithExpression_end);
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    var indexTag = Tag.FunctionDeclaration;
    if (node.isGetter) {
      indexTag = Tag.FunctionDeclaration_getter;
    } else if (node.isSetter) {
      indexTag = Tag.FunctionDeclaration_setter;
    }
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: _sink.offset,
        tag: indexTag,
        name: node.name.name,
        variableNames: null,
      ),
    );

    _writeByte(Tag.FunctionDeclaration);

    _writeByte(
      AstBinaryFlags.encode(
        isExternal: node.externalKeyword != null,
        isGet: node.isGetter,
        isSet: node.isSetter,
      ),
    );

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    var resolutionIndex = _getNextResolutionIndex();

    _pushScopeTypeParameters(node.functionExpression.typeParameters);

    _writeMarker(MarkerTag.FunctionDeclaration_functionExpression);
    _writeNode(node.functionExpression);
    _writeMarker(MarkerTag.FunctionDeclaration_returnType);
    _writeOptionalNode(node.returnType);
    _writeMarker(MarkerTag.FunctionDeclaration_namedCompilationUnitMember);
    _storeNamedCompilationUnitMember(node);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as ExecutableElementImpl;
      _writeMarker(MarkerTag.FunctionDeclaration_returnTypeType);
      _writeActualReturnType(resolutionSink, element.returnType);
      resolutionSink.localElements.popScope();
    }

    _writeMarker(MarkerTag.FunctionDeclaration_end);

    _writeUInt30(resolutionIndex);
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    _writeByte(Tag.FunctionExpression);

    var body = node.body;
    _writeByte(
      AstBinaryFlags.encode(
        isAsync: body.isAsynchronous,
        isGenerator: body.isGenerator,
      ),
    );

    _writeMarker(MarkerTag.FunctionExpression_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.FunctionExpression_parameters);
    _writeOptionalNode(node.parameters);
    _writeMarker(MarkerTag.FunctionExpression_end);
  }

  @override
  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
    _writeByte(Tag.FunctionExpressionInvocation);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      resolutionSink.writeByte(
        MethodInvocationRewriteTag.functionExpressionInvocation,
      );
    }

    _writeMarker(MarkerTag.FunctionExpressionInvocation_function);
    _writeNode(node.function);
    _writeMarker(MarkerTag.FunctionExpressionInvocation_invocationExpression);
    _storeInvocationExpression(node);
    _writeMarker(MarkerTag.FunctionExpressionInvocation_end);
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.FunctionTypeAlias,
        name: node.name.name,
        variableNames: null,
      ),
    );

    _writeByte(Tag.FunctionTypeAlias);

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    var resolutionIndex = _getNextResolutionIndex();

    _pushScopeTypeParameters(node.typeParameters);

    _writeMarker(MarkerTag.FunctionTypeAlias_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.FunctionTypeAlias_returnType);
    _writeOptionalNode(node.returnType);
    _writeMarker(MarkerTag.FunctionTypeAlias_parameters);
    _writeNode(node.parameters);

    _writeMarker(MarkerTag.FunctionTypeAlias_typeAlias);
    _storeTypeAlias(node);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as FunctionTypeAliasElementImpl;
      _writeMarker(MarkerTag.FunctionTypeAlias_returnTypeType);
      _writeActualReturnType(resolutionSink, element.function.returnType);
      // TODO(scheglov) pack into one byte
      _writeMarker(MarkerTag.FunctionTypeAlias_flags);
      resolutionSink.writeByte(element.isSimplyBounded ? 1 : 0);
      resolutionSink.writeByte(element.hasSelfReference ? 1 : 0);

      resolutionSink.localElements.popScope();
    }

    _writeMarker(MarkerTag.FunctionTypeAlias_end);

    _writeUInt30(resolutionIndex);
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    _writeByte(Tag.FunctionTypedFormalParameter);

    _pushScopeTypeParameters(node.typeParameters);
    _writeMarker(MarkerTag.FunctionTypedFormalParameter_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.FunctionTypedFormalParameter_returnType);
    _writeOptionalNode(node.returnType);
    _writeMarker(MarkerTag.FunctionTypedFormalParameter_parameters);
    _writeNode(node.parameters);
    _writeMarker(MarkerTag.FunctionTypedFormalParameter_normalFormalParameter);
    _storeNormalFormalParameter(node, null);
    _writeMarker(MarkerTag.FunctionTypedFormalParameter_end);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      resolutionSink.localElements.popScope();
    }
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    _writeByte(Tag.GenericFunctionType);

    _writeByte(
      AstBinaryFlags.encode(
        hasQuestion: node.question != null,
      ),
    );

    _pushScopeTypeParameters(node.typeParameters);

    _writeMarker(MarkerTag.GenericFunctionType_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.GenericFunctionType_returnType);
    _writeOptionalNode(node.returnType);
    _writeMarker(MarkerTag.GenericFunctionType_parameters);
    _writeNode(node.parameters);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.GenericFunctionType_type);
      resolutionSink.writeType(node.type);
      resolutionSink.localElements.popScope();
    }

    _writeMarker(MarkerTag.GenericFunctionType_end);
  }

  @override
  void visitGenericTypeAlias(GenericTypeAlias node) {
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.GenericTypeAlias,
        name: node.name.name,
      ),
    );

    _writeByte(Tag.GenericTypeAlias);

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    var resolutionIndex = _getNextResolutionIndex();

    _pushScopeTypeParameters(node.typeParameters);

    _writeMarker(MarkerTag.GenericTypeAlias_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.GenericTypeAlias_type);
    _writeNode(node.type);
    _writeMarker(MarkerTag.GenericTypeAlias_typeAlias);
    _storeTypeAlias(node);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as TypeAliasElementImpl;
      // TODO(scheglov) pack into one byte
      _writeMarker(MarkerTag.GenericTypeAlias_flags);
      resolutionSink.writeByte(element.isSimplyBounded ? 1 : 0);
      resolutionSink.writeByte(element.hasSelfReference ? 1 : 0);
      resolutionSink.localElements.popScope();
    }

    _writeMarker(MarkerTag.GenericTypeAlias_end);

    _writeUInt30(resolutionIndex);
  }

  @override
  void visitHideCombinator(HideCombinator node) {
    _writeByte(Tag.HideCombinator);
    _writeInformativeUint30(node.keyword.offset);
    _writeNodeList(node.hiddenNames);
  }

  @override
  void visitIfElement(IfElement node) {
    _writeByte(Tag.IfElement);
    _writeMarker(MarkerTag.IfElement_condition);
    _writeNode(node.condition);
    _writeMarker(MarkerTag.IfElement_thenElement);
    _writeNode(node.thenElement);
    _writeMarker(MarkerTag.IfElement_elseElement);
    _writeOptionalNode(node.elseElement);
    _writeMarker(MarkerTag.IfElement_end);
  }

  @override
  void visitImplementsClause(ImplementsClause node) {
    _writeByte(Tag.ImplementsClause);
    _writeMarker(MarkerTag.ImplementsClause_interfaces);
    _writeNodeList(node.interfaces);
    _writeMarker(MarkerTag.ImplementsClause_end);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    var resolutionIndex = _getNextResolutionIndex();

    _writeByte(Tag.ImportDirective);

    var prefix = node.prefix;
    _writeByte(
      AstBinaryFlags.encode(
        hasPrefix: prefix != null,
        isDeferred: node.deferredKeyword != null,
      ),
    );

    if (prefix != null) {
      _writeStringReference(prefix.name);
      _writeInformativeUint30(prefix.offset);
    }

    _writeMarker(MarkerTag.ImportDirective_namespaceDirective);
    _storeNamespaceDirective(node);
    _writeUInt30(resolutionIndex);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.element as ImportElementImpl;
      _writeMarker(MarkerTag.ImportDirective_importedLibrary);
      resolutionSink.writeElement(element.importedLibrary);
    }

    _writeMarker(MarkerTag.ImportDirective_end);
  }

  @override
  void visitIndexExpression(IndexExpression node) {
    _writeByte(Tag.IndexExpression);
    _writeByte(
      AstBinaryFlags.encode(
        hasPeriod: node.period != null,
        hasQuestion: node.question != null,
      ),
    );
    _writeMarker(MarkerTag.IndexExpression_target);
    _writeOptionalNode(node.target);
    _writeMarker(MarkerTag.IndexExpression_index);
    _writeNode(node.index);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.IndexExpression_staticElement);
      resolutionSink.writeElement(node.staticElement);
    }

    _writeMarker(MarkerTag.IndexExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.IndexExpression_end);
  }

  @override
  void visitInstanceCreationExpression(InstanceCreationExpression node) {
    _writeByte(Tag.InstanceCreationExpression);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      if (node.constructorName.name != null) {
        resolutionSink.writeByte(
          MethodInvocationRewriteTag.instanceCreationExpression_withName,
        );
      } else {
        resolutionSink.writeByte(
          MethodInvocationRewriteTag.instanceCreationExpression_withoutName,
        );
      }
    }

    _writeByte(
      AstBinaryFlags.encode(
        isConst: node.keyword?.type == Keyword.CONST,
        isNew: node.keyword?.type == Keyword.NEW,
      ),
    );

    _writeMarker(MarkerTag.InstanceCreationExpression_constructorName);
    _writeNode(node.constructorName);
    _writeMarker(MarkerTag.InstanceCreationExpression_argumentList);
    _writeNode(node.argumentList);
    _writeMarker(MarkerTag.InstanceCreationExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.InstanceCreationExpression_end);
  }

  @override
  void visitIntegerLiteral(IntegerLiteral node) {
    var value = node.value;

    if (value == null) {
      _writeByte(Tag.IntegerLiteralNull);
      _writeStringReference(node.literal.lexeme);
    } else {
      var isPositive = value >= 0;
      if (!isPositive) {
        value = -value;
      }

      if (value & 0xFF == value) {
        _writeByte(
          isPositive
              ? Tag.IntegerLiteralPositive1
              : Tag.IntegerLiteralNegative1,
        );
        _writeByte(value);
      } else {
        _writeByte(
          isPositive ? Tag.IntegerLiteralPositive : Tag.IntegerLiteralNegative,
        );
        _writeUInt32(value >> 32);
        _writeUInt32(value & 0xFFFFFFFF);
      }
    }

    // TODO(scheglov) Dont write type, AKA separate true `int` and `double`?
    _storeExpression(node);
  }

  @override
  void visitInterpolationExpression(InterpolationExpression node) {
    _writeByte(Tag.InterpolationExpression);
    _writeByte(
      AstBinaryFlags.encode(
        isStringInterpolationIdentifier:
            node.leftBracket.type == TokenType.STRING_INTERPOLATION_IDENTIFIER,
      ),
    );
    _writeNode(node.expression);
  }

  @override
  void visitInterpolationString(InterpolationString node) {
    _writeByte(Tag.InterpolationString);
    _writeStringReference(node.value);
  }

  @override
  void visitIsExpression(IsExpression node) {
    _writeByte(Tag.IsExpression);
    _writeByte(
      AstBinaryFlags.encode(
        hasNot: node.notOperator != null,
      ),
    );
    _writeMarker(MarkerTag.IsExpression_expression);
    _writeNode(node.expression);
    _writeMarker(MarkerTag.IsExpression_type);
    _writeNode(node.type);
    _writeMarker(MarkerTag.IsExpression_expression2);
    _storeExpression(node);
    _writeMarker(MarkerTag.IsExpression_end);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    _writeByte(Tag.LibraryDirective);
    _writeDocumentationCommentString(node.documentationComment);
    visitLibraryIdentifier(node.name);
    _storeDirective(node);
  }

  @override
  void visitLibraryIdentifier(LibraryIdentifier node) {
    _writeByte(Tag.LibraryIdentifier);
    _writeNodeList(node.components);
  }

  @override
  void visitListLiteral(ListLiteral node) {
    _writeByte(Tag.ListLiteral);

    _writeByte(
      AstBinaryFlags.encode(
        isConst: node.constKeyword != null,
      ),
    );

    _writeMarker(MarkerTag.ListLiteral_typeArguments);
    _writeOptionalNode(node.typeArguments);
    _writeMarker(MarkerTag.ListLiteral_elements);
    _writeNodeList(node.elements);

    _writeMarker(MarkerTag.ListLiteral_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.ListLiteral_end);
  }

  @override
  void visitMapLiteralEntry(MapLiteralEntry node) {
    _writeByte(Tag.MapLiteralEntry);
    _writeMarker(MarkerTag.MapLiteralEntry_key);
    _writeNode(node.key);
    _writeMarker(MarkerTag.MapLiteralEntry_value);
    _writeNode(node.value);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    var indexTag = Tag.MethodDeclaration;
    if (node.isGetter) {
      indexTag = Tag.MethodDeclaration_getter;
    } else if (node.isSetter) {
      indexTag = Tag.MethodDeclaration_setter;
    }
    _classMemberIndexItems.add(
      _ClassMemberIndexItem(
        offset: _sink.offset,
        tag: indexTag,
        name: node.name.name,
      ),
    );

    _writeByte(Tag.MethodDeclaration);

    _writeUInt30(
      AstBinaryFlags.encode(
        isAbstract: node.body is EmptyFunctionBody,
        isAsync: node.body.isAsynchronous,
        isExternal: node.externalKeyword != null,
        isGenerator: node.body.isGenerator,
        isGet: node.isGetter,
        isNative: node.body is NativeFunctionBody,
        isOperator: node.operatorKeyword != null,
        isSet: node.isSetter,
        isStatic: node.isStatic,
      ),
    );

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    var resolutionIndex = _getNextResolutionIndex();

    _pushScopeTypeParameters(node.typeParameters);

    _writeDeclarationName(node.name);
    _writeMarker(MarkerTag.MethodDeclaration_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.MethodDeclaration_returnType);
    _writeOptionalNode(node.returnType);
    _writeMarker(MarkerTag.MethodDeclaration_parameters);
    _writeOptionalNode(node.parameters);

    _writeMarker(MarkerTag.MethodDeclaration_classMember);
    _storeClassMember(node);

    _writeUInt30(resolutionIndex);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as ExecutableElementImpl;
      _writeMarker(MarkerTag.MethodDeclaration_returnTypeType);
      _writeActualReturnType(resolutionSink, element.returnType);
      _writeMarker(MarkerTag.MethodDeclaration_inferenceError);
      _writeTopLevelInferenceError(resolutionSink, element);
      // TODO(scheglov) move this flag into ClassElementImpl?
      if (element is MethodElementImpl) {
        _writeMarker(MarkerTag.MethodDeclaration_flags);
        resolutionSink.writeByte(
          element.isOperatorEqualWithParameterTypeFromObject ? 1 : 0,
        );
      }
      resolutionSink.localElements.popScope();
    }

    _writeMarker(MarkerTag.MethodDeclaration_end);
  }

  @override
  void visitMethodInvocation(MethodInvocation node) {
    _writeByte(Tag.MethodInvocation);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      resolutionSink.writeByte(MethodInvocationRewriteTag.none);
    }

    _writeByte(
      AstBinaryFlags.encode(
        hasPeriod: node.operator?.type == TokenType.PERIOD,
        hasPeriod2: node.operator?.type == TokenType.PERIOD_PERIOD,
      ),
    );
    _writeMarker(MarkerTag.MethodInvocation_target);
    _writeOptionalNode(node.target);
    _writeMarker(MarkerTag.MethodInvocation_methodName);
    _writeNode(node.methodName);
    _writeMarker(MarkerTag.MethodInvocation_invocationExpression);
    _storeInvocationExpression(node);
    _writeMarker(MarkerTag.MethodInvocation_end);
  }

  @override
  void visitMixinDeclaration(MixinDeclaration node) {
    var classOffset = _sink.offset;
    var resolutionIndex = _getNextResolutionIndex();

    _writeByte(Tag.MixinDeclaration);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as MixinElementImpl;
      resolutionSink.writeByte(element.isSimplyBounded ? 1 : 0);
      resolutionSink.writeStringList(element.superInvokedNames);
    }

    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDocumentationCommentString(node.documentationComment);

    _pushScopeTypeParameters(node.typeParameters);

    _writeMarker(MarkerTag.MixinDeclaration_typeParameters);
    _writeOptionalNode(node.typeParameters);
    _writeMarker(MarkerTag.MixinDeclaration_onClause);
    _writeOptionalNode(node.onClause);
    _writeMarker(MarkerTag.MixinDeclaration_implementsClause);
    _writeOptionalNode(node.implementsClause);
    _writeMarker(MarkerTag.MixinDeclaration_namedCompilationUnitMember);
    _storeNamedCompilationUnitMember(node);
    _writeMarker(MarkerTag.MixinDeclaration_end);
    _writeUInt30(resolutionIndex);

    _classMemberIndexItems.clear();
    _writeNodeList(node.members);
    _hasConstConstructor = false;

    if (resolutionSink != null) {
      resolutionSink.localElements.popScope();
    }

    // TODO(scheglov) write member index
    var classIndexOffset = _sink.offset;
    _writeClassMemberIndex();

    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: classOffset,
        tag: Tag.MixinDeclaration,
        name: node.name.name,
        classIndexOffset: classIndexOffset,
      ),
    );
  }

  @override
  void visitNamedExpression(NamedExpression node) {
    _writeByte(Tag.NamedExpression);

    var nameNode = node.name.label;
    _writeStringReference(nameNode.name);
    _writeInformativeUint30(nameNode.offset);

    _writeMarker(MarkerTag.NamedExpression_expression);
    _writeNode(node.expression);
    _writeMarker(MarkerTag.NamedExpression_end);
  }

  @override
  void visitNativeClause(NativeClause node) {
    _writeByte(Tag.NativeClause);
    _writeMarker(MarkerTag.NativeClause_name);
    _writeOptionalNode(node.name);
    _writeMarker(MarkerTag.NativeClause_end);
  }

  @override
  void visitNullLiteral(NullLiteral node) {
    _writeByte(Tag.NullLiteral);
  }

  @override
  void visitOnClause(OnClause node) {
    _writeByte(Tag.OnClause);
    _writeMarker(MarkerTag.OnClause_superclassConstraints);
    _writeNodeList(node.superclassConstraints);
    _writeMarker(MarkerTag.OnClause_end);
  }

  @override
  void visitParenthesizedExpression(ParenthesizedExpression node) {
    _writeByte(Tag.ParenthesizedExpression);
    _writeMarker(MarkerTag.ParenthesizedExpression_expression);
    _writeNode(node.expression);
    _writeMarker(MarkerTag.ParenthesizedExpression_expression2);
    _storeExpression(node);
    _writeMarker(MarkerTag.ParenthesizedExpression_end);
  }

  @override
  void visitPartDirective(PartDirective node) {
    _writeByte(Tag.PartDirective);
    _storeUriBasedDirective(node);
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    _writeByte(Tag.PartOfDirective);
    _writeMarker(MarkerTag.PartOfDirective_libraryName);
    _writeOptionalNode(node.libraryName);
    _writeMarker(MarkerTag.PartOfDirective_uri);
    _writeOptionalNode(node.uri);
    _writeMarker(MarkerTag.PartOfDirective_directive);
    _storeDirective(node);
    _writeMarker(MarkerTag.PartOfDirective_end);
  }

  @override
  void visitPostfixExpression(PostfixExpression node) {
    _writeByte(Tag.PostfixExpression);

    _writeMarker(MarkerTag.PostfixExpression_operand);
    _writeNode(node.operand);

    var operatorToken = node.operator.type;
    var binaryToken = TokensWriter.astToBinaryTokenType(operatorToken);
    _writeByte(binaryToken.index);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.PostfixExpression_staticElement);
      resolutionSink.writeElement(node.staticElement);
      if (operatorToken.isIncrementOperator) {
        _writeMarker(MarkerTag.PostfixExpression_readElement);
        resolutionSink.writeElement(node.readElement);
        _writeMarker(MarkerTag.PostfixExpression_readType);
        resolutionSink.writeType(node.readType);
        _writeMarker(MarkerTag.PostfixExpression_writeElement);
        resolutionSink.writeElement(node.writeElement);
        _writeMarker(MarkerTag.PostfixExpression_writeType);
        resolutionSink.writeType(node.writeType);
      }
    }
    _writeMarker(MarkerTag.PostfixExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.PostfixExpression_end);
  }

  @override
  void visitPrefixedIdentifier(PrefixedIdentifier node) {
    _writeByte(Tag.PrefixedIdentifier);
    _writeMarker(MarkerTag.PrefixedIdentifier_prefix);
    _writeNode(node.prefix);
    _writeMarker(MarkerTag.PrefixedIdentifier_identifier);
    _writeNode(node.identifier);

    // TODO(scheglov) In actual prefixed identifier, the type of the identifier.
    _writeMarker(MarkerTag.PrefixedIdentifier_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.PrefixedIdentifier_end);
  }

  @override
  void visitPrefixExpression(PrefixExpression node) {
    _writeByte(Tag.PrefixExpression);

    var operatorToken = node.operator.type;
    var binaryToken = TokensWriter.astToBinaryTokenType(operatorToken);
    _writeByte(binaryToken.index);

    _writeMarker(MarkerTag.PrefixExpression_operand);
    _writeNode(node.operand);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.PrefixExpression_staticElement);
      resolutionSink.writeElement(node.staticElement);
      if (operatorToken.isIncrementOperator) {
        _writeMarker(MarkerTag.PrefixExpression_readElement);
        resolutionSink.writeElement(node.readElement);
        _writeMarker(MarkerTag.PrefixExpression_readType);
        resolutionSink.writeType(node.readType);
        _writeMarker(MarkerTag.PrefixExpression_writeElement);
        resolutionSink.writeElement(node.writeElement);
        _writeMarker(MarkerTag.PrefixExpression_writeType);
        resolutionSink.writeType(node.writeType);
      }
    }

    _writeMarker(MarkerTag.PrefixExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.PrefixExpression_end);
  }

  @override
  void visitPropertyAccess(PropertyAccess node) {
    _writeByte(Tag.PropertyAccess);

    var operatorType = node.operator.type;
    _writeByte(
      AstBinaryFlags.encode(
        hasPeriod: operatorType == TokenType.PERIOD ||
            operatorType == TokenType.QUESTION_PERIOD,
        hasPeriod2: operatorType == TokenType.PERIOD_PERIOD ||
            operatorType == TokenType.QUESTION_PERIOD_PERIOD,
        hasQuestion: operatorType == TokenType.QUESTION_PERIOD ||
            operatorType == TokenType.QUESTION_PERIOD_PERIOD,
      ),
    );

    _writeMarker(MarkerTag.PropertyAccess_target);
    _writeOptionalNode(node.target);
    _writeMarker(MarkerTag.PropertyAccess_propertyName);
    _writeNode(node.propertyName);
    // TODO(scheglov) Get from the property?
    _writeMarker(MarkerTag.PropertyAccess_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.PropertyAccess_end);
  }

  @override
  void visitRedirectingConstructorInvocation(
      RedirectingConstructorInvocation node) {
    _writeByte(Tag.RedirectingConstructorInvocation);

    _writeMarker(MarkerTag.RedirectingConstructorInvocation_constructorName);
    _writeOptionalNode(node.constructorName);
    _writeMarker(MarkerTag.RedirectingConstructorInvocation_argumentList);
    _writeNode(node.argumentList);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.RedirectingConstructorInvocation_staticElement);
      resolutionSink.writeElement(node.staticElement);
    }

    _writeMarker(MarkerTag.RedirectingConstructorInvocation_end);
  }

  @override
  void visitSetOrMapLiteral(SetOrMapLiteral node) {
    _writeByte(Tag.SetOrMapLiteral);

    _writeByte(
      AstBinaryFlags.encode(
        isConst: node.constKeyword != null,
      ),
    );

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var isMapBit = node.isMap ? (1 << 0) : 0;
      var isSetBit = node.isSet ? (1 << 1) : 0;
      _writeMarker(MarkerTag.SetOrMapLiteral_flags);
      resolutionSink.writeByte(isMapBit | isSetBit);
    }

    _writeMarker(MarkerTag.SetOrMapLiteral_typeArguments);
    _writeOptionalNode(node.typeArguments);
    _writeMarker(MarkerTag.SetOrMapLiteral_elements);
    _writeNodeList(node.elements);

    _writeMarker(MarkerTag.SetOrMapLiteral_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.SetOrMapLiteral_end);
  }

  @override
  void visitShowCombinator(ShowCombinator node) {
    _writeByte(Tag.ShowCombinator);
    _writeInformativeUint30(node.keyword.offset);
    _writeNodeList(node.shownNames);
  }

  @override
  void visitSimpleFormalParameter(SimpleFormalParameter node) {
    _writeByte(Tag.SimpleFormalParameter);

    _writeMarker(MarkerTag.SimpleFormalParameter_type);
    _writeOptionalNode(node.type);
    _writeMarker(MarkerTag.SimpleFormalParameter_normalFormalParameter);
    _storeNormalFormalParameter(node, node.keyword);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as ParameterElementImpl;
      _writeMarker(MarkerTag.SimpleFormalParameter_flags);
      resolutionSink.writeByte(element.inheritsCovariant ? 1 : 0);
    }

    _writeMarker(MarkerTag.SimpleFormalParameter_end);
  }

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    _writeByte(Tag.SimpleIdentifier);
    _writeStringReference(node.name);
    _writeInformativeUint30(node.offset);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.SimpleIdentifier_staticElement);
      resolutionSink.writeElement(node.staticElement);
      // TODO(scheglov) It is inefficient to write many null types.
    }

    _writeMarker(MarkerTag.SimpleIdentifier_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.SimpleIdentifier_end);
  }

  @override
  void visitSimpleStringLiteral(SimpleStringLiteral node) {
    _writeByte(Tag.SimpleStringLiteral);
    _writeStringReference(node.literal.lexeme);
    _writeStringReference(node.value);
  }

  @override
  void visitSpreadElement(SpreadElement node) {
    _writeByte(Tag.SpreadElement);
    _writeByte(
      AstBinaryFlags.encode(
        hasQuestion:
            node.spreadOperator.type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION,
      ),
    );
    _writeMarker(MarkerTag.SpreadElement_expression);
    _writeNode(node.expression);
    _writeMarker(MarkerTag.SpreadElement_end);
  }

  @override
  void visitStringInterpolation(StringInterpolation node) {
    _writeByte(Tag.StringInterpolation);
    _writeMarker(MarkerTag.StringInterpolation_elements);
    _writeNodeList(node.elements);
    _writeMarker(MarkerTag.StringInterpolation_end);
  }

  @override
  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    _writeByte(Tag.SuperConstructorInvocation);

    _writeMarker(MarkerTag.SuperConstructorInvocation_constructorName);
    _writeOptionalNode(node.constructorName);
    _writeMarker(MarkerTag.SuperConstructorInvocation_argumentList);
    _writeNode(node.argumentList);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.SuperConstructorInvocation_staticElement);
      resolutionSink.writeElement(node.staticElement);
    }

    _writeMarker(MarkerTag.SuperConstructorInvocation_end);
  }

  @override
  void visitSuperExpression(SuperExpression node) {
    _writeByte(Tag.SuperExpression);
    _writeMarker(MarkerTag.SuperExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.SuperExpression_end);
  }

  @override
  void visitSymbolLiteral(SymbolLiteral node) {
    _writeByte(Tag.SymbolLiteral);

    var components = node.components;
    _writeUInt30(components.length);
    for (var token in components) {
      _writeStringReference(token.lexeme);
    }
    _storeExpression(node);
  }

  @override
  void visitThisExpression(ThisExpression node) {
    _writeByte(Tag.ThisExpression);
    _writeMarker(MarkerTag.ThisExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.ThisExpression_end);
  }

  @override
  void visitThrowExpression(ThrowExpression node) {
    _writeByte(Tag.ThrowExpression);
    _writeMarker(MarkerTag.ThrowExpression_expression);
    _writeNode(node.expression);
    _writeMarker(MarkerTag.ThrowExpression_expression2);
    _storeExpression(node);
    _writeMarker(MarkerTag.ThrowExpression_end);
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.TopLevelVariableDeclaration,
        variableNames: node.variables.variables
            .map((variable) => variable.name.name)
            .toList(),
      ),
    );

    _writeByte(Tag.TopLevelVariableDeclaration);
    _writeByte(
      AstBinaryFlags.encode(
        isExternal: node.externalKeyword != null,
      ),
    );

    _writeInformativeVariableCodeRanges(node.offset, node.variables);
    _writeDocumentationCommentString(node.documentationComment);

    var resolutionIndex = _getNextResolutionIndex();

    _shouldStoreVariableInitializers = node.variables.isConst;
    try {
      _writeMarker(MarkerTag.TopLevelVariableDeclaration_variables);
      _writeNode(node.variables);
    } finally {
      _shouldStoreVariableInitializers = false;
    }

    _writeMarker(MarkerTag.TopLevelVariableDeclaration_compilationUnitMember);
    _storeCompilationUnitMember(node);
    _writeMarker(MarkerTag.TopLevelVariableDeclaration_end);

    _writeUInt30(resolutionIndex);
  }

  @override
  void visitTypeArgumentList(TypeArgumentList node) {
    _writeByte(Tag.TypeArgumentList);
    _writeMarker(MarkerTag.TypeArgumentList_arguments);
    _writeNodeList(node.arguments);
    _writeMarker(MarkerTag.TypeArgumentList_end);
  }

  @override
  void visitTypeName(TypeName node) {
    _writeByte(Tag.TypeName);

    _writeByte(
      AstBinaryFlags.encode(
        hasQuestion: node.question != null,
        hasTypeArguments: node.typeArguments != null,
      ),
    );

    _writeMarker(MarkerTag.TypeName_name);
    _writeNode(node.name);
    _writeMarker(MarkerTag.TypeName_typeArguments);
    _writeOptionalNode(node.typeArguments);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.TypeName_type);
      resolutionSink.writeType(node.type);
    }

    _writeMarker(MarkerTag.TypeName_end);
  }

  @override
  void visitTypeParameter(TypeParameter node) {
    _writeByte(Tag.TypeParameter);
    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);
    _writeDeclarationName(node.name);
    _writeMarker(MarkerTag.TypeParameter_bound);
    _writeOptionalNode(node.bound);
    _writeMarker(MarkerTag.TypeParameter_declaration);
    _storeDeclaration(node);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as TypeParameterElementImpl;
      _writeMarker(MarkerTag.TypeParameter_variance);
      resolutionSink.writeByte(
        _encodeVariance(element),
      );
      _writeMarker(MarkerTag.TypeParameter_defaultType);
      resolutionSink.writeType(element.defaultType);
    }

    _writeMarker(MarkerTag.TypeParameter_end);
  }

  @override
  void visitTypeParameterList(TypeParameterList node) {
    _writeByte(Tag.TypeParameterList);
    _writeMarker(MarkerTag.TypeParameterList_typeParameters);
    _writeNodeList(node.typeParameters);
    _writeMarker(MarkerTag.TypeParameterList_end);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    _writeByte(Tag.VariableDeclaration);
    _writeByte(
      AstBinaryFlags.encode(
        hasInitializer: node.initializer != null,
      ),
    );
    _writeDeclarationName(node.name);

    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      // TODO(scheglov) Enforce not null, remove `?` in `?.type` below.
      var element = node.declaredElement as VariableElementImpl;
      _writeMarker(MarkerTag.VariableDeclaration_type);
      _writeActualType(resolutionSink, element.type);
      _writeMarker(MarkerTag.VariableDeclaration_inferenceError);
      _writeTopLevelInferenceError(resolutionSink, element);
      if (element is FieldElementImpl) {
        _writeMarker(MarkerTag.VariableDeclaration_inheritsCovariant);
        resolutionSink.writeByte(element.inheritsCovariant ? 1 : 0);
      }
    }

    Expression? initializerToWrite;
    if (_shouldStoreVariableInitializers) {
      var initializer = node.initializer;
      if (_isSerializableExpression(initializer)) {
        initializerToWrite = initializer;
      }
    }
    _writeMarker(MarkerTag.VariableDeclaration_initializer);
    _writeOptionalNode(initializerToWrite);
    _writeMarker(MarkerTag.VariableDeclaration_end);
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    _writeByte(Tag.VariableDeclarationList);
    _writeByte(
      AstBinaryFlags.encode(
        isConst: node.isConst,
        isFinal: node.isFinal,
        isLate: node.lateKeyword != null,
        isVar: node.keyword?.keyword == Keyword.VAR,
      ),
    );
    _writeMarker(MarkerTag.VariableDeclarationList_type);
    _writeOptionalNode(node.type);
    _writeMarker(MarkerTag.VariableDeclarationList_variables);
    _writeNodeList(node.variables);
    _writeMarker(MarkerTag.VariableDeclarationList_annotatedNode);
    _storeAnnotatedNode(node);
    _writeMarker(MarkerTag.VariableDeclarationList_end);
  }

  @override
  void visitWithClause(WithClause node) {
    _writeByte(Tag.WithClause);
    _writeMarker(MarkerTag.WithClause_mixinTypes);
    _writeNodeList(node.mixinTypes);
    _writeMarker(MarkerTag.WithClause_end);
  }

  void _pushScopeTypeParameters(TypeParameterList? node) {
    var resolutionSink = _resolutionSink;
    if (resolutionSink == null) {
      return;
    }

    resolutionSink.localElements.pushScope();

    if (node == null) {
      return;
    }

    for (var typeParameter in node.typeParameters) {
      resolutionSink.localElements.declare(typeParameter.declaredElement!);
    }
  }

  void _storeAnnotatedNode(AnnotatedNode node) {
    _writeMarker(MarkerTag.AnnotatedNode_metadata);
    _writeNodeList(node.metadata);
    _writeMarker(MarkerTag.AnnotatedNode_end);
  }

  void _storeClassMember(ClassMember node) {
    _writeMarker(MarkerTag.ClassMember_declaration);
    _storeDeclaration(node);
  }

  void _storeCompilationUnitMember(CompilationUnitMember node) {
    _storeDeclaration(node);
  }

  void _storeDeclaration(Declaration node) {
    _storeAnnotatedNode(node);
  }

  void _storeDirective(Directive node) {
    _writeInformativeUint30(node.keyword.offset);
    _storeAnnotatedNode(node);
  }

  void _storeExpression(Expression node) {
    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      _writeMarker(MarkerTag.Expression_staticType);
      resolutionSink.writeType(node.staticType);
    }
  }

  void _storeForEachParts(ForEachParts node) {
    _writeMarker(MarkerTag.ForEachParts_iterable);
    _writeNode(node.iterable);
    _writeMarker(MarkerTag.ForEachParts_forLoopParts);
    _storeForLoopParts(node);
    _writeMarker(MarkerTag.ForEachParts_end);
  }

  void _storeForLoopParts(ForLoopParts node) {}

  void _storeFormalParameter(FormalParameter node) {
    var resolutionSink = _resolutionSink;
    if (resolutionSink != null) {
      var element = node.declaredElement as ParameterElementImpl;
      _writeMarker(MarkerTag.FormalParameter_type);
      _writeActualType(resolutionSink, element.type);
    }
  }

  void _storeForParts(ForParts node) {
    _writeMarker(MarkerTag.ForParts_condition);
    _writeOptionalNode(node.condition);
    _writeMarker(MarkerTag.ForParts_updaters);
    _writeNodeList(node.updaters);
    _writeMarker(MarkerTag.ForParts_forLoopParts);
    _storeForLoopParts(node);
    _writeMarker(MarkerTag.ForParts_end);
  }

  void _storeInvocationExpression(InvocationExpression node) {
    _writeMarker(MarkerTag.InvocationExpression_typeArguments);
    _writeOptionalNode(node.typeArguments);
    _writeMarker(MarkerTag.InvocationExpression_argumentList);
    _writeNode(node.argumentList);
    _writeMarker(MarkerTag.InvocationExpression_expression);
    _storeExpression(node);
    _writeMarker(MarkerTag.InvocationExpression_end);
    // TODO(scheglov) typeArgumentTypes and staticInvokeType?
  }

  void _storeNamedCompilationUnitMember(NamedCompilationUnitMember node) {
    _writeDeclarationName(node.name);
    _storeCompilationUnitMember(node);
  }

  void _storeNamespaceDirective(NamespaceDirective node) {
    _writeMarker(MarkerTag.NamespaceDirective_combinators);
    _writeNodeList(node.combinators);
    _writeMarker(MarkerTag.NamespaceDirective_configurations);
    _writeNodeList(node.configurations);
    _writeMarker(MarkerTag.NamespaceDirective_uriBasedDirective);
    _storeUriBasedDirective(node);
    _writeMarker(MarkerTag.NamespaceDirective_end);
  }

  void _storeNormalFormalParameter(
    NormalFormalParameter node,
    Token? keyword, {
    bool hasQuestion = false,
  }) {
    _writeByte(
      AstBinaryFlags.encode(
        hasName: node.identifier != null,
        hasQuestion: hasQuestion,
        isConst: keyword?.type == Keyword.CONST,
        isCovariant: node.covariantKeyword != null,
        isFinal: keyword?.type == Keyword.FINAL,
        isRequired: node.requiredKeyword != null,
        isVar: keyword?.type == Keyword.VAR,
      ),
    );

    // TODO(scheglov) Don't store when in DefaultFormalParameter?
    _writeInformativeUint30(node.offset);
    _writeInformativeUint30(node.length);

    _writeMarker(MarkerTag.NormalFormalParameter_metadata);
    _writeNodeList(node.metadata);
    if (node.identifier != null) {
      _writeDeclarationName(node.identifier!);
    }
    _writeMarker(MarkerTag.NormalFormalParameter_formalParameter);
    _storeFormalParameter(node);
    _writeMarker(MarkerTag.NormalFormalParameter_end);
  }

  void _storeTypeAlias(TypeAlias node) {
    _storeNamedCompilationUnitMember(node);
  }

  void _storeUriBasedDirective(UriBasedDirective node) {
    _writeMarker(MarkerTag.UriBasedDirective_uri);
    _writeNode(node.uri);
    _writeMarker(MarkerTag.UriBasedDirective_directive);
    _storeDirective(node);
    _writeMarker(MarkerTag.UriBasedDirective_end);
  }

  void _writeActualReturnType(ResolutionSink resolutionSink, DartType type) {
    resolutionSink.writeType(type);
  }

  void _writeActualType(ResolutionSink resolutionSink, DartType type) {
    resolutionSink.writeType(type);
  }

  void _writeByte(int byte) {
    assert((byte & 0xFF) == byte);
    _sink.addByte(byte);
  }

  void _writeClassMemberIndex() {
    _writeUInt30(_classMemberIndexItems.length);
    for (var declaration in _classMemberIndexItems) {
      _writeUInt30(declaration.offset);
      _writeByte(declaration.tag);
      if (declaration.name != null) {
        _writeStringReference(declaration.name!);
      } else {
        _writeUInt30(declaration.fieldNames!.length);
        for (var name in declaration.fieldNames!) {
          _writeStringReference(name);
        }
      }
    }
  }

  void _writeDeclarationName(SimpleIdentifier node) {
    _writeByte(Tag.SimpleIdentifier);
    _writeStringReference(node.name);
    _writeInformativeUint30(node.offset);
  }

  /// We write tokens as a list, so this must be the last entity written.
  void _writeDocumentationCommentString(Comment? node) {
    if (node != null && _withInformative) {
      var tokens = node.tokens;
      _writeUInt30(tokens.length);
      for (var token in tokens) {
        _writeStringReference(token.lexeme);
      }
    } else {
      _writeUInt30(0);
    }
  }

  _writeDouble(double value) {
    _sink.addDouble(value);
  }

  void _writeFeatureSet(FeatureSet featureSet) {
    var experimentStatus = featureSet as ExperimentStatus;
    var encoded = experimentStatus.toStorage();
    _writeUint8List(encoded);
  }

  void _writeInformativeUint30(int value) {
    if (_withInformative) {
      _writeUInt30(value);
    }
  }

  void _writeInformativeVariableCodeRanges(
    int firstOffset,
    VariableDeclarationList node,
  ) {
    if (_withInformative) {
      var variables = node.variables;
      _writeUInt30(variables.length * 2);
      var isFirst = true;
      for (var variable in variables) {
        var offset = isFirst ? firstOffset : variable.offset;
        var end = variable.end;
        _writeUInt30(offset);
        _writeUInt30(end - offset);
        isFirst = false;
      }
    }
  }

  void _writeLanguageVersion(LibraryLanguageVersion languageVersion) {
    _writeUInt30(languageVersion.package.major);
    _writeUInt30(languageVersion.package.minor);

    var override = languageVersion.override;
    if (override != null) {
      _writeUInt30(override.major + 1);
      _writeUInt30(override.minor + 1);
    } else {
      _writeUInt30(0);
      _writeUInt30(0);
    }
  }

  void _writeLineInfo(LineInfo lineInfo) {
    if (_withInformative) {
      _writeUint30List(lineInfo.lineStarts);
    } else {
      _writeUint30List(const <int>[0]);
    }
  }

  void _writeMarker(MarkerTag tag) {
    if (enableDebugResolutionMarkers) {
      var resolutionSink = _resolutionSink;
      if (resolutionSink != null) {
        resolutionSink.writeUInt30(tag.index);
      }
    }
  }

  void _writeNode(AstNode node) {
    node.accept(this);
  }

  void _writeNodeList(List<AstNode> nodeList) {
    _writeUInt30(nodeList.length);
    for (var i = 0; i < nodeList.length; ++i) {
      nodeList[i].accept(this);
    }
  }

  void _writeOptionalDeclarationName(SimpleIdentifier? node) {
    if (node == null) {
      _writeByte(Tag.Nothing);
    } else {
      _writeByte(Tag.Something);
      _writeDeclarationName(node);
    }
  }

  void _writeOptionalNode(AstNode? node) {
    if (node == null) {
      _writeByte(Tag.Nothing);
    } else {
      _writeByte(Tag.Something);
      _writeNode(node);
    }
  }

  void _writeStringReference(String string) {
    var index = _stringIndexer[string];
    _writeUInt30(index);
  }

  void _writeTopLevelInferenceError(
    ResolutionSink resolutionSink,
    ElementImpl element,
  ) {
    TopLevelInferenceError? error;
    if (element is MethodElementImpl) {
      error = element.typeInferenceError;
    } else if (element is PropertyInducingElementImpl) {
      error = element.typeInferenceError;
    } else {
      return;
    }

    if (error != null) {
      resolutionSink.writeByte(error.kind.index);
      resolutionSink.writeStringList(error.arguments);
    } else {
      resolutionSink.writeByte(TopLevelInferenceErrorKind.none.index);
    }
  }

  @pragma("vm:prefer-inline")
  void _writeUInt30(int value) {
    _sink.writeUInt30(value);
  }

  void _writeUint30List(List<int> values) {
    var length = values.length;
    _writeUInt30(length);
    for (var i = 0; i < length; i++) {
      _writeUInt30(values[i]);
    }
  }

  void _writeUInt32(int value) {
    _sink.addByte4((value >> 24) & 0xFF, (value >> 16) & 0xFF,
        (value >> 8) & 0xFF, value & 0xFF);
  }

  void _writeUint8List(List<int> values) {
    var length = values.length;
    _writeUInt30(length);
    for (var i = 0; i < length; i++) {
      _writeByte(values[i]);
    }
  }

  static int _encodeVariance(TypeParameterElementImpl element) {
    if (element.isLegacyCovariant) {
      return 0;
    }

    var variance = element.variance;
    if (variance == Variance.unrelated) {
      return 1;
    } else if (variance == Variance.covariant) {
      return 2;
    } else if (variance == Variance.contravariant) {
      return 3;
    } else if (variance == Variance.invariant) {
      return 4;
    } else {
      throw UnimplementedError('$variance');
    }
  }

  /// Return `true` if the expression might be successfully serialized.
  ///
  /// This does not mean that the expression is constant, it just means that
  /// we know that it might be serialized and deserialized. For example
  /// function expressions are problematic, and are not necessary to
  /// deserialize, so we choose not to do this.
  static bool _isSerializableExpression(Expression? node) {
    if (node == null) return false;

    var visitor = _IsSerializableExpressionVisitor();
    node.accept(visitor);
    return visitor.result;
  }
}

/// An item in the class index, used to read only requested class members.
class _ClassMemberIndexItem {
  final int offset;
  final int tag;
  final String? name;
  final List<String>? fieldNames;

  _ClassMemberIndexItem({
    required this.offset,
    required this.tag,
    this.name,
    this.fieldNames,
  });
}

class _IsSerializableExpressionVisitor extends RecursiveAstVisitor<void> {
  bool result = true;

  @override
  void visitFunctionExpression(FunctionExpression node) {
    result = false;
  }
}

/// An item in the unit index, used to read only requested unit members.
class _UnitMemberIndexItem {
  final int offset;
  final int tag;
  final String? name;
  final List<String>? variableNames;

  /// The absolute offset of the index of class members, `0` if not a class.
  final int classIndexOffset;

  _UnitMemberIndexItem({
    required this.offset,
    required this.tag,
    this.name,
    this.variableNames,
    this.classIndexOffset = 0,
  });
}
