// 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);
    });
  }
}
