// Copyright (c) 2022, 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:async';
import 'dart:typed_data';

// ignore: implementation_imports
import 'package:_js_interop_checks/src/deprecated_js_interop_imports.dart'
    show
        DeprecatedJsInteropImportPaths,
        findDeprecatedJsInteropImportPaths,
        formatImportTree,
        hasDeprecatedJsInteropImports;
// ignore: implementation_imports
import 'package:_js_interop_checks/src/transformations/static_interop_class_eraser.dart';
import 'package:collection/collection.dart';
// ignore: implementation_imports
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/core_types.dart' as ir;
import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator;
import 'package:kernel/target/targets.dart' hide DiagnosticReporter;
import 'package:kernel/type_environment.dart' as ir;
import 'package:kernel/verifier.dart';

import '../../compiler_api.dart' as api;
import '../common.dart';
import '../diagnostics/diagnostic_listener.dart';
import '../environment.dart';
import '../ir/annotations.dart';
import '../ir/constants.dart';
import '../kernel/dart2js_target.dart'
    show
        Dart2jsConstantsBackend,
        Dart2jsDartLibrarySupport,
        Dart2jsTarget,
        implicitlyUsedLibraries;
import '../kernel/front_end_adapter.dart';
import '../kernel/transformations/global/transform.dart' as global_transforms;
import '../options.dart';

class Input {
  final CompilerOptions options;
  final api.CompilerInput compilerInput;
  final DiagnosticReporter reporter;

  /// Shared state between compilations. Only used when loading from source.
  final fe.InitializedCompilerState? initializedCompilerState;

  // TODO(johnniwinther): Remove this when #34942 is fixed.
  /// Force in-memory serialization/deserialization of the loaded component.
  ///
  /// This is used for testing.
  final bool forceSerialization;

  Input(
    this.options,
    this.compilerInput,
    this.reporter,
    this.initializedCompilerState,
    this.forceSerialization,
  );
}

/// Result of invoking the CFE to produce the kernel IR.
class Output {
  final ir.Component component;

  /// The [Uri] of the root library containing main.
  /// Note: rootLibraryUri will be null for some modules, for example in the
  /// case of dependent libraries processed modularly.
  final Uri? rootLibraryUri;

  /// Returns the [Uri]s of all libraries that have been loaded that are
  /// reachable from the [rootLibraryUri].
  ///
  /// Note that [component] may contain some libraries that are excluded here.
  final List<Uri>? libraries;

  final fe.InitializedCompilerState? initializedCompilerState;

  Output withNewComponent(ir.Component component) =>
      Output(component, rootLibraryUri, libraries, initializedCompilerState);

  Output(
    this.component,
    this.rootLibraryUri,
    this.libraries,
    this.initializedCompilerState,
  );
}

Library _findEntryLibrary(Component component, Uri entryUri) {
  final entryLibrary = component.libraries.firstWhereOrNull(
    (l) => l.fileUri == entryUri,
  );
  if (entryLibrary == null) {
    throw ArgumentError('Entry uri $entryUri not found in dill.');
  }
  return entryLibrary;
}

ir.Reference _findMainMethod(Library entryLibrary) {
  var mainMethod = entryLibrary.procedures.firstWhereOrNull(
    (p) => p.name.text == 'main',
  );

  // In some cases, a main method is defined in another file, and then
  // exported. In these cases, we search for the main method in
  // [additionalExports].
  ir.Reference? mainMethodReference;
  if (mainMethod == null) {
    mainMethodReference = entryLibrary.additionalExports.firstWhereOrNull(
      (p) => p.canonicalName?.name == 'main',
    );
  } else {
    mainMethodReference = mainMethod.reference;
  }
  if (mainMethodReference == null) {
    throw ArgumentError(
      'Entry uri ${entryLibrary.fileUri} has no main method.',
    );
  }
  return mainMethodReference;
}

String _getPlatformFilename(String targetName) => "${targetName}_platform.dill";

class _LoadFromKernelResult {
  final ir.Component? component;
  final Library? entryLibrary;

  _LoadFromKernelResult(this.component, this.entryLibrary);
}

void _simplifyConstConditionals(
  ir.Component component,
  CompilerOptions options,
  ir.ClassHierarchy classHierarchy,
  DiagnosticReporter reporter,
) {
  void reportMessage(
    fe.LocatedMessage message,
    List<fe.LocatedMessage>? context,
  ) {
    reportLocatedMessage(reporter, message, context);
  }

  bool shouldNotInline(ir.TreeNode node) {
    if (node is! ir.Annotatable) {
      return false;
    }
    return computePragmaAnnotationDataFromIr(node).any(
      (PragmaAnnotationData pragma) =>
          pragma == const PragmaAnnotationData('noInline') ||
          pragma == const PragmaAnnotationData('never-inline'),
    );
  }

  fe.ConstConditionalSimplifier(
    Dart2jsDartLibrarySupport(deprecatedJsInterop: options.deprecatedJsInterop),
    const Dart2jsConstantsBackend(supportsUnevaluatedConstants: false),
    component,
    reportMessage,
    environmentDefines: options.environment,
    classHierarchy: classHierarchy,
    shouldNotInline: shouldNotInline,
    removeAsserts: !options.enableUserAssertions,
  ).run();
}

