// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:kernel/ast.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;

import '../common.dart';
import '../common/names.dart';
import '../common/elements.dart';
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../ir/constants.dart';
import '../ir/impact.dart';
import '../ir/impact_data.dart';
import '../ir/runtime_type_analysis.dart';
import '../ir/visitors.dart';
import '../js_backend/annotations.dart';
import '../js_backend/backend_impact.dart';
import '../js_backend/backend_usage.dart';
import '../js_backend/custom_elements_analysis.dart';
import '../js_backend/native_data.dart';
import '../js_backend/runtime_types_resolution.dart';
import '../js_model/elements.dart';
import '../native/behavior.dart';
import '../native/enqueue.dart';
import '../options.dart';
import '../universe/call_structure.dart';
import '../universe/feature.dart';
import '../universe/selector.dart';
import '../universe/use.dart';
import '../universe/world_builder.dart';
import '../universe/world_impact.dart';
import 'element_map.dart';

/// [ImpactRegistry] that converts kernel based impact data to world impact
/// object based on the K model.
class KernelImpactConverter implements ImpactRegistry {
  final KernelToElementMap elementMap;
  final DiagnosticReporter reporter;
  final CompilerOptions _options;
  final MemberEntity currentMember;
  final ConstantValuefier _constantValuefier;
  final ir.StaticTypeContext staticTypeContext;
  final BackendImpacts _impacts;
  final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
  final BackendUsageBuilder _backendUsageBuilder;
  final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
  final RuntimeTypesNeedBuilder _rtiNeedBuilder;
  final AnnotationsData _annotationsData;
  WorldImpactBuilder? _impactBuilder;
  WorldImpactBuilder get impactBuilder => _impactBuilder!;

  KernelImpactConverter(
    this.elementMap,
    this.currentMember,
    this.reporter,
    this._options,
    this._constantValuefier,
    this.staticTypeContext,
    this._impacts,
    this._nativeResolutionEnqueuer,
    this._backendUsageBuilder,
    this._customElementsResolutionAnalysis,
    this._rtiNeedBuilder,
    this._annotationsData,
  );

  ir.TypeEnvironment get typeEnvironment => elementMap.typeEnvironment;

  CommonElements get commonElements => elementMap.commonElements;

  NativeBasicData get _nativeBasicData => elementMap.nativeBasicData;

  ElementEnvironment get elementEnvironment => elementMap.elementEnvironment;

  DartTypes get dartTypes => commonElements.dartTypes;

  String typeToString(DartType type) =>
      type.toStructuredText(dartTypes, _options);

  Object? _computeReceiverConstraint(ir.DartType receiverType) {
    if (receiverType is ir.InterfaceType) {
      return defaultReceiverClass(
        commonElements,
        _nativeBasicData,
        elementMap.getClass(receiverType.classNode),
      );
    } else if (receiverType is ir.NullType) {
      return elementMap.getClass(typeEnvironment.coreTypes.deprecatedNullClass);
    }
    return null;
  }

  void registerBackendImpact(BackendImpact impact) {
    impact.registerImpact(impactBuilder, elementEnvironment);
    _backendUsageBuilder.processBackendImpact(impact);
  }

  void registerNativeImpact(NativeBehavior behavior) {
    _nativeResolutionEnqueuer.registerNativeBehavior(
      impactBuilder,
      behavior,
      impactBuilder,
    );
  }

  // TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType].
  void onIsCheck(DartType type) {
    registerBackendImpact(_impacts.typeCheck);
    var typeWithoutNullability = type.withoutNullability;
    if (!dartTypes.treatAsRawType(typeWithoutNullability) ||
        typeWithoutNullability.containsTypeVariables ||
        typeWithoutNullability is FunctionType) {
      registerBackendImpact(_impacts.genericTypeCheck);
      if (typeWithoutNullability is TypeVariableType) {
        registerBackendImpact(_impacts.typeVariableTypeCheck);
      }
    }
    if (typeWithoutNullability is FunctionType) {
      registerBackendImpact(_impacts.functionTypeCheck);
    }
    if (typeWithoutNullability is InterfaceType &&
        _nativeBasicData.isNativeClass(typeWithoutNullability.element)) {
      registerBackendImpact(_impacts.nativeTypeCheck);
    }
    if (typeWithoutNullability is FutureOrType) {
      registerBackendImpact(_impacts.futureOrTypeCheck);
    }
  }

