// Copyright (c) 2017, 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.

library;

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

import '../common.dart';
import '../common/elements.dart';
import '../common/tasks.dart';
import '../common/work.dart';
import '../compiler.dart';
import '../deferred_load/deferred_load.dart' show DeferredLoadTask;
import '../elements/entities.dart';
import '../enqueue.dart';
import '../ir/annotations.dart';
import '../ir/closure.dart' show ClosureScopeModel;
import '../ir/impact.dart';
import '../ir/modular.dart';
import '../ir/scope.dart' show ScopeModel;
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/field_analysis.dart' show KFieldAnalysis;
import '../js_backend/interceptor_data.dart';
import '../js_backend/native_data.dart';
import '../js_backend/no_such_method_registry.dart';
import '../js_backend/resolution_listener.dart';
import '../js_backend/runtime_types_resolution.dart';
import '../js_model/elements.dart';
import '../kernel/dart2js_target.dart';
import '../kernel/no_such_method_resolver.dart';
import '../native/enqueue.dart' show NativeResolutionEnqueuer;
import '../native/resolver.dart';
import '../options.dart';
import '../resolution/enqueuer.dart';
import '../universe/class_hierarchy.dart';
import '../universe/resolution_world_builder.dart';
import '../universe/world_builder.dart';
import '../universe/world_impact.dart';
import '../util/enumset.dart';
import 'element_map.dart';
import 'element_map_impl.dart';
import 'native_basic_data.dart';

/// Front end strategy that loads '.dill' files and builds a resolved element
/// model from kernel IR nodes.
class KernelFrontendStrategy {
  final CompilerOptions _options;
  final CompilerTask _compilerTask;
  late final KernelToElementMap _elementMap;
  late final RuntimeTypesNeedBuilder _runtimeTypesNeedBuilder =
      _options.disableRtiOptimization
      ? const TrivialRuntimeTypesNeedBuilder()
      : RuntimeTypesNeedBuilderImpl(elementEnvironment);

  RuntimeTypesNeedBuilder get runtimeTypesNeedBuilderForTesting =>
      _runtimeTypesNeedBuilder;

  late KernelAnnotationProcessor _annotationProcessor;

  final Map<MemberEntity, ClosureScopeModel> closureModels = {};

  late ModularStrategy _modularStrategy;
  late IrAnnotationData _irAnnotationData;

  late NativeDataBuilder _nativeDataBuilder;
  NativeDataBuilder get nativeDataBuilder => _nativeDataBuilder;

  late final BackendUsageBuilder _backendUsageBuilder = BackendUsageBuilder(
    this,
  );

  late NativeResolutionEnqueuer _nativeResolutionEnqueuer;

  /// Resolution support for generating table of interceptors and
  /// constructors for custom elements.
  late CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;

  late KFieldAnalysis _fieldAnalysis;

  /// Support for classifying `noSuchMethod` implementations.
  late NoSuchMethodRegistry noSuchMethodRegistry;

  KernelFrontendStrategy(
    this._compilerTask,
    this._options,
    DiagnosticReporter reporter,
  ) : _elementMap = KernelToElementMap(reporter, _options) {
    _modularStrategy = KernelModularStrategy(_compilerTask, _elementMap);
    noSuchMethodRegistry = NoSuchMethodRegistry(
      commonElements,
      NoSuchMethodResolver(_elementMap),
    );
  }

  NativeResolutionEnqueuer get nativeResolutionEnqueuerForTesting =>
      _nativeResolutionEnqueuer;

  KFieldAnalysis get fieldAnalysisForTesting => _fieldAnalysis;

  /// Called before processing of the resolution queue is started.
  void onResolutionStart() {
    // TODO(johnniwinther): Avoid the compiler.elementEnvironment.getThisType
    // calls. Currently needed to ensure resolution of the classes for various
    // queries in native behavior computation, inference and codegen.
    elementEnvironment.getThisType(commonElements.jsArrayClass);
    elementEnvironment.getThisType(commonElements.jsExtendableArrayClass);

    _validateInterceptorImplementsAllObjectMethods(
      commonElements.jsInterceptorClass,
    );
    // The null-interceptor must also implement *all* methods.
    _validateInterceptorImplementsAllObjectMethods(commonElements.jsNullClass);
  }

