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

import 'dart:collection';

import 'package:_fe_analyzer_shared/src/messages/codes.dart'
    show Message, LocatedMessage;
import 'package:_js_interop_checks/js_interop_checks.dart';
import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart';
import 'package:_js_interop_checks/src/transformations/shared_interop_transformer.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart' hide Pattern;
import 'package:kernel/reference_from_index.dart';
import 'package:kernel/target/changed_structure_notifier.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/transformations/track_widget_constructor_locations.dart';
import 'package:kernel/type_environment.dart';

import 'constants.dart' show DevCompilerConstantsBackend;
import 'kernel_helpers.dart';

/// A kernel [Target] to configure the Dart Front End for dartdevc.
class DevCompilerTarget extends Target {
  DevCompilerTarget(this.flags);

  @override
  final TargetFlags flags;

  WidgetCreatorTracker? _widgetTracker;

  Map<String, Class>? _nativeClasses;

  DiagnosticReporter<Message, LocatedMessage>? _diagnosticReporter;

  @override
  int get enabledLateLowerings => LateLowering.all;

  @override
  bool get supportsLateLoweringSentinel => false;

  @override
  bool get useStaticFieldLowering => false;

  // TODO(johnniwinther,sigmund): Remove this when js-interop handles getter
  //  calls encoded with an explicit property get or disallows getter calls.
  @override
  bool get supportsExplicitGetterCalls => false;

  @override
  int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.all;

  @override
  String get name => 'dartdevc';

  @override
  List<String> get extraRequiredLibraries => const [
        'dart:_ddc_only',
        'dart:_runtime',
        'dart:_async_status_codes',
        'dart:_js_shared_embedded_names',
        'dart:_recipe_syntax',
        'dart:_rti',
        'dart:_debugger',
        'dart:_foreign_helper',
        'dart:_interceptors',
        'dart:_internal',
        'dart:_isolate_helper',
        'dart:_js_annotations',
        'dart:_js_helper',
        'dart:_js_names',
        'dart:_js_primitives',
        'dart:_js_types',
        'dart:_metadata',
        'dart:_native_typed_data',
        'dart:async',
        'dart:collection',
        'dart:convert',
        'dart:developer',
        'dart:io',
        'dart:isolate',
        'dart:js',
        'dart:js_interop',
        'dart:js_interop_unsafe',
        'dart:js_util',
        'dart:math',
        'dart:typed_data',
        'dart:indexed_db',
        'dart:html',
        'dart:html_common',
        'dart:svg',
        'dart:web_audio',
        'dart:web_gl',
      ];

  // The libraries required to be indexed via CoreTypes.
  @override
  List<String> get extraIndexedLibraries => const [
        'dart:async',
        'dart:collection',
        'dart:html',
        'dart:indexed_db',
        'dart:js',
        'dart:js_util',
        'dart:js_interop',
        'dart:js_interop_unsafe',
        'dart:math',
        'dart:svg',
        'dart:typed_data',
        'dart:web_audio',
        'dart:web_gl',
        'dart:_foreign_helper',
        'dart:_interceptors',
        'dart:_js_helper',
        'dart:_js_types',
        'dart:_native_typed_data',
        'dart:_runtime',
        'dart:_rti',
      ];

  @override
  bool mayDefineRestrictedType(Uri uri) =>
      uri.isScheme('dart') &&
      (uri.path == 'core' ||
          uri.path == 'typed_data' ||
          uri.path == '_interceptors' ||
          uri.path == '_js_helper' ||
          uri.path == '_native_typed_data' ||
          uri.path == '_runtime');

  /// Returns [true] if [uri] represents a test script has been whitelisted to
  /// import private platform libraries.
  ///
  /// Unit tests for the dart:_runtime library have imports like this. It is
  /// only allowed from a specific SDK test directory or through the modular
  /// test framework.
  bool _allowedTestLibrary(Uri uri) {
    // Multi-root scheme used by modular test framework.
    if (uri.isScheme('dev-dart-app')) return true;
    // Test package used by expression evaluation tests.
    if (uri.isScheme('package') && uri.path == 'eval_test/test.dart') {
      return true;
    }
    return allowedNativeTest(uri);
  }

  bool _allowedDartLibrary(Uri uri) => uri.isScheme('dart');

  @override
  bool enableNative(Uri uri) =>
      _allowedTestLibrary(uri) || _allowedDartLibrary(uri);

