// Copyright (c) 2016, 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:io' show Directory, File, IOSink, Platform;
import 'dart:typed_data';

import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
    show ScannerConfiguration;
import 'package:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
    show Utf8BytesScanner;
import 'package:_fe_analyzer_shared/src/util/relativize.dart'
    show isWindows, relativizeUri;
import 'package:front_end/src/api_prototype/compiler_options.dart'
    show DiagnosticMessage;
import 'package:front_end/src/base/compiler_context.dart' show CompilerContext;
import 'package:front_end/src/base/messages.dart'
    show DiagnosticMessageFromJson;
import 'package:front_end/src/base/processed_options.dart'
    show ProcessedOptions;
import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation;
import 'package:front_end/src/kernel/kernel_target.dart' show KernelTarget;
import 'package:front_end/src/kernel/utils.dart' show ByteSink;
import 'package:kernel/ast.dart'
    show
        Block,
        Component,
        Library,
        LibraryPart,
        Procedure,
        ReturnStatement,
        Source,
        Statement;
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:kernel/error_formatter.dart' show ErrorFormatter;
import 'package:kernel/kernel.dart' show loadComponentFromBinary;
import 'package:kernel/naive_type_checker.dart' show NaiveTypeChecker;
import 'package:kernel/text/ast_to_text.dart' show Printer;
import 'package:testing/testing.dart'
    show
        ChainContext,
        Expectation,
        ExpectationSet,
        Result,
        StdioProcess,
        Step,
        TestDescription;

import '../testing/suite.dart' show CompilationSetup, CompileMode;
import '../test_utils.dart';

final Uri platformBinariesLocation = computePlatformBinariesLocation();

mixin MatchContext implements ChainContext {
  bool get updateExpectations;

  String get updateExpectationsOption;

  bool get canBeFixWithUpdateExpectations;

  @override
  ExpectationSet get expectationSet;

  Expectation get expectationFileMismatch =>
      expectationSet["ExpectationFileMismatch"];

  Expectation get expectationFileMismatchSerialized =>
      expectationSet["ExpectationFileMismatchSerialized"];

  Expectation get expectationFileMissing =>
      expectationSet["ExpectationFileMissing"];

  Future<Result<O>> match<O>(String suffix, String actual, Uri uri, O output,
      {Expectation? onMismatch, bool? overwriteUpdateExpectationsWith}) async {
    bool updateExpectations =
        overwriteUpdateExpectationsWith ?? this.updateExpectations;
    actual = actual.trim();
    if (actual.isNotEmpty) {
      actual += "\n";
    }
    File expectedFile = new File("${uri.toFilePath()}$suffix");
    if (await expectedFile.exists()) {
      String expected = await expectedFile.readAsString();
      if (expected.replaceAll("\r\n", "\n") != actual) {
        if (updateExpectations) {
          return updateExpectationFile<O>(expectedFile.uri, actual, output);
        }
        String diff = await runDiff(expectedFile.uri, actual);
        onMismatch ??= expectationFileMismatch;
        return new Result<O>(
            output, onMismatch, "$uri doesn't match ${expectedFile.uri}\n$diff",
            autoFixCommand: onMismatch == expectationFileMismatch
                ? updateExpectationsOption
                : null,
            canBeFixWithUpdateExpectations:
                onMismatch == expectationFileMismatch &&
                    canBeFixWithUpdateExpectations);
      } else {
        return new Result<O>.pass(output);
      }
    } else {
      if (actual.isEmpty) return new Result<O>.pass(output);
      if (updateExpectations) {
        return updateExpectationFile(expectedFile.uri, actual, output);
      }
      return new Result<O>(
          output,
          expectationFileMissing,
          """
Please create file ${expectedFile.path} with this content:
$actual""",
          autoFixCommand: updateExpectationsOption);
    }
  }

  Future<Result<O>> updateExpectationFile<O>(
    Uri uri,
    String actual,
    O output,
  ) async {
    if (actual.isEmpty) {
      await new File.fromUri(uri).delete();
    } else {
      await openWrite(uri, (IOSink sink) {
        sink.write(actual);
      });
    }
    return new Result<O>.pass(output);
  }
}