  @override
  void registerParameterCheck(ir.DartType irType) {
    DartType type = elementMap.getDartType(irType);
    if (type is! DynamicType) {
      impactBuilder.registerTypeUse(TypeUse.parameterCheck(type));
      if (_annotationsData.getParameterCheckPolicy(currentMember).isEmitted) {
        onIsCheck(type);
      }
    }
  }

  List<DartType>? _getTypeArguments(List<ir.DartType> types) {
    if (types.isEmpty) return null;
    return types.map(elementMap.getDartType).toList();
  }

  @override
  void registerLazyField() {
    registerBackendImpact(_impacts.lazyField);
  }

  @override
  void registerFieldNode(ir.Field field) {
    if (field.isInstanceMember &&
        _nativeBasicData.isNativeClass(
          elementMap.getClass(field.enclosingClass!),
        )) {
      MemberEntity member = elementMap.getMember(field);
      // TODO(johnniwinther): NativeDataBuilder already has the native behavior
      // at this point. Use that instead.
      bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
      Iterable<ConstantValue> metadata = elementMap.elementEnvironment
          .getMemberMetadata(member as JMember);
      Iterable<String> createsAnnotations = getCreatesAnnotations(
        dartTypes,
        reporter,
        commonElements,
        metadata,
      );
      Iterable<String> returnsAnnotations = getReturnsAnnotations(
        dartTypes,
        reporter,
        commonElements,
        metadata,
      );
      registerNativeImpact(
        elementMap.getNativeBehaviorForFieldLoad(
          field,
          createsAnnotations,
          returnsAnnotations,
          isJsInterop: isJsInterop,
        ),
      );
      registerNativeImpact(elementMap.getNativeBehaviorForFieldStore(field));
    }
  }

  @override
  void registerExternalConstructorNode(ir.Constructor constructor) {
    MemberEntity member = elementMap.getMember(constructor);
    if (constructor.isExternal && !commonElements.isForeignHelper(member)) {
      // TODO(johnniwinther): NativeDataBuilder already has the native behavior
      // at this point. Use that instead.
      bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
      Iterable<ConstantValue> metadata = elementMap.elementEnvironment
          .getMemberMetadata(member as JMember);
      Iterable<String> createsAnnotations = getCreatesAnnotations(
        dartTypes,
        reporter,
        commonElements,
        metadata,
      );
      Iterable<String> returnsAnnotations = getReturnsAnnotations(
        dartTypes,
        reporter,
        commonElements,
        metadata,
      );
      registerNativeImpact(
        elementMap.getNativeBehaviorForMethod(
          constructor,
          createsAnnotations,
          returnsAnnotations,
          isJsInterop: isJsInterop,
        ),
      );
    }
  }

  @override
  void registerSyncStar(ir.DartType elementType) {
    registerBackendImpact(_impacts.syncStarBody);
    impactBuilder.registerStaticUse(
      StaticUse.staticInvoke(
        commonElements.syncStarIterableFactory,
        CallStructure.unnamed(1, 1),
        <DartType>[elementMap.getDartType(elementType)],
      ),
    );
  }

  @override
  void registerAsync(ir.DartType elementType) {
    registerBackendImpact(_impacts.asyncBody);
    impactBuilder.registerStaticUse(
      StaticUse.staticInvoke(
        commonElements.asyncAwaitCompleterFactory,
        CallStructure.unnamed(0, 1),
        <DartType>[elementMap.getDartType(elementType)],
      ),
    );
  }

  @override
  void registerAsyncStar(ir.DartType elementType) {
    registerBackendImpact(_impacts.asyncStarBody);
    impactBuilder.registerStaticUse(
      StaticUse.staticInvoke(
        commonElements.asyncStarStreamControllerFactory,
        CallStructure.unnamed(1, 1),
        <DartType>[elementMap.getDartType(elementType)],
      ),
    );
  }

  @override
  void registerExternalProcedureNode(ir.Procedure procedure) {
    MemberEntity member = elementMap.getMember(procedure);
    if (procedure.isExternal && !commonElements.isForeignHelper(member)) {
      // TODO(johnniwinther): NativeDataBuilder already has the native behavior
      // at this point. Use that instead.
      bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
      Iterable<ConstantValue> metadata = elementMap.elementEnvironment
          .getMemberMetadata(member as JMember);
      Iterable<String> createsAnnotations = getCreatesAnnotations(
        dartTypes,
        reporter,
        commonElements,
        metadata,
      );
      Iterable<String> returnsAnnotations = getReturnsAnnotations(
        dartTypes,
        reporter,
        commonElements,
        metadata,
      );
      registerNativeImpact(
        elementMap.getNativeBehaviorForMethod(
          procedure,
          createsAnnotations,
          returnsAnnotations,
          isJsInterop: isJsInterop,
        ),
      );
    }
  }