  void _validateInterceptorImplementsAllObjectMethods(
    ClassEntity interceptorClass,
  ) {
    ClassEntity objectClass = commonElements.objectClass;
    elementEnvironment.forEachClassMember(objectClass, (
      _,
      MemberEntity member,
    ) {
      if (!member.isInstanceMember) return;
      MemberEntity interceptorMember = elementEnvironment
          .lookupLocalClassMember(interceptorClass, member.memberName)!;
      // Interceptors must override all Object methods due to calling convention
      // differences.
      assert(
        interceptorMember.enclosingClass == interceptorClass,
        failedAt(
          interceptorMember,
          "Member ${member.name} not overridden in $interceptorClass. "
          "Found $interceptorMember from "
          "${interceptorMember.enclosingClass}.",
        ),
      );
    });
  }

  ResolutionEnqueuer createResolutionEnqueuer(
    CompilerTask task,
    Compiler compiler,
  ) {
    RuntimeTypesNeedBuilder rtiNeedBuilder = _runtimeTypesNeedBuilder;
    BackendImpacts impacts = BackendImpacts(commonElements, compiler.options);
    final nativeBasicData = _elementMap.nativeBasicData;
    _nativeResolutionEnqueuer = NativeResolutionEnqueuer(
      compiler.options,
      elementEnvironment,
      commonElements,
      _elementMap.types,
      NativeClassFinder(elementEnvironment, nativeBasicData),
    );
    _nativeDataBuilder = NativeDataBuilder(nativeBasicData);
    _customElementsResolutionAnalysis = CustomElementsResolutionAnalysis(
      elementEnvironment,
      commonElements,
      nativeBasicData,
      _backendUsageBuilder,
    );
    _fieldAnalysis = KFieldAnalysis(elementMap);
    ClassHierarchyBuilder classHierarchyBuilder = ClassHierarchyBuilder(
      commonElements,
      elementMap,
    );
    AnnotationsDataBuilder annotationsDataBuilder = AnnotationsDataBuilder();
    // TODO(johnniwinther): This is a hack. The annotation data is built while
    // using it. With CFE constants the annotations data can be built fully
    // before creating the resolution enqueuer.
    AnnotationsData annotationsData = AnnotationsDataImpl(
      compiler.options,
      compiler.reporter,
      annotationsDataBuilder.pragmaAnnotations,
    );
    InterceptorDataBuilder interceptorDataBuilder = InterceptorDataBuilderImpl(
      nativeBasicData,
      elementEnvironment,
      commonElements,
    );
    return ResolutionEnqueuer(
      task,
      compiler.reporter,
      ResolutionEnqueuerListener(
        compiler.options,
        elementEnvironment,
        commonElements,
        impacts,
        nativeBasicData,
        interceptorDataBuilder,
        _backendUsageBuilder,
        noSuchMethodRegistry,
        _customElementsResolutionAnalysis,
        _nativeResolutionEnqueuer,
        _fieldAnalysis,
        compiler.deferredLoadTask,
      ),
      ResolutionWorldBuilder(
        _options,
        elementMap,
        elementEnvironment,
        _elementMap.types,
        commonElements,
        nativeBasicData,
        nativeDataBuilder,
        interceptorDataBuilder,
        _backendUsageBuilder,
        rtiNeedBuilder,
        _fieldAnalysis,
        _nativeResolutionEnqueuer,
        noSuchMethodRegistry,
        annotationsDataBuilder,
        const StrongModeWorldStrategy(),
        classHierarchyBuilder,
      ),
      KernelWorkItemBuilder(
        _compilerTask,
        elementMap,
        nativeBasicData,
        nativeDataBuilder,
        annotationsDataBuilder,
        closureModels,
        compiler.impactCache,
        _fieldAnalysis,
        _modularStrategy,
        _irAnnotationData,
        impacts,
        _nativeResolutionEnqueuer,
        _backendUsageBuilder,
        _customElementsResolutionAnalysis,
        rtiNeedBuilder,
        annotationsData,
      ),
      annotationsData,
    );
  }