class ErrorCommentChecker
    extends Step<ComponentResult, ComponentResult, ChainContext> {
  final CompileMode compileMode;
  const ErrorCommentChecker(this.compileMode);
  static const bool throwOnNoMatch = false;

  @override
  String get name => "ErrorCommentChecker";

  static const Set<String> ignoreBecauseOfFailures = {
    "extension_types/conflicting_static_and_instance",
    "extension_types/implements_conflicts",
    "general/bounds_enums",
    "general/bounds_type_parameters",
    "general/covariant_equals",
    "general/getter_vs_setter_type",
    "general/nested_variance",
    "general/new_as_selector",
    "general/top_level_variance",
    "general/type_variable_uses",
    "generic_metadata/alias_from_opt_in",
    "inference/block_bodied_lambdas_infer_bottom_sync",
    "inference/future_then_conditional",
    "inference/future_then_ifNull",
    "inference/generic_methods_infer_js_builtin",
    "inference/instantiate_to_bounds_generic2_has_bound_defined_after",
    "inference/instantiate_to_bounds_generic2_has_bound_defined_before",
    "inference/void_return_type_subtypes_dynamic",
    "nnbd_mixed/hierarchy/in_dill_out_in/in_out_in",
    "nnbd_mixed/hierarchy/in_out_dill_in/in_out_in",
    "nnbd/getter_vs_setter_type_nnbd",
    "nnbd/getter_vs_setter_type",
    "nnbd/null_access",
    "patterns/exhaustiveness/bool_switch",
    "patterns/exhaustiveness/enum_switch",
    "patterns/for_final_variable",
    "patterns/pattern_types",
    "records/type_record_as_supertype"
  };

  @override
  Future<Result<ComponentResult>> run(
      ComponentResult result, ChainContext context) {
    if (compileMode != CompileMode.full) return Future.value(pass(result));
    // TODO(jensj): Delete this once failures are fixed.
    if (ignoreBecauseOfFailures.contains(result.description.shortName)) {
      return Future.value(pass(result));
    }

    Component component = result.component;
    for (Library lib in component.libraries) {
      if (!result.userLibraries.contains(lib.importUri)) continue;
      if (!lib.fileUri.isScheme("file")) continue;
      List<Uri> uris = [];
      List<String> filenames = [];
      for (LibraryPart part in lib.parts) {
        // This is a bit simplistic but will probably work for our use here.
        uris.add(lib.fileUri.resolve(part.partUri));
        filenames.add(uris.last.pathSegments.last);
      }
      uris.add(lib.fileUri);
      filenames.add(uris.last.pathSegments.last);

      Set<String> expectProblemOn = {};
      Set<String> expectNoProblemOn = {};
      for (Uri uri in uris) {
        Set<int> expectErrorOnLines = {};
        Set<int> expectNoErrorOnLines = {};
        Map<int, List<CommentToken>> linesToComments =
            extractCommentsFromLines(uri);
        categorizeCommentLines(
            linesToComments, expectErrorOnLines, expectNoErrorOnLines);
        for (int line in expectErrorOnLines) {
          expectProblemOn.add("${uri.pathSegments.last}:$line");
        }
        for (int line in expectNoErrorOnLines) {
          expectNoProblemOn.add("${uri.pathSegments.last}:$line");
        }
      }

      // Now check.
      if (expectProblemOn.isNotEmpty || expectNoProblemOn.isNotEmpty) {
        List<String> failures = [];
        Set<String> notYetSeen = new Set<String>.of(expectProblemOn);
        // Sanity check: No overlap between error and no-error expectations.
        Set<String> overlap = expectProblemOn.intersection(expectNoProblemOn);
        if (overlap.isNotEmpty) {
          for (String fileAndLine in overlap) {
            failures.add("Test error: "
                "$fileAndLine is marked as both error and no error.");
          }
        }

        List<String>? libraryProblems = lib.problemsAsJson;
        RegExp extractLineRegExp = RegExp(
            "(${filenames.map((e) => RegExp.escape(e)).join("|")}):(\\d+)");

        if (libraryProblems != null) {
          for (String jsonString in libraryProblems) {
            DiagnosticMessageFromJson message =
                new DiagnosticMessageFromJson.fromJson(jsonString);
            // By taking all of these we accept it if it's just mentioned in a
            // context message too. Is that the precision we want?
            for (String plainTextProblem in message.plainTextFormatted) {
              List<RegExpMatch> matches =
                  extractLineRegExp.allMatches(plainTextProblem).toList();
              if (matches.isEmpty && throwOnNoMatch) {
                throw "Couldn't extract any offsets from "
                    "'$plainTextProblem' with '$extractLineRegExp'";
              }
              for (RegExpMatch match in matches) {
                String lineString = match.group(0)!;
                notYetSeen.remove(lineString);
                if (expectNoProblemOn.contains(lineString)) {
                  failures.add("Found error at $lineString "
                      "but didn't expect any:\n"
                      "$plainTextProblem");
                }
              }
            }
          }
        }

        for (String line in notYetSeen) {
          failures.add("Expected error on $line but didn't find any.");
        }

        if (failures.isNotEmpty) {
          return new Future.value(new Result<ComponentResult>(
              result,
              context.expectationSet["ErrorCommentCheckFailure"],
              "Found ${failures.length} failures:\n\n * "
              "${failures.join("\n\n * ")}\n"));
        }
      }
    }

    return Future.value(pass(result));
  }

  void categorizeCommentLines(Map<int, List<CommentToken>> linesToComments,
      Set<int> expectErrorOnLines, Set<int> expectNoErrorOnLines) {
    for (MapEntry<int, List<CommentToken>> entry in linesToComments.entries) {
      for (CommentToken comment in entry.value) {
        String message = comment.lexeme.trim().toLowerCase();
        while (message.startsWith("//") || message.startsWith("/*")) {
          message = message.substring(2).trim();
        }
        // TODO(jensj): Possibly reduce these cases by updating tests.
        // See discussion in
        // https://dart-review.googlesource.com/c/sdk/+/346301.
        if (message == "error" ||
            message == "error." ||
            message == "error */" ||
            message == "error*/" ||
            message.startsWith("error in strong mode") ||
            message.startsWith("error:") ||
            message.startsWith("error,") ||
            message.startsWith("error.") ||
            message.startsWith("error - ") ||
            message.startsWith("error (") ||
            message.startsWith("error on ") ||
            message.startsWith("error in ") ||
            message.startsWith("error since ") ||
            message.startsWith("error because ") ||
            message.startsWith("not ok.") ||
            message.startsWith("note: illegal ") ||
            message.startsWith("parse error:") ||
            message.startsWith("parse error,") ||
            message.startsWith("compile-time error") ||
            message.endsWith(" compile-time error")) {
          expectErrorOnLines.add(entry.key);
        } else if (message == "ok" ||
            message == "ok." ||
            message == "ok," ||
            message == "ok */" ||
            message.startsWith("ok: ") ||
            message.startsWith("ok, ") ||
            message.startsWith("ok (") ||
            message.startsWith("ok because ") ||
            message.startsWith("ok to ") ||
            message.startsWith("now ok") ||
            message.startsWith("no error.") ||
            message.startsWith("no error:") ||
            message.startsWith("no error ") ||
            message.startsWith("not a compile time error") ||
            message.startsWith("not an error") ||
            message == "shouldn't result in a compile-time error.") {
          expectNoErrorOnLines.add(entry.key);
        }
      }
    }
  }

  Map<int, List<CommentToken>> extractCommentsFromLines(Uri uri) {
    if (!uri.isScheme("file")) return const {};
    File f = new File.fromUri(uri);
    if (!f.existsSync()) return const {};
    Uint8List rawBytes = f.readAsBytesSync();
    Utf8BytesScanner scanner = new Utf8BytesScanner(
      rawBytes,
      configuration: const ScannerConfiguration(
          enableExtensionMethods: true,
          enableNonNullable: true,
          enableTripleShift: true),
      includeComments: true,
      languageVersionChanged: (scanner, languageVersion) {
        // Nothing - but don't overwrite the previous settings.
      },
    );
    Token firstToken = scanner.tokenize();
    List<int> lineStarts = scanner.lineStarts;

    Token? token = firstToken;
    Token? previousToken;
    Source lineStartsHelper = new Source.emptySource(lineStarts, null, null);
    Map<int, List<CommentToken>> linesToComments = {};
    while (token != null && !token.isEof) {
      CommentToken? precedingComments = token.precedingComments;
      while (precedingComments != null) {
        int commentLine = lineStartsHelper
            .getLocation(Uri.base /* dummy */, precedingComments.offset)
            .line;
        int tokenLine = lineStartsHelper
            .getLocation(Uri.base /* dummy */, token.offset)
            .line;
        int likelyAboutLine = tokenLine;
        if (previousToken != null) {
          int previousTokenLine = lineStartsHelper
              .getLocation(Uri.base /* dummy */, previousToken.offset)
              .line;
          if (previousTokenLine == commentLine) likelyAboutLine = commentLine;
        }
        if (!precedingComments.lexeme.startsWith("// Copyright (c)") &&
            !precedingComments.lexeme
                .startsWith("// for details. All rights reserved.") &&
            !precedingComments.lexeme.startsWith("// BSD-style license")) {
          (linesToComments[likelyAboutLine] ??= []).add(precedingComments);
        }

        Token? next = precedingComments.next;
        if (next is CommentToken) {
          precedingComments = next;
        } else {
          precedingComments = null;
        }
      }
      previousToken = token;
      token = token.next;
    }
    return linesToComments;
  }
}