// Perform any backend-specific transforms here that can be done on both
// serialized components and components from source.
void _doTransformsOnKernelLoad(
  Component component,
  CompilerOptions options,
  DiagnosticReporter reporter,
) {
  if (options.stage.shouldRunGlobalTransforms) {
    ir.CoreTypes coreTypes = ir.CoreTypes(component);
    // Ignore ambiguous supertypes.
    final classHierarchy = ir.ClassHierarchy(
      component,
      coreTypes,
      onAmbiguousSupertypes: (_, _, _) {},
    );
    ir.TypeEnvironment typeEnvironment = ir.TypeEnvironment(
      coreTypes,
      classHierarchy,
    );
    final constantsEvaluator = Dart2jsConstantEvaluator(
      component,
      typeEnvironment,
      (fe.LocatedMessage message, List<fe.LocatedMessage>? context) =>
          reportLocatedMessage(reporter, message, context),
      environment: Environment(options.environment),
      deprecatedJsInterop: options.deprecatedJsInterop,
    );
    StaticInteropClassEraser(coreTypes).visitComponent(component);
    global_transforms.transformLibraries(
      component.libraries,
      constantsEvaluator,
      coreTypes,
      options,
    );
    _simplifyConstConditionals(component, options, classHierarchy, reporter);
  }
}

/// Reports how each deprecated JS interop import is reachable from
/// [entryLibrary].
///
/// When compiling from source, the CFE already reports an error at each such
/// import when deprecated JS interop is disabled. This adds a single message
/// after those errors showing the shortest import paths from the entrypoint to
/// the deprecated JS interop libraries as a tree. Libraries in packages other
/// than the entrypoint's own package are grouped by package, and repeated
/// subtrees are only shown once.
///
/// The message is an info if an error was already reported. Otherwise, such
/// as when the imports are in libraries loaded from a `.dill` file, it is an
/// error that also explains how to fix the imports, so that compilation fails
/// instead of silently producing no output.
///
/// Does nothing unless deprecated JS interop is disabled. The import graph is
/// only built if some library in [component] imports a deprecated JS interop
/// library. Returns `true` if any deprecated JS interop imports reachable from
/// [entryLibrary] were found.
bool _reportDeprecatedJsInteropImports(
  CompilerOptions options,
  Component component,
  Library? entryLibrary,
  DiagnosticReporter reporter,
) {
  if (options.deprecatedJsInterop || entryLibrary == null) return false;
  if (!hasDeprecatedJsInteropImports(component.libraries)) return false;
  final importPaths = findDeprecatedJsInteropImportPaths(entryLibrary);
  if (importPaths.isEmpty) return false;
  if (reporter.hasReportedError) {
    reporter.reportInfoMessage(noLocationSpannable, MessageKind.generic, {
      'text': _importPathsText(importPaths),
    });
  } else {
    reporter.reportErrorMessage(noLocationSpannable, MessageKind.generic, {
      'text': _unreportedImportsErrorText(importPaths),
    });
  }
  return true;
}

/// Explains how to fix imports of deprecated JS interop libraries, as in the
/// error that the CFE reports at each such import.
const String _deprecatedJsInteropMigrationHint =
    "Migrate to 'package:web' and 'dart:js_interop' (see "
    'https://dart.dev/interop/js-interop/past-js-interop), or temporarily '
    "enable the 'deprecated-js-interop' option.";

/// Returns the text of the error listing [importPaths] when the CFE hasn't
/// reported the imports, which also explains why they are an error and how to
/// fix them.
String _unreportedImportsErrorText(
  DeprecatedJsInteropImportPaths importPaths,
) => [
  'Imports of deprecated JS interop libraries are not allowed.',
  _importPathsText(importPaths),
  _deprecatedJsInteropMigrationHint,
].join('\n');

/// Returns the text of the info message listing [importPaths] from the main
/// library.
String _importPathsText(DeprecatedJsInteropImportPaths importPaths) {
  final tree = formatImportTree(importPaths, rootLabel: 'main library');
  return [
    'Deprecated JS interop libraries are imported through:',
    for (final line in tree.split('\n')) '  $line',
  ].join('\n');
}

