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

// ignore_for_file: implementation_imports

/// A library to invoke the CFE to compute kernel summary files.
///
/// Used by `utils/bazel/kernel_worker.dart`.
library;

import 'dart:async';
import 'dart:io';

import 'package:args/args.dart';
import 'package:build_integration/file_system/multi_root.dart';
import 'package:compiler/src/kernel/dart2js_target.dart';
import 'package:dart2wasm/target.dart';
import 'package:dev_compiler/src/kernel/target.dart';
import 'package:front_end/src/api_prototype/file_system.dart';
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart';
import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
import 'package:front_end/src/api_unstable/frontend_server.dart';
import 'package:kernel/ast.dart' show Component, Library;
import 'package:kernel/target/targets.dart';
import 'package:vm/kernel_front_end.dart';
import 'package:vm/modular/target/flutter.dart';
import 'package:vm/modular/target/flutter_runner.dart';
import 'package:vm/modular/target/vm.dart';
import 'package:vm/native_assets/synthesizer.dart';

/// If the last arg starts with `@`, this reads the file it points to and treats
/// each line as an additional arg.
///
/// This is how individual work request args are differentiated from startup
/// args in bazel (individual work request args go in that file).
List<String> preprocessArgs(List<String> args) {
  args = new List.of(args);
  if (args.isEmpty) {
    return args;
  }
  String lastArg = args.last;
  if (lastArg.startsWith('@')) {
    File argsFile = new File(lastArg.substring(1));
    try {
      args.removeLast();
      args.addAll(argsFile.readAsLinesSync());
    } on FileSystemException catch (e) {
      throw new Exception('Failed to read file specified by $lastArg : $e');
    }
  }
  return args;
}

/// An [ArgParser] for generating kernel summaries.
final ArgParser summaryArgsParser = new ArgParser()
  ..addFlag('help', negatable: false, abbr: 'h')
  ..addFlag(
    'exclude-non-sources',
    negatable: false,
    help:
        'Whether source files loaded implicitly should be included as '
        'part of the summary.',
  )
  ..addFlag(
    'summary-only',
    defaultsTo: true,
    negatable: true,
    help: 'Whether to only build summary files.',
  )
  ..addFlag(
    'summary',
    defaultsTo: true,
    negatable: true,
    help: 'Whether or not to build summary files.',
  )
  ..addOption(
    'target',
    allowed: const [
      'vm',
      'flutter',
      'flutter_runner',
      'dart2js',
      'dart2js_summary',
      'dart2wasm',
      'ddc',
    ],
    help:
        'Build kernel for the vm, flutter, flutter_runner, dart2js, '
        'dart2wasm or ddc.',
  )
  ..addOption('dart-sdk-summary')
  ..addMultiOption('redirect')
  ..addMultiOption('input-summary')
  ..addMultiOption('input-linked')
  ..addMultiOption('multi-root')
  ..addOption('multi-root-scheme', defaultsTo: 'org-dartlang-multi-root')
  ..addOption('libraries-file')
  ..addOption('packages-file')
  ..addMultiOption('source')
  ..addOption('output')
  ..addFlag('reuse-compiler-result', defaultsTo: false)
  ..addFlag('use-incremental-compiler', defaultsTo: false)
  ..addOption('used-inputs')
  ..addFlag(
    'track-creation-locations',
    defaultsTo: false,
    aliases: [
      // TODO(http://dartbug.com/63225): Remove this once flutter is migrated
      // to the new flag.
      'track-widget-creation',
    ],
  )
  ..addFlag('include-unsupported-platform-library-stubs', defaultsTo: false)
  ..addMultiOption(
    'enable-experiment',
    help: 'Enable a language experiment when invoking the CFE.',
  )
  ..addMultiOption('define', abbr: 'D')
  ..addFlag('verbose', defaultsTo: false)
  // TODO(jensj): Remove this.
  ..addFlag('sound-null-safety', defaultsTo: true)
  ..addFlag('null-environment', defaultsTo: false, negatable: false)
  ..addOption(
    'verbosity',
    defaultsTo: fe.Verbosity.defaultValue,
    help:
        'Sets the verbosity level used for filtering messages during '
        'compilation.',
    allowed: fe.Verbosity.allowedValues,
    allowedHelp: fe.Verbosity.allowedValuesHelp,
  )
  // TODO(johnniwinther): Remove the macros-related options.
  ..addFlag(
    'require-prebuilt-macros',
    defaultsTo: false,
    help:
        'Require that prebuilt macros for all macro applications be '
        'passed via --precompiled-macro. If not, fail the build.',
  )
  ..addMultiOption(
    'precompiled-macro',
    help:
        'Configuration for precompiled macro binaries or kernel files.\n'
        'The expected format of this option is as follows: '
        '<absolute-path-to-binary>;<macro-library-uri>\nFor example: '
        '--precompiled-macro="/path/to/compiled/macro;'
        'package:some_macro/some_macro.dart". Multiple library uris may be '
        'passed as well (separated by semicolons).',
  )
  ..addOption(
    'macro-serialization-mode',
    help: 'The serialization mode for communicating with macros.',
    allowed: ['bytedata', 'json'],
    defaultsTo: 'bytedata',
  )
  ..addOption('native-assets', help: 'Path to native assets yaml file.');

