// 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.

// ignore: implementation_imports
import 'package:front_end/src/api_prototype/static_weak_references.dart'
    as ir
    show StaticWeakReferences;
// ignore: implementation_imports
import 'package:front_end/src/api_unstable/dart2js.dart' show Operator;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import 'package:kernel/type_algebra.dart' as ir;

import '../common.dart';
import '../common/elements.dart';
import '../common/names.dart' show Identifiers, Uris;
import '../elements/entities.dart';
import '../elements/types.dart';
import '../kernel/element_map.dart';
import '../options.dart';
import '../util/enumset.dart';
import 'constants.dart';
import 'impact.dart';
import 'protobuf_impacts.dart';
import 'runtime_type_analysis.dart';
import 'util.dart';

/// Checks [node] against available [ConditionalImpactHandler] to see if any
/// are applicable to it. Returns null if there is no matching handler.
ConditionalImpactHandler? _getConditionalImpactHandler(
  KernelToElementMap elementMap,
  ir.Member node,
) {
  return ProtobufImpactHandler.createIfApplicable(elementMap, node);
}

abstract class ConditionalImpactHandler {
  /// Invoked before children of [node] are analyzed. Returns a temporary
  /// [ImpactData] if one should be used for the scope of [node] or null
  /// otherwise.
  ImpactData? beforeInstanceInvocation(ir.InstanceInvocation node);

  /// Invoked after children of [node] are analyzed. Returns a
  /// [ConditionalImpactData] containing the conditional data to register for
  /// [node]. Returns null if [node] is not relevant to this handler.
  ConditionalImpactData? afterInstanceInvocation(ir.InstanceInvocation node);
}

class _ConditionalImpactBuilder extends ImpactBuilder {
  final ConditionalImpactHandler _conditionalHandler;

  _ConditionalImpactBuilder._(
    super.elementMap,
    super.node,
    this._conditionalHandler,
  ) : super._();

  @override
  void visitInstanceInvocation(ir.InstanceInvocation node) {
    final oldData = _data;
    _data = _conditionalHandler.beforeInstanceInvocation(node) ?? _data;

    super.visitInstanceInvocation(node);

    final conditionalData = _conditionalHandler.afterInstanceInvocation(node);
    if (conditionalData != null) {
      final replacement = conditionalData.replacement;
      if (replacement != null) {
        final replacementImpact = _data = ImpactData();
        replacement.accept(this);
        conditionalData.replacementImpactData = replacementImpact;
      }
      _data = oldData;
      registerConditionalImpact(conditionalData);
    } else {
      _data = oldData;
    }
  }
}

/// Visitor that builds an [ImpactData] object for the world impact.
class ImpactBuilder extends ir.RecursiveVisitor implements ImpactRegistry {
  ImpactData _data = ImpactData();
  final ir.Member node;
  final KernelToElementMap _elementMap;
  final ir.StaticTypeContext staticTypeContext;

  factory ImpactBuilder(KernelToElementMap elementMap, ir.Member node) {
    final conditionalHandler = _getConditionalImpactHandler(elementMap, node);

    return conditionalHandler != null
        ? _ConditionalImpactBuilder._(elementMap, node, conditionalHandler)
        : ImpactBuilder._(elementMap, node);
  }

  ImpactBuilder._(this._elementMap, this.node)
    : staticTypeContext = ir.StaticTypeContext(
        node,
        _elementMap.typeEnvironment,
      );

  CommonElements get _commonElements => _elementMap.commonElements;
  DiagnosticReporter get _reporter => _elementMap.reporter;
  ir.ClassHierarchy get classHierarchy => _elementMap.classHierarchy;
  ir.TypeEnvironment get typeEnvironment => _elementMap.typeEnvironment;
  CompilerOptions get _options => _elementMap.options;

