// 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:io' show exitCode;

import 'dart:typed_data' show Uint8List;

import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;

import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;

import 'package:kernel/kernel.dart'
    show
        CanonicalName,
        Component,
        Location,
        NonNullableByDefaultCompiledMode,
        Version;

import 'package:kernel/target/targets.dart'
    show NoneTarget, Target, TargetFlags;

import 'package:package_config/package_config.dart';

import '../api_prototype/compiler_options.dart'
    show CompilerOptions, InvocationMode, Verbosity, DiagnosticMessage;

import '../api_prototype/experimental_flags.dart' as flags;

import '../api_prototype/file_system.dart'
    show FileSystem, FileSystemEntity, FileSystemException;

import '../api_prototype/terminal_color_support.dart'
    show printDiagnosticMessage;

import '../fasta/command_line_reporting.dart' as command_line_reporting;

import '../fasta/compiler_context.dart' show CompilerContext;

import '../fasta/fasta_codes.dart'
    show
        FormattedMessage,
        LocatedMessage,
        Message,
        PlainAndColorizedString,
        messageCantInferPackagesFromManyInputs,
        messageCantInferPackagesFromPackageUri,
        messageCompilingWithSoundNullSafety,
        messageCompilingWithoutSoundNullSafety,
        messageInternalProblemProvidedBothCompileSdkAndSdkSummary,
        messageMissingInput,
        noLength,
        templateCannotReadSdkSpecification,
        templateCantReadFile,
        templateDebugTrace,
        templateExceptionReadingFile,
        templateInputFileNotFound,
        templateInternalProblemUnsupported,
        templatePackagesFileFormat,
        templateSdkRootNotFound,
        templateSdkSpecificationNotFound,
        templateSdkSummaryNotFound;

import '../fasta/messages.dart' show getLocation;

import '../fasta/problems.dart' show DebugAbort, unimplemented;

import '../fasta/ticker.dart' show Ticker;

import '../fasta/uri_translator.dart' show UriTranslator;

import 'libraries_specification.dart'
    show
        LibrariesSpecification,
        LibrariesSpecificationException,
        TargetLibrariesSpecification;

import 'nnbd_mode.dart';

/// All options needed for the front end implementation.
///
/// This includes: all of [CompilerOptions] in a form useful to the
/// implementation, default values for options that were not provided,
/// and information derived from how the compiler was invoked (like the
/// entry-points given to the compiler and whether a modular or whole-program
/// API was used).
///
/// The intent is that the front end should immediately wrap any incoming
/// [CompilerOptions] object in this class before doing further processing, and
/// should thereafter access all options via the wrapper.  This ensures that
/// options are interpreted in a consistent way and that data derived from
/// options is not unnecessarily recomputed.
class ProcessedOptions {
  /// The raw [CompilerOptions] which this class wraps.
  final CompilerOptions _raw;

  /// The package map derived from the options, or `null` if the package map has
  /// not been computed yet.
  PackageConfig? _packages;

  /// The uri for .packages derived from the options, or `null` if the package
  /// map has not been computed yet or there is no .packages in effect.
  Uri? _packagesUri;
  Uri? get packagesUri => _packagesUri;

  /// The object that knows how to resolve "package:" and "dart:" URIs,
  /// or `null` if it has not been computed yet.
  UriTranslator? _uriTranslator;

  /// The SDK summary, or `null` if it has not been read yet.
  ///
  /// A summary, also referred to as "outline" internally, is a [Component]
  /// where all method bodies are left out. In essence, it contains just API
  /// signatures and constants. The summary should include inferred top-level
  /// types unless legacy mode is enabled.
  Component? _sdkSummaryComponent;

  /// The component for each uri in `options.additionalDills`.
  ///
  /// A summary, also referred to as "outline" internally, is a [Component]
  /// where all method bodies are left out. In essence, it contains just API
  /// signatures and constants. The summaries should include inferred top-level
  /// types unless legacy mode is enabled.
  List<Component>? _additionalDillComponents;