class ComputeKernelResult {
  final bool succeeded;
  final fe.InitializedCompilerState? previousState;

  new(this.succeeded, this.previousState);
}

/// Computes a kernel file based on [args].
///
/// If [isWorker] is true then exit codes will not be set on failure.
///
/// If [outputBuffer] is provided then messages will be written to that buffer
/// instead of printed to the console.
///
/// Returns whether or not the summary was successfully output.
Future<ComputeKernelResult> computeKernel(
  List<String> args, {
  bool isWorker = false,
  StringBuffer? outputBuffer,
  Map<Uri, List<int>>? inputDigests,
  fe.InitializedCompilerState? previousState,
}) async {
  inputDigests ??= <Uri, List<int>>{};
  StringSink out = outputBuffer ?? stderr;
  bool succeeded = true;

  ArgResults parsedArgs = summaryArgsParser.parse(args);

  if (parsedArgs['help']) {
    out.writeln(summaryArgsParser.usage);
    if (!isWorker) exit(0);
    return new ComputeKernelResult(false, previousState);
  }

  // Bazel creates an overlay file system where some files may be located in the
  // source tree, some in a gendir, and some in a bindir. The multi-root file
  // system hides this from the front end.
  List<Uri> multiRoots = (parsedArgs['multi-root'] as List<String>)
      .map(Uri.base.resolve)
      .toList();
  if (multiRoots.isEmpty) multiRoots.add(Uri.base);
  MultiRootFileSystem mrfs = new MultiRootFileSystem(
    parsedArgs['multi-root-scheme'],
    multiRoots,
    fe.StandardFileSystem.instance,
  );
  FileSystem fileSystem = mrfs;
  List<Uri> sources = (parsedArgs['source'] as List<String>)
      .map(toUri)
      .toList();
  bool excludeNonSources = parsedArgs['exclude-non-sources'] as bool;

  bool summaryOnly = parsedArgs['summary-only'] as bool;
  bool summary = parsedArgs['summary'] as bool;
  if (summaryOnly && !summary) {
    throw new ArgumentError('--summary-only conflicts with --no-summary');
  }
  bool trackCreationLocations = parsedArgs['track-creation-locations'] as bool;
  bool includeUnsupportedPlatformLibraryStubs =
      parsedArgs['include-unsupported-platform-library-stubs'] as bool;

  // TODO(sigmund,jakemac): make target mandatory. We allow null to be backwards
  // compatible while we migrate existing clients of this tool.
  String targetName =
      (parsedArgs['target'] as String?) ?? (summaryOnly ? 'ddc' : 'vm');
  TargetFlags targetFlags = new TargetFlags(
    trackCreationLocations: trackCreationLocations,
    includeUnsupportedPlatformLibraryStubs:
        includeUnsupportedPlatformLibraryStubs,
  );
  Target target;
  switch (targetName) {
    case 'vm':
      target = new VmTarget(targetFlags);
      if (summaryOnly) {
        out.writeln('error: --summary-only not supported for the vm target');
      }
      break;
    case 'flutter':
      target = new FlutterTarget(targetFlags);
      if (summaryOnly) {
        throw new ArgumentError(
          'error: --summary-only not supported for the flutter target',
        );
      }
      break;
    case 'flutter_runner':
      target = new FlutterRunnerTarget(targetFlags);
      if (summaryOnly) {
        throw new ArgumentError(
          'error: --summary-only not supported for the '
          'flutter_runner target',
        );
      }
      break;
    case 'dart2js':
      target = new Dart2jsTarget('dart2js', targetFlags);
      if (summaryOnly) {
        out.writeln(
          'error: --summary-only not supported for the dart2js target',
        );
      }
      break;
    case 'dart2js_summary':
      target = new Dart2jsSummaryTarget(
        'dart2js',
        sources,
        excludeNonSources,
        targetFlags,
      );
      if (!summaryOnly) {
        out.writeln(
          'error: --no-summary-only not supported for '
          'the dart2js summary target',
        );
      }
      break;
    case 'ddc':
      // TODO(jakemac):If `generateKernel` changes to return a summary
      // component, process the component instead.
      target = new DevCompilerSummaryTarget(
        sources,
        excludeNonSources,
        targetFlags,
      );
      if (!summaryOnly) {
        out.writeln(
          'error: --no-summary-only not supported for the '
          'ddc target',
        );
      }
      break;
    case 'dart2wasm':
      target = new WasmTarget();
      break;
    default:
      out.writeln('error: unsupported target: $targetName');
      return new ComputeKernelResult(false, previousState);
  }

  List<Uri> linkedInputs = (parsedArgs['input-linked'] as List<String>)
      .map(toUri)
      .toList();

  List<Uri> summaryInputs = (parsedArgs['input-summary'] as List<String>)
      .map(toUri)
      .toList();

  fe.InitializedCompilerState state;
  bool usingIncrementalCompiler = parsedArgs['use-incremental-compiler'];
  bool recordUsedInputs = parsedArgs["used-inputs"] != null;
  bool usingNullEnvironment = parsedArgs['null-environment'];
  Map<String, String>? nullableEnvironmentDefines;
  Map<String, String> environmentDefines = _parseEnvironmentDefines(
    parsedArgs['define'],
  );
  if (usingNullEnvironment) {
    if (environmentDefines.isNotEmpty) {
      throw new ArgumentError(
        '`--null-environment` not supported with defines.',
      );
    } else if (!target.constantsBackend.supportsUnevaluatedConstants) {
      throw new ArgumentError(
        '`--null-environment` not supported on `$targetName`.',
      );
    } else if (usingIncrementalCompiler) {
      throw new ArgumentError(
        '`--null-environment` not supported with incremental compilation.',
      );
    }
  } else {
    nullableEnvironmentDefines = environmentDefines;
  }
  bool verbose = parsedArgs['verbose'] as bool;
  fe.Verbosity verbosity = fe.Verbosity.parseArgument(parsedArgs['verbosity']);
  Uri? sdkSummaryUri = toUriNullable(parsedArgs['dart-sdk-summary']);

  Map<Uri, Uri> redirectsToFrom = {};
  for (String redirect in parsedArgs['redirect']) {
    List<String> split = redirect.split("|");
    if (split.length != 2) throw "Invalid redirect input: '$redirect'";
    redirectsToFrom[toUri(split[1])] = toUri(split[0]);
  }

  if (redirectsToFrom.isNotEmpty) {
    // If redirecting from a->b and we were asked to compile b, we want
    // the output to look like we compiled a.
    List<Uri> newSources = [];
    for (Uri source in sources) {
      newSources.add(redirectsToFrom[source] ?? source);
    }
    // Dart2jsSummaryTarget and DevCompilerSummaryTarget has a pointer to
    // sources, so to keep it up to date we'll clear and add instead of
    // overwriting.
    sources.clear();
    sources.addAll(newSources);

    // Make the filesystem map from a to b, so that if asked to read a,
    // actually return data from b. If asked to read b throw.
    fe.InitializedCompilerState helper = fe.initializeCompiler(
      null,
      sdkSummaryUri,
      toUriNullable(parsedArgs['libraries-file']),
      toUriNullable(parsedArgs['packages-file']),
      [...summaryInputs, ...linkedInputs],
      target,
      fileSystem,
      parsedArgs['enable-experiment'] as List<String>,
      nullableEnvironmentDefines,
      verbose: verbose,
    );
    UriTranslator uriTranslator = await helper.processedOpts.getUriTranslator();
    _FakeFileSystem fakeFileSystem = fileSystem = new _FakeFileSystem(
      fileSystem,
    );
    for (MapEntry<Uri, Uri> entry in redirectsToFrom.entries) {
      fakeFileSystem.addRedirect(
        uriTranslator.translate(entry.value, false) ?? entry.value,
        uriTranslator.translate(entry.key, false) ?? entry.key,
      );
    }
  }

  if (usingIncrementalCompiler) {
    // If digests weren't given and if not in worker mode, create fake data and
    // ensure we don't have a previous state (as that wouldn't be safe with
    // fake input digests).
    if (!isWorker && inputDigests.isEmpty) {
      previousState = null;
      if (sdkSummaryUri != null) {
        inputDigests[sdkSummaryUri] = const [0];
      }
      for (Uri uri in summaryInputs) {
        inputDigests[uri] = const [0];
      }
      for (Uri uri in linkedInputs) {
        inputDigests[uri] = const [0];
      }
    }

    state = await fe.initializeIncrementalCompiler(
      previousState,
      {
        "target=$targetName",
        // trackCreationLocations is in TargetFlags.
        "trackCreationLocations=$trackCreationLocations",
        // includeUnsupportedPlatformLibraryStubs is in TargetFlags.
        "includeUnsupportedPlatformLibraryStubs="
            "$includeUnsupportedPlatformLibraryStubs",
        "multiRootScheme=${mrfs.markerScheme}",
        "multiRootRoots=${mrfs.roots}",
      },
      sdkSummaryUri,
      toUriNullable(parsedArgs['packages-file']),
      toUriNullable(parsedArgs['libraries-file']),
      [...summaryInputs, ...linkedInputs],
      inputDigests,
      target,
      fileSystem,
      (parsedArgs['enable-experiment'] as List<String>),
      summaryOnly,
      nullableEnvironmentDefines!,
      trackNeededDillLibraries: recordUsedInputs,
      verbose: verbose,
    );
  } else {
    state = fe.initializeCompiler(
      // TODO(sigmund): pass an old state once we can make use of it.
      null,
      sdkSummaryUri,
      toUriNullable(parsedArgs['libraries-file']),
      toUriNullable(parsedArgs['packages-file']),
      [...summaryInputs, ...linkedInputs],
      target,
      fileSystem,
      parsedArgs['enable-experiment'] as List<String>,
      nullableEnvironmentDefines,
      verbose: verbose,
    );
  }

  void onDiagnostic(fe.CfeDiagnosticMessage message) {
    if (fe.Verbosity.shouldPrint(verbosity, message)) {
      fe.printDiagnosticMessage(message, out.writeln);
    }
    if (message.severity == fe.CfeSeverity.error) {
      succeeded = false;
    }
  }

  List<int>? kernel;
  bool wroteUsedDills = false;
  String? nativeAssets = parsedArgs['native-assets'];
  Library? nativeAssetsLibrary;
  if (nativeAssets != null) {
    Uri nativeAssetsUri = Uri.base.resolve(nativeAssets);

    nativeAssetsLibrary =
        await NativeAssetsSynthesizer.synthesizeLibraryFromYamlFile(
          nativeAssetsUri,
          new ErrorDetector(),
        );
  }

  if (usingIncrementalCompiler) {
    state.options.onDiagnostic = onDiagnostic;
    IncrementalCompilerResult incrementalCompilerResult = await state
        .incrementalCompiler!
        .computeDelta(
          entryPoints: sources,
          fullComponent: true,
          trackNeededDillLibraries: recordUsedInputs,
        );
    Component incrementalComponent = incrementalCompilerResult.component;

    if (recordUsedInputs) {
      Set<Uri> usedOutlines = {};
      for (Library lib in incrementalCompilerResult.neededDillLibraries!) {
        if (lib.importUri.isScheme("dart")) continue;
        Uri? uri = state.libraryToInputDill![lib.importUri];
        if (uri == null) {
          throw new StateError(
            "Library ${lib.importUri} was recorded as used, "
            "but was not in the list of known libraries.",
          );
        }
        usedOutlines.add(uri);
      }
      File outputUsedFile = new File(parsedArgs["used-inputs"]);
      outputUsedFile.createSync(recursive: true);
      outputUsedFile.writeAsStringSync(usedOutlines.join("\n"));
      wroteUsedDills = true;
    }

    kernel = await state.incrementalCompiler!.context.runInContext((_) {
      if (summaryOnly) {
        incrementalComponent.uriToSource.clear();
        incrementalComponent.problemsAsJson = null;
        incrementalComponent.setMainMethodAndMode(null, true);
        makeStable(incrementalComponent);
        return new Future.value(
          fe.serializeComponent(
            incrementalComponent,
            includeSources: false,
            includeOffsets: false,
          ),
        );
      }

      makeStable(incrementalComponent);
      setNativeAssetsLibrary(incrementalComponent, nativeAssetsLibrary);

      return new Future.value(
        fe.serializeComponent(
          incrementalComponent,
          filter: excludeNonSources
              ? (library) =>
                    sources.contains(library.importUri) ||
                    library == nativeAssetsLibrary
              : null,
          includeOffsets: true,
        ),
      );
    });
  } else if (summaryOnly) {
    kernel = await fe.compileSummary(
      state,
      sources,
      onDiagnostic,
      includeOffsets: false,
    );
  } else {
    Component? component = await fe.compileComponent(
      state,
      sources,
      onDiagnostic,
      buildSummary: summary,
    );
    if (component != null) {
      setNativeAssetsLibrary(component, nativeAssetsLibrary);
      kernel = fe.serializeComponent(
        component,
        filter: excludeNonSources
            ? (library) =>
                  sources.contains(library.importUri) ||
                  library == nativeAssetsLibrary
            : null,
        includeOffsets: true,
      );
    }
  }
  state.options.onDiagnostic = null; // See http://dartbug.com/36983.

  if (!wroteUsedDills && recordUsedInputs) {
    // The path taken didn't record inputs used: Say we used everything.
    File outputUsedFile = new File(parsedArgs["used-inputs"]);
    outputUsedFile.createSync(recursive: true);
    Set<Uri> allFiles = {...summaryInputs, ...linkedInputs};
    outputUsedFile.writeAsStringSync(allFiles.join("\n"));
    wroteUsedDills = true;
  }

  if (kernel != null) {
    File outputFile = new File(parsedArgs['output']);
    outputFile.createSync(recursive: true);
    outputFile.writeAsBytesSync(kernel);
  } else {
    assert(!succeeded);
  }

  return new ComputeKernelResult(succeeded, state);
}