class Print extends Step<ComponentResult, ComponentResult, ChainContext> {
  const Print();

  @override
  String get name => "print";

  @override
  Future<Result<ComponentResult>> run(ComponentResult result, _) async {
    Component component = result.component;

    StringBuffer sb = new StringBuffer();
    await CompilerContext.runWithDefaultOptions((compilerContext) async {
      compilerContext.uriToSource.addAll(component.uriToSource);

      Printer printer = new Printer(sb,
          showOffsets: result.compilationSetup.folderOptions.showOffsets);
      for (Library library in component.libraries) {
        if (result.userLibraries.contains(library.importUri)) {
          printer.writeLibraryFile(library);
        }
      }
      printer.writeConstantTable(component);
    });
    print("$sb");
    return pass(result);
  }
}

class TypeCheck extends Step<ComponentResult, ComponentResult, ChainContext> {
  const TypeCheck();

  @override
  String get name => "typeCheck";

  @override
  Future<Result<ComponentResult>> run(
      ComponentResult result, ChainContext context) {
    Component component = result.component;
    ErrorFormatter errorFormatter = new ErrorFormatter();
    NaiveTypeChecker checker =
        new NaiveTypeChecker(errorFormatter, component, ignoreSdk: true);
    checker.checkComponent(component);
    if (errorFormatter.numberOfFailures == 0) {
      return new Future.value(pass(result));
    } else {
      errorFormatter.failures.forEach(print);
      print('------- Found ${errorFormatter.numberOfFailures} errors -------');
      return new Future.value(new Result<ComponentResult>(
          null,
          context.expectationSet["TypeCheckError"],
          '${errorFormatter.numberOfFailures} type errors'));
    }
  }
}