  @override
  void registerIntLiteral() {
    registerBackendImpact(_impacts.intLiteral);
  }

  @override
  void registerDoubleLiteral() {
    registerBackendImpact(_impacts.doubleLiteral);
  }

  @override
  void registerBoolLiteral() {
    registerBackendImpact(_impacts.boolLiteral);
  }

  @override
  void registerStringLiteral() {
    registerBackendImpact(_impacts.stringLiteral);
  }

  @override
  void registerSymbolLiteral() {
    registerBackendImpact(_impacts.constSymbol);
  }

  @override
  void registerNullLiteral() {
    registerBackendImpact(_impacts.nullLiteral);
  }

  @override
  void registerListLiteral(
    ir.DartType elementType, {
    required bool isConst,
    required bool isEmpty,
  }) {
    // TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when
    // factory constructors are registered directly.
    impactBuilder.registerTypeUse(
      TypeUse.instantiation(
        commonElements.listType(elementMap.getDartType(elementType)),
      ),
    );
  }

  @override
  void registerSetLiteral(
    ir.DartType elementType, {
    required bool isConst,
    required bool isEmpty,
  }) {
    // TODO(johnniwinther): Use the [isEmpty] property when factory
    // constructors are registered directly.
    if (isConst) {
      registerBackendImpact(_impacts.constantSetLiteral);
    } else {
      impactBuilder.registerTypeUse(
        TypeUse.instantiation(
          commonElements.setType(elementMap.getDartType(elementType)),
        ),
      );
    }
  }

  @override
  void registerMapLiteral(
    ir.DartType keyType,
    ir.DartType valueType, {
    required bool isConst,
    required bool isEmpty,
  }) {
    // TODO(johnniwinther): Use the [isEmpty] property when factory
    // constructors are registered directly.
    if (isConst) {
      registerBackendImpact(_impacts.constantMapLiteral);
    } else {
      impactBuilder.registerTypeUse(
        TypeUse.instantiation(
          commonElements.mapType(
            elementMap.getDartType(keyType),
            elementMap.getDartType(valueType),
          ),
        ),
      );
    }
  }

  @override
  void registerRecordLiteral(
    ir.RecordType recordType, {
    required bool isConst,
  }) {
    registerBackendImpact(_impacts.recordInstantiation);
    final type = elementMap.getDartType(recordType) as RecordType;
    impactBuilder.registerTypeUse(TypeUse.recordInstantiation(type));
  }

  @override
  void registerNew(
    ir.Member target,
    ir.InterfaceType type,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
    ir.LibraryDependency? import, {
    required bool isConst,
  }) {
    ConstructorEntity constructor = elementMap.getConstructor(target);
    CallStructure callStructure = CallStructure(
      positionalArguments + namedArguments.length,
      namedArguments,
      typeArguments.length,
    );
    ImportEntity? deferredImport = elementMap.getImport(import);
    impactBuilder.registerStaticUse(
      isConst
          ? StaticUse.constConstructorInvoke(
            constructor,
            callStructure,
            elementMap.getInterfaceType(type),
            deferredImport,
          )
          : StaticUse.typedConstructorInvoke(
            constructor,
            callStructure,
            elementMap.getInterfaceType(type),
            deferredImport,
          ),
    );
    if (type.typeArguments.any((ir.DartType type) => type is! ir.DynamicType)) {
      registerBackendImpact(_impacts.typeVariableBoundCheck);
    }

    if (target.isExternal &&
        constructor.isFromEnvironmentConstructor &&
        !isConst) {
      registerBackendImpact(_impacts.throwUnsupportedError);
      // We need to register the external constructor as live below, so don't
      // return here.
    }
  }

  @override
  void registerConstInstantiation(
    ir.Class cls,
    List<ir.DartType> typeArguments,
    ir.LibraryDependency? import,
  ) {
    ImportEntity? deferredImport = elementMap.getImport(import);
    InterfaceType type = elementMap.createInterfaceType(cls, typeArguments);
    impactBuilder.registerTypeUse(
      TypeUse.constInstantiation(type, deferredImport),
    );
  }