  String _typeToString(DartType type) =>
      type.toStructuredText(_elementMap.types, _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() {
    node.accept(this);
    return ImpactBuilderData(node, _data);
  }

  @override
  void visitBlock(ir.Block node) {
    assert(
      _pendingRuntimeTypeUseData.isEmpty,
      "Incomplete RuntimeTypeUseData: $_pendingRuntimeTypeUseData",
    );
    for (var e in node.statements) {
      e.accept(this);
    }
    assert(
      _pendingRuntimeTypeUseData.isEmpty,
      "Incomplete RuntimeTypeUseData: $_pendingRuntimeTypeUseData",
    );
  }

  @override
  void visitIntLiteral(ir.IntLiteral node) {
    registerIntLiteral();
  }

  @override
  void visitDoubleLiteral(ir.DoubleLiteral node) {
    registerDoubleLiteral();
  }

  @override
  void visitBoolLiteral(ir.BoolLiteral node) {
    registerBoolLiteral();
  }

  @override
  void visitStringLiteral(ir.StringLiteral node) {
    registerStringLiteral();
  }

  @override
  void visitSymbolLiteral(ir.SymbolLiteral node) {
    registerSymbolLiteral();
  }

  @override
  void visitNullLiteral(ir.NullLiteral node) {
    registerNullLiteral();
  }

  @override
  void visitListLiteral(ir.ListLiteral node) {
    registerListLiteral(
      node.typeArgument,
      isConst: node.isConst,
      isEmpty: node.expressions.isEmpty,
    );
    for (var e in node.expressions) {
      e.accept(this);
    }
  }

  @override
  void visitSetLiteral(ir.SetLiteral node) {
    registerSetLiteral(
      node.typeArgument,
      isConst: node.isConst,
      isEmpty: node.expressions.isEmpty,
    );
    for (var e in node.expressions) {
      e.accept(this);
    }
  }

  @override
  void visitMapLiteral(ir.MapLiteral node) {
    registerMapLiteral(
      node.keyType,
      node.valueType,
      isConst: node.isConst,
      isEmpty: node.entries.isEmpty,
    );
    for (var e in node.entries) {
      e.accept(this);
    }
  }

  @override
  void visitRecordLiteral(ir.RecordLiteral node) {
    registerRecordLiteral(node.recordType, isConst: node.isConst);
    for (var e in node.positional) {
      e.accept(this);
    }
    for (var e in node.named) {
      e.value.accept(this);
    }
  }

  @override
  void visitStaticGet(ir.StaticGet node) {
    registerStaticGet(node.target, getDeferredImport(node));
  }

  @override
  void visitStaticTearOff(ir.StaticTearOff node) {
    registerStaticTearOff(node.target, getDeferredImport(node));
  }

  @override
  void visitStaticSet(ir.StaticSet node) {
    registerStaticSet(node.target, getDeferredImport(node));
    node.value.accept(this);
  }

  @override
  void visitAssertStatement(ir.AssertStatement node) {
    registerAssert(withMessage: node.message != null);
    node.condition.accept(this);
    node.message?.accept(this);
  }

  @override
  void visitInstantiation(ir.Instantiation node) {
    registerGenericInstantiation(
      node.expression.getStaticType(staticTypeContext) as ir.FunctionType,
      node.typeArguments,
    );
    node.expression.accept(this);
  }

  void handleAsyncMarker(ir.FunctionNode function) {
    switch (function.asyncMarker) {
      case ir.AsyncMarker.Sync:
        break;

      case ir.AsyncMarker.SyncStar:
        registerSyncStar(function.emittedValueType!);
        break;

      case ir.AsyncMarker.Async:
        registerAsync(function.emittedValueType!);
        break;

      case ir.AsyncMarker.AsyncStar:
        registerAsyncStar(function.emittedValueType!);
        break;
    }
  }

  @override
  void visitStringConcatenation(ir.StringConcatenation node) {
    registerStringConcatenation();
    for (var e in node.expressions) {
      e.accept(this);
    }
  }

  @override
  void visitFunctionDeclaration(ir.FunctionDeclaration node) {
    registerLocalFunction(node);
    node.function.accept(this);
  }

  @override
  void visitFunctionExpression(ir.FunctionExpression node) {
    registerLocalFunction(node);
    node.function.accept(this);
  }

  @override
  void visitVariableDeclaration(ir.VariableDeclaration node) {
    if (node.initializer == null) {
      registerLocalWithoutInitializer();
    }
    // Don't visit the annotations as any impacts generated by that code are not
    // real and should not be included in compiled code.
    node.initializer?.accept(this);
  }

  @override
  void visitIsExpression(ir.IsExpression node) {
    registerIsCheck(node.type);
    node.operand.accept(this);
  }

  @override
  void visitAsExpression(ir.AsExpression node) {
    final operandType = node.operand.getStaticType(staticTypeContext);
    final isCalculatedTypeSubtype = typeEnvironment.isSubtypeOf(
      operandType,
      node.type,
      ir.SubtypeCheckMode.withNullabilities,
    );
    if (!isCalculatedTypeSubtype) {
      // Only register needed cast.
      if (node.isTypeError) {
        registerImplicitCast(node.type);
      } else {
        registerAsCast(node.type);
      }
    }
    node.operand.accept(this);
  }

  @override
  void visitThrow(ir.Throw node) {
    registerThrow();
    node.expression.accept(this);
  }

  ir.InterfaceType? getInterfaceTypeOf(ir.DartType type) {
    while (type is ir.TypeParameterType) {
      type = type.parameter.bound;
    }
    if (type is ir.InterfaceType) {
      return type;
    } else if (type is ir.NullType) {
      return typeEnvironment.coreTypes.deprecatedNullType;
    }
    return null;
  }

  @override
  void visitForInStatement(ir.ForInStatement node) {
    // TODO(fishythefish): Clean up this logic.
    ir.DartType iterableType = node.iterable.getStaticType(staticTypeContext);
    ir.DartType iteratorType = const ir.DynamicType();
    ir.InterfaceType? iterableInterfaceType = getInterfaceTypeOf(iterableType);
    if (iterableInterfaceType != null) {
      if (node.isAsync) {
        List<ir.DartType>? typeArguments = typeEnvironment
            .getTypeArgumentsAsInstanceOf(
              iterableInterfaceType,
              typeEnvironment.coreTypes.streamClass,
            );
        if (typeArguments != null) {
          iteratorType = ir.InterfaceType(
            typeEnvironment.coreTypes.streamIteratorClass,
            ir.Nullability.nonNullable,
            typeArguments,
          );
        }
      } else {
        ir.Member? member = classHierarchy.getInterfaceMember(
          iterableInterfaceType.classNode,
          ir.Name(Identifiers.iterator),
        );
        if (member != null) {
          iteratorType = ir.Substitution.fromTypeDeclarationType(
            typeEnvironment.getTypeAsInstanceOf(
              iterableInterfaceType,
              member.enclosingClass!,
              typeEnvironment.coreTypes,
            )!,
          ).substituteType(member.getterType);
        }
      }
    }
    if (node.isAsync) {
      registerAsyncForIn(iterableType, iteratorType);
    } else {
      registerSyncForIn(iterableType, iteratorType);
    }
    node.iterable.accept(this);
    node.variable.accept(this);
    node.body.accept(this);
  }

  @override
  void visitCatch(ir.Catch node) {
    registerCatch();
    if (node.stackTrace != null) {
      registerStackTrace();
    }
    if (node.guard is! ir.DynamicType) {
      registerCatchType(node.guard);
    }
    node.body.accept(this);
  }

  @override
  void visitTypeLiteral(ir.TypeLiteral node) {
    registerTypeLiteral(node.type, getDeferredImport(node));
  }

  @override
  void visitFieldInitializer(ir.FieldInitializer node) {
    registerFieldInitialization(node.field);
    node.value.accept(this);
  }

  @override
  void visitLoadLibrary(ir.LoadLibrary node) {
    registerLoadLibrary();
  }

  @override
  void visitRedirectingInitializer(ir.RedirectingInitializer node) {
    registerRedirectingInitializer(
      node.target,
      node.arguments.positional.length,
      _getNamedArguments(node.arguments),
      node.arguments.types,
    );
    node.arguments.accept(this);
  }

  @override
  void visitFunctionNode(ir.FunctionNode node) {
    handleAsyncMarker(node);
    for (ir.TypeParameter parameter in node.typeParameters) {
      registerParameterCheck(parameter.bound);
    }
    for (ir.VariableDeclaration parameter in node.positionalParameters) {
      registerParameterCheck(parameter.type);
      parameter.initializer?.accept(this);
    }
    for (ir.VariableDeclaration parameter in node.namedParameters) {
      registerParameterCheck(parameter.type);
      parameter.initializer?.accept(this);
    }
    node.body?.accept(this);
  }

  @override
  void visitConstructor(ir.Constructor node) {
    if (node.isExternal) registerExternalConstructorNode(node);
    // Don't visit the annotations as any impacts generated by that code are not
    // real and should not be included in compiled code.
    for (var e in node.initializers) {
      e.accept(this);
    }
    node.function.accept(this);
  }

  @override
  void visitField(ir.Field node) {
    registerParameterCheck(node.type);
    if (node.initializer != null) {
      if (!node.isInstanceMember &&
          !node.isConst &&
          node.initializer is! ir.NullLiteral) {
        registerLazyField();
      }
    } else {
      registerNullLiteral();
    }
    // TODO(sigmund): only save relevant fields (e.g. those for jsinterop
    // or native types).
    registerFieldNode(node);
    // Don't visit the annotations as any impacts generated by that code are not
    // real and should not be included in compiled code.
    node.initializer?.accept(this);
  }

  @override
  void visitProcedure(ir.Procedure node) {
    if (node.isExternal) registerExternalProcedureNode(node);
    // Don't visit the annotations as any impacts generated by that code are not
    // real and should not be included in compiled code.
    node.function.accept(this);
  }

  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(
          currentElementSpannable,
          MessageKind.stringExpected,
          {'type': _typeToString(argumentType)},
        );
        return;
      }
      registerConstSymbolConstructorInvocationNode();
    }
  }

  @override
  void visitConstructorInvocation(ir.ConstructorInvocation node) {
    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);
    }
    node.arguments.accept(this);
  }

  @override
  void visitStaticInvocation(ir.StaticInvocation node) {
    if (ir.StaticWeakReferences.isWeakReference(node)) {
      registerWeakStaticTearOff(
        ir.StaticWeakReferences.getWeakReferenceTarget(node),
        getDeferredImport(
          ir.StaticWeakReferences.getWeakReferenceArgument(node),
        ),
      );
      // We don't explicitly visit the argument for weak references.
    } else {
      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() => 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),
        );
      }
      // TODO(sigmund): consider using `_elementMap.getForeignKind` here. We
      // currently don't use it because when this step is run modularly we try
      // to keep most operations at the kernel level, otherwise it may triggers
      // additional unnecessary work.
      final name = node.target.name.text;
      if (node.target.enclosingClass == null &&
          node.target.enclosingLibrary.importUri == Uris.dartForeignHelper &&
          getForeignKindFromName(name) != ForeignKind.none) {
        registerForeignStaticInvocationNode(node);
      }
      node.arguments.accept(this);
    }
  }

  @override
  void visitDynamicInvocation(ir.DynamicInvocation node) {
    int positionArguments = node.arguments.positional.length;
    List<String> namedArguments = _getNamedArguments(node.arguments);
    List<ir.DartType> typeArguments = node.arguments.types;
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    registerDynamicInvocation(
      receiverType,
      node.name,
      positionArguments,
      namedArguments,
      typeArguments,
    );
    if (Operator.fromText(node.name.text) == null &&
        receiverType is ir.DynamicType) {
      // We might implicitly call a getter that returns a function.
      registerFunctionInvocation(
        const ir.DynamicType(),
        positionArguments,
        namedArguments,
        typeArguments,
      );
    }
    node.arguments.accept(this);
    node.receiver.accept(this);
  }

  @override
  void visitFunctionInvocation(ir.FunctionInvocation node) {
    int positionArguments = node.arguments.positional.length;
    List<String> namedArguments = _getNamedArguments(node.arguments);
    List<ir.DartType> typeArguments = node.arguments.types;
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    registerFunctionInvocation(
      receiverType,
      positionArguments,
      namedArguments,
      typeArguments,
    );
    node.arguments.accept(this);
    node.receiver.accept(this);
  }

  @override
  void visitInstanceInvocation(ir.InstanceInvocation node) {
    int positionArguments = node.arguments.positional.length;
    List<String> namedArguments = _getNamedArguments(node.arguments);
    List<ir.DartType> typeArguments = node.arguments.types;
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    final interfaceTarget = node.interfaceTarget;

    if (interfaceTarget.kind == ir.ProcedureKind.Getter) {
      registerInstanceInvocation(
        receiverType,
        interfaceTarget,
        positionArguments,
        namedArguments,
        typeArguments,
      );
      registerFunctionInvocation(
        interfaceTarget.getterType,
        positionArguments,
        namedArguments,
        typeArguments,
      );
    } else {
      registerInstanceInvocation(
        receiverType,
        interfaceTarget,
        positionArguments,
        namedArguments,
        typeArguments,
      );
    }
    node.arguments.accept(this);
    node.receiver.accept(this);
  }

  @override
  void visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) {
    int positionArguments = node.arguments.positional.length;
    List<String> namedArguments = _getNamedArguments(node.arguments);
    List<ir.DartType> typeArguments = node.arguments.types;
    registerLocalFunctionInvocation(
      node.localFunction,
      positionArguments,
      namedArguments,
      typeArguments,
    );
    node.arguments.accept(this);
  }

  @override
  void visitEqualsCall(ir.EqualsCall node) {
    final leftType = node.left.getStaticType(staticTypeContext);
    registerInstanceInvocation(
      leftType,
      node.interfaceTarget,
      1,
      const <String>[],
      const <ir.DartType>[],
    );
    node.left.accept(this);
    node.right.accept(this);
  }

  @override
  void visitEqualsNull(ir.EqualsNull node) {
    registerNullLiteral();
    node.expression.accept(this);
  }

  @override
  void visitDynamicGet(ir.DynamicGet node) {
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    registerDynamicGet(receiverType, node.name);
    node.receiver.accept(this);
  }

  @override
  void visitInstanceGet(ir.InstanceGet node) {
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    registerInstanceGet(receiverType, node.interfaceTarget);
    if (node.name.text == Identifiers.runtimeType_) {
      // This handles `runtimeType` access on non-Never types, like in
      // `'foo'.runtimeType`.
      handleRuntimeTypeGet(receiverType, node);
    }
    node.receiver.accept(this);
  }

  @override
  void visitInstanceTearOff(ir.InstanceTearOff node) {
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    registerInstanceGet(receiverType, node.interfaceTarget);
    assert(
      node.name.text != Identifiers.runtimeType_,
      "Unexpected .runtimeType instance tear-off.",
    );
    node.receiver.accept(this);
  }

  @override
  void visitFunctionTearOff(ir.FunctionTearOff node) {
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    registerDynamicGet(receiverType, ir.Name.callName);
    node.receiver.accept(this);
  }

  @override
  void visitInstanceGetterInvocation(ir.InstanceGetterInvocation node) {
    int positionArguments = node.arguments.positional.length;
    List<String> namedArguments = _getNamedArguments(node.arguments);
    List<ir.DartType> typeArguments = node.arguments.types;
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    final interfaceTarget = node.interfaceTarget;

    if (interfaceTarget is ir.Field ||
        (interfaceTarget is ir.Procedure &&
            interfaceTarget.kind == ir.ProcedureKind.Getter)) {
      registerInstanceInvocation(
        receiverType,
        interfaceTarget,
        positionArguments,
        namedArguments,
        typeArguments,
      );
      registerFunctionInvocation(
        interfaceTarget.getterType,
        positionArguments,
        namedArguments,
        typeArguments,
      );
    } else {
      registerInstanceInvocation(
        receiverType,
        interfaceTarget,
        positionArguments,
        namedArguments,
        typeArguments,
      );
    }
    node.receiver.accept(this);
    node.arguments.accept(this);
  }

  @override
  void visitDynamicSet(ir.DynamicSet node) {
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    registerDynamicSet(receiverType, node.name);
    node.receiver.accept(this);
    node.value.accept(this);
  }

  @override
  void visitInstanceSet(ir.InstanceSet node) {
    final receiverType = node.receiver.getStaticType(staticTypeContext);
    registerInstanceSet(receiverType, node.interfaceTarget);
    node.receiver.accept(this);
    node.value.accept(this);
  }

  @override
  void visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
    registerSuperInvocation(
      getEffectiveSuperTarget(node.interfaceTarget),
      node.arguments.positional.length,
      _getNamedArguments(node.arguments),
      node.arguments.types,
    );
    node.arguments.accept(this);
  }

  @override
  void visitSuperPropertyGet(ir.SuperPropertyGet node) {
    registerSuperGet(getEffectiveSuperTarget(node.interfaceTarget));
  }

  @override
  void visitSuperPropertySet(ir.SuperPropertySet node) {
    registerSuperSet(getEffectiveSuperTarget(node.interfaceTarget));
    node.value.accept(this);
  }

  @override
  void visitSuperInitializer(ir.SuperInitializer node) {
    registerSuperInitializer(
      node.parent as ir.Constructor,
      node.target,
      node.arguments.positional.length,
      _getNamedArguments(node.arguments),
      node.arguments.types,
    );
    node.arguments.accept(this);
  }

  final Map<ir.InstanceGet, RuntimeTypeUseData> _pendingRuntimeTypeUseData = {};

  void handleRuntimeTypeGet(ir.DartType receiverType, ir.InstanceGet node) {
    RuntimeTypeUseData data = computeRuntimeTypeUse(
      _pendingRuntimeTypeUseData,
      node,
    );
    if (data.leftRuntimeTypeExpression == node) {
      // [node] is the left (or single) occurrence of `.runtimeType` so we
      // can set the static type of the receiver expression.
      data.receiverType = receiverType;
    } else {
      // [node] is the right occurrence of `.runtimeType` so we
      // can set the static type of the argument expression.
      assert(
        data.rightRuntimeTypeExpression == node,
        "Unexpected RuntimeTypeUseData for $node: $data",
      );
      data.argumentType = receiverType;
    }
    if (data.isComplete) {
      /// We now have all need static types so we can remove the data from
      /// the cache and handle the runtime type use.
      _pendingRuntimeTypeUseData.remove(data.leftRuntimeTypeExpression);
      if (data.rightRuntimeTypeExpression != null) {
        _pendingRuntimeTypeUseData.remove(data.rightRuntimeTypeExpression);
      }
      handleRuntimeTypeUse(
        node,
        data.kind,
        data.receiverType!,
        data.argumentType,
      );
    }
  }

  void handleRuntimeTypeUse(
    ir.Expression node,
    RuntimeTypeUseKind kind,
    ir.DartType receiverType,
    ir.DartType? argumentType,
  ) {
    if (_options.omitImplicitChecks) {
      switch (kind) {
        case RuntimeTypeUseKind.string:
          if (!_options.laxRuntimeTypeToString &&
              // Silent on Golem to avoid excessive compiler diagnostics.
              !_options.benchmarkingProduction) {
            _reporter.reportHintMessage(
              computeSourceSpanFromTreeNode(node),
              MessageKind.runtimeTypeToString,
            );
          }
          break;
        case RuntimeTypeUseKind.equals:
        case RuntimeTypeUseKind.unknown:
          break;
      }
    }
    registerRuntimeTypeUse(kind, receiverType, argumentType);
  }

  @override
  void visitConstantExpression(ir.ConstantExpression node) {
    assert(node.constant is! ir.UnevaluatedConstant);
    ir.LibraryDependency? import = getDeferredImport(node);
    ConstantImpactVisitor(
      this,
      import,
      node,
      staticTypeContext,
    ).visitConstant(node.constant);
  }

  void _registerFeature(_Feature feature) {
    _data._features = _data._features.add(feature);
  }

  void _registerTypeUse(ir.DartType type, _TypeUseKind kind) {
    (_data._typeUses ??= []).add(_TypeUse(type, kind));
  }

  @override
  void registerSuperInitializer(
    ir.Constructor source,
    ir.Constructor target,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    (_data._superInitializers ??= []).add(
      _SuperInitializer(
        source,
        target,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
      ),
    );
  }

  @override
  void registerSuperSet(ir.Member target) {
    (_data._superSets ??= []).add(target);
  }

  @override
  void registerSuperGet(ir.Member target) {
    (_data._superGets ??= []).add(target);
  }

  @override
  void registerSuperInvocation(
    ir.Member target,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    (_data._superInvocations ??= []).add(
      _SuperInvocation(
        target,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
      ),
    );
  }

  @override
  void registerInstanceSet(ir.DartType receiverType, ir.Member target) {
    (_data._instanceSets ??= []).add(_InstanceAccess(receiverType, target));
  }

  @override
  void registerDynamicSet(ir.DartType receiverType, ir.Name name) {
    (_data._dynamicSets ??= []).add(_DynamicAccess(receiverType, name));
  }

  @override
  void registerInstanceGet(ir.DartType receiverType, ir.Member target) {
    (_data._instanceGets ??= []).add(_InstanceAccess(receiverType, target));
  }

  @override
  void registerDynamicGet(ir.DartType receiverType, ir.Name name) {
    (_data._dynamicGets ??= []).add(_DynamicAccess(receiverType, name));
  }

  @override
  void registerFunctionInvocation(
    ir.DartType receiverType,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    (_data._functionInvocations ??= []).add(
      _FunctionInvocation(
        receiverType,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
      ),
    );
  }

  @override
  void registerInstanceInvocation(
    ir.DartType receiverType,
    ir.Member target,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    (_data._instanceInvocations ??= []).add(
      _InstanceInvocation(
        receiverType,
        target,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
      ),
    );
  }

  @override
  void registerDynamicInvocation(
    ir.DartType receiverType,
    ir.Name name,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    (_data._dynamicInvocations ??= []).add(
      _DynamicInvocation(
        receiverType,
        name,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
      ),
    );
  }

  @override
  void registerLocalFunctionInvocation(
    ir.FunctionDeclaration localFunction,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    (_data._localFunctionInvocations ??= []).add(
      _LocalFunctionInvocation(
        localFunction,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
      ),
    );
  }

  @override
  void registerStaticInvocation(
    ir.Procedure target,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
    ir.LibraryDependency? import,
  ) {
    (_data._staticInvocations ??= []).add(
      _StaticInvocation(
        target,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
        import,
      ),
    );
  }

  @override
  void registerNew(
    ir.Member constructor,
    ir.InterfaceType type,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
    ir.LibraryDependency? import, {
    required bool isConst,
  }) {
    (_data._constructorInvocations ??= []).add(
      _ConstructorInvocation(
        constructor,
        type,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
        import,
        isConst: isConst,
      ),
    );
  }

  @override
  void registerConstInstantiation(
    ir.Class cls,
    List<ir.DartType> typeArguments,
    ir.LibraryDependency? import,
  ) {
    (_data._constInstantiations ??= []).add(
      _ConstInstantiation(cls, typeArguments, import),
    );
  }

  @override
  void registerLazyField() {
    _registerFeature(_Feature.lazyField);
  }

  @override
  void registerParameterCheck(ir.DartType type) {
    _registerTypeUse(type, _TypeUseKind.parameterCheck);
  }

  @override
  void registerRedirectingInitializer(
    ir.Constructor constructor,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    (_data._redirectingInitializers ??= []).add(
      _RedirectingInitializer(
        constructor,
        _CallStructure(positionalArguments, namedArguments, typeArguments),
      ),
    );
  }

  @override
  void registerLoadLibrary() {
    _registerFeature(_Feature.loadLibrary);
  }

  @override
  void registerFieldInitialization(ir.Field node) {
    (_data._fieldInitializers ??= []).add(node);
  }

  @override
  void registerFieldConstantInitialization(
    ir.Field node,
    ConstantReference constant,
  ) {
    (_data._fieldConstantInitializers ??= {})
        .putIfAbsent(node, () => [])
        .add(constant);
  }

  @override
  void registerTypeLiteral(ir.DartType type, ir.LibraryDependency? import) {
    (_data._typeLiterals ??= []).add(_TypeLiteral(type, import));
  }

  @override
  void registerCatchType(ir.DartType type) {
    _registerTypeUse(type, _TypeUseKind.catchType);
  }

  @override
  void registerStackTrace() {
    _registerFeature(_Feature.stackTrace);
  }

  @override
  void registerCatch() {
    _registerFeature(_Feature.catchClause);
  }

  @override
  void registerAsyncForIn(ir.DartType iterableType, ir.DartType iteratorType) {
    (_data._forInData ??= []).add(
      _ForInData(iterableType, iteratorType, isAsync: true),
    );
  }

  @override
  void registerSyncForIn(ir.DartType iterableType, ir.DartType iteratorType) {
    (_data._forInData ??= []).add(
      _ForInData(iterableType, iteratorType, isAsync: false),
    );
  }

  @override
  void registerThrow() {
    _registerFeature(_Feature.throwExpression);
  }

  @override
  void registerAsCast(ir.DartType type) {
    _registerTypeUse(type, _TypeUseKind.asCast);
  }

  @override
  void registerImplicitCast(ir.DartType type) {
    _registerTypeUse(type, _TypeUseKind.implicitCast);
  }

  @override
  void registerIsCheck(ir.DartType type) {
    _registerTypeUse(type, _TypeUseKind.isCheck);
  }

  @override
  void registerLocalWithoutInitializer() {
    _registerFeature(_Feature.localWithoutInitializer);
  }

  @override
  void registerLocalFunction(ir.TreeNode node) {
    (_data._localFunctions ??= []).add(node);
  }

  @override
  void registerStringConcatenation() {
    _registerFeature(_Feature.stringConcatenation);
  }

  @override
  void registerAsyncStar(ir.DartType elementType) {
    _registerTypeUse(elementType, _TypeUseKind.asyncStarMarker);
  }

  @override
  void registerAsync(ir.DartType elementType) {
    _registerTypeUse(elementType, _TypeUseKind.asyncMarker);
  }

  @override
  void registerSyncStar(ir.DartType elementType) {
    _registerTypeUse(elementType, _TypeUseKind.syncStarMarker);
  }

  @override
  void registerGenericInstantiation(
    ir.FunctionType expressionType,
    List<ir.DartType> typeArguments,
  ) {
    (_data._genericInstantiations ??= []).add(
      _GenericInstantiation(expressionType, typeArguments),
    );
  }

  @override
  void registerAssert({required bool withMessage}) {
    _registerFeature(
      withMessage ? _Feature.assertWithMessage : _Feature.assertWithoutMessage,
    );
  }

  @override
  void registerStaticSet(ir.Member member, ir.LibraryDependency? import) {
    (_data._staticSets ??= []).add(_StaticAccess(member, import));
  }

  @override
  void registerStaticGet(ir.Member member, ir.LibraryDependency? import) {
    (_data._staticGets ??= []).add(_StaticAccess(member, import));
  }

  @override
  void registerStaticTearOff(
    ir.Procedure procedure,
    ir.LibraryDependency? import,
  ) {
    (_data._staticTearOffs ??= []).add(_StaticAccess(procedure, import));
  }

  @override
  void registerWeakStaticTearOff(
    ir.Procedure procedure,
    ir.LibraryDependency? import,
  ) {
    (_data._weakStaticTearOffs ??= []).add(_StaticAccess(procedure, import));
  }

  @override
  void registerMapLiteral(
    ir.DartType keyType,
    ir.DartType valueType, {
    required bool isConst,
    required bool isEmpty,
  }) {
    (_data._mapLiterals ??= []).add(
      _MapLiteral(keyType, valueType, isConst: isConst, isEmpty: isEmpty),
    );
  }

  @override
  void registerListLiteral(
    ir.DartType elementType, {
    required bool isConst,
    required bool isEmpty,
  }) {
    (_data._listLiterals ??= []).add(
      _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty),
    );
  }

  @override
  void registerSetLiteral(
    ir.DartType elementType, {
    required bool isConst,
    required bool isEmpty,
  }) {
    (_data._setLiterals ??= []).add(
      _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty),
    );
  }

  @override
  void registerRecordLiteral(
    ir.RecordType recordType, {
    required bool isConst,
  }) {
    (_data._recordLiterals ??= []).add(
      _RecordLiteral(recordType, isConst: isConst),
    );
  }

  @override
  void registerNullLiteral() {
    _registerFeature(_Feature.nullLiteral);
  }

  @override
  void registerSymbolLiteral() {
    _registerFeature(_Feature.symbolLiteral);
  }

  @override
  void registerStringLiteral() {
    _registerFeature(_Feature.stringLiteral);
  }

  @override
  void registerBoolLiteral() {
    _registerFeature(_Feature.boolLiteral);
  }

  @override
  void registerDoubleLiteral() {
    _registerFeature(_Feature.doubleLiteral);
  }

  @override
  void registerIntLiteral() {
    _registerFeature(_Feature.intLiteral);
  }

  @override
  void registerRuntimeTypeUse(
    RuntimeTypeUseKind kind,
    ir.DartType receiverType,
    ir.DartType? argumentType,
  ) {
    (_data._runtimeTypeUses ??= []).add(
      _RuntimeTypeUse(kind, receiverType, argumentType),
    );
  }

  @override
  void registerExternalConstructorNode(ir.Constructor node) {
    (_data._externalConstructorNodes ??= []).add(node);
  }

  @override
  void registerFieldNode(ir.Field node) {
    (_data._fieldNodes ??= []).add(node);
  }

  @override
  void registerExternalProcedureNode(ir.Procedure node) {
    (_data._externalProcedureNodes ??= []).add(node);
  }

  @override
  void registerForeignStaticInvocationNode(ir.StaticInvocation node) {
    (_data._foreignStaticInvocationNodes ??= []).add(node);
  }

  @override
  void registerConstSymbolConstructorInvocationNode() {
    _data._hasConstSymbolConstructorInvocation = true;
  }

  @override
  void registerConditionalImpact(ConditionalImpactData impact) {
    // Ensure conditional impact is registered on parent impact, `_data`.
    (_data._conditionalImpacts ??= []).add(impact);
  }
}