  @override
  bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) =>
      super.allowPlatformPrivateLibraryAccess(importer, imported) ||
      _allowedTestLibrary(importer) ||
      (importer.isScheme('package') &&
          (importer.path.startsWith('dart2js_runtime_metrics/') ||
              importer.path == 'js/js.dart'));

  @override
  bool get errorOnUnexactWebIntLiterals => true;

  @override
  bool get enableNoSuchMethodForwarders => true;

  @override
  void performModularTransformationsOnLibraries(
      Component component,
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      List<Library> libraries,
      Map<String, String>? environmentDefines,
      DiagnosticReporter diagnosticReporter,
      ReferenceFromIndex? referenceFromIndex,
      {void Function(String msg)? logger,
      ChangedStructureNotifier? changedStructureNotifier}) {
    _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
    _diagnosticReporter =
        diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>;
    _performTransformations(coreTypes, hierarchy, libraries);
  }

  @override
  void performTransformationsOnProcedure(
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
      Procedure procedure,
      Map<String, String>? environmentDefines,
      {void Function(String)? logger}) {
    _performTransformations(coreTypes, hierarchy, [procedure]);
  }

  void _performTransformations(
    CoreTypes coreTypes,
    ClassHierarchy hierarchy,
    List<TreeNode> nodes,
  ) {
    final jsInteropReporter = JsInteropDiagnosticReporter(_diagnosticReporter!);
    final jsInteropChecks = JsInteropChecks(
        coreTypes, hierarchy, jsInteropReporter, _nativeClasses!);
    for (var node in nodes) {
      // Process and validate first before doing anything with exports.
      node.accept(jsInteropChecks);
    }
    final sharedInteropTransformer = SharedInteropTransformer(
        TypeEnvironment(coreTypes, hierarchy),
        jsInteropReporter,
        jsInteropChecks.exportChecker,
        jsInteropChecks.extensionIndex);
    final jsUtilOptimizer = JsUtilOptimizer(
        coreTypes, hierarchy, jsInteropChecks.extensionIndex,
        isDart2JS: false);
    for (var node in nodes) {
      _CovarianceTransformer(node).transform();
      // Shared interop transformer has static checks, so we still visit.
      node.accept(sharedInteropTransformer);
      if (!jsInteropReporter.hasJsInteropErrors) {
        // We can't guarantee calls are well-formed, so don't transform.
        node.accept(jsUtilOptimizer);
      }
    }
  }

  @override
  void performPreConstantEvaluationTransformations(
      Component component,
      CoreTypes coreTypes,
      List<Library> libraries,
      DiagnosticReporter diagnosticReporter,
      {void Function(String msg)? logger,
      ChangedStructureNotifier? changedStructureNotifier}) {
    if (flags.trackWidgetCreation) {
      _widgetTracker ??= WidgetCreatorTracker();
      _widgetTracker!.transform(component, libraries, changedStructureNotifier);
    }
  }

  @override
  Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver,
      String name, Arguments arguments, int offset, bool isSuper) {
    // TODO(jmesserly): preserve source information?
    // (These method are synthetic. Also unclear if the offset will correspond
    // to the file where the class resides, or the file where the method we're
    // mocking resides).
    Expression createInvocation(String name, List<Expression> positional) {
      // TODO(jmesserly): this uses the implementation _Invocation class,
      // because the CFE does not resolve the redirecting factory constructors
      // like it would for user code. Our code generator expects all redirecting
      // factories to be resolved to the real constructor.
      var ctor = coreTypes.index
          .getClass('dart:core', '_Invocation')
          .constructors
          .firstWhere((c) => c.name.text == name);
      return ConstructorInvocation(ctor, Arguments(positional));
    }

    if (name.startsWith('get:')) {
      return createInvocation('getter', [SymbolLiteral(name.substring(4))]);
    }
    if (name.startsWith('set:')) {
      return createInvocation('setter',
          [SymbolLiteral(name.substring(4)), arguments.positional.single]);
    }
    var ctorArgs = <Expression>[
      SymbolLiteral(name),
      if (arguments.types.isNotEmpty)
        ListLiteral([for (var t in arguments.types) TypeLiteral(t)])
      else
        NullLiteral(),
      ListLiteral(arguments.positional),
      if (arguments.named.isNotEmpty)
        MapLiteral([
          for (var n in arguments.named)
            MapLiteralEntry(SymbolLiteral(n.name), n.value)
        ], keyType: coreTypes.symbolNonNullableRawType)
      else
        NullLiteral(),
    ];
    return createInvocation('method', ctorArgs);
  }

  @override
  Expression instantiateNoSuchMethodError(CoreTypes coreTypes,
      Expression receiver, String name, Arguments arguments, int offset,
      {bool isMethod = false,
      bool isGetter = false,
      bool isSetter = false,
      bool isField = false,
      bool isLocalVariable = false,
      bool isDynamic = false,
      bool isSuper = false,
      bool isStatic = false,
      bool isConstructor = false,
      bool isTopLevel = false}) {
    // TODO(sigmund): implement;
    return InvalidExpression(null);
  }

  @override
  ConstantsBackend get constantsBackend => const DevCompilerConstantsBackend();

  @override
  DartLibrarySupport get dartLibrarySupport =>
      const DevCompilerDartLibrarySupport();
}

