blob: 84007bda4f4bcf08c095befd194c8069d0c1ecab [file] [log] [blame]
// 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,
});
}