| // 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. |
| |
| // @dart = 2.10 |
| |
| 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.dart'; |
| import '../options.dart'; |
| import '../serialization/serialization.dart'; |
| import '../util/enumset.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 KernelToElementMap _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.Member target, ir.DartType resultType) { |
| assert(target is ir.Procedure && 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 |
| Null 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) { |
| if (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, |
| node.target, |
| node.arguments.positional.length, |
| _getNamedArguments(node.arguments), |
| node.arguments.types); |
| } |
| |
| @override |
| Null 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) { |
| ir.LibraryDependency import = getDeferredImport(node); |
| ConstantImpactVisitor(this, import, node, staticTypeContext) |
| .visitConstant(node.constant); |
| } |
| |
| void _registerFeature(_Feature feature) { |
| _data._features ??= EnumSet<_Feature>(); |
| _data._features.add(feature); |
| } |
| |
| void _registerTypeUse(ir.DartType type, _TypeUseKind kind) { |
| _data._typeUses ??= []; |
| _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 ??= []; |
| _data._superInitializers.add(_SuperInitializer(source, target, |
| _CallStructure(positionalArguments, namedArguments, typeArguments))); |
| } |
| |
| @override |
| void registerSuperSet(ir.Member target) { |
| _data._superSets ??= []; |
| _data._superSets.add(target); |
| } |
| |
| @override |
| void registerSuperGet(ir.Member target) { |
| _data._superGets ??= []; |
| _data._superGets.add(target); |
| } |
| |
| @override |
| void registerSuperInvocation(ir.Member target, int positionalArguments, |
| List<String> namedArguments, List<ir.DartType> typeArguments) { |
| _data._superInvocations ??= []; |
| _data._superInvocations.add(_SuperInvocation(target, |
| _CallStructure(positionalArguments, namedArguments, typeArguments))); |
| } |
| |
| @override |
| void registerInstanceSet( |
| ir.DartType receiverType, ClassRelation relation, ir.Member target) { |
| _data._instanceSets ??= []; |
| _data._instanceSets.add(_InstanceAccess(receiverType, relation, target)); |
| } |
| |
| @override |
| void registerDynamicSet( |
| ir.DartType receiverType, ClassRelation relation, ir.Name name) { |
| _data._dynamicSets ??= []; |
| _data._dynamicSets.add(_DynamicAccess(receiverType, relation, name)); |
| } |
| |
| @override |
| void registerInstanceGet( |
| ir.DartType receiverType, ClassRelation relation, ir.Member target) { |
| _data._instanceGets ??= []; |
| _data._instanceGets.add(_InstanceAccess(receiverType, relation, target)); |
| } |
| |
| @override |
| void registerDynamicGet( |
| ir.DartType receiverType, ClassRelation relation, ir.Name name) { |
| _data._dynamicGets ??= []; |
| _data._dynamicGets.add(_DynamicAccess(receiverType, relation, name)); |
| } |
| |
| @override |
| void registerFunctionInvocation( |
| ir.DartType receiverType, |
| int positionalArguments, |
| List<String> namedArguments, |
| List<ir.DartType> typeArguments) { |
| _data._functionInvocations ??= []; |
| _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 ??= []; |
| _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 ??= []; |
| _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 ??= []; |
| _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 ??= []; |
| _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, |
| {bool isConst}) { |
| _data._constructorInvocations ??= []; |
| _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 ??= []; |
| _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 ??= []; |
| _data._redirectingInitializers.add(_RedirectingInitializer(constructor, |
| _CallStructure(positionalArguments, namedArguments, typeArguments))); |
| } |
| |
| @override |
| void registerLoadLibrary() { |
| _registerFeature(_Feature.loadLibrary); |
| } |
| |
| @override |
| void registerFieldInitialization(ir.Field node) { |
| _data._fieldInitializers ??= []; |
| _data._fieldInitializers.add(node); |
| } |
| |
| @override |
| void registerFieldConstantInitialization( |
| ir.Field node, ConstantReference constant) { |
| _data._fieldConstantInitializers ??= {}; |
| _data._fieldConstantInitializers.putIfAbsent(node, () => []).add(constant); |
| } |
| |
| @override |
| void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import) { |
| _data._typeLiterals ??= []; |
| _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 ??= []; |
| _data._forInData.add(_ForInData( |
| iterableType, iteratorType, iteratorClassRelation, |
| isAsync: true)); |
| } |
| |
| @override |
| void registerSyncForIn(ir.DartType iterableType, ir.DartType iteratorType, |
| ClassRelation iteratorClassRelation) { |
| _data._forInData ??= []; |
| _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 ??= []; |
| _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 ??= []; |
| _data._genericInstantiations |
| .add(_GenericInstantiation(expressionType, typeArguments)); |
| } |
| |
| @override |
| void registerAssert({bool withMessage}) { |
| _registerFeature(withMessage |
| ? _Feature.assertWithMessage |
| : _Feature.assertWithoutMessage); |
| } |
| |
| @override |
| void registerStaticSet(ir.Member member, ir.LibraryDependency import) { |
| _data._staticSets ??= []; |
| _data._staticSets.add(_StaticAccess(member, import)); |
| } |
| |
| @override |
| void registerStaticGet(ir.Member member, ir.LibraryDependency import) { |
| _data._staticGets ??= []; |
| _data._staticGets.add(_StaticAccess(member, import)); |
| } |
| |
| @override |
| void registerStaticTearOff( |
| ir.Procedure procedure, ir.LibraryDependency import) { |
| _data._staticTearOffs ??= []; |
| _data._staticTearOffs.add(_StaticAccess(procedure, import)); |
| } |
| |
| @override |
| void registerMapLiteral(ir.DartType keyType, ir.DartType valueType, |
| {bool isConst, bool isEmpty}) { |
| _data._mapLiterals ??= []; |
| _data._mapLiterals.add( |
| _MapLiteral(keyType, valueType, isConst: isConst, isEmpty: isEmpty)); |
| } |
| |
| @override |
| void registerListLiteral(ir.DartType elementType, |
| {bool isConst, bool isEmpty}) { |
| _data._listLiterals ??= []; |
| _data._listLiterals.add( |
| _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty)); |
| } |
| |
| @override |
| void registerSetLiteral(ir.DartType elementType, |
| {bool isConst, bool isEmpty}) { |
| _data._setLiterals ??= []; |
| _data._setLiterals.add( |
| _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty)); |
| } |
| |
| @override |
| void registerNullLiteral() { |
| _registerFeature(_Feature.nullLiteral); |
| } |
| |
| @override |
| void registerSymbolLiteral(String value) { |
| _data._symbolLiterals ??= {}; |
| _data._symbolLiterals.add(value); |
| } |
| |
| @override |
| void registerStringLiteral(String value) { |
| _data._stringLiterals ??= {}; |
| _data._stringLiterals.add(value); |
| } |
| |
| @override |
| void registerBoolLiteral(bool value) { |
| _data._boolLiterals ??= {}; |
| _data._boolLiterals.add(value); |
| } |
| |
| @override |
| void registerDoubleLiteral(double value) { |
| _data._doubleLiterals ??= {}; |
| _data._doubleLiterals.add(value); |
| } |
| |
| @override |
| void registerIntLiteral(int value) { |
| _data._intLiterals ??= {}; |
| _data._intLiterals.add(value); |
| } |
| |
| @override |
| void registerRuntimeTypeUse(RuntimeTypeUseKind kind, ir.DartType receiverType, |
| ir.DartType argumentType) { |
| _data._runtimeTypeUses ??= []; |
| _data._runtimeTypeUses |
| .add(_RuntimeTypeUse(kind, receiverType, argumentType)); |
| } |
| |
| @override |
| void registerConstructorNode(ir.Constructor node) { |
| _data._constructorNodes ??= []; |
| _data._constructorNodes.add(node); |
| } |
| |
| @override |
| void registerFieldNode(ir.Field node) { |
| _data._fieldNodes ??= []; |
| _data._fieldNodes.add(node); |
| } |
| |
| @override |
| void registerProcedureNode(ir.Procedure node) { |
| _data._procedureNodes ??= []; |
| _data._procedureNodes.add(node); |
| } |
| |
| @override |
| void registerStaticInvocationNode(ir.StaticInvocation node) { |
| _data._staticInvocationNodes ??= []; |
| _data._staticInvocationNodes.add(node); |
| } |
| |
| @override |
| void registerSwitchStatementNode(ir.SwitchStatement node) { |
| _data._switchStatementNodes ??= []; |
| _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.readList( |
| () => _SuperInitializer.fromDataSource(source), |
| emptyAsNull: true); |
| _superSets = |
| source.readList(() => source.readMemberNode(), emptyAsNull: true); |
| _superGets = |
| source.readList(() => source.readMemberNode(), emptyAsNull: true); |
| _superInvocations = source.readList( |
| () => _SuperInvocation.fromDataSource(source), |
| emptyAsNull: true); |
| _instanceSets = source.readList( |
| () => _InstanceAccess.fromDataSource(source), |
| emptyAsNull: true); |
| _dynamicSets = source.readList(() => _DynamicAccess.fromDataSource(source), |
| emptyAsNull: true); |
| _instanceGets = source.readList( |
| () => _InstanceAccess.fromDataSource(source), |
| emptyAsNull: true); |
| _dynamicGets = source.readList(() => _DynamicAccess.fromDataSource(source), |
| emptyAsNull: true); |
| _functionInvocations = source.readList( |
| () => _FunctionInvocation.fromDataSource(source), |
| emptyAsNull: true); |
| _instanceInvocations = source.readList( |
| () => _InstanceInvocation.fromDataSource(source), |
| emptyAsNull: true); |
| _dynamicInvocations = source.readList( |
| () => _DynamicInvocation.fromDataSource(source), |
| emptyAsNull: true); |
| _localFunctionInvocations = source.readList( |
| () => _LocalFunctionInvocation.fromDataSource(source), |
| emptyAsNull: true); |
| _staticInvocations = source.readList( |
| () => _StaticInvocation.fromDataSource(source), |
| emptyAsNull: true); |
| _constructorInvocations = source.readList( |
| () => _ConstructorInvocation.fromDataSource(source), |
| emptyAsNull: true); |
| _features = EnumSet<_Feature>.fromValue(source.readInt()); |
| _typeUses = source.readList(() => _TypeUse.fromDataSource(source), |
| emptyAsNull: true); |
| _redirectingInitializers = source.readList( |
| () => _RedirectingInitializer.fromDataSource(source), |
| emptyAsNull: true); |
| _fieldInitializers = source.readMemberNodes<ir.Field>(emptyAsNull: true); |
| _fieldConstantInitializers = |
| source.readMemberNodeMap(source.readTreeNodes, emptyAsNull: true); |
| _typeLiterals = source.readList(() => _TypeLiteral.fromDataSource(source), |
| emptyAsNull: true); |
| _localFunctions = source.readTreeNodes(emptyAsNull: true); |
| _genericInstantiations = source.readList( |
| () => _GenericInstantiation.fromDataSource(source), |
| emptyAsNull: true); |
| _staticSets = source.readList(() => _StaticAccess.fromDataSource(source), |
| emptyAsNull: true); |
| _staticGets = source.readList(() => _StaticAccess.fromDataSource(source), |
| emptyAsNull: true); |
| _staticTearOffs = source.readList( |
| () => _StaticAccess.fromDataSource(source), |
| emptyAsNull: true); |
| _mapLiterals = source.readList(() => _MapLiteral.fromDataSource(source), |
| emptyAsNull: true); |
| _listLiterals = source.readList( |
| () => _ContainerLiteral.fromDataSource(source), |
| emptyAsNull: true); |
| _setLiterals = source.readList( |
| () => _ContainerLiteral.fromDataSource(source), |
| emptyAsNull: true); |
| _symbolLiterals = source.readStrings(emptyAsNull: true)?.toSet(); |
| _stringLiterals = source.readStrings(emptyAsNull: true)?.toSet(); |
| _boolLiterals = |
| source.readList(() => source.readBool(), emptyAsNull: true)?.toSet(); |
| _doubleLiterals = source |
| .readList(() => source.readDoubleValue(), emptyAsNull: true) |
| ?.toSet(); |
| _intLiterals = source |
| .readList(() => source.readIntegerValue(), emptyAsNull: true) |
| ?.toSet(); |
| _runtimeTypeUses = source.readList( |
| () => _RuntimeTypeUse.fromDataSource(source), |
| emptyAsNull: true); |
| |
| // TODO(johnniwinther): Remove these when CFE provides constants. |
| _constructorNodes = |
| source.readMemberNodes<ir.Constructor>(emptyAsNull: true); |
| _fieldNodes = source.readMemberNodes<ir.Field>(emptyAsNull: true); |
| _procedureNodes = source.readMemberNodes<ir.Procedure>(emptyAsNull: true); |
| _switchStatementNodes = |
| source.readTreeNodes<ir.SwitchStatement>(emptyAsNull: true); |
| _staticInvocationNodes = |
| source.readTreeNodes<ir.StaticInvocation>(emptyAsNull: true); |
| _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.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, 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(); |
| 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(); |
| ir.Constructor targetConstructor = source.readMemberNode(); |
| _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(); |
| _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(); |
| _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, |
| {this.isConst}); |
| |
| factory _ConstructorInvocation.fromDataSource(DataSourceReader source) { |
| source.begin(tag); |
| ir.Member constructor = source.readMemberNode(); |
| ir.InterfaceType type = source.readDartTypeNode(); |
| _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(); |
| _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(); |
| 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, {this.isConst, 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, {this.isConst, 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.readDartTypeNode(allowNull: true); |
| source.end(tag); |
| return _RuntimeTypeUse(kind, receiverType, argumentType); |
| } |
| |
| void toDataSink(DataSinkWriter sink) { |
| sink.begin(tag); |
| sink.writeEnum(kind); |
| sink.writeDartTypeNode(receiverType); |
| sink.writeDartTypeNode(argumentType, allowNull: true); |
| sink.end(tag); |
| } |
| } |
| |
| class _ForInData { |
| final ir.DartType iterableType; |
| final ir.DartType iteratorType; |
| final ClassRelation iteratorClassRelation; |
| final bool isAsync; |
| |
| _ForInData(this.iterableType, this.iteratorType, this.iteratorClassRelation, |
| {this.isAsync}); |
| } |