class DevCompilerDartLibrarySupport extends CustomizedDartLibrarySupport {
  // This is required so that `dart.library._ddc_only` can be used as an import
  // condition. Libraries with leading underscores are otherwise considered
  // unsupported regardless of the library specification.
  const DevCompilerDartLibrarySupport() : super(supported: const {'_ddc_only'});
}

/// Analyzes a component to determine if any covariance checks in private
/// members can be eliminated, and adjusts the flags to remove those checks.
///
/// See [_CovarianceTransformer.transform].
class _CovarianceTransformer extends RecursiveVisitor {
  /// The set of private instance members in [_library] that (potentially) need
  /// covariance checks.
  ///
  /// Members need checks if they are accessed through a receiver whose type is
  /// not exactly known (i.e. the actual receiver could be a subtype of its
  /// static type). If the receiver expression is `this`, `super` or non-factory
  /// instance creation, it is known to have an exact type.
  final _checkedMembers = HashSet<Member>();

  /// List of private instance procedures.
  ///
  /// [transform] uses this list to eliminate covariance flags for members that
  /// aren't in [_checkedMembers].
  final _privateProcedures = <Procedure>[];

  /// List of private instance fields.
  ///
  /// [transform] uses this list to eliminate covariance flags for members that
  /// aren't in [_checkedMembers].
  final _privateFields = <Field>[];

  late final Library _library;

  /// Create covariance transformer from a node.
  ///
  /// The [_node] is expected to be a [Library] in initial compilation
  /// and a [Procedure] in the interactive expression compilation.
  _CovarianceTransformer(TreeNode node) {
    assert(
      node is Library || node is Procedure,
      'Unexpected node in _CovarianceTransformer',
    );
    if (node is Library) _library = node;
    if (node is Procedure) _library = node.enclosingLibrary;
  }

  /// Transforms [_library], eliminating unnecessary checks for private members.
  ///
  /// Kernel will mark covariance checks on members, for example:
  /// - a field with [Field.isCovariantByClass] or
  ///   [Field.isCovariantByDeclaration].
  /// - a method/setter with parameter(s) or type parameter(s) that have
  ///   `isCovariantByClass` or `isCovariantByDeclaration` set.
  ///
  /// If the check can be safely eliminated, those properties will be set to
  /// false so the JS compiler does not emit checks.
  ///
  /// Public members always need covariance checks (we cannot see all potential
  /// call sites), but in some cases we can eliminate these checks for private
  /// members.
  ///
  /// Private members only need covariance checks if they are accessed through a
  /// receiver whose type is not exactly known (i.e. the actual receiver could
  /// be a subtype of its static type). If the receiver expression is `this`,
  /// `super` or non-factory instance creation, it is known to have an exact
  /// type, so no callee check is necessary to ensure soundness (normal
  /// subtyping checks at the call site are sufficient).
  ///
  /// However to eliminate a check, we must know that all call sites are safe.
  /// So the first pass is to collect any potentially-unsafe call sites, this
  /// is done by [_checkTarget] and [_checkTearoff].
  ///
  /// Method tearoffs must also be marked potentially-unsafe, regardless of
  /// whether the receiver type is known, because they could escape. Also their
  /// runtime type must store `Object` in for covariant parameters (this
  /// affects `is`, casts, and the `.runtimeType` property).
  ///
  /// Note 1: dynamic calls do not need to be considered here, because they
  /// will be checked based on runtime type information.
  ///
  /// Node 2: public members in private classes cannot be treated as private
  /// unless we know that the member is not exposed via some public interface
  /// (implemented by their class or a subclass) that needs a covariance check.
  /// That is somewhat complex to analyze, so for now we ignore it.
  void transform() {
    _library.visitChildren(this);

    // Update the tree based on the methods that need checks.
    for (var field in _privateFields) {
      if (!_checkedMembers.contains(field)) {
        field.isCovariantByDeclaration = false;
        field.isCovariantByClass = false;
      }
    }
    void clearCovariant(VariableDeclaration parameter) {
      parameter.isCovariantByDeclaration = false;
      parameter.isCovariantByClass = false;
    }

    for (var member in _privateProcedures) {
      if (!_checkedMembers.contains(member)) {
        var function = member.function;
        function.positionalParameters.forEach(clearCovariant);
        function.namedParameters.forEach(clearCovariant);
        for (var t in function.typeParameters) {
          t.isCovariantByClass = false;
        }
      }
    }
  }