  /// The location of the SDK, or `null` if the location hasn't been determined
  /// yet.
  Uri? _sdkRoot;
  Uri? get sdkRoot {
    _ensureSdkDefaults();
    return _sdkRoot;
  }

  Uri? _sdkSummary;
  Uri? get sdkSummary {
    _ensureSdkDefaults();
    return _sdkSummary;
  }

  List<int>? _sdkSummaryBytes;
  bool _triedLoadingSdkSummary = false;

  /// Get the bytes of the SDK outline, if any.
  Future<List<int>?> loadSdkSummaryBytes() async {
    if (_sdkSummaryBytes == null && !_triedLoadingSdkSummary) {
      if (sdkSummary == null) return null;
      FileSystemEntity entry = fileSystem.entityForUri(sdkSummary!);
      _sdkSummaryBytes = await _readAsBytes(entry);
      _triedLoadingSdkSummary = true;
    }
    return _sdkSummaryBytes;
  }

  Uri? _librariesSpecificationUri;
  Uri? get librariesSpecificationUri {
    _ensureSdkDefaults();
    return _librariesSpecificationUri;
  }

  Ticker ticker;

  Uri? get packagesUriRaw => _raw.packagesFileUri;

  bool get verbose => _raw.verbose;

  bool get verify => _raw.verify;

  bool get skipPlatformVerification => _raw.skipPlatformVerification;

  bool get debugDump => _raw.debugDump;

  bool get omitPlatform => _raw.omitPlatform;

  bool get setExitCodeOnProblem => _raw.setExitCodeOnProblem;

  bool get embedSourceText => _raw.embedSourceText;

  bool get throwOnErrorsForDebugging => _raw.throwOnErrorsForDebugging;

  bool get throwOnWarningsForDebugging => _raw.throwOnWarningsForDebugging;

  bool get emitDeps => _raw.emitDeps;

  NnbdMode get nnbdMode => _raw.nnbdMode;

  bool get warnOnReachabilityCheck => _raw.warnOnReachabilityCheck;

  /// The entry-points provided to the compiler.
  final List<Uri> inputs;

  /// The Uri where output is generated, may be null.
  final Uri? output;

  final Map<String, String>? environmentDefines;

  bool get errorOnUnevaluatedConstant => _raw.errorOnUnevaluatedConstant;

  /// The number of fatal diagnostics encountered so far.
  int fatalDiagnosticCount = 0;