class ConditionalImpactData {
  final ir.TreeNode? original;
  final ir.TreeNode? replacement;
  final List<ir.Member> originalConditions;
  final ImpactData impactData;
  late ImpactData replacementImpactData;

  ConditionalImpactData(
    this.originalConditions,
    this.impactData, {
    this.original,
    this.replacement,
  });
}

/// 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 = EnumSet.empty();
  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<_StaticAccess>? _weakStaticTearOffs;
  List<_MapLiteral>? _mapLiterals;
  List<_ContainerLiteral>? _listLiterals;
  List<_ContainerLiteral>? _setLiterals;
  List<_RecordLiteral>? _recordLiterals;
  List<_RuntimeTypeUse>? _runtimeTypeUses;
  List<_ForInData>? _forInData;
  List<ConditionalImpactData>? _conditionalImpacts;

  // TODO(johnniwinther): Remove these when CFE provides constants.
  List<ir.Constructor>? _externalConstructorNodes;
  List<ir.Field>? _fieldNodes;
  List<ir.Procedure>? _externalProcedureNodes;
  List<ir.StaticInvocation>? _foreignStaticInvocationNodes;
  bool _hasConstSymbolConstructorInvocation = false;

  ImpactData();

  /// 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.target);
      }
    }
    if (_dynamicSets != null) {
      for (_DynamicAccess data in _dynamicSets!) {
        registry.registerDynamicSet(data.receiverType, data.name);
      }
    }
    if (_instanceGets != null) {
      for (_InstanceAccess data in _instanceGets!) {
        registry.registerInstanceGet(data.receiverType, data.target);
      }
    }
    if (_dynamicGets != null) {
      for (_DynamicAccess data in _dynamicGets!) {
        registry.registerDynamicGet(data.receiverType, 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.target,
          data.callStructure.positionalArguments,
          data.callStructure.namedArguments,
          data.callStructure.typeArguments,
        );
      }
    }
    if (_dynamicInvocations != null) {
      for (_DynamicInvocation data in _dynamicInvocations!) {
        registry.registerDynamicInvocation(
          data.receiverType,
          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.isNotEmpty) {
      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;
          case _Feature.symbolLiteral:
            registry.registerSymbolLiteral();
            break;
          case _Feature.stringLiteral:
            registry.registerStringLiteral();
            break;
          case _Feature.boolLiteral:
            registry.registerBoolLiteral();
            break;
          case _Feature.doubleLiteral:
            registry.registerDoubleLiteral();
            break;
          case _Feature.intLiteral:
            registry.registerIntLiteral();
            break;
        }
      }
    }
    if (_typeUses != null) {
      for (_TypeUse data in _typeUses!) {
        switch (data.kind) {
          case _TypeUseKind.parameterCheck:
            registry.registerParameterCheck(data.type);
            break;
          case _TypeUseKind.catchType:
            registry.registerCatchType(data.type);
            break;
          case _TypeUseKind.asCast:
            registry.registerAsCast(data.type);
            break;
          case _TypeUseKind.implicitCast:
            registry.registerImplicitCast(data.type);
            break;
          case _TypeUseKind.isCheck:
            registry.registerIsCheck(data.type);
            break;
          case _TypeUseKind.asyncStarMarker:
            registry.registerAsyncStar(data.type);
            break;
          case _TypeUseKind.asyncMarker:
            registry.registerAsync(data.type);
            break;
          case _TypeUseKind.syncStarMarker:
            registry.registerSyncStar(data.type);
            break;
        }
      }
    }
    if (_redirectingInitializers != null) {
      for (_RedirectingInitializer data in _redirectingInitializers!) {
        registry.registerRedirectingInitializer(
          data.constructor,
          data.callStructure.positionalArguments,
          data.callStructure.namedArguments,
          data.callStructure.typeArguments,
        );
      }
    }
    if (_fieldInitializers != null) {
      for (ir.Field data in _fieldInitializers!) {
        registry.registerFieldInitialization(data);
      }
    }
    if (_fieldConstantInitializers != null) {
      _fieldConstantInitializers!.forEach((
        ir.Field field,
        List<ConstantReference> constants,
      ) {
        for (ConstantReference constant in constants) {
          registry.registerFieldConstantInitialization(field, constant);
        }
      });
    }
    if (_typeLiterals != null) {
      for (_TypeLiteral data in _typeLiterals!) {
        registry.registerTypeLiteral(data.type, data.import);
      }
    }
    if (_localFunctions != null) {
      for (ir.TreeNode data in _localFunctions!) {
        registry.registerLocalFunction(data);
      }
    }
    if (_genericInstantiations != null) {
      for (_GenericInstantiation data in _genericInstantiations!) {
        registry.registerGenericInstantiation(
          data.expressionType,
          data.typeArguments,
        );
      }
    }
    if (_staticSets != null) {
      for (_StaticAccess data in _staticSets!) {
        registry.registerStaticSet(data.target, data.import);
      }
    }
    if (_staticGets != null) {
      for (_StaticAccess data in _staticGets!) {
        registry.registerStaticGet(data.target, data.import);
      }
    }
    if (_staticTearOffs != null) {
      for (_StaticAccess data in _staticTearOffs!) {
        registry.registerStaticTearOff(
          data.target as ir.Procedure,
          data.import,
        );
      }
    }
    if (_weakStaticTearOffs != null) {
      for (_StaticAccess data in _weakStaticTearOffs!) {
        registry.registerWeakStaticTearOff(
          data.target as ir.Procedure,
          data.import,
        );
      }
    }
    if (_mapLiterals != null) {
      for (_MapLiteral data in _mapLiterals!) {
        registry.registerMapLiteral(
          data.keyType,
          data.valueType,
          isConst: data.isConst,
          isEmpty: data.isEmpty,
        );
      }
    }
    if (_listLiterals != null) {
      for (_ContainerLiteral data in _listLiterals!) {
        registry.registerListLiteral(
          data.elementType,
          isConst: data.isConst,
          isEmpty: data.isEmpty,
        );
      }
    }
    if (_setLiterals != null) {
      for (_ContainerLiteral data in _setLiterals!) {
        registry.registerSetLiteral(
          data.elementType,
          isConst: data.isConst,
          isEmpty: data.isEmpty,
        );
      }
    }
    if (_recordLiterals != null) {
      for (_RecordLiteral data in _recordLiterals!) {
        registry.registerRecordLiteral(data.recordType, isConst: data.isConst);
      }
    }
    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);
        } else {
          registry.registerSyncForIn(data.iterableType, data.iteratorType);
        }
      }
    }

    _conditionalImpacts?.forEach(registry.registerConditionalImpact);

    // TODO(johnniwinther): Remove these when CFE provides constants.
    if (_externalConstructorNodes != null) {
      for (ir.Constructor data in _externalConstructorNodes!) {
        registry.registerExternalConstructorNode(data);
      }
    }
    if (_fieldNodes != null) {
      for (ir.Field data in _fieldNodes!) {
        registry.registerFieldNode(data);
      }
    }
    if (_externalProcedureNodes != null) {
      for (ir.Procedure data in _externalProcedureNodes!) {
        registry.registerExternalProcedureNode(data);
      }
    }
    if (_foreignStaticInvocationNodes != null) {
      for (ir.StaticInvocation data in _foreignStaticInvocationNodes!) {
        registry.registerForeignStaticInvocationNode(data);
      }
    }
    if (_hasConstSymbolConstructorInvocation) {
      registry.registerConstSymbolConstructorInvocationNode();
    }
  }
}

