blob: 72b1c1aaa18f4700bdced795bc25c3338351faf4 [file] [log] [blame]
// Copyright (c) 2022, 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:kernel/ast.dart' as ir
show
Class,
DartType,
Library,
LibraryDependency,
Member,
Name,
TreeNode,
TypeParameter;
import '../common.dart';
import '../constants/values.dart' show ConstantValue;
import '../deferred_load/output_unit.dart';
import '../elements/entities.dart';
import '../elements/indexed.dart';
import '../elements/types.dart' show DartType;
import '../inferrer/abstract_value_domain.dart' show AbstractValue;
import '../js/js.dart' as js;
import '../js_model/type_recipe.dart';
import 'deferrable.dart';
import 'member_data.dart' show ComponentLookup;
export 'member_data.dart' show ComponentLookup;
export 'tags.dart';
abstract class StringInterner {
String internString(String string);
}
/// NNBD-migrated interface for methods of DataSinkWriter.
///
/// This is a pure interface or facade for DataSinkWriter.
///
/// This interface has the same name as the implementation class. Using the same
/// name allows some libraries that use DataSinkWriter to be migrated before the
/// serialization library by changing
///
/// import '../serialization/serialization.dart';
///
/// to:
///
/// import '../serialization/serialization_interfaces.dart';
///
/// Documentation of the methods can be found in source.dart.
// TODO(sra): Copy documentation for methods?
abstract class DataSinkWriter {
int get length;
void begin(String tag);
void end(Object tag);
void writeBool(bool value);
void writeInt(int value);
void writeIntOrNull(int? value);
void writeString(String value);
void writeStringOrNull(String? value);
void writeStringMap<V>(Map<String, V>? map, void f(V value),
{bool allowNull = false});
void writeStrings(Iterable<String>? values, {bool allowNull = false});
void writeEnum(dynamic value);
void writeUri(Uri value);
void writeMemberNode(ir.Member nvalue);
void writeMemberNodes(Iterable<ir.Member>? values, {bool allowNull = false});
void writeMemberNodeMap<V>(Map<ir.Member, V>? map, void f(V value),
{bool allowNull = false});
void writeName(ir.Name value);
void writeLibraryDependencyNode(ir.LibraryDependency value);
void writeLibraryDependencyNodeOrNull(ir.LibraryDependency? value);
void writeTreeNode(ir.TreeNode value);
void writeTreeNodeOrNull(ir.TreeNode value);
void writeTreeNodes(Iterable<ir.TreeNode>? values, {bool allowNull = false});
void writeTreeNodeMap<V>(Map<ir.TreeNode, V> map, void f(V value));
void writeClassNode(ir.Class value);
// TODO(48820): 'covariant ClassEntity' is used below because the
// implementation takes IndexedClass. What this means is that in pre-NNBD
// code, the call site to the implementation DataSinkWriter has an implicit
// downcast from ClassEntity to IndexedClass. With NNND, these casts become
// explicit and quite tedious. It is cleaner to move the cast into the method,
// which is what 'covariant' achieves.
//
// If we want to retire this facade interface, we will have to make the
// DataSinkWriter implementation accept ClassEntity and manually check for
// IndexedClass. This is not necessarily a bad thing, since it opens the way
// for being able to serialize some non-indexed entities.
void writeClass(covariant ClassEntity value); // IndexedClass
void writeClassOrNull(covariant ClassEntity? value); // IndexedClass
void writeClasses(Iterable<ClassEntity>? values, {bool allowNull = false});
void writeClassMap<V>(Map<ClassEntity, V>? map, void f(V value),
{bool allowNull = false});
void writeTypeVariable(
covariant TypeVariableEntity value); // IndexedTypeVariable
void writeMember(covariant MemberEntity member); // IndexMember
void writeMemberOrNull(covariant MemberEntity? member); // IndexMember
void writeMembers(Iterable<MemberEntity>? values, {bool allowNull = false});
void writeMemberMap<V>(
Map<MemberEntity, V>? map, void f(MemberEntity member, V value),
{bool allowNull = false});
void writeLibrary(covariant LibraryEntity value); // IndexedLibrary
void writeLibraryOrNull(covariant LibraryEntity? value); // IndexedLibrary
void writeLibraryMap<V>(Map<LibraryEntity, V>? map, void f(V value),
{bool allowNull = false});
void writeLibraryNode(ir.Library value);
void writeTypeRecipe(TypeRecipe value);
void writeDartTypeNode(ir.DartType value);
void writeDartTypeNodeOrNull(ir.DartType? value);
void writeDartTypeNodes(Iterable<ir.DartType>? values,
{bool allowNull = false});
void writeDartType(DartType value);
void writeDartTypeOrNull(DartType? value);
void writeDartTypesOrNull(Iterable<DartType>? values);
void writeDartTypes(Iterable<DartType> values);
void writeTypeParameterNode(ir.TypeParameter value);
void writeTypeParameterNodes(Iterable<ir.TypeParameter> values);
void writeTypeVariableMap<V>(
Map<IndexedTypeVariable, V> map, void f(V value));
void inMemberContext(ir.Member context, void f());
void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V>? map, void f(V value),
{bool allowNull = false});
void writeCached<E extends Object>(E? value, void f(E value));
void writeList<E extends Object>(Iterable<E>? values, void f(E value),
{bool allowNull = false});
void writeConstant(ConstantValue value);
void writeConstantOrNull(ConstantValue? value);
void writeConstantMap<V>(Map<ConstantValue, V>? map, void f(V value),
{bool allowNull = false});
void writeValueOrNull<E>(E? value, void f(E value));
void writeDoubleValue(double value);
void writeIntegerValue(int value);
void writeLocalOrNull(Local? local);
void writeLocalMap<V>(Map<Local, V> map, void f(V value));
void writeImport(ImportEntity import);
void writeImportOrNull(ImportEntity? import);
void writeImports(Iterable<ImportEntity>? values, {bool allowNull = false});
void writeImportMap<V>(Map<ImportEntity, V>? map, void f(V value),
{bool allowNull = false});
void writeAbstractValue(AbstractValue value);
void writeJsNodeOrNull(js.Node? value);
void writeSourceSpan(SourceSpan value);
void writeDeferrable(void f());
}
/// Migrated interface for methods of DataSourceReader.
abstract class DataSourceReader {
int get length;
int get startOffset;
int get endOffset;
void registerComponentLookup(ComponentLookup componentLookup);
void registerLocalLookup(LocalLookup localLookup);
void registerEntityLookup(EntityLookup entityLookup);
void registerEntityReader(EntityReader reader);
void begin(String tag);
void end(String tag);
bool readBool();
int readInt();
int? readIntOrNull();
String readString();
String? readStringOrNull();
List<String>? readStrings({bool emptyAsNull = false});
Map<String, V>? readStringMap<V>(V f(), {bool emptyAsNull = false});
E readEnum<E>(List<E> values);
Uri readUri();
ir.Member readMemberNode();
List<E> readMemberNodes<E extends ir.Member>();
List<E>? readMemberNodesOrNull<E extends ir.Member>();
Map<K, V> readMemberNodeMap<K extends ir.Member, V>(V f());
Map<K, V>? readMemberNodeMapOrNull<K extends ir.Member, V>(V f());
ir.Name readName();
ir.LibraryDependency readLibraryDependencyNode();
ir.LibraryDependency readLibraryDependencyNodeOrNull();
ir.TreeNode readTreeNode();
ir.TreeNode? readTreeNodeOrNull();
List<E> readTreeNodes<E extends ir.TreeNode>();
List<E>? readTreeNodesOrNull<E extends ir.TreeNode>();
Map<K, V> readTreeNodeMap<K extends ir.TreeNode, V>(V f());
Map<K, V> readTreeNodeMapOrNull<K extends ir.TreeNode, V>(V f());
ir.Class readClassNode();
ClassEntity readClass(); // IndexedClass
ClassEntity? readClassOrNull(); // IndexedClass
List<E> readClasses<E extends ClassEntity>();
List<E>? readClassesOrNull<E extends ClassEntity>();
Map<K, V> readClassMap<K extends ClassEntity, V>(V f());
Map<K, V>? readClassMapOrNull<K extends ClassEntity, V>(V f());
TypeVariableEntity readTypeVariable(); // IndexedTypeVariable
MemberEntity readMember();
MemberEntity? readMemberOrNull();
List<E> readMembers<E extends MemberEntity>();
List<E>? readMembersOrNull<E extends MemberEntity>();
Map<K, V> readMemberMap<K extends MemberEntity, V>(V f(MemberEntity member));
Map<K, V>? readMemberMapOrNull<K extends MemberEntity, V>(
V f(MemberEntity member));
LibraryEntity readLibrary(); // IndexedLibrary;
LibraryEntity? readLibraryOrNull(); // IndexedLibrary;
Map<K, V> readLibraryMap<K extends LibraryEntity, V>(V f());
Map<K, V>? readLibraryMapOrNull<K extends LibraryEntity, V>(V f());
ir.Library readLibraryNode();
TypeRecipe readTypeRecipe();
ir.DartType readDartTypeNode();
ir.DartType? readDartTypeNodeOrNull();
List<ir.DartType> readDartTypeNodes();
List<ir.DartType>? readDartTypeNodesOrNull();
DartType readDartType();
DartType? readDartTypeOrNull();
List<DartType> readDartTypes();
List<DartType>? readDartTypesOrNull();
Map<K, V> readTypeVariableMap<K extends IndexedTypeVariable, V>(V f());
ir.TypeParameter readTypeParameterNode();
List<ir.TypeParameter> readTypeParameterNodes();
T inMemberContext<T>(ir.Member context, T f());
Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f());
Map<K, V>? readTreeNodeMapInContextOrNull<K extends ir.TreeNode, V>(V f());
E readCached<E extends Object>(E f());
E? readCachedOrNull<E extends Object>(E f());
List<E> readList<E extends Object>(E f());
List<E>? readListOrNull<E extends Object>(E f());
ConstantValue readConstant();
ConstantValue? readConstantOrNull();
Map<K, V> readConstantMap<K extends ConstantValue, V>(V f());
Map<K, V>? readConstantMapOrNull<K extends ConstantValue, V>(V f());
E? readValueOrNull<E>(E f());
double readDoubleValue();
int readIntegerValue();
ImportEntity readImport();
ImportEntity? readImportOrNull();
List<ImportEntity> readImports();
List<ImportEntity>? readImportsOrNull();
Map<ImportEntity, V> readImportMap<V>(V f());
Map<ImportEntity, V>? readImportMapOrNull<V>(V f());
AbstractValue readAbstractValue();
js.Node? readJsNodeOrNull();
SourceSpan readSourceSpan();
Local? readLocalOrNull();
Map<K, V> readLocalMap<K extends Local, V>(V f());
E readWithSource<E>(DataSourceReader source, E f());
E readWithOffset<E>(int offset, E f());
Deferrable<E> readDeferrable<E>(E f(), {bool cacheData = true});
}
/// Interface used for looking up locals by index during deserialization.
abstract class LocalLookup {
Local getLocalByIndex(MemberEntity memberContext, int index);
}
/// Interface used for reading codegen only data during deserialization.
abstract class CodegenReader {
AbstractValue readAbstractValue(DataSourceReader source);
OutputUnit readOutputUnitReference(DataSourceReader source);
js.Node readJsNode(DataSourceReader source);
TypeRecipe readTypeRecipe(DataSourceReader source);
}
/// Interface used for writing codegen only data during serialization.
abstract class CodegenWriter {
void writeAbstractValue(DataSinkWriter sink, AbstractValue value);
void writeOutputUnitReference(DataSinkWriter sink, OutputUnit value);
void writeJsNode(DataSinkWriter sink, js.Node node);
void writeTypeRecipe(DataSinkWriter sink, TypeRecipe recipe);
}
/// Interface used for looking up entities by index during deserialization.
abstract class EntityLookup {
/// Returns the indexed library corresponding to [index].
IndexedLibrary getLibraryByIndex(int index);
/// Returns the indexed class corresponding to [index].
IndexedClass getClassByIndex(int index);
/// Returns the indexed member corresponding to [index].
IndexedMember getMemberByIndex(int index);
/// Returns the indexed type variable corresponding to [index].
IndexedTypeVariable getTypeVariableByIndex(int index);
}
/// Decoding strategy for entity references.
class EntityReader {
const EntityReader();
IndexedLibrary readLibraryFromDataSource(
DataSourceReader source, EntityLookup entityLookup) {
return entityLookup.getLibraryByIndex(source.readInt());
}
IndexedClass readClassFromDataSource(
DataSourceReader source, EntityLookup entityLookup) {
return entityLookup.getClassByIndex(source.readInt());
}
IndexedMember readMemberFromDataSource(
DataSourceReader source, EntityLookup entityLookup) {
return entityLookup.getMemberByIndex(source.readInt());
}
IndexedTypeVariable readTypeVariableFromDataSource(
DataSourceReader source, EntityLookup entityLookup) {
return entityLookup.getTypeVariableByIndex(source.readInt());
}
}
/// Encoding strategy for entity references.
class EntityWriter {
const EntityWriter();
void writeLibraryToDataSink(DataSinkWriter sink, IndexedLibrary value) {
sink.writeInt(value.libraryIndex);
}
void writeClassToDataSink(DataSinkWriter sink, IndexedClass value) {
sink.writeInt(value.classIndex);
}
void writeMemberToDataSink(DataSinkWriter sink, IndexedMember value) {
sink.writeInt(value.memberIndex);
}
void writeTypeVariableToDataSink(
DataSinkWriter sink, IndexedTypeVariable value) {
sink.writeInt(value.typeVariableIndex);
}
}