  @override
  void registerConstSymbolConstructorInvocationNode() {
    registerBackendImpact(_impacts.constSymbol);
  }

  @override
  void registerSuperInitializer(
    ir.Constructor source,
    ir.Constructor target,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    // TODO(johnniwinther): Maybe rewrite `node.target` to point to a
    // synthesized unnamed mixin constructor when needed. This would require us
    // to consider impact building a required pre-step for inference and
    // ssa-building.
    ConstructorEntity constructor = elementMap.getSuperConstructor(
      source,
      target,
    );
    impactBuilder.registerStaticUse(
      StaticUse.superConstructorInvoke(
        constructor,
        CallStructure(
          positionalArguments + namedArguments.length,
          namedArguments,
          typeArguments.length,
        ),
      ),
    );
  }

  @override
  void registerStaticInvocation(
    ir.Procedure procedure,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
    ir.LibraryDependency? import,
  ) {
    FunctionEntity target = elementMap.getMethod(procedure);
    CallStructure callStructure = CallStructure(
      positionalArguments + namedArguments.length,
      namedArguments,
      typeArguments.length,
    );
    List<DartType>? dartTypeArguments = _getTypeArguments(typeArguments);
    if (commonElements.isExtractTypeArguments(target)) {
      _handleExtractTypeArguments(target, dartTypeArguments!, callStructure);
      return;
    } else {
      ImportEntity? deferredImport = elementMap.getImport(import);
      impactBuilder.registerStaticUse(
        StaticUse.staticInvoke(
          target,
          callStructure,
          dartTypeArguments,
          deferredImport,
        ),
      );
    }
  }

  @override
  void registerForeignStaticInvocationNode(ir.StaticInvocation node) {
    switch (elementMap.getForeignKind(node)) {
      case ForeignKind.js:
        registerNativeImpact(elementMap.getNativeBehaviorForJsCall(node));
        break;
      case ForeignKind.jsBuiltin:
        registerNativeImpact(
          elementMap.getNativeBehaviorForJsBuiltinCall(node),
        );
        break;
      case ForeignKind.jsEmbeddedGlobal:
        registerNativeImpact(
          elementMap.getNativeBehaviorForJsEmbeddedGlobalCall(node),
        );
        break;
      case ForeignKind.jsInterceptorConstant:
        InterfaceType? type = elementMap.getInterfaceTypeForJsInterceptorCall(
          node,
        );
        if (type != null) {
          impactBuilder.registerTypeUse(TypeUse.instantiation(type));
        }
        break;
      case ForeignKind.none:
        break;
    }
  }

  void _handleExtractTypeArguments(
    FunctionEntity target,
    List<DartType> typeArguments,
    CallStructure callStructure,
  ) {
    // extractTypeArguments<Map>(obj, fn) has additional impacts:
    //
    //   1. All classes implementing Map need to carry type arguments (similar
    //      to checking `o is Map<K, V>`).
    //
    //   2. There is an invocation of fn with some number of type arguments.
    //
    impactBuilder.registerStaticUse(
      StaticUse.staticInvoke(target, callStructure, typeArguments),
    );

    if (typeArguments.length != 1) return;
    DartType matchedType = dartTypes.eraseLegacy(typeArguments.first);

    if (matchedType is! InterfaceType) return;
    InterfaceType interfaceType = matchedType;
    ClassEntity cls = interfaceType.element;
    InterfaceType thisType = elementMap.elementEnvironment.getThisType(cls);
    _registerIsCheckInternal(thisType);

    Selector selector = Selector.callClosure(
      0,
      const <String>[],
      thisType.typeArguments.length,
    );
    impactBuilder.registerDynamicUse(
      DynamicUse(selector, null, thisType.typeArguments),
    );
  }

  @override
  void registerStaticTearOff(
    ir.Procedure procedure,
    ir.LibraryDependency? import,
  ) {
    impactBuilder.registerStaticUse(
      StaticUse.staticTearOff(
        elementMap.getMethod(procedure),
        elementMap.getImport(import),
      ),
    );
  }

  @override
  void registerWeakStaticTearOff(
    ir.Procedure procedure,
    ir.LibraryDependency? import,
  ) {
    impactBuilder.registerStaticUse(
      StaticUse.weakStaticTearOff(
        elementMap.getMethod(procedure),
        elementMap.getImport(import),
      ),
    );
  }

