// 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' show KernelToElementMap;
import '../options.dart';
import '../serialization/serialization_interfaces.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 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
  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) {
    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
  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>();
    _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.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, 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.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,
      {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);
  }
}