  /// Registers a component with this strategy.
  void registerComponent(ir.Component component) {
    _elementMap.addComponent(component);
  }

  /// Registers a set of loaded libraries with this strategy.
  void registerLoadedLibraries(ir.Component component, List<Uri> libraries) {
    registerComponent(component);
    _irAnnotationData = processAnnotations(
      ModularCore(component, _elementMap.typeEnvironment),
    );
    _annotationProcessor = KernelAnnotationProcessor(
      elementMap,
      elementMap.nativeBasicDataBuilder,
      _irAnnotationData,
    );
    for (Uri uri in libraries) {
      LibraryEntity library = elementEnvironment.lookupLibrary(uri)!;
      if (maybeEnableNative(library.canonicalUri)) {
        _annotationProcessor.extractNativeAnnotations(library);
      }
      _annotationProcessor.extractJsInteropAnnotations(library);
    }
  }

  IrAnnotationData get irAnnotationDataForTesting => _irAnnotationData;

  ModularStrategy get modularStrategyForTesting => _modularStrategy;

  /// Returns the [ElementEnvironment] for the element model used in this
  /// strategy.
  KernelElementEnvironment get elementEnvironment =>
      _elementMap.elementEnvironment;

  /// Returns the [CommonElements] for the element model used in this
  /// strategy.
  KCommonElements get commonElements => _elementMap.commonElements;

  KernelToElementMap get elementMap => _elementMap;

  /// Creates a [DeferredLoadTask] for the element model used in this strategy.
  DeferredLoadTask createDeferredLoadTask(Compiler compiler) =>
      DeferredLoadTask(compiler, _elementMap);

  /// Computes the main function from [mainLibrary] adding additional world
  /// impact to [impactBuilder].
  FunctionEntity? computeMain(WorldImpactBuilder impactBuilder) {
    return elementEnvironment.mainFunction;
  }

  /// Creates a [SourceSpan] from [spannable] in context of [currentElement].
  SourceSpan spanFromSpannable(Spannable spannable, Entity? currentElement) {
    return _elementMap.getSourceSpan(spannable, currentElement);
  }
}

class KernelWorkItemBuilder implements WorkItemBuilder {
  final CompilerTask _compilerTask;
  final KernelToElementMap _elementMap;
  final KernelNativeMemberResolver _nativeMemberResolver;
  final AnnotationsDataBuilder _annotationsDataBuilder;
  final Map<MemberEntity, ClosureScopeModel> _closureModels;
  final Map<Entity, WorldImpact> _impactCache;
  final KFieldAnalysis _fieldAnalysis;
  final ModularStrategy _modularStrategy;
  final IrAnnotationData _irAnnotationData;
  final BackendImpacts _impacts;
  final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
  final BackendUsageBuilder _backendUsageBuilder;
  final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
  final RuntimeTypesNeedBuilder _rtiNeedBuilder;
  final AnnotationsData _annotationsData;

  KernelWorkItemBuilder(
    this._compilerTask,
    this._elementMap,
    NativeBasicData nativeBasicData,
    NativeDataBuilder nativeDataBuilder,
    this._annotationsDataBuilder,
    this._closureModels,
    this._impactCache,
    this._fieldAnalysis,
    this._modularStrategy,
    this._irAnnotationData,
    this._impacts,
    this._nativeResolutionEnqueuer,
    this._backendUsageBuilder,
    this._customElementsResolutionAnalysis,
    this._rtiNeedBuilder,
    this._annotationsData,
  ) : _nativeMemberResolver = KernelNativeMemberResolver(
        _elementMap,
        nativeBasicData,
        nativeDataBuilder,
      );

  @override
  WorkItem createWorkItem(MemberEntity entity) {
    return KernelWorkItem(
      _compilerTask,
      _elementMap,
      _nativeMemberResolver,
      _annotationsDataBuilder,
      entity,
      _closureModels,
      _impactCache,
      _fieldAnalysis,
      _modularStrategy,
      _irAnnotationData,
      _impacts,
      _nativeResolutionEnqueuer,
      _backendUsageBuilder,
      _customElementsResolutionAnalysis,
      _rtiNeedBuilder,
      _annotationsData,
    );
  }
}