class MatchExpectation
    extends Step<ComponentResult, ComponentResult, MatchContext> {
  final String suffix;
  final bool serializeFirst;
  final bool isLastMatchStep;

  /// Check if a textual representation of the component matches the expectation
  /// located at [suffix]. If [serializeFirst] is true, the input component will
  /// be serialized, deserialized, and the textual representation of that is
  /// compared. It is still the original component that is returned though.
  const MatchExpectation(this.suffix,
      {this.serializeFirst = false, required this.isLastMatchStep});

  @override
  String get name => "match expectations";

  @override
  Future<Result<ComponentResult>> run(
      ComponentResult result, MatchContext context) {
    Component component = result.component;

    Component componentToText = component;
    if (serializeFirst) {
      if (result.compilationSetup.folderOptions.showOffsets) {
        // Not all offsets are serialized so the output won't match and there is
        // currently no reason to check this.
        // TODO(johnniwinther): Find a way to avoid or verify the discrepancies.
        return new Future.value(new Result<ComponentResult>.pass(result));
      }
      // TODO(johnniwinther): Use library filter instead.
      List<Library> sdkLibraries =
          component.libraries.where((l) => !result.isUserLibrary(l)).toList();

      ByteSink sink = new ByteSink();
      Component writeMe = new Component(
          libraries: component.libraries.where(result.isUserLibrary).toList())
        ..setMainMethodAndMode(null, false, component.mode);
      writeMe.uriToSource.addAll(component.uriToSource);
      if (component.problemsAsJson != null) {
        writeMe.problemsAsJson =
            new List<String>.from(component.problemsAsJson!);
      }
      BinaryPrinter binaryPrinter = new BinaryPrinter(sink);
      binaryPrinter.writeComponentFile(writeMe);
      Uint8List bytes = sink.builder.takeBytes();

      BinaryBuilder binaryBuilder = new BinaryBuilder(bytes);
      componentToText = new Component(libraries: sdkLibraries);
      binaryBuilder.readComponent(componentToText);
      component.adoptChildren();
    }

    Uri uri = result.description.uri;
    Iterable<Library> libraries =
        componentToText.libraries.where(result.isUserLibrary);
    Uri base = uri.resolve(".");

    StringBuffer buffer = new StringBuffer();

    List<Iterable<String>> errors = result.compilationSetup.errors;
    Set<String> reportedErrors = <String>{};
    for (Iterable<String> message in errors) {
      reportedErrors.add(message.join('\n'));
    }
    Set<String> problemsAsJson = <String>{};
    void addProblemsAsJson(List<String>? problems) {
      if (problems != null) {
        for (String jsonString in problems) {
          DiagnosticMessage message =
              new DiagnosticMessageFromJson.fromJson(jsonString);
          problemsAsJson.add(message.plainTextFormatted.join('\n'));
        }
      }
    }

    addProblemsAsJson(componentToText.problemsAsJson);
    libraries.forEach((Library library) {
      addProblemsAsJson(library.problemsAsJson);
    });

    bool hasProblemsOutsideComponent = false;
    for (String reportedError in reportedErrors) {
      if (!problemsAsJson.contains(reportedError)) {
        if (!hasProblemsOutsideComponent) {
          buffer.writeln('//');
          buffer.writeln('// Problems outside component:');
        }
        buffer.writeln('//');
        buffer.writeln('// ${reportedError.split('\n').join('\n// ')}');
        hasProblemsOutsideComponent = true;
      }
    }
    if (hasProblemsOutsideComponent) {
      buffer.writeln('//');
    }
    if (isLastMatchStep) {
      // Clear errors only in the last match step. This is needed to verify
      // problems reported outside the component in both the serialized and
      // non-serialized step.
      errors.clear();
    }
    Printer printer = new Printer(buffer,
        showOffsets: result.compilationSetup.folderOptions.showOffsets)
      ..writeProblemsAsJson(
          "Problems in component", componentToText.problemsAsJson);
    libraries.forEach((Library library) {
      printer.writeLibraryFile(library);
      printer.endLine();
    });
    printer.writeConstantTable(componentToText);

    if (result.extraConstantStrings.isNotEmpty) {
      buffer.writeln("");
      buffer.writeln("Extra constant evaluation status:");
      for (String extraConstantString in result.extraConstantStrings) {
        buffer.writeln(extraConstantString);
      }
    }
    addConstantCoverageToExpectation(result.component, buffer,
        skipImportUri: (Uri? importUri) =>
            !result.isUserLibraryImportUri(importUri));

    String actual = "$buffer";
    String binariesPath =
        relativizeUri(Uri.base, platformBinariesLocation, isWindows);
    if (binariesPath.endsWith("/dart-sdk/lib/_internal/")) {
      // We are running from something like out/ReleaseX64/dart-sdk/bin/dart
      String search = binariesPath.substring(
          0, binariesPath.length - "lib/_internal/".length);
      actual = _replaceSdkLocation(actual, search, "sdk/");
    } else {
      // We are running from something like out/ReleaseX64/dart
    }
    actual = _replaceSdkLocation(actual, "sdk/", "sdk/");
    actual = actual.replaceAll("$base", "org-dartlang-testcase:///");
    actual = actual.replaceAll("\\n", "\n");
    return context.match<ComponentResult>(suffix, actual, uri, result,
        onMismatch: serializeFirst
            ? context.expectationFileMismatchSerialized
            : context.expectationFileMismatch,
        overwriteUpdateExpectationsWith: serializeFirst ? false : null);
  }

  /// Replace SDK locations starting with [path] with [replacement] and '*'
  /// instead of the line/column.
  ///
  /// For instance replacing
  ///
  ///     out/ReleaseX64/dart-sdk/lib/core/enum.dart:101:13
  ///
  /// with
  ///
  ///     sdk/lib/core/enum.dart:*
  ///
  /// This is done to avoid expectations to depend on the actual location
  /// of the SDK or the position within the SDK file.
  String _replaceSdkLocation(String text, String path, String replacement) {
    // Replace path with line/column.
    RegExp regExp = new RegExp(
        '^// ${RegExp.escape(path)}([^:\r\n]*):\\d+:\\d+:',
        multiLine: true);
    text = text.replaceAllMapped(
        regExp, (Match match) => '// $replacement${match[1]}:*:');
    // Replace path with no line/column.
    return text.replaceAll(path, replacement);
  }
}

class WriteDill extends Step<ComponentResult, ComponentResult, ChainContext> {
  final bool skipVm;

  const WriteDill({required this.skipVm});

  @override
  String get name => "write .dill";

  @override
  Future<Result<ComponentResult>> run(ComponentResult result, _) async {
    Component component = result.component;
    Procedure? mainMethod = component.mainMethod;
    bool writeToFile = !skipVm;
    if (mainMethod == null) {
      writeToFile = false;
    } else {
      Statement? mainBody = mainMethod.function.body;
      if (mainBody is Block && mainBody.statements.isEmpty ||
          mainBody is ReturnStatement && mainBody.expression == null) {
        writeToFile = false;
      }
    }
    ByteSink sink = new ByteSink();
    bool good = false;
    try {
      // TODO(johnniwinther): Use library filter instead.
      // Avoid serializing the sdk.
      Component userCode = new Component(
          nameRoot: component.root,
          uriToSource: new Map<Uri, Source>.from(component.uriToSource));
      userCode.setMainMethodAndMode(
          component.mainMethodName, true, component.mode);
      List<Library> auxiliaryLibraries = [];
      for (Library library in component.libraries) {
        bool includeLibrary;
        if (library.importUri.isScheme("dart")) {
          if (result.isUserLibrary(library)) {
            // dart:test, test:extra etc as used will say yes to being a user
            // library.
            includeLibrary = true;
          } else if (library.isSynthetic) {
            // OK --- serialize that.
            includeLibrary = true;
          } else {
            // Skip serialization of "real" platform libraries.
            includeLibrary = false;
          }
        } else if (result.isUserLibrary(library)) {
          includeLibrary = true;
        } else {
          // This library is neither part of the user libraries nor part of the
          // platform libraries. To run this, we need to include it in the
          // dill.
          auxiliaryLibraries.add(library);
          includeLibrary = false;
        }
        if (includeLibrary) {
          userCode.libraries.add(library);
        }
      }

      // We first ensure that we can serialize with possible references to
      // libraries that aren't included in the serialization.
      new BinaryPrinter(sink).writeComponentFile(userCode);

      // We then serialize with any such libraries to
      //   a) ensure that we can do that too, and that
      //   b) the output is complete (modulo the platform) so that the VM can
      //      actually run it.
      if (auxiliaryLibraries.isNotEmpty) {
        userCode.libraries.addAll(auxiliaryLibraries);
        sink = new ByteSink();
        new BinaryPrinter(sink).writeComponentFile(userCode);
      }
      good = true;
    } catch (e, s) {
      return fail(result, e, s);
    } finally {
      if (good && writeToFile) {
        Directory tmp = await Directory.systemTemp.createTemp();
        Uri uri = tmp.uri.resolve("generated.dill");
        File generated = new File.fromUri(uri);
        IOSink ioSink = generated.openWrite();
        ioSink.add(sink.builder.takeBytes());
        await ioSink.close();
        result = new ComponentResult(
            result.description,
            result.component,
            result.userLibraries,
            result.compilationSetup,
            result.sourceTarget,
            uri);
        print("Wrote component to `${generated.path}`.");
      } else {
        print("Wrote component to memory.");
      }
    }
    return pass(result);
  }
}

class ReadDill extends Step<Uri, Uri, ChainContext> {
  const ReadDill();

  @override
  String get name => "read .dill";

  @override
  Future<Result<Uri>> run(Uri uri, _) {
    try {
      loadComponentFromBinary(uri.toFilePath());
    } catch (e, s) {
      return new Future.value(fail(uri, e, s));
    }
    return new Future.value(pass(uri));
  }
}

Future<String> runDiff(Uri expected, String actual) async {
  if (Platform.isWindows) {
    // TODO(johnniwinther): Work-around for Windows. For some reason piping
    // the actual result through stdin doesn't work; it shows a diff as if the
    // actual result is the empty string.
    Directory tempDirectory = Directory.systemTemp.createTempSync();
    Uri uri = tempDirectory.uri.resolve('actual');
    File file = new File.fromUri(uri)..writeAsStringSync(actual);
    StdioProcess process = await StdioProcess.run(
        "git",
        <String>[
          "diff",
          "--no-index",
          "-u",
          expected.toFilePath(),
          uri.toFilePath()
        ],
        runInShell: true);
    file.deleteSync();
    tempDirectory.deleteSync();
    return process.output;
  } else {
    StdioProcess process = await StdioProcess.run(
        "git", <String>["diff", "--no-index", "-u", expected.toFilePath(), "-"],
        input: actual, runInShell: true);
    return process.output;
  }
}

Future<void> openWrite(Uri uri, f(IOSink sink)) async {
  IOSink sink = new File.fromUri(uri).openWrite();
  try {
    await f(sink);
  } finally {
    await sink.close();
  }
  print("Wrote $uri");
}

class ComponentResult {
  final TestDescription description;
  final Component component;
  final Set<Uri> userLibraries;
  final Uri? outputUri;
  final CompilationSetup compilationSetup;
  final KernelTarget sourceTarget;
  final List<String> extraConstantStrings = [];

  ComponentResult(this.description, this.component, this.userLibraries,
      this.compilationSetup, this.sourceTarget,
      [this.outputUri]);

  bool isUserLibrary(Library library) {
    return isUserLibraryImportUri(library.importUri);
  }

  bool isUserLibraryImportUri(Uri? importUri) {
    // TODO(johnniwinther): Support patch libraries user libraries.
    return userLibraries.contains(importUri);
  }

  ProcessedOptions get options => compilationSetup.options;
}