/// Returns the library compiled from source for [entryUri], falling back to
/// the library that declares `main`.
Library? _findSourceEntryLibrary(Component component, Uri entryUri) =>
    component.libraries.firstWhereOrNull(
      (library) => library.importUri == entryUri || library.fileUri == entryUri,
    ) ??
    component.mainMethod?.enclosingLibrary;

/// Returns [state] if it can be reused for a compilation with [options], or
/// `null` otherwise.
///
/// The CFE reuses compiler state, including its target, without comparing
/// targets. State created for a target with a different
/// [CompilerOptions.deprecatedJsInterop] value would resolve `dart.library.*`
/// conditions incorrectly, so it must be discarded.
fe.InitializedCompilerState? _reusableCompilerState(
  fe.InitializedCompilerState? state,
  CompilerOptions options,
) {
  final oldTarget = state?.options.target;
  if (oldTarget is Dart2jsTarget &&
      oldTarget.deprecatedJsInterop != options.deprecatedJsInterop) {
    return null;
  }
  return state;
}

Future<_LoadFromKernelResult> _loadFromKernel(
  CompilerOptions options,
  api.CompilerInput compilerInput,
  String targetName,
  DiagnosticReporter reporter,
) async {
  Library? entryLibrary;
  var resolvedUri = options.compilationTarget;
  ir.Component component = ir.Component();

  Future<void> read(Uri uri) async {
    api.Input<Uint8List> input = await compilerInput.readFromUri(
      uri,
      inputKind: api.InputKind.binary,
    );
    BinaryBuilder(input.data).readComponent(component);
  }

  await read(resolvedUri);

  if (options.platformBinaries != null &&
      options.stage.shouldReadPlatformBinaries) {
    var platformUri = options.platformBinaries?.resolve(
      _getPlatformFilename(targetName),
    );
    // TODO(joshualitt): Change how we detect this case so it is less
    // brittle.
    if (platformUri != resolvedUri) await read(platformUri!);
  }

  // Concatenate dills.
  if (options.dillDependencies != null) {
    for (Uri dependency in options.dillDependencies!) {
      await read(dependency);
    }
  }

  if (options.entryUri != null) {
    entryLibrary = _findEntryLibrary(component, options.entryUri!);
    var mainMethod = _findMainMethod(entryLibrary);
    component.setMainMethodAndMode(mainMethod, true);
  }

  if (_reportDeprecatedJsInteropImports(
    options,
    component,
    entryLibrary ?? component.mainMethod?.enclosingLibrary,
    reporter,
  )) {
    return _LoadFromKernelResult(null, entryLibrary);
  }
  _doTransformsOnKernelLoad(component, options, reporter);
  registerSources(component, compilerInput);
  return _LoadFromKernelResult(component, entryLibrary);
}

class _LoadFromSourceResult {
  final ir.Component? component;
  final fe.InitializedCompilerState initializedCompilerState;

  _LoadFromSourceResult(this.component, this.initializedCompilerState);
}

Future<_LoadFromSourceResult> _loadFromSource(
  CompilerOptions options,
  api.CompilerInput compilerInput,
  DiagnosticReporter reporter,
  fe.InitializedCompilerState? initializedCompilerState,
  String targetName,
) async {
  bool verbose = false;
  bool cfeConstants = options.features.cfeConstants.isEnabled;
  Map<String, String>? environment = cfeConstants ? options.environment : null;
  Target target = Dart2jsTarget(
    targetName,
    TargetFlags(),
    options: options,
    supportsUnevaluatedConstants: !cfeConstants,
  );
  fe.FileSystem fileSystem = CompilerFileSystem(compilerInput);
  fe.Verbosity verbosity = options.verbosity;
  void onDiagnostic(fe.CfeDiagnosticMessage message) {
    if (fe.Verbosity.shouldPrint(verbosity, message)) {
      reportFrontEndMessage(reporter, message);
    }
  }

  List<Uri> sources = [options.compilationTarget];

  List<Uri> dependencies = [];
  if (options.platformBinaries != null) {
    dependencies.add(
      options.platformBinaries!.resolve(_getPlatformFilename(targetName)),
    );
  }
  if (options.dillDependencies != null) {
    dependencies.addAll(options.dillDependencies!);
  }

  initializedCompilerState = fe.initializeCompiler(
    _reusableCompilerState(initializedCompilerState, options),
    target,
    options.librariesSpecificationUri,
    dependencies,
    options.packageConfig,
    explicitExperimentalFlags: options.explicitExperimentalFlags,
    environmentDefines: environment,
    invocationModes: options.cfeInvocationModes,
    verbosity: verbosity,
  );
  ir.Component? component = await fe.compile(
    initializedCompilerState,
    verbose,
    fileSystem,
    onDiagnostic,
    sources,
  );

  if (component != null) {
    assert(() {
      verifyComponent(
        target,
        VerificationStage.afterModularTransformations,
        component,
      );
      return true;
    }());

    if (_reportDeprecatedJsInteropImports(
      options,
      component,
      _findSourceEntryLibrary(component, options.compilationTarget),
      reporter,
    )) {
      return _LoadFromSourceResult(null, initializedCompilerState);
    }
    _doTransformsOnKernelLoad(component, options, reporter);

    registerSources(component, compilerInput);
  }

  return _LoadFromSourceResult(component, initializedCompilerState);
}

