// 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 '../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 'dart2js_target.dart';
import 'element_map.dart';
import 'element_map_impl.dart';
import 'native_basic_data.dart';
import 'no_such_method_resolver.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.classPragmaAnnotations,
      annotationsDataBuilder.memberPragmaAnnotations,
    );
    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 = processPragmaAnnotations(
        _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);
    });
  }
}