class KernelWorkItem implements WorkItem {
  final CompilerTask _compilerTask;
  final KernelToElementMap _elementMap;
  final KernelNativeMemberResolver _nativeMemberResolver;
  final AnnotationsDataBuilder _annotationsDataBuilder;
  @override
  final MemberEntity element;
  final Map<MemberEntity, ClosureScopeModel> _closureModels;
  final Map<Entity, WorldImpact> _impactCache;
  final KFieldAnalysis _fieldAnalysis;
  final ModularStrategy _modularStrategy;
  final IrAnnotationData _irAnnotationData;
  final BackendImpacts _impacts;
  final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
  final BackendUsageBuilder _backendUsageBuilder;
  final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis;
  final RuntimeTypesNeedBuilder _rtiNeedBuilder;
  final AnnotationsData _annotationsData;

  KernelWorkItem(
    this._compilerTask,
    this._elementMap,
    this._nativeMemberResolver,
    this._annotationsDataBuilder,
    this.element,
    this._closureModels,
    this._impactCache,
    this._fieldAnalysis,
    this._modularStrategy,
    this._irAnnotationData,
    this._impacts,
    this._nativeResolutionEnqueuer,
    this._backendUsageBuilder,
    this._customElementsResolutionAnalysis,
    this._rtiNeedBuilder,
    this._annotationsData,
  );

  @override
  WorldImpact run() {
    return _compilerTask.measure(() {
      ir.Member node = _elementMap.getMemberNode(element);
      _nativeMemberResolver.resolveNativeMember(node, _irAnnotationData);

      List<PragmaAnnotationData> pragmaAnnotationData = _modularStrategy
          .getPragmaAnnotationData(node);

      EnumSet<PragmaAnnotation> annotations = processMemberAnnotations(
        _elementMap.options,
        _elementMap.reporter,
        node,
        pragmaAnnotationData,
      );
      _annotationsDataBuilder.registerPragmaAnnotations(element, annotations);
      // TODO(sra): Replace the above three statements with a single call to a
      // new API on AnnotationsData that causes the annotations to be parsed and
      // checked.

      ModularMemberData modularMemberData = _modularStrategy
          .getModularMemberData(node);
      ScopeModel scopeModel = modularMemberData.scopeModel;
      if (scopeModel.closureScopeModel != null) {
        _closureModels[element] = scopeModel.closureScopeModel!;
      }
      if (element is FieldEntity && !element.isInstanceMember) {
        _fieldAnalysis.registerStaticField(
          element as JField,
          scopeModel.initializerComplexity,
        );
      }
      ImpactBuilderData impactBuilderData = modularMemberData.impactBuilderData;
      return _compilerTask.measureSubtask('worldImpact', () {
        WorldImpact worldImpact = _elementMap.computeWorldImpact(
          element as JMember,
          _impacts,
          _nativeResolutionEnqueuer,
          _backendUsageBuilder,
          _customElementsResolutionAnalysis,
          _rtiNeedBuilder,
          _annotationsData,
          impactBuilderData,
        );
        _impactCache[element] = worldImpact;
        return worldImpact;
      });
    });
  }

  @override
  String toString() => 'KernelWorkItem($element)';
}

class KernelModularStrategy extends ModularStrategy {
  final CompilerTask _compilerTask;
  final KernelToElementMap _elementMap;

  KernelModularStrategy(this._compilerTask, this._elementMap);

  @override
  List<PragmaAnnotationData> getPragmaAnnotationData(ir.Member node) {
    return computePragmaAnnotationDataFromIr(node);
  }

  @override
  ModularMemberData getModularMemberData(ir.Member node) {
    ScopeModel scopeModel = _compilerTask.measureSubtask(
      'closures',
      () => ScopeModel.from(node, _elementMap.typeEnvironment),
    );
    return _compilerTask.measureSubtask('worldImpact', () {
      return computeModularMemberData(_elementMap, node, scopeModel);
    });
  }
}