Output _createOutput(
  CompilerOptions options,
  DiagnosticReporter reporter,
  Library? entryLibrary,
  ir.Component component,
  fe.InitializedCompilerState? initializedCompilerState,
) {
  Uri? rootLibraryUri;
  Iterable<ir.Library> libraries = component.libraries;
  if (component.mainMethod == null) {
    // TODO(sigmund): move this so that we use the same error template
    // from the CFE.
    reporter.reportError(
      reporter.createMessage(noLocationSpannable, MessageKind.generic, {
        'text': "No 'main' method found.",
      }),
    );
  }

  // If we are building from dill and are passed an [entryUri], then we use
  // that to find the appropriate [entryLibrary]. Otherwise, we fallback to
  // the [enclosingLibrary] of the [mainMethod].
  // NOTE: Under some circumstances, the [entryLibrary] exports the
  // [mainMethod] from another library, and thus the [enclosingLibrary] of
  // the [mainMethod] may not be the same as the [entryLibrary].
  var root = entryLibrary ?? component.mainMethod!.enclosingLibrary;
  rootLibraryUri = root.importUri;

  // Filter unreachable libraries: [Component] was built by linking in the
  // entire SDK libraries, not all of them are used. We include anything
  // that is reachable from `main`. Note that all internal libraries that
  // the compiler relies on are reachable from `dart:core`.
  var seen = <Library>{};
  void search(ir.Library current) {
    if (!seen.add(current)) return;
    for (ir.LibraryDependency dep in current.dependencies) {
      search(dep.targetLibrary);
    }
  }

  search(root);

  // Libraries dependencies do not show implicit imports to certain internal
  // libraries.
  const Set<String> alwaysInclude = {
    'dart:_internal',
    'dart:core',
    'dart:async',
    ...implicitlyUsedLibraries,
  };
  for (String uri in alwaysInclude) {
    Library library = component.libraries.firstWhere((lib) {
      return '${lib.importUri}' == uri;
    });
    search(library);
  }

  libraries = libraries.where(seen.contains);
  return Output(
    component,
    rootLibraryUri,
    libraries.map((lib) => lib.importUri).toList(),
    initializedCompilerState,
  );
}

/// Loads an entire Kernel [Component] from a file on disk.
Future<Output?> run(Input input) async {
  CompilerOptions options = input.options;
  api.CompilerInput compilerInput = input.compilerInput;
  DiagnosticReporter reporter = input.reporter;

  String targetName = options.compileForServer ? "dart2js_server" : "dart2js";

  Library? entryLibrary;
  ir.Component? component;
  fe.InitializedCompilerState? initializedCompilerState =
      input.initializedCompilerState;
  if (options.shouldLoadFromDill) {
    _LoadFromKernelResult result = await _loadFromKernel(
      options,
      compilerInput,
      targetName,
      reporter,
    );
    component = result.component;
    entryLibrary = result.entryLibrary;
  } else {
    _LoadFromSourceResult result = await _loadFromSource(
      options,
      compilerInput,
      reporter,
      input.initializedCompilerState,
      targetName,
    );
    component = result.component;
    initializedCompilerState = result.initializedCompilerState;
  }
  if (component == null) return null;
  if (input.forceSerialization) {
    // TODO(johnniwinther): Remove this when #34942 is fixed.
    Uint8List data = fe.serializeComponent(component);
    component = ir.Component();
    BinaryBuilder(data).readComponent(component);
    // Ensure we use the new deserialized entry point library.
    entryLibrary = _findEntryLibrary(component, options.entryUri!);
  }
  return _createOutput(
    options,
    reporter,
    entryLibrary,
    component,
    initializedCompilerState,
  );
}

/// Registers with the dart2js compiler all sources embedded in a kernel
/// component. This may include sources that were read from disk directly as
/// files, but also sources that were embedded in binary `.dill` files (like the
/// platform kernel file).
///
/// This registration improves how locations are presented when errors
/// or crashes are reported by the dart2js compiler.
void registerSources(ir.Component component, api.CompilerInput compilerInput) {
  component.uriToSource.forEach((uri, source) {
    compilerInput.registerUtf8ContentsForDiagnostics(uri, source.source);
  });
}