  @override
  void registerStaticGet(ir.Member member, ir.LibraryDependency? import) {
    impactBuilder.registerStaticUse(
      StaticUse.staticGet(
        elementMap.getMember(member),
        elementMap.getImport(import),
      ),
    );
  }

  @override
  void registerStaticSet(ir.Member member, ir.LibraryDependency? import) {
    impactBuilder.registerStaticUse(
      StaticUse.staticSet(
        elementMap.getMember(member),
        elementMap.getImport(import),
      ),
    );
  }

  @override
  void registerSuperInvocation(
    ir.Member target,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    FunctionEntity method = elementMap.getMember(target) as FunctionEntity;
    List<DartType>? dartTypeArguments = _getTypeArguments(typeArguments);
    impactBuilder.registerStaticUse(
      StaticUse.superInvoke(
        method,
        CallStructure(
          positionalArguments + namedArguments.length,
          namedArguments,
          typeArguments.length,
        ),
        dartTypeArguments,
      ),
    );
  }

  @override
  void registerSuperGet(ir.Member target) {
    MemberEntity member = elementMap.getMember(target);
    if (member.isFunction) {
      impactBuilder.registerStaticUse(
        StaticUse.superTearOff(member as FunctionEntity),
      );
    } else {
      impactBuilder.registerStaticUse(StaticUse.superGet(member));
    }
  }

  @override
  void registerSuperSet(ir.Member target) {
    MemberEntity member = elementMap.getMember(target);
    if (member is FieldEntity) {
      impactBuilder.registerStaticUse(StaticUse.superFieldSet(member));
    } else {
      impactBuilder.registerStaticUse(
        StaticUse.superSetterSet(member as FunctionEntity),
      );
    }
  }

  @override
  void registerLocalFunctionInvocation(
    ir.FunctionDeclaration localFunction,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    CallStructure callStructure = CallStructure(
      positionalArguments + namedArguments.length,
      namedArguments,
      typeArguments.length,
    );
    List<DartType>? dartTypeArguments = _getTypeArguments(typeArguments);
    // Invocation of a local function. No need for dynamic use, but
    // we need to track the type arguments.
    impactBuilder.registerStaticUse(
      StaticUse.closureCall(
        elementMap.getLocalFunction(localFunction),
        callStructure,
        dartTypeArguments,
      ),
    );
    // TODO(johnniwinther): Yet, alas, we need the dynamic use for now. Remove
    // this when kernel adds an `isFunctionCall` flag to
    // [ir.MethodInvocation].
    impactBuilder.registerDynamicUse(
      DynamicUse(callStructure.callSelector, null, dartTypeArguments),
    );
  }

  @override
  void registerDynamicInvocation(
    ir.DartType receiverType,
    ir.Name name,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    Selector selector = elementMap.getInvocationSelector(
      name,
      positionalArguments,
      namedArguments,
      typeArguments.length,
    );
    List<DartType>? dartTypeArguments = _getTypeArguments(typeArguments);
    impactBuilder.registerDynamicUse(
      DynamicUse(
        selector,
        _computeReceiverConstraint(receiverType),
        dartTypeArguments,
      ),
    );
  }

  @override
  void registerFunctionInvocation(
    ir.DartType receiverType,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    CallStructure callStructure = CallStructure(
      positionalArguments + namedArguments.length,
      namedArguments,
      typeArguments.length,
    );
    List<DartType>? dartTypeArguments = _getTypeArguments(typeArguments);
    impactBuilder.registerDynamicUse(
      DynamicUse(
        callStructure.callSelector,
        _computeReceiverConstraint(receiverType),
        dartTypeArguments,
      ),
    );
  }

  @override
  void registerInstanceInvocation(
    ir.DartType receiverType,
    ir.Member target,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    List<DartType>? dartTypeArguments = _getTypeArguments(typeArguments);
    impactBuilder.registerDynamicUse(
      DynamicUse(
        elementMap.getInvocationSelector(
          target.name,
          positionalArguments,
          namedArguments,
          typeArguments.length,
        ),
        _computeReceiverConstraint(receiverType),
        dartTypeArguments,
      ),
    );
  }