  /// Checks if [target] is a private member called through a [receiver] that
  /// will potentially need a covariance check.
  ///
  /// If the member needs a check it will be stored in [_checkedMembers].
  ///
  /// See [transform] for more information.
  void _checkTarget(Expression receiver, Member? target) {
    if (target != null &&
        target.name.isPrivate &&
        target.isInstanceMember &&
        receiver is! ThisExpression &&
        receiver is! ConstructorInvocation) {
      assert(target.enclosingLibrary == _library,
          'call to private member must be in same library');
      _checkedMembers.add(target);
    }
  }

  /// Checks if [target] is a tearoff of a private member.
  ///
  /// In this case we will need a covariance check, because the method could
  /// escape, and it also has a different runtime type.
  ///
  /// See [transform] for more information.
  void _checkTearoff(Member? target) {
    if (target != null &&
        target.name.isPrivate &&
        target.isInstanceMember &&
        target is Procedure &&
        !target.isAccessor) {
      assert(target.enclosingLibrary == _library,
          'tearoff of private member must be in same library');
      _checkedMembers.add(target);
    }
  }

  @override
  void visitProcedure(Procedure node) {
    if (node.name.isPrivate &&
        // The member must be private to this library. Member signatures,
        // forwarding stubs and noSuchMethod forwarders for private members in
        // other libraries can be injected.
        node.name.library == _library &&
        node.isInstanceMember &&
        // No need to check abstract methods.
        node.function.body != null) {
      _privateProcedures.add(node);
    }
    super.visitProcedure(node);
  }

  @override
  void visitField(Field node) {
    if (node.name.isPrivate &&
        // The member must be private to this library. Member signatures,
        // forwarding stubs and noSuchMethod forwarders for private members in
        // other libraries can be injected.
        node.name.library == _library &&
        isCovariantField(node)) {
      _privateFields.add(node);
    }
    super.visitField(node);
  }

  @override
  void visitInstanceGet(InstanceGet node) {
    _checkTearoff(node.interfaceTarget);
    super.visitInstanceGet(node);
  }

  @override
  void visitInstanceSet(InstanceSet node) {
    _checkTarget(node.receiver, node.interfaceTarget);
    super.visitInstanceSet(node);
  }

  @override
  void visitInstanceInvocation(InstanceInvocation node) {
    _checkTarget(node.receiver, node.interfaceTarget);
    super.visitInstanceInvocation(node);
  }

  @override
  void visitInstanceGetterInvocation(InstanceGetterInvocation node) {
    _checkTarget(node.receiver, node.interfaceTarget);
    super.visitInstanceGetterInvocation(node);
  }

  @override
  void visitInstanceTearOff(InstanceTearOff node) {
    _checkTearoff(node.interfaceTarget);
    super.visitInstanceTearOff(node);
  }

  @override
  void visitEqualsCall(EqualsCall node) {
    _checkTarget(node.left, node.interfaceTarget);
    super.visitEqualsCall(node);
  }
}

List<Pattern> _allowedNativeTestPatterns = [
  'tests/dartdevc',
  'tests/web/native',
  'tests/web/internal',
];

bool allowedNativeTest(Uri uri) {
  var path = uri.path;
  return _allowedNativeTestPatterns.any((pattern) => path.contains(pattern));
}