  /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions].
  ProcessedOptions({CompilerOptions? options, List<Uri>? inputs, this.output})
      : this._raw = options ?? new CompilerOptions(),
        this.inputs = inputs ?? <Uri>[],
        // TODO(askesc): Copy the map when kernel_service supports that.
        this.environmentDefines = options?.environmentDefines,
        // TODO(sigmund, ahe): create ticker even earlier or pass in a stopwatch
        // collecting time since the start of the VM.
        this.ticker = new Ticker(isVerbose: options?.verbose ?? false);

  FormattedMessage format(
      LocatedMessage message, Severity severity, List<LocatedMessage>? context,
      {List<Uri>? involvedFiles}) {
    int offset = message.charOffset;
    Uri? uri = message.uri;
    Location? location =
        offset == -1 || uri == null ? null : getLocation(uri, offset);
    PlainAndColorizedString formatted =
        command_line_reporting.format(message, severity, location: location);
    List<FormattedMessage>? formattedContext;
    if (context != null && context.isNotEmpty) {
      formattedContext =
          new List<FormattedMessage>.generate(context.length, (int i) {
        return format(context[i], Severity.context, null);
      });
    }
    return message.withFormatting(formatted, location?.line ?? -1,
        location?.column ?? -1, severity, formattedContext,
        involvedFiles: involvedFiles);
  }

  void report(LocatedMessage message, Severity severity,
      {List<LocatedMessage>? context, List<Uri>? involvedFiles}) {
    if (command_line_reporting.isHidden(severity)) return;
    if (command_line_reporting.isCompileTimeError(severity)) {
      CompilerContext.current.logError(message, severity);
    }
    if (CompilerContext.current.options.setExitCodeOnProblem) {
      exitCode = 1;
    }
    reportDiagnosticMessage(
        format(message, severity, context, involvedFiles: involvedFiles));
    if (command_line_reporting.shouldThrowOn(severity)) {
      if (fatalDiagnosticCount++ < _raw.skipForDebugging) {
        // Skip this one. The interesting one comes later.
        return;
      }
      if (_raw.skipForDebugging < 0) {
        print(templateDebugTrace
            .withArguments("$severity", "${StackTrace.current}")
            .message);
      } else {
        throw new DebugAbort(
            message.uri, message.charOffset, severity, StackTrace.current);
      }
    }
  }

  void reportDiagnosticMessage(DiagnosticMessage message) {
    (_raw.onDiagnostic ?? _defaultDiagnosticMessageHandler)(message);
  }

  void _defaultDiagnosticMessageHandler(DiagnosticMessage message) {
    if (Verbosity.shouldPrint(_raw.verbosity, message)) {
      printDiagnosticMessage(message, print);
    }
  }

  // TODO(askesc): Remove this and direct callers directly to report.
  void reportWithoutLocation(Message message, Severity severity) {
    report(message.withoutLocation(), severity);
  }

  /// If `CompilerOptions.invocationModes` contains `InvocationMode.compile`, an
  /// info message about the null safety compilation mode is emitted.
  void reportNullSafetyCompilationModeInfo() {
    if (_raw.invocationModes.contains(InvocationMode.compile)) {
      switch (nnbdMode) {
        case NnbdMode.Weak:
          reportWithoutLocation(messageCompilingWithoutSoundNullSafety,
              messageCompilingWithoutSoundNullSafety.severity);
          break;
        case NnbdMode.Strong:
          reportWithoutLocation(messageCompilingWithSoundNullSafety,
              messageCompilingWithSoundNullSafety.severity);
          break;
        case NnbdMode.Agnostic:
          break;
      }
    }
  }

  /// Runs various validations checks on the input options. For instance,
  /// if an option is a path to a file, it checks that the file exists.
  Future<bool> validateOptions({bool errorOnMissingInput: true}) async {
    if (verbose) print(debugString());

    if (errorOnMissingInput && inputs.isEmpty) {
      reportWithoutLocation(messageMissingInput, Severity.error);
      return false;
    }

    if (_raw.sdkRoot != null &&
        !await fileSystem.entityForUri(sdkRoot!).exists()) {
      reportWithoutLocation(
          templateSdkRootNotFound.withArguments(sdkRoot!), Severity.error);
      return false;
    }

    Uri? summary = sdkSummary;
    if (summary != null && !await fileSystem.entityForUri(summary).exists()) {
      reportWithoutLocation(
          templateSdkSummaryNotFound.withArguments(summary), Severity.error);
      return false;
    }

    if (compileSdk && summary != null) {
      reportWithoutLocation(
          messageInternalProblemProvidedBothCompileSdkAndSdkSummary,
          Severity.internalProblem);
      return false;
    }

    for (Uri source in _raw.additionalDills) {
      // TODO(ahe): Remove this check, the compiler itself should handle and
      // recover from this.
      if (!await fileSystem.entityForUri(source).exists()) {
        reportWithoutLocation(
            templateInputFileNotFound.withArguments(source), Severity.error);
        return false;
      }
    }
    return true;
  }

  /// Determine whether to generate code for the SDK when compiling a
  /// whole-program.
  bool get compileSdk => _raw.compileSdk;

  FileSystem? _fileSystem;

  /// Get the [FileSystem] which should be used by the front end to access
  /// files.
  FileSystem get fileSystem => _fileSystem ??= _createFileSystem();

  /// Clear the file system so any CompilerOptions fileSystem change will have
  /// effect.
  void clearFileSystemCache() => _fileSystem = null;

  /// Whether to write a file (e.g. a dill file) when reporting a crash.
  bool get writeFileOnCrashReport => _raw.writeFileOnCrashReport;

  /// The current sdk version string, e.g. "2.6.0-edge.sha1hash".
  /// For instance used for language versioning (specifying the maximum
  /// version).
  String get currentSdkVersion => _raw.currentSdkVersion;

  Target? _target;
  Target get target =>
      _target ??= _raw.target ?? new NoneTarget(new TargetFlags());

  /// Returns `true` if the [flag] is enabled globally by default.
  bool isExperimentEnabledByDefault(flags.ExperimentalFlag flag) {
    return flags.isExperimentEnabled(flag,
        defaultExperimentFlagsForTesting:
            _raw.defaultExperimentFlagsForTesting);
  }

  /// Returns `true` if the [flag] is enabled globally.
  ///
  /// This is `true` either if the [flag] is passed through an explicit
  /// `--enable-experiment` option or if the [flag] is expired and on by
  /// default.
  bool isExperimentEnabledGlobally(flags.ExperimentalFlag flag) {
    return flags.isExperimentEnabled(flag,
        explicitExperimentalFlags: _raw.explicitExperimentalFlags,
        defaultExperimentFlagsForTesting:
            _raw.defaultExperimentFlagsForTesting);
  }

  /// Returns `true` if the experiment with the given [flag] is enabled either
  /// explicitly or implicitly for the library with the given [importUri].
  ///
  /// Note that the library can still opt out of the experiment by having a
  /// lower language version than required for the experiment. See
  /// [getExperimentEnabledVersionInLibrary].
  bool isExperimentEnabledInLibrary(
      flags.ExperimentalFlag flag, Uri importUri) {
    return _raw.isExperimentEnabledInLibrary(flag, importUri);
  }

  /// Returns the minimum language version needed for a library with the given
  /// [importUri] to opt in to the experiment with the given [flag].
  ///
  /// Note that the experiment might not be enabled at all for the library, as
  /// computed by [isExperimentEnabledInLibrary].
  Version getExperimentEnabledVersionInLibrary(
      flags.ExperimentalFlag flag, Uri importUri) {
    return _raw.getExperimentEnabledVersionInLibrary(flag, importUri);
  }

  /// Return `true` if the experiment with the given [flag] is enabled for the
  /// library with the given [importUri] and language [version].
  bool isExperimentEnabledInLibraryByVersion(
      flags.ExperimentalFlag flag, Uri importUri, Version version) {
    return _raw.isExperimentEnabledInLibraryByVersion(flag, importUri, version);
  }

  Component _validateNullSafetyMode(Component component) {
    if (component.mode == NonNullableByDefaultCompiledMode.Invalid) {
      throw new FormatException(
          'Provided .dill file for the following libraries has an invalid null '
          'safety mode and does not support null safety:\n'
          '${component.libraries.join('\n')}');
    }
    if (nnbdMode == NnbdMode.Strong &&
        !(component.mode == NonNullableByDefaultCompiledMode.Strong ||
            component.mode == NonNullableByDefaultCompiledMode.Agnostic)) {
      throw new FormatException(
          'Provided .dill file for the following libraries does not '
          'support sound null safety:\n'
          '${component.libraries.join('\n')}');
    }
    return component;
  }

  /// Get an outline component that summarizes the SDK, if any.
  // TODO(sigmund): move, this doesn't feel like an "option".
  Future<Component?> loadSdkSummary(CanonicalName? nameRoot) async {
    if (_sdkSummaryComponent == null) {
      if (sdkSummary == null) return null;
      List<int>? bytes = await loadSdkSummaryBytes();
      if (bytes != null && bytes.isNotEmpty) {
        _sdkSummaryComponent =
            loadComponent(bytes, nameRoot, fileUri: sdkSummary);
      }
    }
    return _sdkSummaryComponent;
  }

  void set sdkSummaryComponent(Component platform) {
    if (_sdkSummaryComponent != null) {
      throw new StateError("sdkSummary already loaded.");
    }
    _validateNullSafetyMode(platform);
    _sdkSummaryComponent = platform;
  }

  /// Get the components for each of the underlying `additionalDill`
  /// provided via [CompilerOptions].
  // TODO(sigmund): move, this doesn't feel like an "option".
  Future<List<Component>> loadAdditionalDills(CanonicalName? nameRoot) async {
    if (_additionalDillComponents == null) {
      List<Uri> uris = _raw.additionalDills;
      // ignore: unnecessary_null_comparison
      if (uris == null || uris.isEmpty) return const <Component>[];
      // TODO(sigmund): throttle # of concurrent operations.
      List<List<int>?> allBytes = await Future.wait(
          uris.map((uri) => _readAsBytes(fileSystem.entityForUri(uri))));
      List<Component> result = [];
      for (int i = 0; i < uris.length; i++) {
        List<int>? bytes = allBytes[i];
        if (bytes == null) continue;
        result.add(loadComponent(bytes, nameRoot, fileUri: uris[i]));
      }
      _additionalDillComponents = result;
    }
    return _additionalDillComponents!;
  }

  void set loadAdditionalDillsComponents(List<Component> components) {
    if (_additionalDillComponents != null) {
      throw new StateError("inputAdditionalDillsComponents already loaded.");
    }
    components.forEach(_validateNullSafetyMode);
    _additionalDillComponents = components;
  }

  /// Helper to load a .dill file from [uri] using the existing [nameRoot].
  Component loadComponent(List<int> bytes, CanonicalName? nameRoot,
      {bool? alwaysCreateNewNamedNodes, Uri? fileUri}) {
    Component component =
        target.configureComponent(new Component(nameRoot: nameRoot));
    // TODO(ahe): Control lazy loading via an option.
    new BinaryBuilder(bytes,
            filename: fileUri == null ? null : '$fileUri',
            disableLazyReading: false,
            alwaysCreateNewNamedNodes: alwaysCreateNewNamedNodes)
        .readComponent(component);
    return _validateNullSafetyMode(component);
  }

  /// Get the [UriTranslator] which resolves "package:" and "dart:" URIs.
  ///
  /// This is an asynchronous method since file system operations may be
  /// required to locate/read the packages file as well as SDK metadata.
  Future<UriTranslator> getUriTranslator({bool bypassCache: false}) async {
    if (bypassCache) {
      _uriTranslator = null;
      _packages = null;
    }
    if (_uriTranslator == null) {
      ticker.logMs("Started building UriTranslator");
      TargetLibrariesSpecification libraries =
          await _computeLibrarySpecification();
      ticker.logMs("Read libraries file");
      PackageConfig packages = await _getPackages();
      ticker.logMs("Read packages file");
      _uriTranslator = new UriTranslator(libraries, packages);
    }
    return _uriTranslator!;
  }

  Future<TargetLibrariesSpecification> _computeLibrarySpecification() async {
    String name = target.name;
    // TODO(sigmund): Eek! We should get to the point where there is no
    // fasta-specific targets and the target names are meaningful.
    if (name.endsWith('_fasta')) name = name.substring(0, name.length - 6);

    if (librariesSpecificationUri == null ||
        !await fileSystem.entityForUri(librariesSpecificationUri!).exists()) {
      if (compileSdk) {
        reportWithoutLocation(
            templateSdkSpecificationNotFound
                .withArguments(librariesSpecificationUri!),
            Severity.error);
      }
      return new TargetLibrariesSpecification(name);
    }

    String json = await fileSystem
        .entityForUri(librariesSpecificationUri!)
        .readAsString();
    try {
      LibrariesSpecification spec =
          await LibrariesSpecification.parse(librariesSpecificationUri!, json);
      return spec.specificationFor(name);
    } on LibrariesSpecificationException catch (e) {
      reportWithoutLocation(
          templateCannotReadSdkSpecification.withArguments('${e.error}'),
          Severity.error);
      return new TargetLibrariesSpecification(name);
    }
  }

  /// Get the package map which maps package names to URIs.
  ///
  /// This is an asynchronous getter since file system operations may be
  /// required to locate/read the packages file.
  Future<PackageConfig> _getPackages() async {
    if (_packages != null) return _packages!;
    _packagesUri = null;
    if (_raw.packagesFileUri != null) {
      return _packages = await createPackagesFromFile(_raw.packagesFileUri!);
    }

    if (inputs.length > 1) {
      // TODO(sigmund): consider not reporting an error if we would infer
      // the same .packages file from all of the inputs.
      reportWithoutLocation(
          messageCantInferPackagesFromManyInputs, Severity.error);
      return _packages = PackageConfig.empty;
    }
    if (inputs.isEmpty) {
      return _packages = PackageConfig.empty;
    }

    Uri input = inputs.first;

    // When compiling the SDK the input files are normally `dart:` URIs.
    if (input.scheme == 'dart') return _packages = PackageConfig.empty;

    if (input.scheme == 'packages') {
      report(
          messageCantInferPackagesFromPackageUri.withLocation(
              input, -1, noLength),
          Severity.error);
      return _packages = PackageConfig.empty;
    }

    return _packages = await _findPackages(inputs.first);
  }

  Future<Uint8List?> _readFile(Uri uri, bool reportError) async {
    try {
      // TODO(ahe): We need to compute line endings for this file.
      FileSystemEntity entityForUri = fileSystem.entityForUri(uri);
      if (!reportError && !await entityForUri.exists()) return null;
      List<int> fileContents = await entityForUri.readAsBytes();
      if (fileContents is Uint8List) {
        return fileContents;
      } else {
        return new Uint8List.fromList(fileContents);
      }
    } on FileSystemException catch (e) {
      if (reportError) {
        reportWithoutLocation(
            templateCantReadFile.withArguments(uri, e.message), Severity.error);
      }
    } catch (e) {
      Message message = templateExceptionReadingFile.withArguments(uri, '$e');
      reportWithoutLocation(message, Severity.error);
      // We throw a new exception to ensure that the message include the uri
      // that led to the exception. Exceptions in Uri don't include the
      // offending uri in the exception message.
      throw new ArgumentError(message.message);
    }
    return null;
  }

  /// Create a [PackageConfig] given the Uri to a `.packages` or
  /// `package_config.json` file.
  ///
  /// If the file doesn't exist, it returns null (and an error is reported
  /// based in [forceCreation]).
  /// If the file does exist but is invalid an error is always reported and an
  /// empty package config is returned.
  Future<PackageConfig?> _createPackagesFromFile(
      Uri requestedUri, bool forceCreation, bool requireJson) async {
    Uint8List? contents = await _readFile(requestedUri, forceCreation);
    if (contents == null) {
      if (forceCreation) {
        _packagesUri = null;
        return PackageConfig.empty;
      }
      return null;
    }

    _packagesUri = requestedUri;
    try {
      void Function(Object error) onError = (Object error) {
        if (error is FormatException) {
          report(
              templatePackagesFileFormat
                  .withArguments(error.message)
                  .withLocation(requestedUri, error.offset ?? -1, noLength),
              Severity.error);
        } else {
          reportWithoutLocation(
              templateCantReadFile.withArguments(requestedUri, "$error"),
              Severity.error);
        }
      };
      if (requireJson) {
        return PackageConfig.parseBytes(contents, requestedUri,
            onError: onError);
      }
      return await loadPackageConfigUri(requestedUri, preferNewest: false,
          loader: (uri) {
        if (uri != requestedUri) {
          throw new StateError(
              "Unexpected request from package config package");
        }
        return new Future.value(contents);
      }, onError: onError);
    } on FormatException catch (e) {
      report(
          templatePackagesFileFormat
              .withArguments(e.message)
              .withLocation(requestedUri, e.offset ?? -1, noLength),
          Severity.error);
    } catch (e) {
      reportWithoutLocation(
          templateCantReadFile.withArguments(requestedUri, "$e"),
          Severity.error);
    }
    _packagesUri = null;
    return PackageConfig.empty;
  }

  /// Create a [PackageConfig] given the Uri to a `.packages` or
  /// `package_config.json` file.
  ///
  /// Note that if a `.packages` file is provided and an appropriately placed
  /// (relative to the .packages file) `package_config.json` file exists, the
  /// `package_config.json` file will be used instead.
  Future<PackageConfig> createPackagesFromFile(Uri file) async {
    // If the input is a ".packages" file we assume the standard layout, and
    // if a ".dart_tool/package_config.json" exists, we'll use that (and require
    // it to be a json file).
    PackageConfig? result;
    if (file.path.endsWith("/.packages")) {
      // .packages -> try the package_config first.
      Uri tryFirst = file.resolve(".dart_tool/package_config.json");
      result = await _createPackagesFromFile(tryFirst, false, true);
      if (result != null) return result;
    }
    result = await _createPackagesFromFile(file, true, false);
    return result ?? PackageConfig.empty;
  }

  /// Finds a package resolution strategy using a [FileSystem].
  ///
  /// The [scriptUri] points to a Dart script with a valid scheme accepted by
  /// the [FileSystem].
  ///
  /// This function first tries to locate a `.dart_tool/package_config.json`
  /// (then a `.packages`) file in the `scriptUri` directory.
  /// If that is not found, it starts checking parent directories, and stops if
  /// it finds it. Otherwise it gives up and returns [PackageConfig.empty].
  ///
  /// Note: this is a fork from `package:package_config`s discovery to make sure
  /// we use the expected error reporting etc.
  Future<PackageConfig> _findPackages(Uri scriptUri) async {
    Uri dir = scriptUri.resolve('.');
    if (!dir.isAbsolute) {
      reportWithoutLocation(
          templateInternalProblemUnsupported
              .withArguments("Expected input Uri to be absolute: $scriptUri."),
          Severity.internalProblem);
      return PackageConfig.empty;
    }

    Future<Uri?> checkInDir(Uri dir) async {
      Uri? candidate;
      try {
        candidate = dir.resolve('.dart_tool/package_config.json');
        if (await fileSystem.entityForUri(candidate).exists()) return candidate;
        candidate = dir.resolve('.packages');
        if (await fileSystem.entityForUri(candidate).exists()) return candidate;
        return null;
      } catch (e) {
        Message message =
            templateExceptionReadingFile.withArguments(candidate!, '$e');
        reportWithoutLocation(message, Severity.error);
        // We throw a new exception to ensure that the message include the uri
        // that led to the exception. Exceptions in Uri don't include the
        // offending uri in the exception message.
        throw new ArgumentError(message.message);
      }
    }

    // Check for $cwd/.packages
    Uri? candidate = await checkInDir(dir);
    if (candidate != null) return createPackagesFromFile(candidate);

    // Check for cwd(/..)+/.packages
    Uri parentDir = dir.resolve('..');
    while (parentDir.path != dir.path) {
      candidate = await checkInDir(parentDir);
      if (candidate != null) break;
      dir = parentDir;
      parentDir = dir.resolve('..');
    }

    if (candidate != null) return createPackagesFromFile(candidate);
    return PackageConfig.empty;
  }

  bool _computedSdkDefaults = false;

  /// Ensure [_sdkRoot], [_sdkSummary] and [_librarySpecUri] are initialized.
  ///
  /// If they are not set explicitly, they are inferred based on the default
  /// behavior described in [CompilerOptions].
  void _ensureSdkDefaults() {
    if (_computedSdkDefaults) return;
    _computedSdkDefaults = true;
    Uri? root = _raw.sdkRoot;
    if (root != null) {
      // Normalize to always end in '/'
      if (!root.path.endsWith('/')) {
        root = root.replace(path: root.path + '/');
      }
      _sdkRoot = root;
    } else if (compileSdk) {
      // TODO(paulberry): implement the algorithm for finding the SDK
      // automagically.
      unimplemented('infer the default sdk location', -1, null);
    }

    if (_raw.sdkSummary != null) {
      _sdkSummary = _raw.sdkSummary;
    } else if (!compileSdk) {
      // Infer based on the sdkRoot, but only when `compileSdk` is false,
      // otherwise the default intent was to compile the sdk from sources and
      // not to load an sdk summary file.
      _sdkSummary = root?.resolve("vm_platform_strong.dill");
    }

    if (_raw.librariesSpecificationUri != null) {
      _librariesSpecificationUri = _raw.librariesSpecificationUri;
    } else if (compileSdk) {
      _librariesSpecificationUri = sdkRoot!.resolve('lib/libraries.json');
    }
  }

  /// Create a [FileSystem] specific to the current options.
  FileSystem _createFileSystem() {
    return _raw.fileSystem;
  }

  String debugString() {
    StringBuffer sb = new StringBuffer();
    writeList(String name, List elements) {
      if (elements.isEmpty) {
        sb.writeln('$name: <empty>');
        return;
      }
      sb.writeln('$name:');
      elements.forEach((s) {
        sb.writeln('  - $s');
      });
    }

    sb.writeln('Inputs: ${inputs}');
    sb.writeln('Output: ${output}');

    sb.writeln('Was diagnostic message handler provided: '
        '${_raw.onDiagnostic == null ? "no" : "yes"}');

    sb.writeln('FileSystem: ${_fileSystem.runtimeType} '
        '(provided: ${_raw.fileSystem.runtimeType})');

    writeList('Additional Dills', _raw.additionalDills);

    sb.writeln('Packages uri: ${_raw.packagesFileUri}');
    sb.writeln('Packages: ${_packages}');

    sb.writeln('Compile SDK: ${compileSdk}');
    sb.writeln('SDK root: ${_sdkRoot} (provided: ${_raw.sdkRoot})');
    sb.writeln('SDK specification: ${_librariesSpecificationUri} '
        '(provided: ${_raw.librariesSpecificationUri})');
    sb.writeln('SDK summary: ${_sdkSummary} (provided: ${_raw.sdkSummary})');

    sb.writeln('Target: ${_target?.name} (provided: ${_raw.target?.name})');

    sb.writeln('throwOnErrorsForDebugging: ${throwOnErrorsForDebugging}');
    sb.writeln('throwOnWarningsForDebugging: ${throwOnWarningsForDebugging}');
    sb.writeln('exit on problem: ${setExitCodeOnProblem}');
    sb.writeln('Embed sources: ${embedSourceText}');
    sb.writeln('debugDump: ${debugDump}');
    sb.writeln('verbose: ${verbose}');
    sb.writeln('verify: ${verify}');
    return '$sb';
  }

  Future<List<int>?> _readAsBytes(FileSystemEntity file) async {
    try {
      return await file.readAsBytes();
    } on FileSystemException catch (error) {
      report(
          templateCantReadFile
              .withArguments(error.uri, error.message)
              .withoutLocation(),
          Severity.error);
      return null;
    }
  }
}

/// A [FileSystem] that only allows access to files that have been explicitly
/// allowlisted.
class HermeticFileSystem implements FileSystem {
  final Set<Uri> includedFiles;
  final FileSystem _realFileSystem;

  HermeticFileSystem(this.includedFiles, this._realFileSystem);

  FileSystemEntity entityForUri(Uri uri) {
    if (includedFiles.contains(uri)) return _realFileSystem.entityForUri(uri);
    throw new HermeticAccessException(uri);
  }
}

class HermeticAccessException extends FileSystemException {
  HermeticAccessException(Uri uri)
      : super(
            uri,
            'Invalid access to $uri: '
            'the file is accessed in a modular hermetic build, '
            'but it was not explicitly listed as an input.');

  @override
  String toString() => message;
}