  @override
  void registerDynamicGet(ir.DartType receiverType, ir.Name name) {
    impactBuilder.registerDynamicUse(
      DynamicUse(
        Selector.getter(elementMap.getName(name)),
        _computeReceiverConstraint(receiverType),
        const <DartType>[],
      ),
    );
  }

  @override
  void registerInstanceGet(ir.DartType receiverType, ir.Member target) {
    impactBuilder.registerDynamicUse(
      DynamicUse(
        Selector.getter(elementMap.getName(target.name)),
        _computeReceiverConstraint(receiverType),
        const <DartType>[],
      ),
    );
  }

  @override
  void registerDynamicSet(ir.DartType receiverType, ir.Name name) {
    impactBuilder.registerDynamicUse(
      DynamicUse(
        Selector.setter(elementMap.getName(name)),
        _computeReceiverConstraint(receiverType),
        const <DartType>[],
      ),
    );
  }

  @override
  void registerInstanceSet(ir.DartType receiverType, ir.Member target) {
    impactBuilder.registerDynamicUse(
      DynamicUse(
        Selector.setter(elementMap.getName(target.name)),
        _computeReceiverConstraint(receiverType),
        const <DartType>[],
      ),
    );
  }

  @override
  void registerRuntimeTypeUse(
    RuntimeTypeUseKind kind,
    ir.DartType receiverType,
    ir.DartType? argumentType,
  ) {
    DartType receiverDartType = elementMap.getDartType(receiverType);
    DartType? argumentDartType =
        argumentType == null ? null : elementMap.getDartType(argumentType);

    // Enable runtime type support if we discover a getter called
    // runtimeType. We have to enable runtime type before hitting the
    // codegen, so that constructors know whether they need to generate code
    // for runtime type.
    _backendUsageBuilder.registerRuntimeTypeUse(
      RuntimeTypeUse(kind, receiverDartType, argumentDartType),
    );
  }

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

  @override
  void registerGenericInstantiation(
    ir.FunctionType expressionType,
    List<ir.DartType> typeArguments,
  ) {
    // TODO(johnniwinther): Track which arities are used in instantiation.
    final instantiation = GenericInstantiation(
      elementMap.getDartType(expressionType).withoutNullability as FunctionType,
      typeArguments.map(elementMap.getDartType).toList(),
    );
    registerBackendImpact(
      _impacts.getGenericInstantiation(instantiation.typeArguments.length),
    );
    _rtiNeedBuilder.registerGenericInstantiation(instantiation);
  }

  @override
  void registerStringConcatenation() {
    registerBackendImpact(_impacts.stringInterpolation);
    registerBackendImpact(_impacts.stringJuxtaposition);
  }

  @override
  void registerLocalFunction(covariant ir.LocalFunction node) {
    Local function = elementMap.getLocalFunction(node);
    impactBuilder.registerStaticUse(StaticUse.closure(function));
    registerBackendImpact(_impacts.closure);
    registerBackendImpact(_impacts.computeSignature);
  }

  @override
  void registerLocalWithoutInitializer() {
    impactBuilder.registerTypeUse(
      TypeUse.instantiation(commonElements.nullType),
    );
    registerBackendImpact(_impacts.nullLiteral);
  }

  void _registerIsCheckInternal(DartType type) {
    impactBuilder.registerTypeUse(TypeUse.isCheck(type));
    onIsCheck(type);
  }

  @override
  void registerIsCheck(ir.DartType irType) {
    _registerIsCheckInternal(elementMap.getDartType(irType));
  }

  @override
  void registerImplicitCast(ir.DartType irType) {
    DartType type = elementMap.getDartType(irType);
    impactBuilder.registerTypeUse(TypeUse.implicitCast(type));
    if (_annotationsData
        .getImplicitDowncastCheckPolicy(currentMember)
        .isEmitted) {
      onIsCheck(type);
    }
  }

  @override
  void registerAsCast(ir.DartType irType) {
    DartType type = elementMap.getDartType(irType);
    impactBuilder.registerTypeUse(TypeUse.asCast(type));
    if (_annotationsData.getExplicitCastCheckPolicy(currentMember).isEmitted) {
      onIsCheck(type);
      registerBackendImpact(_impacts.asCheck);
    }
  }

  @override
  void registerThrow() {
    registerBackendImpact(_impacts.throwExpression);
  }

