// 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';
import 'package:analyzer/src/util/either.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_typeArguments);
    _writeOptionalNode(node.typeArguments);
    _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: Either2.t1(node.name.name),
        classIndexOffset: classIndexOffset,
      ),
    );
  }

  @override
  void visitClassTypeAlias(ClassTypeAlias node) {
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.ClassTypeAlias,
        name: Either2.t1(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) {
    var resolutionIndex = _getNextResolutionIndex();
    _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);
    _writeUInt30(resolutionIndex);
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    var resolutionIndex = _getNextResolutionIndex();
    unitMemberIndexItems.add(
      _UnitMemberIndexItem(
        offset: _sink.offset,
        tag: Tag.EnumDeclaration,
        name: Either2.t1(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: Either2.t1(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: Either2.t1(node.name.name),
      ),
    );

    _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: Either2.t1(node.name.name),
      ),
    );

    _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 TypeAliasElementImpl;
      var function = element.aliasedElement as GenericFunctionTypeElement;
      _writeMarker(MarkerTag.FunctionTypeAlias_returnTypeType);
      _writeActualReturnType(resolutionSink, 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: Either2.t1(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: Either2.t1(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,
        name: Either2.t2(
          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 Either2<String, List<String>> name;

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

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