final Uri _nativeAssetsLibraryUri = Uri.parse('vm:ffi:native-assets');

void setNativeAssetsLibrary(Component component, Library? nativeAssetsLibrary) {
  if (nativeAssetsLibrary == null) {
    return;
  }
  assert(nativeAssetsLibrary.importUri == _nativeAssetsLibraryUri);
  component.libraries.removeWhere(
    (l) => l.importUri == _nativeAssetsLibraryUri,
  );
  component.libraries.add(nativeAssetsLibrary..parent = component);
}

/// Make sure the output is stable by sorting libraries and additional exports.
void makeStable(Component c) {
  // Make sure the output is stable.
  c.libraries.sort((l1, l2) {
    return "${l1.fileUri}".compareTo("${l2.fileUri}");
  });
  c.problemsAsJson?.sort();
  c.computeCanonicalNames();
  for (Library library in c.libraries) {
    library.additionalExports.sort();
    library.problemsAsJson?.sort();
  }
}

class _FakeFileSystem extends FileSystem {
  final Map<Uri, Uri> redirectsFromTo = {};
  final Set<Uri> redirectsTo = {};
  final FileSystem fs;
  new(this.fs);

  void addRedirect(Uri from, Uri to) {
    redirectsTo.add(to);
    redirectsFromTo[from] = to;
  }