class _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,
    );
  }
}

class _SuperInitializer {
  final ir.Constructor source;
  final ir.Constructor target;
  final _CallStructure callStructure;

  _SuperInitializer(this.source, this.target, this.callStructure);
}

class _SuperInvocation {
  final ir.Member target;
  final _CallStructure callStructure;

  _SuperInvocation(this.target, this.callStructure);
}

class _InstanceAccess {
  final ir.DartType receiverType;
  final ir.Member target;

  _InstanceAccess(this.receiverType, this.target);
}

class _DynamicAccess {
  final ir.DartType receiverType;
  final ir.Name name;

  _DynamicAccess(this.receiverType, this.name);
}

class _FunctionInvocation {
  final ir.DartType receiverType;
  final _CallStructure callStructure;

  _FunctionInvocation(this.receiverType, this.callStructure);
}

class _InstanceInvocation {
  final ir.DartType receiverType;
  final ir.Member target;
  final _CallStructure callStructure;

  _InstanceInvocation(this.receiverType, this.target, this.callStructure);
}

class _DynamicInvocation {
  final ir.DartType receiverType;
  final ir.Name name;
  final _CallStructure callStructure;

  _DynamicInvocation(this.receiverType, this.name, this.callStructure);
}

class _LocalFunctionInvocation {
  final ir.FunctionDeclaration localFunction;
  final _CallStructure callStructure;

