blob: fb1f3b2490a8aa08b69e9005d8d03937eb8cdda5 [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:kernel/ast.dart' as ir;
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import '../common.dart';
import '../common/elements.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../ir/scope.dart';
import '../kernel/element_map_interfaces.dart'
show KernelToElementMapForImpactData;
import '../options.dart';
import '../serialization/serialization.dart';
import '../util/enumset.dart';
import 'class_relation.dart';
import 'constants.dart';
import 'impact.dart';
import 'runtime_type_analysis.dart';
import 'static_type.dart';
import 'util.dart';
/// Visitor that builds an [ImpactData] object for the world impact.
class ImpactBuilder extends StaticTypeVisitor implements ImpactRegistry {
final ImpactData _data = ImpactData();
final KernelToElementMapForImpactData _elementMap;
@override
final VariableScopeModel variableScopeModel;
@override
final ir.StaticTypeContext staticTypeContext;
@override
final bool useAsserts;
@override
final inferEffectivelyFinalVariableTypes;
ImpactBuilder(
this._elementMap,
this.staticTypeContext,
StaticTypeCacheImpl staticTypeCache,
ir.ClassHierarchy classHierarchy,
this.variableScopeModel,
{this.useAsserts = false,
this.inferEffectivelyFinalVariableTypes = true})
: super(
staticTypeContext.typeEnvironment, classHierarchy, staticTypeCache);
CommonElements get _commonElements => _elementMap.commonElements;
DiagnosticReporter get _reporter => _elementMap.reporter;
String _typeToString(DartType type) =>
type.toStructuredText(_elementMap.types, _elementMap.options);
CompilerOptions get _options => _elementMap.options;
/// Return the named arguments names as a list of strings.
List<String> _getNamedArguments(ir.Arguments arguments) =>
arguments.named.map((n) => n.name).toList();
ImpactBuilderData computeImpact(ir.Member node) {
if (retainDataForTesting) {
typeMapsForTesting = {};
}
node.accept(this);
return ImpactBuilderData(
node, impactData, typeMapsForTesting, getStaticTypeCache());
}
ImpactData get impactData => _data;
@override
void handleIntLiteral(ir.IntLiteral node) {
registerIntLiteral(node.value);
}
@override
void handleDoubleLiteral(ir.DoubleLiteral node) {
registerDoubleLiteral(node.value);
}
@override
void handleBoolLiteral(ir.BoolLiteral node) {
registerBoolLiteral(node.value);
}
@override
void handleStringLiteral(ir.StringLiteral node) {
registerStringLiteral(node.value);
}
@override
void handleSymbolLiteral(ir.SymbolLiteral node) {
registerSymbolLiteral(node.value);
}
@override
void handleNullLiteral(ir.NullLiteral node) {
registerNullLiteral();
}
@override
void handleListLiteral(ir.ListLiteral node) {
registerListLiteral(node.typeArgument,
isConst: node.isConst, isEmpty: node.expressions.isEmpty);
}
@override
void handleSetLiteral(ir.SetLiteral node) {
registerSetLiteral(node.typeArgument,
isConst: node.isConst, isEmpty: node.expressions.isEmpty);
}
@override
void handleMapLiteral(ir.MapLiteral node) {
registerMapLiteral(node.keyType, node.valueType,
isConst: node.isConst, isEmpty: node.entries.isEmpty);
}
@override
void handleStaticGet(
ir.Expression node, ir.Member target, ir.DartType resultType) {
assert(!(target is ir.Procedure && target.kind == ir.ProcedureKind.Method),
"Static tear off registered as static get: $node");
registerStaticGet(target, getDeferredImport(node));
}
@override
void handleStaticTearOff(
ir.Expression node, ir.Procedure target, ir.DartType resultType) {
assert(target.kind == ir.ProcedureKind.Method,
"Static get registered as static tear off: $node");
registerStaticTearOff(target, getDeferredImport(node));
}
@override
void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {
registerStaticSet(node.target, getDeferredImport(node));
}
@override
void handleAssertStatement(ir.AssertStatement node) {
registerAssert(withMessage: node.message != null);
}
@override
void handleInstantiation(ir.Instantiation node,
ir.FunctionType expressionType, ir.DartType resultType) {
registerGenericInstantiation(expressionType, node.typeArguments);
}
void handleAsyncMarker(ir.FunctionNode function) {
ir.AsyncMarker asyncMarker = function.asyncMarker;
ir.DartType returnType = function.returnType;
switch (asyncMarker) {
case ir.AsyncMarker.Sync:
break;
case ir.AsyncMarker.SyncStar:
ir.DartType elementType = const ir.DynamicType();
if (returnType is ir.InterfaceType) {
if (returnType.classNode == typeEnvironment.coreTypes.iterableClass) {
elementType = returnType.typeArguments.first;
}
}
registerSyncStar(elementType);
break;
case ir.AsyncMarker.Async:
ir.DartType elementType = const ir.DynamicType();
if (returnType is ir.InterfaceType &&
returnType.classNode == typeEnvironment.coreTypes.futureClass) {
elementType = returnType.typeArguments.first;
} else if (returnType is ir.FutureOrType) {
elementType = returnType.typeArgument;
}
registerAsync(elementType);
break;
case ir.AsyncMarker.AsyncStar:
ir.DartType elementType = const ir.DynamicType();
if (returnType is ir.InterfaceType) {
if (returnType.classNode == typeEnvironment.coreTypes.streamClass) {
elementType = returnType.typeArguments.first;
}
}
registerAsyncStar(elementType);
break;
case ir.AsyncMarker.SyncYielding:
failedAt(CURRENT_ELEMENT_SPANNABLE,
"Unexpected async marker: ${asyncMarker}");
}
}
@override
void handleStringConcatenation(ir.StringConcatenation node) {
registerStringConcatenation();
}
@override
void handleFunctionDeclaration(ir.FunctionDeclaration node) {
registerLocalFunction(node);
handleAsyncMarker(node.function);
}
@override
void handleFunctionExpression(ir.FunctionExpression node) {
registerLocalFunction(node);
handleAsyncMarker(node.function);
}
@override
void handleVariableDeclaration(ir.VariableDeclaration node) {
if (node.initializer == null) {
registerLocalWithoutInitializer();
}
}
@override
void handleIsExpression(ir.IsExpression node) {
registerIsCheck(node.type);
}
@override
void handleAsExpression(ir.AsExpression node, ir.DartType operandType,
{bool? isCalculatedTypeSubtype}) {
if (isCalculatedTypeSubtype ??
typeEnvironment.isSubtypeOf(operandType, node.type,
ir.SubtypeCheckMode.ignoringNullabilities)) {
// Skip unneeded casts.
return;
}
if (node.isTypeError) {
registerImplicitCast(node.type);
} else {
registerAsCast(node.type);
}
}
@override
void handleThrow(ir.Throw node) {
registerThrow();
}
@override
void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType,
ir.DartType iteratorType) {
if (node.isAsync) {
registerAsyncForIn(iterableType, iteratorType,
computeClassRelationFromType(iteratorType));
} else {
registerSyncForIn(iterableType, iteratorType,
computeClassRelationFromType(iteratorType));
}
}
@override
void handleCatch(ir.Catch node) {
registerCatch();
if (node.stackTrace != null) {
registerStackTrace();
}
if (node.guard is! ir.DynamicType) {
registerCatchType(node.guard);
}
}
@override
void handleTypeLiteral(ir.TypeLiteral node) {
registerTypeLiteral(node.type, getDeferredImport(node));
}
@override
void handleFieldInitializer(ir.FieldInitializer node) {
registerFieldInitialization(node.field);
}
@override
void handleLoadLibrary(ir.LoadLibrary node) {
registerLoadLibrary();
}
@override
void handleRedirectingInitializer(
ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {
registerRedirectingInitializer(
node.target,
node.arguments.positional.length,
_getNamedArguments(node.arguments),
node.arguments.types);
}
@override
void handleParameter(ir.VariableDeclaration parameter) {
registerParameterCheck(parameter.type);
}
@override
void handleSignature(ir.FunctionNode node) {
for (ir.TypeParameter parameter in node.typeParameters) {
registerParameterCheck(parameter.bound);
}
}
@override
void handleConstructor(ir.Constructor node) {
registerConstructorNode(node);
}
@override
void handleField(ir.Field field) {
registerParameterCheck(field.type);
if (field.initializer != null) {
if (!field.isInstanceMember &&
!field.isConst &&
field.initializer is! ir.NullLiteral) {
registerLazyField();
}
} else {
registerNullLiteral();
}
registerFieldNode(field);
}
@override
void handleProcedure(ir.Procedure procedure) {
handleAsyncMarker(procedure.function);
registerProcedureNode(procedure);
}
void _handleConstConstructorInvocation(ir.ConstructorInvocation node) {
assert(node.isConst);
ConstructorEntity constructor = _elementMap.getConstructor(node.target);
if (_commonElements.isSymbolConstructor(constructor)) {
DartType argumentType = _elementMap.getDartType(
node.arguments.positional.first.getStaticType(staticTypeContext));
// TODO(joshualitt): Does the CFE check this for us?
if (argumentType != _commonElements.stringType) {
// TODO(het): Get the actual span for the Symbol constructor argument
_reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
MessageKind.STRING_EXPECTED, {'type': _typeToString(argumentType)});
return;
}
registerConstSymbolConstructorInvocationNode();
}
}
@override
void handleConstructorInvocation(ir.ConstructorInvocation node,
ArgumentTypes argumentTypes, ir.DartType resultType) {
registerNew(
node.target,
node.constructedType,
node.arguments.positional.length,
_getNamedArguments(node.arguments),
node.arguments.types,
getDeferredImport(node),
isConst: node.isConst);
if (node.isConst) {
_handleConstConstructorInvocation(node);
}
}
@override
void handleStaticInvocation(ir.StaticInvocation node,
ArgumentTypes argumentTypes, ir.DartType returnType) {
int positionArguments = node.arguments.positional.length;
List<String> namedArguments = _getNamedArguments(node.arguments);
List<ir.DartType> typeArguments = node.arguments.types;
if (node.target.kind == ir.ProcedureKind.Factory) {
// TODO(johnniwinther): We should not mark the type as instantiated but
// rather follow the type arguments directly.
//
// Consider this:
//
// abstract class A<T> {
// factory A.regular() => new B<T>();
// factory A.redirect() = B<T>;
// }
//
// class B<T> implements A<T> {}
//
// main() {
// print(new A<int>.regular() is B<int>);
// print(new A<String>.redirect() is B<String>);
// }
//
// To track that B is actually instantiated as B<int> and B<String> we
// need to follow the type arguments passed to A.regular and A.redirect
// to B. Currently, we only do this soundly if we register A<int> and
// A<String> as instantiated. We should instead register that A.T is
// instantiated as int and String.
registerNew(
node.target,
ir.InterfaceType(node.target.enclosingClass!,
node.target.enclosingLibrary.nonNullable, typeArguments),
positionArguments,
namedArguments,
node.arguments.types,
getDeferredImport(node),
isConst: node.isConst);
} else {
registerStaticInvocation(node.target, positionArguments, namedArguments,
typeArguments, getDeferredImport(node));
}
registerStaticInvocationNode(node);
}
@override
void handleDynamicInvocation(
ir.InvocationExpression node,
ir.DartType receiverType,
ArgumentTypes argumentTypes,
ir.DartType returnType) {
int positionArguments = node.arguments.positional.length;
List<String> namedArguments = _getNamedArguments(node.arguments);
List<ir.DartType> typeArguments = node.arguments.types;
ClassRelation relation = computeClassRelationFromType(receiverType);
registerDynamicInvocation(receiverType, relation, node.name,
positionArguments, namedArguments, typeArguments);
}
@override
void handleFunctionInvocation(
ir.InvocationExpression node,
ir.DartType receiverType,
ArgumentTypes argumentTypes,
ir.DartType returnType) {
int positionArguments = node.arguments.positional.length;
List<String> namedArguments = _getNamedArguments(node.arguments);
List<ir.DartType> typeArguments = node.arguments.types;
registerFunctionInvocation(
receiverType, positionArguments, namedArguments, typeArguments);
}
@override
void handleInstanceInvocation(
ir.InvocationExpression node,
ir.DartType receiverType,
ir.Member interfaceTarget,
ArgumentTypes argumentTypes) {
int positionArguments = node.arguments.positional.length;
List<String> namedArguments = _getNamedArguments(node.arguments);
List<ir.DartType> typeArguments = node.arguments.types;
ClassRelation relation = computeClassRelationFromType(receiverType);
if (interfaceTarget is ir.Field ||
interfaceTarget is ir.Procedure &&
interfaceTarget.kind == ir.ProcedureKind.Getter) {
registerInstanceInvocation(receiverType, relation, interfaceTarget,
positionArguments, namedArguments, typeArguments);
registerFunctionInvocation(interfaceTarget.getterType, positionArguments,
namedArguments, typeArguments);
} else {
registerInstanceInvocation(receiverType, relation, interfaceTarget,
positionArguments, namedArguments, typeArguments);
}
}
@override
void handleLocalFunctionInvocation(
ir.InvocationExpression node,
ir.FunctionDeclaration function,
ArgumentTypes argumentTypes,
ir.DartType returnType) {
int positionArguments = node.arguments.positional.length;
List<String> namedArguments = _getNamedArguments(node.arguments);
List<ir.DartType> typeArguments = node.arguments.types;
registerLocalFunctionInvocation(
function, positionArguments, namedArguments, typeArguments);
}
@override
void handleEqualsCall(ir.Expression left, ir.DartType leftType,
ir.Expression right, ir.DartType rightType, ir.Member interfaceTarget) {
ClassRelation relation = computeClassRelationFromType(leftType);
registerInstanceInvocation(leftType, relation, interfaceTarget, 1,
const <String>[], const <ir.DartType>[]);
}
@override
void handleEqualsNull(ir.EqualsNull node, ir.DartType expressionType) {
registerNullLiteral();
}
@override
void handleDynamicGet(ir.Expression node, ir.DartType receiverType,
ir.Name name, ir.DartType resultType) {
ClassRelation relation = computeClassRelationFromType(receiverType);
registerDynamicGet(receiverType, relation, name);
}
@override
void handleInstanceGet(ir.Expression node, ir.DartType receiverType,
ir.Member interfaceTarget, ir.DartType resultType) {
ClassRelation relation = computeClassRelationFromType(receiverType);
registerInstanceGet(receiverType, relation, interfaceTarget);
}
@override
void handleDynamicSet(ir.Expression node, ir.DartType receiverType,
ir.Name name, ir.DartType valueType) {
ClassRelation relation = computeClassRelationFromType(receiverType);
registerDynamicSet(receiverType, relation, name);
}
@override
void handleInstanceSet(ir.Expression node, ir.DartType receiverType,
ir.Member interfaceTarget, ir.DartType valueType) {
ClassRelation relation = computeClassRelationFromType(receiverType);
registerInstanceSet(receiverType, relation, interfaceTarget);
}
@override
void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
ArgumentTypes argumentTypes, ir.DartType returnType) {
registerSuperInvocation(
getEffectiveSuperTarget(node.interfaceTarget)!,
node.arguments.positional.length,
_getNamedArguments(node.arguments),
node.arguments.types);
}
@override
void handleSuperPropertyGet(
ir.SuperPropertyGet node, ir.DartType resultType) {
registerSuperGet(getEffectiveSuperTarget(node.interfaceTarget)!);
}
@override
void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) {
registerSuperSet(getEffectiveSuperTarget(node.interfaceTarget)!);
}
@override
void handleSuperInitializer(
ir.SuperInitializer node, ArgumentTypes argumentTypes) {
registerSuperInitializer(
node.parent as ir.Constructor,
node.target,
node.arguments.positional.length,
_getNamedArguments(node.arguments),
node.arguments.types);
}
@override
ir.DartType visitSwitchStatement(ir.SwitchStatement node) {
registerSwitchStatementNode(node);
return super.visitSwitchStatement(node);
}
@override
void handleRuntimeTypeUse(ir.Expression node, RuntimeTypeUseKind kind,
ir.DartType receiverType, ir.DartType? argumentType) {
if (_options.omitImplicitChecks) {
switch (kind) {
case RuntimeTypeUseKind.string:
if (!_options.laxRuntimeTypeToString) {
_reporter.reportHintMessage(computeSourceSpanFromTreeNode(node),
MessageKind.RUNTIME_TYPE_TO_STRING);
}
break;
case RuntimeTypeUseKind.equals:
case RuntimeTypeUseKind.unknown:
break;
}
}
registerRuntimeTypeUse(kind, receiverType, argumentType);
}
@override
void handleConstantExpression(ir.ConstantExpression node) {
// Evaluate any [ir.UnevaluatedConstant]s to ensure they are processed for
// impacts correctly.
// TODO(joshualitt): Remove this when we have CFE constants.
if (node.constant is ir.UnevaluatedConstant) {
_elementMap.constantEvaluator.evaluate(staticTypeContext, node);
}
ir.LibraryDependency? import = getDeferredImport(node);
ConstantImpactVisitor(this, import, node, staticTypeContext)
.visitConstant(node.constant);
}
void _registerFeature(_Feature feature) {
(_data._features ??= EnumSet<_Feature>()).add(feature);
}
void _registerTypeUse(ir.DartType type, _TypeUseKind kind) {
(_data._typeUses ??= []).add(_TypeUse(type, kind));
}
@override
void registerSuperInitializer(
ir.Constructor source,
ir.Constructor target,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
(_data._superInitializers ??= []).add(
_SuperInitializer(source, target,
_CallStructure(positionalArguments, namedArguments, typeArguments)),
);
}
@override
void registerSuperSet(ir.Member target) {
(_data._superSets ??= []).add(target);
}
@override
void registerSuperGet(ir.Member target) {
(_data._superGets ??= []).add(target);
}
@override
void registerSuperInvocation(ir.Member target, int positionalArguments,
List<String> namedArguments, List<ir.DartType> typeArguments) {
(_data._superInvocations ??= []).add(_SuperInvocation(target,
_CallStructure(positionalArguments, namedArguments, typeArguments)));
}
@override
void registerInstanceSet(
ir.DartType receiverType, ClassRelation relation, ir.Member target) {
(_data._instanceSets ??= [])
.add(_InstanceAccess(receiverType, relation, target));
}
@override
void registerDynamicSet(
ir.DartType receiverType, ClassRelation relation, ir.Name name) {
(_data._dynamicSets ??= [])
.add(_DynamicAccess(receiverType, relation, name));
}
@override
void registerInstanceGet(
ir.DartType receiverType, ClassRelation relation, ir.Member target) {
(_data._instanceGets ??= [])
.add(_InstanceAccess(receiverType, relation, target));
}
@override
void registerDynamicGet(
ir.DartType receiverType, ClassRelation relation, ir.Name name) {
(_data._dynamicGets ??= [])
.add(_DynamicAccess(receiverType, relation, name));
}
@override
void registerFunctionInvocation(
ir.DartType receiverType,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
(_data._functionInvocations ??= []).add(_FunctionInvocation(receiverType,
_CallStructure(positionalArguments, namedArguments, typeArguments)));
}
@override
void registerInstanceInvocation(
ir.DartType receiverType,
ClassRelation relation,
ir.Member target,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
(_data._instanceInvocations ??= []).add(_InstanceInvocation(
receiverType,
relation,
target,
_CallStructure(positionalArguments, namedArguments, typeArguments)));
}
@override
void registerDynamicInvocation(
ir.DartType receiverType,
ClassRelation relation,
ir.Name name,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
(_data._dynamicInvocations ??= []).add(_DynamicInvocation(
receiverType,
relation,
name,
_CallStructure(positionalArguments, namedArguments, typeArguments)));
}
@override
void registerLocalFunctionInvocation(
ir.FunctionDeclaration localFunction,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
(_data._localFunctionInvocations ??= []).add(_LocalFunctionInvocation(
localFunction,
_CallStructure(positionalArguments, namedArguments, typeArguments)));
}
@override
void registerStaticInvocation(
ir.Procedure target,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments,
ir.LibraryDependency? import) {
(_data._staticInvocations ??= []).add(_StaticInvocation(
target,
_CallStructure(positionalArguments, namedArguments, typeArguments),
import));
}
@override
void registerNew(
ir.Member constructor,
ir.InterfaceType type,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments,
ir.LibraryDependency? import,
{required bool isConst}) {
(_data._constructorInvocations ??= []).add(_ConstructorInvocation(
constructor,
type,
_CallStructure(positionalArguments, namedArguments, typeArguments),
import,
isConst: isConst));
}
@override
void registerConstInstantiation(ir.Class cls, List<ir.DartType> typeArguments,
ir.LibraryDependency? import) {
(_data._constInstantiations ??= [])
.add(_ConstInstantiation(cls, typeArguments, import));
}
@override
void registerLazyField() {
_registerFeature(_Feature.lazyField);
}
@override
void registerParameterCheck(ir.DartType type) {
_registerTypeUse(type, _TypeUseKind.parameterCheck);
}
@override
void registerRedirectingInitializer(
ir.Constructor constructor,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
(_data._redirectingInitializers ??= []).add(_RedirectingInitializer(
constructor,
_CallStructure(positionalArguments, namedArguments, typeArguments)));
}
@override
void registerLoadLibrary() {
_registerFeature(_Feature.loadLibrary);
}
@override
void registerFieldInitialization(ir.Field node) {
(_data._fieldInitializers ??= []).add(node);
}
@override
void registerFieldConstantInitialization(
ir.Field node, ConstantReference constant) {
(_data._fieldConstantInitializers ??= {})
.putIfAbsent(node, () => [])
.add(constant);
}
@override
void registerTypeLiteral(ir.DartType type, ir.LibraryDependency? import) {
(_data._typeLiterals ??= []).add(_TypeLiteral(type, import));
}
@override
void registerCatchType(ir.DartType type) {
_registerTypeUse(type, _TypeUseKind.catchType);
}
@override
void registerStackTrace() {
_registerFeature(_Feature.stackTrace);
}
@override
void registerCatch() {
_registerFeature(_Feature.catchClause);
}
@override
void registerAsyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
ClassRelation iteratorClassRelation) {
(_data._forInData ??= []).add(_ForInData(
iterableType, iteratorType, iteratorClassRelation,
isAsync: true));
}
@override
void registerSyncForIn(ir.DartType iterableType, ir.DartType iteratorType,
ClassRelation iteratorClassRelation) {
(_data._forInData ??= []).add(_ForInData(
iterableType, iteratorType, iteratorClassRelation,
isAsync: false));
}
@override
void registerThrow() {
_registerFeature(_Feature.throwExpression);
}
@override
void registerAsCast(ir.DartType type) {
_registerTypeUse(type, _TypeUseKind.asCast);
}
@override
void registerImplicitCast(ir.DartType type) {
_registerTypeUse(type, _TypeUseKind.implicitCast);
}
@override
void registerIsCheck(ir.DartType type) {
_registerTypeUse(type, _TypeUseKind.isCheck);
}
@override
void registerLocalWithoutInitializer() {
_registerFeature(_Feature.localWithoutInitializer);
}
@override
void registerLocalFunction(ir.TreeNode node) {
(_data._localFunctions ??= []).add(node);
}
@override
void registerStringConcatenation() {
_registerFeature(_Feature.stringConcatenation);
}
@override
void registerAsyncStar(ir.DartType elementType) {
_registerTypeUse(elementType, _TypeUseKind.asyncStarMarker);
}
@override
void registerAsync(ir.DartType elementType) {
_registerTypeUse(elementType, _TypeUseKind.asyncMarker);
}
@override
void registerSyncStar(ir.DartType elementType) {
_registerTypeUse(elementType, _TypeUseKind.syncStarMarker);
}
@override
void registerGenericInstantiation(
ir.FunctionType expressionType, List<ir.DartType> typeArguments) {
(_data._genericInstantiations ??= [])
.add(_GenericInstantiation(expressionType, typeArguments));
}
@override
void registerAssert({required bool withMessage}) {
_registerFeature(withMessage
? _Feature.assertWithMessage
: _Feature.assertWithoutMessage);
}
@override
void registerStaticSet(ir.Member member, ir.LibraryDependency? import) {
(_data._staticSets ??= []).add(_StaticAccess(member, import));
}
@override
void registerStaticGet(ir.Member member, ir.LibraryDependency? import) {
(_data._staticGets ??= []).add(_StaticAccess(member, import));
}
@override
void registerStaticTearOff(
ir.Procedure procedure, ir.LibraryDependency? import) {
(_data._staticTearOffs ??= []).add(_StaticAccess(procedure, import));
}
@override
void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
{required bool isConst, required bool isEmpty}) {
(_data._mapLiterals ??= []).add(
_MapLiteral(keyType, valueType, isConst: isConst, isEmpty: isEmpty));
}
@override
void registerListLiteral(ir.DartType elementType,
{required bool isConst, required bool isEmpty}) {
(_data._listLiterals ??= []).add(
_ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty));
}
@override
void registerSetLiteral(ir.DartType elementType,
{required bool isConst, required bool isEmpty}) {
(_data._setLiterals ??= []).add(
_ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty));
}
@override
void registerNullLiteral() {
_registerFeature(_Feature.nullLiteral);
}
@override
void registerSymbolLiteral(String value) {
(_data._symbolLiterals ??= {}).add(value);
}
@override
void registerStringLiteral(String value) {
(_data._stringLiterals ??= {}).add(value);
}
@override
void registerBoolLiteral(bool value) {
(_data._boolLiterals ??= {}).add(value);
}
@override
void registerDoubleLiteral(double value) {
(_data._doubleLiterals ??= {}).add(value);
}
@override
void registerIntLiteral(int value) {
(_data._intLiterals ??= {}).add(value);
}
@override
void registerRuntimeTypeUse(RuntimeTypeUseKind kind, ir.DartType receiverType,
ir.DartType? argumentType) {
(_data._runtimeTypeUses ??= [])
.add(_RuntimeTypeUse(kind, receiverType, argumentType));
}
@override
void registerConstructorNode(ir.Constructor node) {
(_data._constructorNodes ??= []).add(node);
}
@override
void registerFieldNode(ir.Field node) {
(_data._fieldNodes ??= []).add(node);
}
@override
void registerProcedureNode(ir.Procedure node) {
(_data._procedureNodes ??= []).add(node);
}
@override
void registerStaticInvocationNode(ir.StaticInvocation node) {
(_data._staticInvocationNodes ??= []).add(node);
}
@override
void registerSwitchStatementNode(ir.SwitchStatement node) {
(_data._switchStatementNodes ??= []).add(node);
}
@override
void registerConstSymbolConstructorInvocationNode() {
_data._hasConstSymbolConstructorInvocation = true;
}
}
/// Data object that contains the world impact data derived purely from kernel.
/// It is critical that all of the data in this class be invariant to changes in
/// the AST that occur after modular compilation and before deserializing the
/// impact data.
class ImpactData {
static const String tag = 'ImpactData';
List<_SuperInitializer>? _superInitializers;
List<ir.Member>? _superSets;
List<ir.Member>? _superGets;
List<_SuperInvocation>? _superInvocations;
List<_InstanceAccess>? _instanceSets;
List<_DynamicAccess>? _dynamicSets;
List<_InstanceAccess>? _instanceGets;
List<_DynamicAccess>? _dynamicGets;
List<_FunctionInvocation>? _functionInvocations;
List<_InstanceInvocation>? _instanceInvocations;
List<_DynamicInvocation>? _dynamicInvocations;
List<_LocalFunctionInvocation>? _localFunctionInvocations;
List<_StaticInvocation>? _staticInvocations;
List<_ConstructorInvocation>? _constructorInvocations;
List<_ConstInstantiation>? _constInstantiations;
EnumSet<_Feature>? _features;
List<_TypeUse>? _typeUses;
List<_RedirectingInitializer>? _redirectingInitializers;
List<ir.Field>? _fieldInitializers;
Map<ir.Field, List<ConstantReference>>? _fieldConstantInitializers;
List<_TypeLiteral>? _typeLiterals;
List<ir.TreeNode>? _localFunctions;
List<_GenericInstantiation>? _genericInstantiations;
List<_StaticAccess>? _staticSets;
List<_StaticAccess>? _staticGets;
List<_StaticAccess>? _staticTearOffs;
List<_MapLiteral>? _mapLiterals;
List<_ContainerLiteral>? _listLiterals;
List<_ContainerLiteral>? _setLiterals;
Set<String>? _symbolLiterals;
Set<String>? _stringLiterals;
Set<bool>? _boolLiterals;
Set<double>? _doubleLiterals;
Set<int>? _intLiterals;
List<_RuntimeTypeUse>? _runtimeTypeUses;
List<_ForInData>? _forInData;
// TODO(johnniwinther): Remove these when CFE provides constants.
List<ir.Constructor>? _constructorNodes;
List<ir.Field>? _fieldNodes;
List<ir.Procedure>? _procedureNodes;
List<ir.SwitchStatement>? _switchStatementNodes;
List<ir.StaticInvocation>? _staticInvocationNodes;
bool _hasConstSymbolConstructorInvocation = false;
ImpactData();
ImpactData.fromDataSource(DataSourceReader source) {
source.begin(tag);
_superInitializers =
source.readListOrNull(() => _SuperInitializer.fromDataSource(source));
_superSets = source.readListOrNull(() => source.readMemberNode());
_superGets = source.readListOrNull(() => source.readMemberNode());
_superInvocations =
source.readListOrNull(() => _SuperInvocation.fromDataSource(source));
_instanceSets =
source.readListOrNull(() => _InstanceAccess.fromDataSource(source));
_dynamicSets =
source.readListOrNull(() => _DynamicAccess.fromDataSource(source));
_instanceGets =
source.readListOrNull(() => _InstanceAccess.fromDataSource(source));
_dynamicGets =
source.readListOrNull(() => _DynamicAccess.fromDataSource(source));
_functionInvocations =
source.readListOrNull(() => _FunctionInvocation.fromDataSource(source));
_instanceInvocations =
source.readListOrNull(() => _InstanceInvocation.fromDataSource(source));
_dynamicInvocations =
source.readListOrNull(() => _DynamicInvocation.fromDataSource(source));
_localFunctionInvocations = source
.readListOrNull(() => _LocalFunctionInvocation.fromDataSource(source));
_staticInvocations =
source.readListOrNull(() => _StaticInvocation.fromDataSource(source));
_constructorInvocations = source
.readListOrNull(() => _ConstructorInvocation.fromDataSource(source));
_features = EnumSet<_Feature>.fromValue(source.readInt());
_typeUses = source.readListOrNull(() => _TypeUse.fromDataSource(source));
_redirectingInitializers = source
.readListOrNull(() => _RedirectingInitializer.fromDataSource(source));
_fieldInitializers = source.readMemberNodesOrNull<ir.Field>();
_fieldConstantInitializers =
source.readMemberNodeMapOrNull(source.readTreeNodes);
_typeLiterals =
source.readListOrNull(() => _TypeLiteral.fromDataSource(source));
_localFunctions = source.readTreeNodesOrNull();
_genericInstantiations = source
.readListOrNull(() => _GenericInstantiation.fromDataSource(source));
_staticSets =
source.readListOrNull(() => _StaticAccess.fromDataSource(source));
_staticGets =
source.readListOrNull(() => _StaticAccess.fromDataSource(source));
_staticTearOffs =
source.readListOrNull(() => _StaticAccess.fromDataSource(source));
_mapLiterals =
source.readListOrNull(() => _MapLiteral.fromDataSource(source));
_listLiterals =
source.readListOrNull(() => _ContainerLiteral.fromDataSource(source));
_setLiterals =
source.readListOrNull(() => _ContainerLiteral.fromDataSource(source));
_symbolLiterals = source.readStrings(emptyAsNull: true)?.toSet();
_stringLiterals = source.readStrings(emptyAsNull: true)?.toSet();
_boolLiterals = source.readListOrNull(() => source.readBool())?.toSet();
_doubleLiterals =
source.readListOrNull(() => source.readDoubleValue())?.toSet();
_intLiterals =
source.readListOrNull(() => source.readIntegerValue())?.toSet();
_runtimeTypeUses =
source.readListOrNull(() => _RuntimeTypeUse.fromDataSource(source));
_forInData = source.readListOrNull(() => _ForInData.fromDataSource(source));
// TODO(johnniwinther): Remove these when CFE provides constants.
_constructorNodes = source.readMemberNodesOrNull<ir.Constructor>();
_fieldNodes = source.readMemberNodesOrNull<ir.Field>();
_procedureNodes = source.readMemberNodesOrNull<ir.Procedure>();
_switchStatementNodes = source.readTreeNodesOrNull<ir.SwitchStatement>();
_staticInvocationNodes = source.readTreeNodesOrNull<ir.StaticInvocation>();
_hasConstSymbolConstructorInvocation = source.readBool();
source.end(tag);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeList(
_superInitializers, (_SuperInitializer o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_superSets, sink.writeMemberNode, allowNull: true);
sink.writeList(_superGets, sink.writeMemberNode, allowNull: true);
sink.writeList(
_superInvocations, (_SuperInvocation o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_instanceSets, (_InstanceAccess o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_dynamicSets, (_DynamicAccess o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_instanceGets, (_InstanceAccess o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_dynamicGets, (_DynamicAccess o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(
_functionInvocations, (_FunctionInvocation o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(
_instanceInvocations, (_InstanceInvocation o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(
_dynamicInvocations, (_DynamicInvocation o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_localFunctionInvocations,
(_LocalFunctionInvocation o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(
_staticInvocations, (_StaticInvocation o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_constructorInvocations,
(_ConstructorInvocation o) => o.toDataSink(sink),
allowNull: true);
sink.writeInt(_features?.value ?? 0);
sink.writeList(_typeUses, (_TypeUse o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_redirectingInitializers,
(_RedirectingInitializer o) => o.toDataSink(sink),
allowNull: true);
sink.writeMemberNodes(_fieldInitializers, allowNull: true);
sink.writeMemberNodeMap(_fieldConstantInitializers, sink.writeTreeNodes,
allowNull: true);
sink.writeList(_typeLiterals, (_TypeLiteral o) => o.toDataSink(sink),
allowNull: true);
sink.writeTreeNodes(_localFunctions, allowNull: true);
sink.writeList(
_genericInstantiations, (_GenericInstantiation o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_staticSets, (_StaticAccess o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_staticGets, (_StaticAccess o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_staticTearOffs, (_StaticAccess o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_mapLiterals, (_MapLiteral o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_listLiterals, (_ContainerLiteral o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_setLiterals, (_ContainerLiteral o) => o.toDataSink(sink),
allowNull: true);
sink.writeStrings(_symbolLiterals, allowNull: true);
sink.writeStrings(_stringLiterals, allowNull: true);
sink.writeList(_boolLiterals, sink.writeBool, allowNull: true);
sink.writeList(_doubleLiterals, sink.writeDoubleValue, allowNull: true);
sink.writeList(_intLiterals, sink.writeIntegerValue, allowNull: true);
sink.writeList(_runtimeTypeUses, (_RuntimeTypeUse o) => o.toDataSink(sink),
allowNull: true);
sink.writeList(_forInData, (_ForInData o) => o.toDataSink(sink),
allowNull: true);
sink.writeMemberNodes(_constructorNodes, allowNull: true);
sink.writeMemberNodes(_fieldNodes, allowNull: true);
sink.writeMemberNodes(_procedureNodes, allowNull: true);
sink.writeTreeNodes(_switchStatementNodes, allowNull: true);
sink.writeTreeNodes(_staticInvocationNodes, allowNull: true);
sink.writeBool(_hasConstSymbolConstructorInvocation);
sink.end(tag);
}
/// Registers the impact data with [registry].
void apply(ImpactRegistry registry) {
if (_superInitializers != null) {
for (_SuperInitializer data in _superInitializers!) {
registry.registerSuperInitializer(
data.source,
data.target,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments);
}
}
if (_superSets != null) {
for (ir.Member data in _superSets!) {
registry.registerSuperSet(data);
}
}
if (_superGets != null) {
for (ir.Member data in _superGets!) {
registry.registerSuperGet(data);
}
}
if (_superInvocations != null) {
for (_SuperInvocation data in _superInvocations!) {
registry.registerSuperInvocation(
data.target,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments);
}
}
if (_instanceSets != null) {
for (_InstanceAccess data in _instanceSets!) {
registry.registerInstanceSet(
data.receiverType, data.classRelation, data.target);
}
}
if (_dynamicSets != null) {
for (_DynamicAccess data in _dynamicSets!) {
registry.registerDynamicSet(
data.receiverType, data.classRelation, data.name);
}
}
if (_instanceGets != null) {
for (_InstanceAccess data in _instanceGets!) {
registry.registerInstanceGet(
data.receiverType, data.classRelation, data.target);
}
}
if (_dynamicGets != null) {
for (_DynamicAccess data in _dynamicGets!) {
registry.registerDynamicGet(
data.receiverType, data.classRelation, data.name);
}
}
if (_functionInvocations != null) {
for (_FunctionInvocation data in _functionInvocations!) {
registry.registerFunctionInvocation(
data.receiverType,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments);
}
}
if (_instanceInvocations != null) {
for (_InstanceInvocation data in _instanceInvocations!) {
registry.registerInstanceInvocation(
data.receiverType,
data.classRelation,
data.target,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments);
}
}
if (_dynamicInvocations != null) {
for (_DynamicInvocation data in _dynamicInvocations!) {
registry.registerDynamicInvocation(
data.receiverType,
data.classRelation,
data.name,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments);
}
}
if (_localFunctionInvocations != null) {
for (_LocalFunctionInvocation data in _localFunctionInvocations!) {
registry.registerLocalFunctionInvocation(
data.localFunction,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments);
}
}
if (_staticInvocations != null) {
for (_StaticInvocation data in _staticInvocations!) {
registry.registerStaticInvocation(
data.target,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments,
data.import);
;
}
}
if (_constructorInvocations != null) {
for (_ConstructorInvocation data in _constructorInvocations!) {
registry.registerNew(
data.constructor,
data.type,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments,
data.import,
isConst: data.isConst);
}
}
if (_constInstantiations != null) {
for (_ConstInstantiation data in _constInstantiations!) {
registry.registerConstInstantiation(
data.cls, data.typeArguments, data.import);
}
}
if (_features != null) {
for (_Feature data in _features!.iterable(_Feature.values)) {
switch (data) {
case _Feature.lazyField:
registry.registerLazyField();
break;
case _Feature.loadLibrary:
registry.registerLoadLibrary();
break;
case _Feature.stackTrace:
registry.registerStackTrace();
break;
case _Feature.catchClause:
registry.registerCatch();
break;
case _Feature.throwExpression:
registry.registerThrow();
break;
case _Feature.localWithoutInitializer:
registry.registerLocalWithoutInitializer();
break;
case _Feature.stringConcatenation:
registry.registerStringConcatenation();
break;
case _Feature.assertWithMessage:
registry.registerAssert(withMessage: true);
break;
case _Feature.assertWithoutMessage:
registry.registerAssert(withMessage: false);
break;
case _Feature.nullLiteral:
registry.registerNullLiteral();
break;
}
}
}
if (_typeUses != null) {
for (_TypeUse data in _typeUses!) {
switch (data.kind) {
case _TypeUseKind.parameterCheck:
registry.registerParameterCheck(data.type);
break;
case _TypeUseKind.catchType:
registry.registerCatchType(data.type);
break;
case _TypeUseKind.asCast:
registry.registerAsCast(data.type);
break;
case _TypeUseKind.implicitCast:
registry.registerImplicitCast(data.type);
break;
case _TypeUseKind.isCheck:
registry.registerIsCheck(data.type);
break;
case _TypeUseKind.asyncStarMarker:
registry.registerAsyncStar(data.type);
break;
case _TypeUseKind.asyncMarker:
registry.registerAsync(data.type);
break;
case _TypeUseKind.syncStarMarker:
registry.registerSyncStar(data.type);
break;
}
}
}
if (_redirectingInitializers != null) {
for (_RedirectingInitializer data in _redirectingInitializers!) {
registry.registerRedirectingInitializer(
data.constructor,
data.callStructure.positionalArguments,
data.callStructure.namedArguments,
data.callStructure.typeArguments);
}
}
if (_fieldInitializers != null) {
for (ir.Field data in _fieldInitializers!) {
registry.registerFieldInitialization(data);
}
}
if (_fieldConstantInitializers != null) {
_fieldConstantInitializers!
.forEach((ir.Field field, List<ConstantReference> constants) {
for (ConstantReference constant in constants) {
registry.registerFieldConstantInitialization(field, constant);
}
});
}
if (_typeLiterals != null) {
for (_TypeLiteral data in _typeLiterals!) {
registry.registerTypeLiteral(data.type, data.import);
}
}
if (_localFunctions != null) {
for (ir.TreeNode data in _localFunctions!) {
registry.registerLocalFunction(data);
}
}
if (_genericInstantiations != null) {
for (_GenericInstantiation data in _genericInstantiations!) {
registry.registerGenericInstantiation(
data.expressionType, data.typeArguments);
}
}
if (_staticSets != null) {
for (_StaticAccess data in _staticSets!) {
registry.registerStaticSet(data.target, data.import);
}
}
if (_staticGets != null) {
for (_StaticAccess data in _staticGets!) {
registry.registerStaticGet(data.target, data.import);
}
}
if (_staticTearOffs != null) {
for (_StaticAccess data in _staticTearOffs!) {
registry.registerStaticTearOff(
data.target as ir.Procedure, data.import);
}
}
if (_mapLiterals != null) {
for (_MapLiteral data in _mapLiterals!) {
registry.registerMapLiteral(data.keyType, data.valueType,
isConst: data.isConst, isEmpty: data.isEmpty);
}
}
if (_listLiterals != null) {
for (_ContainerLiteral data in _listLiterals!) {
registry.registerListLiteral(data.elementType,
isConst: data.isConst, isEmpty: data.isEmpty);
}
}
if (_setLiterals != null) {
for (_ContainerLiteral data in _setLiterals!) {
registry.registerSetLiteral(data.elementType,
isConst: data.isConst, isEmpty: data.isEmpty);
}
}
if (_symbolLiterals != null) {
for (String data in _symbolLiterals!) {
registry.registerSymbolLiteral(data);
}
}
if (_stringLiterals != null) {
for (String data in _stringLiterals!) {
registry.registerStringLiteral(data);
}
}
if (_boolLiterals != null) {
for (bool data in _boolLiterals!) {
registry.registerBoolLiteral(data);
}
}
if (_doubleLiterals != null) {
for (double data in _doubleLiterals!) {
registry.registerDoubleLiteral(data);
}
}
if (_intLiterals != null) {
for (int data in _intLiterals!) {
registry.registerIntLiteral(data);
}
}
if (_runtimeTypeUses != null) {
for (_RuntimeTypeUse data in _runtimeTypeUses!) {
registry.registerRuntimeTypeUse(
data.kind, data.receiverType, data.argumentType);
}
}
if (_forInData != null) {
for (_ForInData data in _forInData!) {
if (data.isAsync) {
registry.registerAsyncForIn(
data.iterableType, data.iteratorType, data.iteratorClassRelation);
} else {
registry.registerSyncForIn(
data.iterableType, data.iteratorType, data.iteratorClassRelation);
}
}
}
// TODO(johnniwinther): Remove these when CFE provides constants.
if (_constructorNodes != null) {
for (ir.Constructor data in _constructorNodes!) {
registry.registerConstructorNode(data);
}
}
if (_fieldNodes != null) {
for (ir.Field data in _fieldNodes!) {
registry.registerFieldNode(data);
}
}
if (_procedureNodes != null) {
for (ir.Procedure data in _procedureNodes!) {
registry.registerProcedureNode(data);
}
}
if (_switchStatementNodes != null) {
for (ir.SwitchStatement data in _switchStatementNodes!) {
registry.registerSwitchStatementNode(data);
}
}
if (_staticInvocationNodes != null) {
for (ir.StaticInvocation data in _staticInvocationNodes!) {
registry.registerStaticInvocationNode(data);
}
}
if (_hasConstSymbolConstructorInvocation) {
registry.registerConstSymbolConstructorInvocationNode();
}
}
}
class _CallStructure {
static const String tag = '_CallStructure';
final List<ir.DartType> typeArguments;
final int positionalArguments;
final List<String> namedArguments;
_CallStructure.internal(
this.typeArguments, this.positionalArguments, this.namedArguments);
factory _CallStructure(int positionalArguments, List<String> namedArguments,
List<ir.DartType> typeArguments) {
return _CallStructure.internal(
typeArguments, positionalArguments, namedArguments);
}
factory _CallStructure.fromDataSource(DataSourceReader source) {
source.begin(tag);
List<ir.DartType> typeArguments = source.readDartTypeNodes();
int positionalArguments = source.readInt();
List<String> namedArguments = source.readStrings() ?? const [];
source.end(tag);
return _CallStructure.internal(
typeArguments, positionalArguments, namedArguments);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNodes(typeArguments);
sink.writeInt(positionalArguments);
sink.writeStrings(namedArguments);
sink.end(tag);
}
}
class _SuperInitializer {
static const String tag = '_SuperInitializer';
final ir.Constructor source;
final ir.Constructor target;
final _CallStructure callStructure;
_SuperInitializer(this.source, this.target, this.callStructure);
factory _SuperInitializer.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.Constructor sourceConstructor =
source.readMemberNode() as ir.Constructor;
ir.Constructor targetConstructor =
source.readMemberNode() as ir.Constructor;
_CallStructure callStructure = _CallStructure.fromDataSource(source);
source.end(tag);
return _SuperInitializer(
sourceConstructor, targetConstructor, callStructure);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeMemberNode(source);
sink.writeMemberNode(target);
callStructure.toDataSink(sink);
sink.end(tag);
}
}
class _SuperInvocation {
static const String tag = '_SuperInvocation';
final ir.Member target;
final _CallStructure callStructure;
_SuperInvocation(this.target, this.callStructure);
factory _SuperInvocation.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.Member member = source.readMemberNode();
_CallStructure callStructure = _CallStructure.fromDataSource(source);
source.end(tag);
return _SuperInvocation(member, callStructure);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeMemberNode(target);
callStructure.toDataSink(sink);
sink.end(tag);
}
}
class _InstanceAccess {
static const String tag = '_InstanceAccess';
final ir.DartType receiverType;
final ClassRelation classRelation;
final ir.Member target;
_InstanceAccess(this.receiverType, this.classRelation, this.target);
factory _InstanceAccess.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType receiverType = source.readDartTypeNode();
ClassRelation classRelation = source.readEnum(ClassRelation.values);
ir.Member target = source.readMemberNode();
source.end(tag);
return _InstanceAccess(receiverType, classRelation, target);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(receiverType);
sink.writeEnum(classRelation);
sink.writeMemberNode(target);
sink.end(tag);
}
}
class _DynamicAccess {
static const String tag = '_DynamicAccess';
final ir.DartType receiverType;
final ClassRelation classRelation;
final ir.Name name;
_DynamicAccess(this.receiverType, this.classRelation, this.name);
factory _DynamicAccess.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType receiverType = source.readDartTypeNode();
ClassRelation classRelation = source.readEnum(ClassRelation.values);
ir.Name name = source.readName();
source.end(tag);
return _DynamicAccess(receiverType, classRelation, name);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(receiverType);
sink.writeEnum(classRelation);
sink.writeName(name);
sink.end(tag);
}
}
class _FunctionInvocation {
static const String tag = '_FunctionInvocation';
final ir.DartType receiverType;
final _CallStructure callStructure;
_FunctionInvocation(this.receiverType, this.callStructure);
factory _FunctionInvocation.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType receiverType = source.readDartTypeNode();
_CallStructure callStructure = _CallStructure.fromDataSource(source);
source.end(tag);
return _FunctionInvocation(receiverType, callStructure);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(receiverType);
callStructure.toDataSink(sink);
sink.end(tag);
}
}
class _InstanceInvocation {
static const String tag = '_InstanceInvocation';
final ir.DartType receiverType;
final ClassRelation classRelation;
final ir.Member target;
final _CallStructure callStructure;
_InstanceInvocation(
this.receiverType, this.classRelation, this.target, this.callStructure);
factory _InstanceInvocation.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType receiverType = source.readDartTypeNode();
ClassRelation classRelation = source.readEnum(ClassRelation.values);
ir.Member target = source.readMemberNode();
_CallStructure callStructure = _CallStructure.fromDataSource(source);
source.end(tag);
return _InstanceInvocation(
receiverType, classRelation, target, callStructure);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(receiverType);
sink.writeEnum(classRelation);
sink.writeMemberNode(target);
callStructure.toDataSink(sink);
sink.end(tag);
}
}
class _DynamicInvocation {
static const String tag = '_DynamicInvocation';
final ir.DartType receiverType;
final ClassRelation classRelation;
final ir.Name name;
final _CallStructure callStructure;
_DynamicInvocation(
this.receiverType, this.classRelation, this.name, this.callStructure);
factory _DynamicInvocation.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType receiverType = source.readDartTypeNode();
ClassRelation classRelation = source.readEnum(ClassRelation.values);
ir.Name name = source.readName();
_CallStructure callStructure = _CallStructure.fromDataSource(source);
source.end(tag);
return _DynamicInvocation(receiverType, classRelation, name, callStructure);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(receiverType);
sink.writeEnum(classRelation);
sink.writeName(name);
callStructure.toDataSink(sink);
sink.end(tag);
}
}
class _LocalFunctionInvocation {
static const String tag = '_LocalFunctionInvocation';
final ir.FunctionDeclaration localFunction;
final _CallStructure callStructure;
_LocalFunctionInvocation(this.localFunction, this.callStructure);
factory _LocalFunctionInvocation.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.FunctionDeclaration localFunction =
source.readTreeNode() as ir.FunctionDeclaration;
_CallStructure callStructure = _CallStructure.fromDataSource(source);
source.end(tag);
return _LocalFunctionInvocation(localFunction, callStructure);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeTreeNode(localFunction);
callStructure.toDataSink(sink);
sink.end(tag);
}
}
class _StaticInvocation {
static const String tag = '_StaticInvocation';
final ir.Procedure target;
final _CallStructure callStructure;
final ir.LibraryDependency? import;
_StaticInvocation(this.target, this.callStructure, this.import);
factory _StaticInvocation.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.Procedure target = source.readMemberNode() as ir.Procedure;
_CallStructure callStructure = _CallStructure.fromDataSource(source);
ir.LibraryDependency? import = source.readLibraryDependencyNodeOrNull();
source.end(tag);
return _StaticInvocation(target, callStructure, import);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeMemberNode(target);
callStructure.toDataSink(sink);
sink.writeLibraryDependencyNodeOrNull(import);
sink.end(tag);
}
}
class _ConstructorInvocation {
static const String tag = '_ConstructorInvocation';
final ir.Member constructor;
final ir.InterfaceType type;
final _CallStructure callStructure;
final ir.LibraryDependency? import;
final bool isConst;
_ConstructorInvocation(
this.constructor, this.type, this.callStructure, this.import,
{required this.isConst});
factory _ConstructorInvocation.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.Member constructor = source.readMemberNode();
ir.InterfaceType type = source.readDartTypeNode() as ir.InterfaceType;
_CallStructure callStructure = _CallStructure.fromDataSource(source);
ir.LibraryDependency? import = source.readLibraryDependencyNodeOrNull();
bool isConst = source.readBool();
source.end(tag);
return _ConstructorInvocation(constructor, type, callStructure, import,
isConst: isConst);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeMemberNode(constructor);
sink.writeDartTypeNode(type);
callStructure.toDataSink(sink);
sink.writeLibraryDependencyNodeOrNull(import);
sink.writeBool(isConst);
sink.end(tag);
}
}
class _ConstInstantiation {
final ir.Class cls;
final List<ir.DartType> typeArguments;
final ir.LibraryDependency? import;
_ConstInstantiation(this.cls, this.typeArguments, this.import);
}
enum _Feature {
lazyField,
loadLibrary,
stackTrace,
catchClause,
throwExpression,
localWithoutInitializer,
stringConcatenation,
assertWithMessage,
assertWithoutMessage,
nullLiteral,
}
class _TypeUse {
static const String tag = '_TypeUse';
final ir.DartType type;
final _TypeUseKind kind;
_TypeUse(this.type, this.kind);
factory _TypeUse.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType type = source.readDartTypeNode();
_TypeUseKind kind = source.readEnum(_TypeUseKind.values);
source.end(tag);
return _TypeUse(type, kind);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(type);
sink.writeEnum(kind);
sink.end(tag);
}
}
enum _TypeUseKind {
parameterCheck,
catchType,
asCast,
implicitCast,
isCheck,
asyncStarMarker,
asyncMarker,
syncStarMarker,
}
class _RedirectingInitializer {
static const String tag = '_RedirectingInitializer';
final ir.Constructor constructor;
final _CallStructure callStructure;
_RedirectingInitializer(this.constructor, this.callStructure);
factory _RedirectingInitializer.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.Constructor constructor = source.readMemberNode() as ir.Constructor;
_CallStructure callStructure = _CallStructure.fromDataSource(source);
source.end(tag);
return _RedirectingInitializer(constructor, callStructure);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeMemberNode(constructor);
callStructure.toDataSink(sink);
sink.end(tag);
}
}
class _TypeLiteral {
static const String tag = '_TypeLiteral';
final ir.DartType type;
final ir.LibraryDependency? import;
_TypeLiteral(this.type, this.import);
factory _TypeLiteral.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType type = source.readDartTypeNode();
ir.LibraryDependency? import = source.readLibraryDependencyNodeOrNull();
source.end(tag);
return _TypeLiteral(type, import);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(type);
sink.writeLibraryDependencyNodeOrNull(import);
sink.end(tag);
}
}
class _GenericInstantiation {
static const String tag = '_GenericInstantiation';
final ir.FunctionType expressionType;
final List<ir.DartType> typeArguments;
_GenericInstantiation(this.expressionType, this.typeArguments);
factory _GenericInstantiation.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.FunctionType expressionType =
source.readDartTypeNode() as ir.FunctionType;
List<ir.DartType> typeArguments = source.readDartTypeNodes();
source.end(tag);
return _GenericInstantiation(expressionType, typeArguments);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(expressionType);
sink.writeDartTypeNodes(typeArguments);
sink.end(tag);
}
}
class _StaticAccess {
static const String tag = '_StaticAccess';
final ir.Member target;
final ir.LibraryDependency? import;
_StaticAccess(this.target, this.import);
factory _StaticAccess.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.Member target = source.readMemberNode();
ir.LibraryDependency? import = source.readLibraryDependencyNodeOrNull();
source.end(tag);
return _StaticAccess(target, import);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeMemberNode(target);
sink.writeLibraryDependencyNodeOrNull(import);
sink.end(tag);
}
}
class _MapLiteral {
static const String tag = '_MapLiteral';
final ir.DartType keyType;
final ir.DartType valueType;
final bool isConst;
final bool isEmpty;
_MapLiteral(this.keyType, this.valueType,
{required this.isConst, required this.isEmpty});
factory _MapLiteral.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType keyType = source.readDartTypeNode();
ir.DartType valueType = source.readDartTypeNode();
bool isConst = source.readBool();
bool isEmpty = source.readBool();
source.end(tag);
return _MapLiteral(keyType, valueType, isConst: isConst, isEmpty: isEmpty);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(keyType);
sink.writeDartTypeNode(valueType);
sink.writeBool(isConst);
sink.writeBool(isEmpty);
sink.end(tag);
}
}
class _ContainerLiteral {
static const String tag = '_ContainerLiteral';
final ir.DartType elementType;
final bool isConst;
final bool isEmpty;
_ContainerLiteral(this.elementType,
{required this.isConst, required this.isEmpty});
factory _ContainerLiteral.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType elementType = source.readDartTypeNode();
bool isConst = source.readBool();
bool isEmpty = source.readBool();
source.end(tag);
return _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(elementType);
sink.writeBool(isConst);
sink.writeBool(isEmpty);
sink.end(tag);
}
}
class _RuntimeTypeUse {
static const String tag = '_RuntimeTypeUse';
final RuntimeTypeUseKind kind;
final ir.DartType receiverType;
final ir.DartType? argumentType;
_RuntimeTypeUse(this.kind, this.receiverType, this.argumentType);
factory _RuntimeTypeUse.fromDataSource(DataSourceReader source) {
source.begin(tag);
RuntimeTypeUseKind kind = source.readEnum(RuntimeTypeUseKind.values);
ir.DartType receiverType = source.readDartTypeNode();
ir.DartType? argumentType = source.readDartTypeNodeOrNull();
source.end(tag);
return _RuntimeTypeUse(kind, receiverType, argumentType);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeEnum(kind);
sink.writeDartTypeNode(receiverType);
sink.writeDartTypeNodeOrNull(argumentType);
sink.end(tag);
}
}
class _ForInData {
static const String tag = '_ForInData';
final ir.DartType iterableType;
final ir.DartType iteratorType;
final ClassRelation iteratorClassRelation;
final bool isAsync;
_ForInData(this.iterableType, this.iteratorType, this.iteratorClassRelation,
{required this.isAsync});
factory _ForInData.fromDataSource(DataSourceReader source) {
source.begin(tag);
ir.DartType iterableType = source.readDartTypeNode();
ir.DartType iteratorType = source.readDartTypeNode();
ClassRelation iteratorClassRelation = source.readEnum(ClassRelation.values);
bool isAsync = source.readBool();
source.end(tag);
return _ForInData(iterableType, iteratorType, iteratorClassRelation,
isAsync: isAsync);
}
void toDataSink(DataSinkWriter sink) {
sink.begin(tag);
sink.writeDartTypeNode(iteratorType);
sink.writeDartTypeNode(iteratorType);
sink.writeEnum(iteratorClassRelation);
sink.writeBool(isAsync);
sink.end(tag);
}
}