  @override
  FileSystemEntity entityForUri(Uri uri) {
    if (redirectsTo.contains(uri)) throw "$uri is a redirection target.";
    uri = redirectsFromTo[uri] ?? uri;
    return fs.entityForUri(uri);
  }
}

class DevCompilerSummaryTarget extends DevCompilerTarget with SummaryMixin {
  @override
  final List<Uri> sources;
  @override
  final bool excludeNonSources;

  new(this.sources, this.excludeNonSources, TargetFlags targetFlags)
    : super(targetFlags);

  @override
  bool isModularlyCompatibleWith(Target other) {
    if (other is! DevCompilerSummaryTarget) return false;
    if (excludeNonSources != other.excludeNonSources) return false;
    return true;
  }

  @override
  void updateModularCompatibilityAs(Target other) {
    assert(other is DevCompilerSummaryTarget);
    sources.clear();
    sources.addAll((other as DevCompilerSummaryTarget).sources);
  }
}

Uri? toUriNullable(String? uriString) {
  if (uriString == null) return null;
  return toUri(uriString);
}

Uri toUri(String uriString) {
  // Windows-style paths use '\', so convert them to '/' in case they've been
  // concatenated with Unix-style paths.
  return Uri.base.resolve(uriString.replaceAll("\\", "/"));
}

Map<String, String> _parseEnvironmentDefines(List<String> args) {
  Map<String, String> environment = {};

  for (String arg in args) {
    int eq = arg.indexOf('=');
    if (eq <= 0) {
      String kind = eq == 0 ? 'name' : 'value';
      throw new FormatException('no $kind given to -D option `$arg`');
    }
    String name = arg.substring(0, eq);
    String value = arg.substring(eq + 1);
    environment[name] = value;
  }

  return environment;
}