  _LocalFunctionInvocation(this.localFunction, this.callStructure);
}

class _StaticInvocation {
  final ir.Procedure target;
  final _CallStructure callStructure;
  final ir.LibraryDependency? import;

  _StaticInvocation(this.target, this.callStructure, this.import);
}

class _ConstructorInvocation {
  final ir.Member constructor;
  final ir.InterfaceType type;
  final _CallStructure callStructure;
  final ir.LibraryDependency? import;
  final bool isConst;

  _ConstructorInvocation(
    this.constructor,
    this.type,
    this.callStructure,
    this.import, {
    required this.isConst,
  });
}

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,
  stringLiteral,
  boolLiteral,
  intLiteral,
  symbolLiteral,
  doubleLiteral,
}

class _TypeUse {
  final ir.DartType type;
  final _TypeUseKind kind;

  _TypeUse(this.type, this.kind);
}

enum _TypeUseKind {
  parameterCheck,
  catchType,
  asCast,
  implicitCast,
  isCheck,
  asyncStarMarker,
  asyncMarker,
  syncStarMarker,
}

class _RedirectingInitializer {
  final ir.Constructor constructor;
  final _CallStructure callStructure;

  _RedirectingInitializer(this.constructor, this.callStructure);
}

class _TypeLiteral {
  final ir.DartType type;
  final ir.LibraryDependency? import;