  @override
  void registerSyncForIn(ir.DartType iterableType, ir.DartType iteratorType) {
    Object? receiverConstraint = _computeReceiverConstraint(iteratorType);
    registerBackendImpact(_impacts.syncForIn);
    impactBuilder.registerDynamicUse(
      DynamicUse(Selectors.iterator, receiverConstraint, const []),
    );
    impactBuilder.registerDynamicUse(
      DynamicUse(Selectors.current, receiverConstraint, const []),
    );
    impactBuilder.registerDynamicUse(
      DynamicUse(Selectors.moveNext, receiverConstraint, const []),
    );
  }

  @override
  void registerAsyncForIn(ir.DartType iterableType, ir.DartType iteratorType) {
    Object? receiverConstraint = _computeReceiverConstraint(iteratorType);
    registerBackendImpact(_impacts.asyncForIn);
    impactBuilder.registerDynamicUse(
      DynamicUse(Selectors.cancel, receiverConstraint, const []),
    );
    impactBuilder.registerDynamicUse(
      DynamicUse(Selectors.current, receiverConstraint, const []),
    );
    impactBuilder.registerDynamicUse(
      DynamicUse(Selectors.moveNext, receiverConstraint, const []),
    );
  }

  @override
  void registerCatch() {
    registerBackendImpact(_impacts.catchStatement);
  }

  @override
  void registerStackTrace() {
    registerBackendImpact(_impacts.stackTraceInCatch);
  }

  @override
  void registerCatchType(ir.DartType irType) {
    DartType type = elementMap.getDartType(irType);
    impactBuilder.registerTypeUse(TypeUse.catchType(type));
    onIsCheck(type);
  }

  @override
  void registerTypeLiteral(ir.DartType irType, ir.LibraryDependency? import) {
    ImportEntity? deferredImport = elementMap.getImport(import);
    DartType type = elementMap.getDartType(irType);
    impactBuilder.registerTypeUse(TypeUse.typeLiteral(type, deferredImport));
    _customElementsResolutionAnalysis.registerTypeLiteral(type);
    type.forEachTypeVariable((TypeVariableType variable) {
      _rtiNeedBuilder.registerTypeVariableLiteral(variable);
      registerBackendImpact(_impacts.typeVariableExpression);
    });
    impactBuilder.registerTypeUse(
      TypeUse.instantiation(commonElements.typeType),
    );
    registerBackendImpact(_impacts.typeLiteral);
  }

  @override
  void registerFieldInitialization(ir.Field node) {
    impactBuilder.registerStaticUse(
      StaticUse.fieldInit(elementMap.getField(node)),
    );
  }

  @override
  void registerFieldConstantInitialization(
    ir.Field node,
    ConstantReference constant,
  ) {
    impactBuilder.registerStaticUse(
      StaticUse.fieldConstantInit(
        elementMap.getField(node),
        _constantValuefier.visitConstant(constant.constant),
      ),
    );
  }

  @override
  void registerRedirectingInitializer(
    ir.Constructor constructor,
    int positionalArguments,
    List<String> namedArguments,
    List<ir.DartType> typeArguments,
  ) {
    ConstructorEntity target = elementMap.getConstructor(constructor);
    impactBuilder.registerStaticUse(
      StaticUse.superConstructorInvoke(
        target,
        CallStructure(
          positionalArguments + namedArguments.length,
          namedArguments,
          typeArguments.length,
        ),
      ),
    );
  }

  @override
  void registerLoadLibrary() {
    impactBuilder.registerStaticUse(
      StaticUse.staticInvoke(
        commonElements.loadDeferredLibrary,
        CallStructure.oneArg,
      ),
    );
    registerBackendImpact(_impacts.loadLibrary);
  }

  /// Converts a [ImpactData] object based on kernel to the corresponding
  /// [WorldImpact] based on the K model.
  WorldImpact convert(ImpactData impactData) {
    final oldBuilder = _impactBuilder;
    final newBuilder = _impactBuilder = WorldImpactBuilderImpl(currentMember);
    impactData.apply(this);
    _impactBuilder = oldBuilder;
    return newBuilder;
  }

  @override
  void registerConditionalImpact(ConditionalImpactData impact) {
    final conditionalUse = ConditionalUse.withReplacement(
      impact: convert(impact.impactData),
      replacementImpact: convert(impact.replacementImpactData),
      originalConditions:
          impact.originalConditions.map(elementMap.getMember).toList(),
      original: impact.original,
      replacement: impact.replacement,
    );
    impactBuilder.registerConditionalUse(conditionalUse);
  }
}