  _TypeLiteral(this.type, this.import);
}

class _GenericInstantiation {
  final ir.FunctionType expressionType;
  final List<ir.DartType> typeArguments;

  _GenericInstantiation(this.expressionType, this.typeArguments);
}

class _StaticAccess {
  final ir.Member target;
  final ir.LibraryDependency? import;

  _StaticAccess(this.target, this.import);
}

class _MapLiteral {
  final ir.DartType keyType;
  final ir.DartType valueType;
  final bool isConst;
  final bool isEmpty;

  _MapLiteral(
    this.keyType,
    this.valueType, {
    required this.isConst,
    required this.isEmpty,
  });
}

class _ContainerLiteral {
  final ir.DartType elementType;
  final bool isConst;
  final bool isEmpty;

  _ContainerLiteral(
    this.elementType, {
    required this.isConst,
    required this.isEmpty,
  });
}

class _RecordLiteral {
  final ir.RecordType recordType;
  final bool isConst;

  _RecordLiteral(this.recordType, {required this.isConst});
}

class _RuntimeTypeUse {
  final RuntimeTypeUseKind kind;
  final ir.DartType receiverType;
  final ir.DartType? argumentType;

  _RuntimeTypeUse(this.kind, this.receiverType, this.argumentType);
}

class _ForInData {
  final ir.DartType iterableType;
  final ir.DartType iteratorType;
  final bool isAsync;

  _ForInData(this.iterableType, this.iteratorType, {required this.isAsync});
}
