// Copyright (c) 2018, 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:convert' show jsonDecode;
import 'dart:developer' show debugger;
import 'dart:io' show Directory, File;

import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
    show DiagnosticMessage, getMessageCodeObject;
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
import "package:dev_compiler/src/kernel/target.dart" show DevCompilerTarget;
import 'package:expect/expect.dart' show Expect;
import 'package:front_end/src/api_prototype/compiler_options.dart'
    show CompilerOptions, parseExperimentalArguments, parseExperimentalFlags;
import 'package:front_end/src/api_prototype/experimental_flags.dart'
    show ExperimentalFlag;
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
    show IncrementalCompilerResult;
import "package:front_end/src/api_prototype/memory_file_system.dart"
    show MemoryFileSystem, MemoryFileSystemEntity;
import 'package:front_end/src/base/compiler_context.dart' show CompilerContext;
import 'package:front_end/src/base/incremental_compiler.dart'
    show AdvancedInvalidationResult, IncrementalCompiler, RecorderForTesting;
import 'package:front_end/src/base/incremental_serializer.dart'
    show IncrementalSerializer;
import 'package:front_end/src/base/nnbd_mode.dart' show NnbdMode;
import 'package:front_end/src/base/processed_options.dart'
    show ProcessedOptions;
import 'package:front_end/src/codes/cfe_codes.dart'
    show DiagnosticMessageFromJson, FormattedMessage;
import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation, computePlatformDillName;
import 'package:front_end/src/kernel/utils.dart' show ByteSink;
import 'package:kernel/ast.dart';
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:kernel/class_hierarchy.dart'
    show ClassHierarchy, ClosedWorldClassHierarchy, ForTestingClassInfo;
import 'package:kernel/src/equivalence.dart'
    show
        EquivalenceResult,
        EquivalenceStrategy,
        EquivalenceVisitor,
        checkEquivalence;
import 'package:kernel/target/targets.dart'
    show
        LateLowering,
        NoneTarget,
        Target,
        TargetFlags,
        TestTargetFlags,
        TestTargetWrapper;
import 'package:kernel/text/ast_to_text.dart'
    show NameSystem, Printer, componentToString;
import "package:testing/testing.dart"
    show
        Chain,
        ChainContext,
        Expectation,
        ExpectationSet,
        Result,
        Step,
        TestDescription;
import "package:vm/modular/target/vm.dart" show VmTarget;
import "package:yaml/yaml.dart" show YamlMap, loadYamlNode;

import 'binary_md_dill_reader.dart' show DillComparer;
import 'fasta/suite_utils.dart';
import 'fasta/testing/environment_keys.dart';
import "incremental_utils.dart" as util;
import 'test_utils.dart';
import 'testing_utils.dart' show checkEnvironment;
import 'utils/io_utils.dart' show computeRepoDir;
import 'utils/symbolic_language_versions.dart';
import 'utils/values.dart';

void main([List<String> arguments = const []]) => internalMain(createContext,
    arguments: arguments,
    displayName: "incremental suite",
    configurationPath: "../testing.json");

/// Top level yaml properties for an incremental test.
class TestProperties {
  /// Value of [type] for selecting a [basicTest].
  static const String type_basic = 'basic';

  /// Value of [type] for selecting a [NewWorldTest].
  static const String type_newworld = 'newworld';

  /// This selects the type of test.
  ///
  /// [type_basic] runs a [basicTest] with additional properties defined in
  /// [BasicTestProperties].
  ///
  /// [type_newworld] runs a [NewWorldTest] with additional properties defined
  /// in [NewWorldTestProperties].
  static const Property<String> type = Property.required(
      'type', StringValue(options: {type_basic, type_newworld}));
}

/// Additional yaml properties for a [basicTest].
// TODO(johnniwinther,jensj): Document all properties.
class BasicTestProperties {
  static const Property<Map<String, String>> sources =
      Property.required('sources', MapValue(StringValue()));

  static const Property<String> entry =
      Property.required('entry', StringValue());

  static const Property<List<String>?> invalidate =
      Property.optional('invalidate', ListValue(StringValue()));
}

/// Additional yaml properties for a [NewWorldTest].
// TODO(johnniwinther,jensj): Document all properties.
class NewWorldTestProperties {
  static const Property<List<World>> worlds =
      Property.required('worlds', ListValue(CustomValue(World.create)));

  static const Property<Map<String, Map<String, String>>?> modules =
      Property.optional('modules', MapValue(MapValue(StringValue())));

  static const Property<bool> omitPlatform =
      Property.optional('omitPlatform', BoolValue(), defaultValue: true);

  static const Property<bool> forceLateLoweringForTesting = Property.optional(
      'forceLateLoweringForTesting', BoolValue(),
      defaultValue: false);

  static const Property<bool> trackWidgetCreation = Property.optional(
      'trackWidgetCreation', BoolValue(),
      defaultValue: false);

  static const Property<bool> incrementalSerialization = Property.optional(
      'incrementalSerialization', BoolValue(),
      defaultValue: false);

  static const String nnbdMode_weak = 'weak';

  static const Property<String?> nnbdMode =
      Property.optional('nnbdMode', StringValue(options: {nnbdMode_weak}));

  static const String target_none = 'none';
  static const String target_dartdevc = 'dartdevc';
  static const String target_dart2js = 'dart2js';
  static const String target_vm = 'vm';

  static const Property<String?> target = Property.optional(
      'target',
      StringValue(
          options: {target_none, target_dartdevc, target_dart2js, target_vm}));
}

/// Yaml properties for a [World] within a [NewWorldTest].
// TODO(johnniwinther,jensj): Document all properties.
class WorldProperties {
  static const Property<List<String>?> modules =
      Property.optional('modules', ListValue(StringValue()));

  static const String worldType_updated = 'updated';

  static const Property<String?> worldType =
      Property.optional('worldType', StringValue(options: {worldType_updated}));

  static const Property<bool> noFullComponent =
      Property.optional('noFullComponent', BoolValue(), defaultValue: false);

  static const Property<bool?> expectInitializeFromDill =
      Property.optional('expectInitializeFromDill', BoolValue());

  static const Property<Map<String, String>> sources = Property.optional(
      'sources', MapValue(StringValue()),
      defaultValue: const {});

  static const Property<bool> badSdk =
      Property.optional('badSdk', BoolValue(), defaultValue: false);

  static const Property<bool> enableStringReplacement = Property.optional(
      'enableStringReplacement', BoolValue(),
      defaultValue: false);

  static const Property<String?> packageConfigFile =
      Property.optional('packageConfigFile', StringValue());

  static const Property<String?> experiments =
      Property.optional("experiments", StringValue());

  static const String nnbdMode_weak = 'weak';

  static const Property<String?> nnbdMode =
      Property.optional("nnbdMode", StringValue(options: {nnbdMode_weak}));

  static const Property<List<String>> entry = Property.required(
      'entry', ListValue(StringValue(), supportSingleton: true));

  static const Property<bool> outlineOnly =
      Property.optional("outlineOnly", BoolValue(), defaultValue: false);

  static const Property<bool> skipOutlineBodyCheck = Property.optional(
      "skipOutlineBodyCheck", BoolValue(),
      defaultValue: false);

  static const Property<bool> fromComponent =
      Property.optional("fromComponent", BoolValue(), defaultValue: false);

  static const Property<List<String>?> invalidate =
      Property.optional("invalidate", ListValue(StringValue()));

  static const Property<bool> simulateTransformer = Property.optional(
      "simulateTransformer", BoolValue(),
      defaultValue: false);

  static const Property<bool?> expectInitializationError =
      Property.optional("expectInitializationError", BoolValue());

  static const Property<bool> compareToPrevious =
      Property.optional("compareToPrevious", BoolValue(), defaultValue: false);

  static const Property<List<String>?> uriToSourcesDoesntInclude =
      Property.optional("uriToSourcesDoesntInclude", ListValue(StringValue()));

  static const Property<List<String>?> uriToSourcesOnlyIncludes =
      Property.optional("uriToSourcesOnlyIncludes", ListValue(StringValue()));

  static const Property<bool> skipClassHierarchyTest = Property.optional(
      "skipClassHierarchyTest", BoolValue(),
      defaultValue: false);

  static const Property<bool> expectsPlatform =
      Property.optional("expectsPlatform", BoolValue(), defaultValue: false);

  static const Property<int?> expectedLibraryCount =
      const Property.optional("expectedLibraryCount", IntValue());

  static const Property<int?> expectedSyntheticLibraryCount =
      Property.optional("expectedSyntheticLibraryCount", IntValue());

  /// The expected result of the advanced invalidation.
  ///
  /// If omitted, this defaults to `noDirectlyInvalidated` which corresponds
  /// to the advanced invalidation result of the initial compilation. This means
  /// that all subsequent world entries must specify the expected advanced
  /// invalidation result.
  static const Property<AdvancedInvalidationResult> advancedInvalidation =
      Property.optional(
          "advancedInvalidation", EnumValue(AdvancedInvalidationResult.values),
          defaultValue: AdvancedInvalidationResult.noDirectlyInvalidated);

  static const Property<bool> checkEntries =
      Property.optional("checkEntries", BoolValue(), defaultValue: false);

  static const Property<bool> checkInvalidatedFiles = Property.optional(
      "checkInvalidatedFiles", BoolValue(),
      defaultValue: true);

  static const Property<List<String>?> expectedInvalidatedUri =
      Property.optional('expectedInvalidatedUri', ListValue(StringValue()));

  static const Property<int?> expectSameErrorsAsWorld =
      Property.optional('expectSameErrorsAsWorld', IntValue());

  static const Property<List<ExpressionCompilation>?> expressionCompilation =
      Property.optional(
          'expressionCompilation',
          ListValue(CustomValue(ExpressionCompilation.create),
              supportSingleton: true));

  static const Property<bool> compareWithFromScratch = Property.optional(
      'compareWithFromScratch', BoolValue(),
      defaultValue: false);

  static const Property<bool> brandNewIncrementalSerializationAllowDifferent =
      Property.optional(
          'brandNewIncrementalSerializationAllowDifferent', BoolValue(),
          defaultValue: false);

  /// Whether the compilation of the world is expected to result in warnings.
  static const Property<bool> warnings =
      Property.optional('warnings', BoolValue(), defaultValue: false);

  /// Whether the compilation of the world is expected to result in compile-time
  /// errors.
  static const Property<bool> errors =
      Property.optional('errors', BoolValue(), defaultValue: false);

  static const Property<List<String>?> neededDillLibraries =
      Property.optional('neededDillLibraries', ListValue(StringValue()));

  static const Property<Map<String, List<String>>?> expectedContent =
      Property.optional('expectedContent', MapValue(ListValue(StringValue())));

  static const Property<bool> incrementalSerializationDoesWork =
      Property.optional('incrementalSerializationDoesWork', BoolValue(),
          defaultValue: false);

  static const Property<List<String>?> serializationShouldNotInclude =
      Property.optional(
          'serializationShouldNotInclude', ListValue(StringValue()));

  static const Property<bool> checkConstantCoverageReferences =
      Property.optional('checkConstantCoverageReferences', BoolValue(),
          defaultValue: true);

  /// If `true`, the compilation is allowed to report an error twice.
  static const Property<bool> allowDuplicateErrors = Property.optional(
      'allowDuplicateErrors', BoolValue(),
      defaultValue: false);

  /// If `true`, the compilation is allowed to report a warning twice.
  static const Property<bool> allowDuplicateWarnings = Property.optional(
      'allowDuplicateWarnings', BoolValue(),
      defaultValue: true);

  /// If `true`, the expect files will contain a print of all errors.
  static const Property<bool> printErrorsInExpect = Property.optional(
      'printErrorsInExpect', BoolValue(),
      defaultValue: false);

  /// If `true`, the just compiled world will be "rejected", i.e.
  /// not saved as the latest component and the previous non-rejected compile
  /// (i.e. the one saved in the latest component) will be relinked, mimicking
  /// a reject via the frontend server. At least for now all checking after this
  /// point will be skipped.
  static const Property<bool> reject =
      Property.optional('reject', BoolValue(), defaultValue: false);
}

/// Yaml properties for an [ExpressionCompilation] with a [World].
// TODO(johnniwinther,jensj): Document all properties.
class ExpressionCompilationProperties {
  static const Property<bool> errors =
      Property.optional('errors', BoolValue(), defaultValue: false);

  static const Property<bool> warnings =
      Property.optional('warnings', BoolValue(), defaultValue: false);

  static const Property<String> uri = Property.required('uri', StringValue());

  static const Property<String> expression =
      Property.required('expression', StringValue());

  static const Property<String?> className =
      Property.optional('className', StringValue());
}

final ExpectationSet staticExpectationSet =
    new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));

const String EXPECTATIONS = '''
[
  {
    "name": "ExpectationFileMismatch",
    "group": "Fail"
  },
  {
    "name": "ExpectationFileMissing",
    "group": "Fail"
  },
  {
    "name": "MissingErrors",
    "group": "Fail"
  },
  {
    "name": "UnexpectedErrors",
    "group": "Fail"
  },
  {
    "name": "MissingWarnings",
    "group": "Fail"
  },
  {
    "name": "UnexpectedWarnings",
    "group": "Fail"
  },
  {
    "name": "ClassHierarchyError",
    "group": "Fail"
  },
  {
    "name": "NeededDillMismatch",
    "group": "Fail"
  },
  {
    "name": "IncrementalSerializationError",
    "group": "Fail"
  },
  {
    "name": "ContentDataMismatch",
    "group": "Fail"
  },
  {
    "name": "MissingInitializationError",
    "group": "Fail"
  },
  {
    "name": "UnexpectedInitializationError",
    "group": "Fail"
  },
  {
    "name": "ReachableLibrariesError",
    "group": "Fail"
  },
  {
    "name": "EquivalenceError",
    "group": "Fail"
  },
  {
    "name": "UriToSourceError",
    "group": "Fail"
  },
  {
    "name": "MissingPlatformLibraries",
    "group": "Fail"
  },
  {
    "name": "UnexpectedPlatformLibraries",
    "group": "Fail"
  },
  {
    "name": "UnexpectedAdvancedInvalidation",
    "group": "Fail"
  },
  {
    "name": "UnexpectedEntryToLibraryCount",
    "group": "Fail"
  },
  {
    "name": "LibraryCountMismatch",
    "group": "Fail"
  },
  {
    "name": "InitializedFromDillMismatch",
    "group": "Fail"
  },
  {
    "name": "NNBDModeMismatch",
    "group": "Fail"
  },
  {
    "name": "ConstantCoverageReferenceWithoutNode",
    "group": "Fail"
  }
]
''';

final Expectation ExpectationFileMismatch =
    staticExpectationSet["ExpectationFileMismatch"];
final Expectation ExpectationFileMissing =
    staticExpectationSet["ExpectationFileMissing"];
final Expectation MissingErrors = staticExpectationSet["MissingErrors"];
final Expectation UnexpectedErrors = staticExpectationSet["UnexpectedErrors"];
final Expectation MissingWarnings = staticExpectationSet["MissingWarnings"];
final Expectation UnexpectedWarnings =
    staticExpectationSet["UnexpectedWarnings"];
final Expectation ClassHierarchyError =
    staticExpectationSet["ClassHierarchyError"];
final Expectation NeededDillMismatch =
    staticExpectationSet["NeededDillMismatch"];
final Expectation IncrementalSerializationError =
    staticExpectationSet["IncrementalSerializationError"];
final Expectation ContentDataMismatch =
    staticExpectationSet["ContentDataMismatch"];
final Expectation MissingInitializationError =
    staticExpectationSet["MissingInitializationError"];
final Expectation UnexpectedInitializationError =
    staticExpectationSet["UnexpectedInitializationError"];
final Expectation ReachableLibrariesError =
    staticExpectationSet["ReachableLibrariesError"];
final Expectation EquivalenceError = staticExpectationSet["EquivalenceError"];
final Expectation UriToSourceError = staticExpectationSet["UriToSourceError"];
final Expectation MissingPlatformLibraries =
    staticExpectationSet["MissingPlatformLibraries"];
final Expectation UnexpectedPlatformLibraries =
    staticExpectationSet["UnexpectedPlatformLibraries"];
final Expectation UnexpectedAdvancedInvalidation =
    staticExpectationSet["UnexpectedAdvancedInvalidation"];
final Expectation UnexpectedEntryToLibraryCount =
    staticExpectationSet["UnexpectedEntryToLibraryCount"];
final Expectation LibraryCountMismatch =
    staticExpectationSet["LibraryCountMismatch"];
final Expectation InitializedFromDillMismatch =
    staticExpectationSet["InitializedFromDillMismatch"];
final Expectation NNBDModeMismatch = staticExpectationSet["NNBDModeMismatch"];
final Expectation ConstantCoverageReferenceWithoutNode =
    staticExpectationSet["ConstantCoverageReferenceWithoutNode"];

Future<Context> createContext(Chain suite, Map<String, String> environment) {
  const Set<String> knownEnvironmentKeys = {
    EnvironmentKeys.updateExpectations,
    EnvironmentKeys.addDebugBreaks,
    EnvironmentKeys.skipTests,
  };
  checkEnvironment(environment, knownEnvironmentKeys);

  // Disable colors to ensure that expectation files are the same across
  // platforms and independent of stdin/stderr.
  colors.enableColors = false;
  Set<String> skipTests =
      environment[EnvironmentKeys.skipTests]?.split(",").toSet() ?? {};
  return new Future.value(new Context(
    environment[EnvironmentKeys.updateExpectations] == "true",
    environment[EnvironmentKeys.addDebugBreaks] == "true",
    skipTests,
  ));
}

class Context extends ChainContext {
  @override
  final List<Step> steps = const <Step>[
    const ReadTest(),
    const RunCompilations(),
  ];

  final bool updateExpectations;

  /// Add a debug break (via dart:developers `debugger()` call) after each
  /// iteration (or 'world run') when doing a "new world test".
  final bool breakBetween;

  final Set<String> skipTests;

  Context(this.updateExpectations, this.breakBetween, this.skipTests);

  @override
  Future<List<TestDescription>> list(Chain suite) async {
    if (skipTests.isEmpty) return await super.list(suite);
    return filterSkipped(await super.list(suite));
  }

  List<TestDescription> filterSkipped(List<TestDescription> all) {
    List<TestDescription> result = [];
    for (TestDescription testDescription in all) {
      if (!skipTests.contains(testDescription.shortName)) {
        result.add(testDescription);
      }
    }
    return result;
  }

  @override
  Future<void> cleanUp(TestDescription description, Result result) async {
    await cleanupHelper?.outDir?.delete(recursive: true);
    cleanupHelper?.outDir = null;
  }

  @override
  final ExpectationSet expectationSet = staticExpectationSet;

  TestData? cleanupHelper;
}

class TestData {
  YamlMap map;
  Directory? outDir;
  Uri loadedFrom;

  TestData(this.map, this.outDir, this.loadedFrom);
}

class ReadTest extends Step<TestDescription, TestData, Context> {
  const ReadTest();

  @override
  String get name => "read test";

  @override
  Future<Result<TestData>> run(
      TestDescription description, Context context) async {
    Uri uri = description.uri;
    String contents = await new File.fromUri(uri).readAsString();
    TestData data = new TestData(
        loadYamlNode(contents, sourceUrl: uri) as YamlMap,
        Directory.systemTemp.createTempSync("incremental_load_from_dill_test"),
        uri);
    context.cleanupHelper = data;
    return pass(data);
  }
}

class RunCompilations extends Step<TestData, TestData, Context> {
  const RunCompilations();

  @override
  String get name => "run compilations";

  @override
  Future<Result<TestData>> run(TestData data, Context context) async {
    Result<TestData>? result;
    YamlMap map = data.map;
    Set<String> keys = new Set<String>.from(map.keys.cast<String>());
    String type = TestProperties.type.read(map, keys);
    switch (type) {
      case TestProperties.type_basic:
        await basicTest(
          BasicTestProperties.sources.read(map, keys),
          BasicTestProperties.entry.read(map, keys),
          BasicTestProperties.invalidate.read(map, keys),
          data.outDir!,
        );
        break;
      case TestProperties.type_newworld:
        result = await new NewWorldTest(
          data: data,
          context: context,
          worlds: NewWorldTestProperties.worlds.read(map, keys),
          omitPlatform: NewWorldTestProperties.omitPlatform.read(map, keys),
          forceLateLoweringForTesting: NewWorldTestProperties
              .forceLateLoweringForTesting
              .read(map, keys),
          trackWidgetCreation:
              NewWorldTestProperties.trackWidgetCreation.read(map, keys),
          incrementalSerialization:
              NewWorldTestProperties.incrementalSerialization.read(map, keys),
          nnbdMode: NewWorldTestProperties.nnbdMode.read(map, keys) ==
                  NewWorldTestProperties.nnbdMode_weak
              ? NnbdMode.Weak
              : NnbdMode.Strong,
          modules: NewWorldTestProperties.modules.read(map, keys),
          targetName: NewWorldTestProperties.target.read(map, keys),
        ).newWorldTest();
        break;
      default:
        throw "Unexpected type: ${type}";
    }

    if (keys.isNotEmpty) throw "Unknown toplevel keys: $keys";
    return result ?? pass(data);
  }
}

Future<Null> basicTest(Map<String, String> sourceFiles, String entryPoint,
    List<String>? invalidate, Directory outDir) async {
  Uri entryPointUri = outDir.uri.resolve(entryPoint);
  Set<String> invalidateFilenames =
      invalidate == null ? new Set<String>() : new Set<String>.from(invalidate);
  List<Uri> invalidateUris = <Uri>[];
  Uri? packagesUri;
  for (String filename in sourceFiles.keys) {
    Uri uri = outDir.uri.resolve(filename);
    if (invalidateFilenames.contains(filename)) {
      invalidateUris.add(uri);
      invalidateFilenames.remove(filename);
    }
    String source = sourceFiles[filename]!;
    if (filename == ".dart_tool/package_config.json") {
      packagesUri = uri;
    }
    File file = new File.fromUri(uri);
    await file.parent.create(recursive: true);
    await file.writeAsString(source);
  }
  for (String invalidateFilename in invalidateFilenames) {
    if (invalidateFilename.startsWith('package:')) {
      invalidateUris.add(Uri.parse(invalidateFilename));
    } else {
      throw "Error in test yaml: $invalidateFilename was not recognized.";
    }
  }

  Uri output = outDir.uri.resolve("full.dill");
  Uri initializedOutput = outDir.uri.resolve("full_from_initialized.dill");

  Stopwatch stopwatch = new Stopwatch()..start();
  CompilerOptions options = getOptions();
  if (packagesUri != null) {
    options.packagesFileUri = packagesUri;
  }
  await normalCompile(entryPointUri, output, options: options);
  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");

  stopwatch.reset();
  options = getOptions();
  if (packagesUri != null) {
    options.packagesFileUri = packagesUri;
  }
  bool initializedResult = await initializedCompile(
      entryPointUri, initializedOutput, output, invalidateUris,
      options: options);
  print("Initialized compile(s) from ${output.pathSegments.last} "
      "took ${stopwatch.elapsedMilliseconds} ms");
  Expect.isTrue(initializedResult);

  // Compare the two files.
  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
  List<int> initializedDillData =
      new File.fromUri(initializedOutput).readAsBytesSync();
  checkIsEqual(normalDillData, initializedDillData);
}

Future<Map<String, List<int>>> createModules(
    Map<String, Map<String, String>> module,
    final List<int> sdkSummaryData,
    Target target,
    Target originalTarget,
    String sdkSummary,
    {required bool trackNeededDillLibraries,
    required Uri checkoutRoot}) async {
  final Uri base = Uri.parse("org-dartlang-test:///");
  final Uri sdkSummaryUri = base.resolve(sdkSummary);

  TestMemoryFileSystem fs =
      new TestMemoryFileSystem(base, holePunchBase: checkoutRoot);
  fs.entityForUri(sdkSummaryUri).writeAsBytesSync(sdkSummaryData);

  // Setup all sources
  for (Map<String, String> moduleSources in module.values) {
    for (String filename in moduleSources.keys) {
      String data = moduleSources[filename]!;
      Uri uri = base.resolve(filename);
      if (await fs.entityForUri(uri).exists()) {
        throw "More than one entry for $filename";
      }
      fs.entityForUri(uri).writeAsStringSync(data);
    }
  }

  Map<String, List<int>> moduleResult = new Map<String, List<int>>();

  for (String moduleName in module.keys) {
    List<Uri> moduleSources = <Uri>[];
    Uri? packagesUri;
    for (String filename in module[moduleName]!.keys) {
      Uri uri = base.resolve(filename);
      if (uri.pathSegments.last == "package_config.json") {
        packagesUri = uri;
      } else {
        moduleSources.add(uri);
      }
    }
    bool outlineOnly = false;
    if (originalTarget is DevCompilerTarget) {
      outlineOnly = true;
    }
    CompilerOptions options =
        getOptions(target: target, sdkSummary: sdkSummary);
    options.fileSystem = fs;
    options.sdkRoot = null;
    options.sdkSummary = sdkSummaryUri;
    options.omitPlatform = true;
    options.onDiagnostic = (DiagnosticMessage message) {
      throw message.ansiFormatted;
    };
    if (packagesUri != null) {
      options.packagesFileUri = packagesUri;
    }
    TestIncrementalCompiler compiler = new TestIncrementalCompiler(
        options, moduleSources.first, /* initializeFrom = */ null, outlineOnly);
    IncrementalCompilerResult? compilerResult = await compiler.computeDelta(
        entryPoints: moduleSources,
        trackNeededDillLibraries: trackNeededDillLibraries);
    Component c = compilerResult.component;
    compilerResult = null;
    c.computeCanonicalNames();
    List<Library> wantedLibs = <Library>[];
    for (Library lib in c.libraries) {
      if (moduleSources.contains(lib.importUri) ||
          moduleSources.contains(lib.fileUri)) {
        wantedLibs.add(lib);
      }
    }
    if (wantedLibs.length != moduleSources.length) {
      throw "Module probably not setup right.";
    }
    Component result = new Component(libraries: wantedLibs)
      ..setMainMethodAndMode(null, false, c.mode);
    List<int> resultBytes = util.postProcess(result);
    moduleResult[moduleName] = resultBytes;
  }

  return moduleResult;
}

class ExpressionCompilation {
  final bool errors;
  final bool warnings;
  final String uri;
  final String expression;
  final String? className;

  ExpressionCompilation(
      {required this.errors,
      required this.warnings,
      required this.uri,
      required this.expression,
      required this.className});

  static ExpressionCompilation create(Map yaml) {
    Set<String> keys = new Set<String>.from(yaml.keys);

    bool errors = ExpressionCompilationProperties.errors.read(yaml, keys);
    bool warnings = ExpressionCompilationProperties.warnings.read(yaml, keys);
    String uri = ExpressionCompilationProperties.uri.read(yaml, keys);
    String expression =
        ExpressionCompilationProperties.expression.read(yaml, keys);
    String? className =
        ExpressionCompilationProperties.className.read(yaml, keys);

    if (keys.isNotEmpty) {
      throw "Unknown key(s) for ExpressionCompilation: $keys";
    }
    return new ExpressionCompilation(
        errors: errors,
        warnings: warnings,
        uri: uri,
        expression: expression,
        className: className);
  }
}

class World {
  final List<String>? modules;
  final bool updateWorldType;
  final bool noFullComponent;
  final bool? expectInitializeFromDill;
  final Map<String, String?> sources;
  final bool useBadSdk;
  final bool enableStringReplacement;
  final String? packageConfigFile;
  final String? experiments;
  final String? nnbdModeString;
  final List<String> entries;
  final bool outlineOnly;
  final bool skipOutlineBodyCheck;
  final bool fromComponent;
  final List<String>? invalidate;
  final bool simulateTransformer;
  final bool? expectInitializationError;
  final bool compareToPrevious;
  final List<String>? uriToSourcesDoesntInclude;
  final List<String>? uriToSourcesOnlyIncludes;
  final bool skipClassHierarchyTest;
  final bool expectsPlatform;
  final int? expectedLibraryCount;
  final int? expectedSyntheticLibraryCount;
  final bool warnings;
  final bool errors;
  final List<String>? neededDillLibraries;
  final Map<String, List<String>>? expectedContent;
  final bool incrementalSerializationDoesWork;
  final bool allowDuplicateErrors;
  final bool allowDuplicateWarnings;
  final bool printErrorsInExpect;
  final bool reject;

  /// The expected result of the advanced invalidation.
  final AdvancedInvalidationResult advancedInvalidation;

  final bool checkEntries;
  final bool checkInvalidatedFiles;
  final List<String>? expectedInvalidatedUri;
  final int? expectSameErrorsAsWorld;
  final List<ExpressionCompilation>? expressionCompilation;
  final bool compareWithFromScratch;

  /// Don't check for equality when we allow it to be different
  /// (e.g. when the old one contains more, and the new one doesn't).
  final bool brandNewIncrementalSerializationAllowDifferent;

  final List<String>? serializationShouldNotInclude;

  /// Whether to check if the serialized constant coverage references
  /// points to anything in itself.
  final bool checkConstantCoverageReferences;

  World({
    required this.modules,
    required this.updateWorldType,
    required this.noFullComponent,
    required this.expectInitializeFromDill,
    required this.sources,
    required this.useBadSdk,
    required this.enableStringReplacement,
    required this.packageConfigFile,
    required this.experiments,
    required this.nnbdModeString,
    required this.entries,
    required this.outlineOnly,
    required this.skipOutlineBodyCheck,
    required this.fromComponent,
    required this.invalidate,
    required this.simulateTransformer,
    required this.expectInitializationError,
    required this.compareToPrevious,
    required this.uriToSourcesDoesntInclude,
    required this.uriToSourcesOnlyIncludes,
    required this.skipClassHierarchyTest,
    required this.expectsPlatform,
    required this.expectedLibraryCount,
    required this.expectedSyntheticLibraryCount,
    required this.advancedInvalidation,
    required this.checkEntries,
    required this.checkInvalidatedFiles,
    required this.expectedInvalidatedUri,
    required this.expectSameErrorsAsWorld,
    required this.expressionCompilation,
    required this.compareWithFromScratch,
    required this.brandNewIncrementalSerializationAllowDifferent,
    required this.warnings,
    required this.errors,
    required this.neededDillLibraries,
    required this.expectedContent,
    required this.incrementalSerializationDoesWork,
    required this.serializationShouldNotInclude,
    required this.checkConstantCoverageReferences,
    required this.allowDuplicateErrors,
    required this.allowDuplicateWarnings,
    required this.printErrorsInExpect,
    required this.reject,
  });

  static World create(Map world) {
    Set<String> keys = new Set<String>.from(world.keys);

    List<String>? modules = WorldProperties.modules.read(world, keys);

    String? worldType = WorldProperties.worldType.read(world, keys);
    bool updateWorldType = worldType == WorldProperties.worldType_updated;

    bool noFullComponent = WorldProperties.noFullComponent.read(world, keys);

    bool? expectInitializeFromDill =
        WorldProperties.expectInitializeFromDill.read(world, keys);

    Map<String, String?> sources = WorldProperties.sources.read(world, keys);

    bool useBadSdk = WorldProperties.badSdk.read(world, keys);

    bool enableStringReplacement =
        WorldProperties.enableStringReplacement.read(world, keys);

    String? packageConfigFile =
        WorldProperties.packageConfigFile.read(world, keys);

    String? experiments = WorldProperties.experiments.read(world, keys);

    String? nnbdModeString = WorldProperties.nnbdMode.read(world, keys);

    List<String> entries = WorldProperties.entry.read(world, keys);

    bool outlineOnly = WorldProperties.outlineOnly.read(world, keys);

    bool skipOutlineBodyCheck =
        WorldProperties.skipOutlineBodyCheck.read(world, keys);

    bool fromComponent = WorldProperties.fromComponent.read(world, keys);

    List<String>? invalidate = WorldProperties.invalidate.read(world, keys);

    bool simulateTransformer =
        WorldProperties.simulateTransformer.read(world, keys);

    bool? expectInitializationError =
        WorldProperties.expectInitializationError.read(world, keys);

    bool compareToPrevious =
        WorldProperties.compareToPrevious.read(world, keys);

    List<String>? uriToSourcesDoesntInclude =
        WorldProperties.uriToSourcesDoesntInclude.read(world, keys);

    List<String>? uriToSourcesOnlyIncludes =
        WorldProperties.uriToSourcesOnlyIncludes.read(world, keys);

    bool skipClassHierarchyTest =
        WorldProperties.skipClassHierarchyTest.read(world, keys);

    bool expectsPlatform = WorldProperties.expectsPlatform.read(world, keys);

    int? expectedLibraryCount =
        WorldProperties.expectedLibraryCount.read(world, keys);

    int? expectedSyntheticLibraryCount =
        WorldProperties.expectedSyntheticLibraryCount.read(world, keys);

    AdvancedInvalidationResult advancedInvalidation =
        WorldProperties.advancedInvalidation.read(world, keys);

    bool checkEntries = WorldProperties.checkEntries.read(world, keys);

    bool checkInvalidatedFiles =
        WorldProperties.checkInvalidatedFiles.read(world, keys);

    List<String>? expectedInvalidatedUri =
        WorldProperties.expectedInvalidatedUri.read(world, keys);

    int? expectSameErrorsAsWorld =
        WorldProperties.expectSameErrorsAsWorld.read(world, keys);

    List<ExpressionCompilation>? expressionCompilation =
        WorldProperties.expressionCompilation.read(world, keys);

    bool compareWithFromScratch =
        WorldProperties.compareWithFromScratch.read(world, keys);

    bool brandNewIncrementalSerializationAllowDifferent = WorldProperties
        .brandNewIncrementalSerializationAllowDifferent
        .read(world, keys);

    bool warnings = WorldProperties.warnings.read(world, keys);

    bool errors = WorldProperties.errors.read(world, keys);

    List<String>? neededDillLibraries =
        WorldProperties.neededDillLibraries.read(world, keys);

    Map<String, List<String>>? expectedContent =
        WorldProperties.expectedContent.read(world, keys);

    bool incrementalSerializationDoesWork =
        WorldProperties.incrementalSerializationDoesWork.read(world, keys);

    List<String>? serializationShouldNotInclude =
        WorldProperties.serializationShouldNotInclude.read(world, keys);

    bool checkConstantCoverageReferences =
        WorldProperties.checkConstantCoverageReferences.read(world, keys);

    bool allowDuplicateErrors =
        WorldProperties.allowDuplicateErrors.read(world, keys);

    bool allowDuplicateWarnings =
        WorldProperties.allowDuplicateWarnings.read(world, keys);

    bool printErrorsInExpect =
        WorldProperties.printErrorsInExpect.read(world, keys);

    bool reject = WorldProperties.reject.read(world, keys);

    if (keys.isNotEmpty) {
      throw "Unknown key(s) for World: $keys";
    }

    return new World(
      modules: modules,
      updateWorldType: updateWorldType,
      noFullComponent: noFullComponent,
      expectInitializeFromDill: expectInitializeFromDill,
      sources: sources,
      useBadSdk: useBadSdk,
      enableStringReplacement: enableStringReplacement,
      packageConfigFile: packageConfigFile,
      experiments: experiments,
      nnbdModeString: nnbdModeString,
      entries: entries,
      outlineOnly: outlineOnly,
      skipOutlineBodyCheck: skipOutlineBodyCheck,
      fromComponent: fromComponent,
      invalidate: invalidate,
      simulateTransformer: simulateTransformer,
      expectInitializationError: expectInitializationError,
      compareToPrevious: compareToPrevious,
      uriToSourcesDoesntInclude: uriToSourcesDoesntInclude,
      uriToSourcesOnlyIncludes: uriToSourcesOnlyIncludes,
      skipClassHierarchyTest: skipClassHierarchyTest,
      expectsPlatform: expectsPlatform,
      expectedLibraryCount: expectedLibraryCount,
      expectedSyntheticLibraryCount: expectedSyntheticLibraryCount,
      advancedInvalidation: advancedInvalidation,
      checkEntries: checkEntries,
      checkInvalidatedFiles: checkInvalidatedFiles,
      expectedInvalidatedUri: expectedInvalidatedUri,
      expectSameErrorsAsWorld: expectSameErrorsAsWorld,
      expressionCompilation: expressionCompilation,
      compareWithFromScratch: compareWithFromScratch,
      brandNewIncrementalSerializationAllowDifferent:
          brandNewIncrementalSerializationAllowDifferent,
      warnings: warnings,
      errors: errors,
      neededDillLibraries: neededDillLibraries,
      expectedContent: expectedContent,
      incrementalSerializationDoesWork: incrementalSerializationDoesWork,
      serializationShouldNotInclude: serializationShouldNotInclude,
      checkConstantCoverageReferences: checkConstantCoverageReferences,
      allowDuplicateErrors: allowDuplicateErrors,
      allowDuplicateWarnings: allowDuplicateWarnings,
      printErrorsInExpect: printErrorsInExpect,
      reject: reject,
    );
  }
}

class NewWorldTest {
  final TestData data;
  final Context context;
  final List<World> worlds;
  final Map<String, Map<String, String>>? modules;
  final bool omitPlatform;
  final bool forceLateLoweringForTesting;
  final bool trackWidgetCreation;
  final bool incrementalSerialization;
  final NnbdMode nnbdMode;
  final String? targetName;

  // These are fields in a class to make it easier to track down memory leaks
  // via the leak detector test.
  Component? newestWholeComponent;
  Component? sdk;
  Component? component;
  Component? component2;
  Component? component3;

  NewWorldTest({
    required this.data,
    required this.context,
    required this.worlds,
    required this.modules,
    required this.omitPlatform,
    required this.forceLateLoweringForTesting,
    required this.trackWidgetCreation,
    required this.incrementalSerialization,
    required this.nnbdMode,
    required this.targetName,
  });

  Future<Result<TestData>> newWorldTest() async {
    final Uri platformBinariesRoot =
        computePlatformBinariesLocation(forceBuildDir: true);

    // This is somewhat of a hack but will do for now.
    final Uri checkoutRoot = data.loadedFrom.resolve("../../../../");

    TestTargetFlags targetFlags = new TestTargetFlags(
        forceLateLoweringsForTesting:
            forceLateLoweringForTesting ? LateLowering.all : null,
        trackWidgetCreation: trackWidgetCreation);
    Target target = new VmTarget(targetFlags);
    if (targetName != null) {
      if (targetName == NewWorldTestProperties.target_none) {
        target = new NoneTarget(targetFlags);
      } else if (targetName == NewWorldTestProperties.target_dartdevc) {
        target = new DevCompilerTarget(targetFlags);
      } else if (targetName == NewWorldTestProperties.target_dart2js) {
        target = new Dart2jsTarget("dart2js", targetFlags);
      } else if (targetName == NewWorldTestProperties.target_vm) {
        // default.
      } else {
        throw "Unknown target name '$targetName'";
      }
    }
    Target originalTarget = target;
    target = new TestTargetWrapper(target, targetFlags);

    String sdkSummary = computePlatformDillName(
        target,
        nnbdMode,
        () => throw new UnsupportedError(
            "No platform dill for target '${targetName}' with $nnbdMode."))!;

    final Uri base = Uri.parse("org-dartlang-test:///");
    final Uri sdkSummaryUri = base.resolve(sdkSummary);
    final Uri initializeFrom = base.resolve("initializeFrom.dill");
    Uri platformUri = platformBinariesRoot.resolve(sdkSummary);
    final List<int> sdkSummaryData =
        await new File.fromUri(platformUri).readAsBytes();

    List<int>? newestWholeComponentData;
    TestMemoryFileSystem? fs;
    Map<String, String?>? sourceFiles;
    CompilerOptions? options;
    TestIncrementalCompiler? compiler;
    IncrementalSerializer? incrementalSerializer;

    Map<String, List<int>>? moduleData;
    Map<String, Component>? moduleComponents;

    if (modules != null) {
      moduleData = await createModules(
          modules!, sdkSummaryData, target, originalTarget, sdkSummary,
          checkoutRoot: checkoutRoot, trackNeededDillLibraries: false);
      sdk = newestWholeComponent = new Component();
      new BinaryBuilder(sdkSummaryData,
              filename: null, disableLazyReading: false)
          .readComponent(newestWholeComponent!);
    }

    int worldNum = 0;
    // TODO: When needed, we can do this for warnings too.
    List<Set<String>> worldErrors = [];
    for (World world in worlds) {
      worldNum++;
      print("----------------");
      print("World #$worldNum");
      print("----------------");
      List<Component>? modulesToUse;
      if (world.modules != null) {
        moduleComponents ??= new Map<String, Component>();

        sdk!.adoptChildren();
        for (Component c in moduleComponents.values) {
          c.adoptChildren();
        }

        modulesToUse = <Component>[];
        for (String moduleName in world.modules!) {
          Component? moduleComponent = moduleComponents[moduleName];
          if (moduleComponent != null) {
            modulesToUse.add(moduleComponent);
          }
        }
        for (String moduleName in world.modules!) {
          Component? moduleComponent = moduleComponents[moduleName];
          if (moduleComponent == null) {
            moduleComponent = new Component(nameRoot: sdk!.root);
            new BinaryBuilder(moduleData![moduleName]!,
                    filename: null,
                    disableLazyReading: false,
                    alwaysCreateNewNamedNodes: true)
                .readComponent(moduleComponent);
            moduleComponents[moduleName] = moduleComponent;
            modulesToUse.add(moduleComponent);
          }
        }
      }

      if (!world.updateWorldType) {
        fs = new TestMemoryFileSystem(base, holePunchBase: checkoutRoot);
      }
      fs!.entityForUri(sdkSummaryUri).writeAsBytesSync(sdkSummaryData);
      bool expectInitializeFromDill = false;
      if (newestWholeComponentData != null &&
          newestWholeComponentData.isNotEmpty) {
        fs
            .entityForUri(initializeFrom)
            .writeAsBytesSync(newestWholeComponentData);
        expectInitializeFromDill = true;
      }
      if (world.expectInitializeFromDill != null) {
        expectInitializeFromDill = world.expectInitializeFromDill!;
      }
      if (!world.updateWorldType) {
        sourceFiles = new Map<String, String?>.from(world.sources);
      } else {
        sourceFiles!.addAll(new Map<String, String?>.from(world.sources));
      }
      Uri? packagesUri;
      for (String filename in sourceFiles.keys) {
        String data = sourceFiles[filename] ?? "";
        Uri uri = base.resolve(filename);
        if (filename == ".dart_tool/package_config.json") {
          packagesUri = uri;
        }
        if (world.enableStringReplacement) {
          data = replaceMarkersWithVersions(data);
        }
        fs.entityForUri(uri).writeAsStringSync(data);
      }
      if (world.packageConfigFile != null) {
        packagesUri = base.resolve(world.packageConfigFile!);
      }

      if (!world.updateWorldType) {
        options = getOptions(target: target, sdkSummary: sdkSummary);
        options.nnbdMode = nnbdMode;
        options.fileSystem = fs;
        options.sdkRoot = null;
        options.sdkSummary = sdkSummaryUri;
        if (world.useBadSdk) {
          options.sdkSummary = sdkSummaryUri.resolve("nonexisting.dill");
        }
        options.omitPlatform = omitPlatform;
        if (world.experiments != null) {
          Map<String, bool> flagsFromOptions =
              parseExperimentalArguments([world.experiments!]);
          // Ensure that we run with non-nullable turned off even when the
          // flag is on by default.
          Map<ExperimentalFlag, bool> explicitExperimentalFlags =
              parseExperimentalFlags(flagsFromOptions,
                  onError: (e) =>
                      throw "Error on parsing experiments flags: $e");
          options.explicitExperimentalFlags = explicitExperimentalFlags;
        } else {
          options.explicitExperimentalFlags = {};
        }
        // A separate "world" can also change nnbd mode ---
        // notice that the platform is not updated though!
        if (world.nnbdModeString != null) {
          String nnbdMode = world.nnbdModeString!;
          switch (nnbdMode) {
            case WorldProperties.nnbdMode_weak:
              options.nnbdMode = NnbdMode.Weak;
              break;
            default:
              throw "Not supported nnbd mode: $nnbdMode";
          }
        }
      }
      if (packagesUri != null) {
        options!.packagesFileUri = packagesUri;
      }
      bool gotError = false;
      final Set<String> formattedErrors = Set<String>();
      bool gotWarning = false;
      final Set<String> formattedWarnings = Set<String>();
      final Set<String> seenDiagnosticCodes = Set<String>();

      options!.onDiagnostic = (DiagnosticMessage message) {
        String? code = getMessageCodeObject(message)?.name;
        if (code != null) seenDiagnosticCodes.add(code);

        String stringId = message.ansiFormatted.join("\n");
        if (message is FormattedMessage) {
          stringId = message.toJsonString();
        } else if (message is DiagnosticMessageFromJson) {
          stringId = message.toJsonString();
        }
        if (message.severity == Severity.error) {
          gotError = true;
          if (!formattedErrors.add(stringId) && !world.allowDuplicateErrors) {
            Expect.fail("Got the same message twice: ${stringId}");
          }
        } else if (message.severity == Severity.warning) {
          gotWarning = true;
          if (!formattedWarnings.add(stringId) &&
              !world.allowDuplicateWarnings) {
            Expect.fail("Got the same message twice: ${stringId}");
          }
        }
      };

      List<Uri> entries = world.entries.map((e) => base.resolve(e)).toList();
      if (!world.updateWorldType) {
        if (incrementalSerialization == true) {
          incrementalSerializer = new IncrementalSerializer();
        }
        if (world.fromComponent) {
          compiler = new TestIncrementalCompiler.fromComponent(
              options,
              entries.first,
              (modulesToUse != null) ? sdk : newestWholeComponent,
              world.outlineOnly,
              incrementalSerializer);
        } else {
          compiler = new TestIncrementalCompiler(options, entries.first,
              initializeFrom, world.outlineOnly, incrementalSerializer);

          if (modulesToUse != null) {
            throw "You probably shouldn't do this! "
                "Any modules will have another sdk loaded!";
          }
        }
      }

      List<Uri> invalidated = <Uri>[];
      if (world.invalidate != null) {
        for (String filename in world.invalidate!) {
          Uri uri = base.resolve(filename);
          invalidated.add(uri);
          compiler!.invalidate(uri);
        }
      }

      if (modulesToUse != null) {
        compiler!.setModulesToLoadOnNextComputeDelta(modulesToUse);
        compiler.invalidateAllSources();
      }

      Stopwatch stopwatch = new Stopwatch()..start();
      IncrementalCompilerResult? compilerResult = await compiler!.computeDelta(
          entryPoints: entries,
          fullComponent: !world.updateWorldType
              ? false
              : (world.noFullComponent ? false : true),
          trackNeededDillLibraries: modulesToUse != null,
          simulateTransformer: world.simulateTransformer);
      component = compilerResult.component;
      // compilerResult is null'ed out at the end to avoid any
      // "artificial memory leak" on that account.
      if (world.outlineOnly && !world.skipOutlineBodyCheck) {
        for (Library lib in component!.libraries) {
          for (Class c in lib.classes) {
            for (Procedure p in c.procedures) {
              if (p.function.body != null &&
                  p.function.body is! EmptyStatement) {
                throw "Got body (${p.function.body.runtimeType})";
              }
            }
          }
          for (Procedure p in lib.procedures) {
            if (p.function.body != null && p.function.body is! EmptyStatement) {
              throw "Got body (${p.function.body.runtimeType})";
            }
          }
        }
      }
      Result<TestData>? result = performErrorAndWarningCheck(world, data,
          gotError, formattedErrors, gotWarning, formattedWarnings);
      if (result != null) return result;
      bool? expectInitializationError = world.expectInitializationError;
      if (expectInitializationError != null) {
        Set<String> seenInitializationError = seenDiagnosticCodes.intersection({
          "InitializeFromDillNotSelfContainedNoDump",
          "InitializeFromDillNotSelfContained",
          "InitializeFromDillUnknownProblem",
          "InitializeFromDillUnknownProblemNoDump",
        });
        if (expectInitializationError) {
          if (seenInitializationError.isEmpty) {
            return new Result<TestData>(data, MissingInitializationError,
                "Expected to see an initialization error but didn't.");
          }
        } else {
          if (seenInitializationError.isNotEmpty) {
            return new Result<TestData>(
                data,
                UnexpectedInitializationError,
                "Expected not to see an initialization error but did: "
                "$seenInitializationError.");
          }
        }
      }
      util.throwOnEmptyMixinBodies(component!);
      await util.throwOnInsufficientUriToSource(component!,
          fileSystem: gotError ? null : fs);
      print("Compile took ${stopwatch.elapsedMilliseconds} ms");

      Result? contentResult = checkExpectedContent(world, component!);
      if (contentResult != null) return contentResult.copyWithOutput(data);
      result = checkNeededDillLibraries(
          world, data, compilerResult.neededDillLibraries, base);
      if (result != null) return result;

      Result? nnbdCheck = checkNNBDSettings(component!);
      if (nnbdCheck != null) return nnbdCheck.copyWithOutput(data);

      if (!world.noFullComponent) {
        Set<Library> allLibraries = new Set<Library>();
        for (Library lib in component!.libraries) {
          computeAllReachableLibrariesFor(lib, allLibraries);
        }
        if (allLibraries.length != component!.libraries.length) {
          return new Result<TestData>(
              data,
              ReachableLibrariesError,
              "Expected for the reachable stuff to be equal to "
              "${component!.libraries} but it was $allLibraries");
        }
        Set<Library> tooMany = allLibraries.toSet()
          ..removeAll(component!.libraries);
        if (tooMany.isNotEmpty) {
          return new Result<TestData>(
              data,
              ReachableLibrariesError,
              "Expected for the reachable stuff to be equal to "
              "${component!.libraries} but these were there too: $tooMany "
              "(and others were missing)");
        }
      }

      util.postProcessComponent(component!);
      String actualSerialized = componentToStringSdkFiltered(component!,
          printErrors: world.printErrorsInExpect ? formattedErrors : null);
      print("*****\n\ncomponent:\n"
          "${actualSerialized}\n\n\n");
      result = checkExpectFile(data, worldNum, "", context, actualSerialized);
      if (result != null) return result;

      if (world.compareToPrevious && newestWholeComponent != null) {
        EquivalenceResult result = checkEquivalence(
            newestWholeComponent!, component!,
            strategy: const Strategy());
        if (!result.isEquivalent) {
          return new Result<TestData>(
              data, EquivalenceError, result.toString());
        }
      }

      if (world.reject) {
        util.postProcess(component!);

        // Reject: We keep the original "newest whole component" and also
        // reject/relink it.
        // This mimics what happens when e.g. flutter "reject"s a compile.
        newestWholeComponent?.relink();

        // Add errors or assert will trigger in later worlds.
        worldErrors.add(formattedErrors.toSet());

        // But otherwise skip other stuff - e.g. doing a leak check will find a
        // leak because we (on purpose) have two of the same library at the same
        // time.
        continue;
      } else {
        // Save it.
        newestWholeComponentData = util.postProcess(component!);
        newestWholeComponent = component;
      }

      if (world.checkConstantCoverageReferences) {
        Result<TestData>? result = checkConstantCoverageReferences(
            newestWholeComponentData, omitPlatform, sdkSummaryData, data);
        if (result != null) return result;
      }

      if (world.uriToSourcesDoesntInclude != null) {
        for (String filename in world.uriToSourcesDoesntInclude!) {
          Uri uri = base.resolve(filename);
          if (component!.uriToSource[uri] != null) {
            return new Result<TestData>(
                data,
                UriToSourceError,
                "Expected no uriToSource for $uri but found "
                "${component!.uriToSource[uri]}");
          }
        }
      }
      if (world.uriToSourcesOnlyIncludes != null) {
        Set<Uri> allowed = {};
        for (String filename in world.uriToSourcesOnlyIncludes!) {
          Uri uri = base.resolve(filename);
          allowed.add(uri);
        }
        for (Uri uri in component!.uriToSource.keys) {
          // null is always there, so allow it implicitly.
          // Dart scheme uris too.
          if (uri.isScheme("org-dartlang-sdk")) continue;
          if (!allowed.contains(uri)) {
            return new Result<TestData>(
                data,
                UriToSourceError,
                "Expected no uriToSource for $uri but found "
                "${component!.uriToSource[uri]}");
          }
        }
      }

      if (!world.skipClassHierarchyTest) {
        result = checkClassHierarchy(compilerResult, data, worldNum, context);
        if (result != null) return result;
      }

      int nonSyntheticLibraries = countNonSyntheticLibraries(component!);
      int nonSyntheticPlatformLibraries =
          countNonSyntheticPlatformLibraries(component!);
      int syntheticLibraries = countSyntheticLibraries(component!);
      if (world.expectsPlatform) {
        if (nonSyntheticPlatformLibraries < 5) {
          return new Result<TestData>(
              data,
              MissingPlatformLibraries,
              "Expected to have at least 5 platform libraries "
              "(actually, the entire sdk), "
              "but got $nonSyntheticPlatformLibraries.");
        }
      } else {
        if (nonSyntheticPlatformLibraries != 0) {
          return new Result<TestData>(
              data,
              UnexpectedPlatformLibraries,
              "Expected to have 0 platform libraries "
              "but got $nonSyntheticPlatformLibraries.");
        }
      }
      if (world.expectedLibraryCount != null) {
        if (nonSyntheticLibraries - nonSyntheticPlatformLibraries !=
            world.expectedLibraryCount!) {
          return new Result<TestData>(
              data,
              LibraryCountMismatch,
              "Expected ${world.expectedLibraryCount} non-synthetic "
              "libraries, got "
              "${nonSyntheticLibraries - nonSyntheticPlatformLibraries} "
              "(not counting platform libraries)");
        }
      }
      if (world.expectedSyntheticLibraryCount != null) {
        if (syntheticLibraries != world.expectedSyntheticLibraryCount!) {
          return new Result<TestData>(
              data,
              LibraryCountMismatch,
              "Expected ${world.expectedSyntheticLibraryCount} synthetic "
              "libraries, got ${syntheticLibraries}");
        }
      }

      AdvancedInvalidationResult? actualAdvancedInvalidation =
          compiler.recorderForTesting.advancedInvalidationResult;
      if (world.advancedInvalidation != actualAdvancedInvalidation) {
        return new Result<TestData>(
            data,
            UnexpectedAdvancedInvalidation,
            "Expected advancedInvalidation: "
            "${world.advancedInvalidation}, "
            "advancedInvalidation: "
            "${actualAdvancedInvalidation}.");
      }

      if (!world.noFullComponent) {
        if (world.checkEntries) {
          List<Library> entryLib = component!.libraries
              .where((Library lib) =>
                  entries.contains(lib.importUri) ||
                  entries.contains(lib.fileUri))
              .toList();
          if (entryLib.length != entries.length) {
            return new Result<TestData>(
                data,
                UnexpectedEntryToLibraryCount,
                "Expected the entries to become libraries. "
                "Got ${entryLib.length} libraries for the expected "
                "${entries.length} entries.");
          }
        }
      }
      if (compiler.initializedFromDillForTesting != expectInitializeFromDill) {
        return new Result<TestData>(
            data,
            InitializedFromDillMismatch,
            "Expected that initializedFromDill would be "
            "$expectInitializeFromDill but was "
            "${compiler.initializedFromDillForTesting}");
      }

      if (incrementalSerialization == true &&
          compiler.initializedFromDillForTesting) {
        Expect.isTrue(compiler.initializedIncrementalSerializerForTesting);
      } else {
        Expect.isFalse(compiler.initializedIncrementalSerializerForTesting);
      }

      if (world.checkInvalidatedFiles) {
        Set<Uri>? filteredInvalidated =
            compiler.getFilteredInvalidatedImportUrisForTesting(invalidated);
        if (world.invalidate != null) {
          Expect.equals(
              world.invalidate!.length,
              filteredInvalidated?.length ?? 0,
              "Unexpected invalidated files: ${filteredInvalidated}, "
              "actual: ${world.invalidate}.");
          if (world.expectedInvalidatedUri != null) {
            Expect.setEquals(
                world.expectedInvalidatedUri!.map((s) => base.resolve(s)),
                filteredInvalidated!);
          }
        } else {
          Expect.isNull(filteredInvalidated);
          Expect.isNull(world.expectedInvalidatedUri);
        }
      }
      Result<List<int>?> serializationResult = checkIncrementalSerialization(
          incrementalSerialization, component!, incrementalSerializer, world);
      if (!serializationResult.isPass) {
        return serializationResult.copyWithOutput(data);
      }
      List<int>? incrementalSerializationBytes = serializationResult.output;

      worldErrors.add(formattedErrors.toSet());
      assert(worldErrors.length == worldNum);
      if (world.expectSameErrorsAsWorld != null) {
        checkErrorsAndWarnings(
          worldErrors[world.expectSameErrorsAsWorld! - 1],
          formattedErrors,
          {},
          {},
        );
      }

      Set<String> prevFormattedErrors = formattedErrors.toSet();
      Set<String> prevFormattedWarnings = formattedWarnings.toSet();

      void clearPrevErrorsEtc() {
        gotError = false;
        formattedErrors.clear();
        gotWarning = false;
        formattedWarnings.clear();
      }

      if (!world.noFullComponent) {
        clearPrevErrorsEtc();
        IncrementalCompilerResult? compilerResult2 =
            await compiler.computeDelta(
                entryPoints: entries,
                fullComponent: true,
                simulateTransformer: world.simulateTransformer);
        component2 = compilerResult2.component;
        compilerResult2 = null;
        Result<TestData>? result = performErrorAndWarningCheck(world, data,
            gotError, formattedErrors, gotWarning, formattedWarnings);
        if (result != null) return result;
        List<int> thisWholeComponent = util.postProcess(component2!);
        String component2String = componentToStringSdkFiltered(component2!,
            printErrors: world.printErrorsInExpect ? formattedErrors : null);
        print("*****\n\ncomponent2:\n$component2String\n\n\n");
        checkIsEqual(newestWholeComponentData, thisWholeComponent);
        checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
            prevFormattedWarnings, formattedWarnings);
        newestWholeComponent = component2;

        Result<List<int>?> serializationResult = checkIncrementalSerialization(
            incrementalSerialization,
            component2!,
            incrementalSerializer,
            world);
        if (!serializationResult.isPass) {
          return serializationResult.copyWithOutput(data);
        }
        List<int>? incrementalSerializationBytes2 = serializationResult.output;

        if ((incrementalSerializationBytes == null &&
                incrementalSerializationBytes2 != null) ||
            (incrementalSerializationBytes != null &&
                incrementalSerializationBytes2 == null)) {
          return new Result<TestData>(
              data,
              IncrementalSerializationError,
              "Incremental serialization gave results in one instance, "
              "but not another.");
        }

        if (incrementalSerializationBytes != null) {
          checkIsEqual(
              incrementalSerializationBytes, incrementalSerializationBytes2!);
        }
      }

      if (world.expressionCompilation != null) {
        int expressionCompilationNum = 0;
        for (ExpressionCompilation compilation
            in world.expressionCompilation!) {
          expressionCompilationNum++;
          clearPrevErrorsEtc();
          Uri uri = base.resolve(compilation.uri);
          Procedure procedure = (await compiler.compileExpression(
            compilation.expression,
            {},
            [],
            "debugExpr",
            uri,
            className: compilation.className,
          ))!;
          if (gotError && !compilation.errors) {
            return new Result<TestData>(data, UnexpectedErrors,
                "Got error(s) on expression compilation: ${formattedErrors}.");
          } else if (!gotError && compilation.errors) {
            return new Result<TestData>(
                data, MissingErrors, "Didn't get any errors.");
          }
          if (gotWarning && !compilation.warnings) {
            return new Result<TestData>(
                data,
                UnexpectedWarnings,
                "Got warning(s) on expression compilation: "
                "${formattedWarnings}.");
          } else if (!gotWarning && compilation.warnings) {
            return new Result<TestData>(
                data, MissingWarnings, "Didn't get any warnings.");
          }
          Result<TestData>? result = checkExpectFile(
              data,
              worldNum,
              ".expression.$expressionCompilationNum",
              context,
              nodeToString(procedure));
          if (result != null) return result;
        }
      }

      if (!world.noFullComponent &&
          (incrementalSerialization == true || world.compareWithFromScratch)) {
        // Do compile from scratch and compare.
        clearPrevErrorsEtc();
        TestIncrementalCompiler? compilerFromScratch;

        IncrementalSerializer? incrementalSerializer2;
        if (incrementalSerialization == true) {
          incrementalSerializer2 = new IncrementalSerializer();
        }

        if (world.fromComponent || modulesToUse != null) {
          compilerFromScratch = new TestIncrementalCompiler.fromComponent(
              options,
              entries.first,
              sdk,
              world.outlineOnly,
              incrementalSerializer2);
        } else {
          compilerFromScratch = new TestIncrementalCompiler(options,
              entries.first, null, world.outlineOnly, incrementalSerializer2);
        }

        if (modulesToUse != null) {
          compilerFromScratch.setModulesToLoadOnNextComputeDelta(modulesToUse);
          compilerFromScratch.invalidateAllSources();
        }

        Stopwatch stopwatch = new Stopwatch()..start();
        IncrementalCompilerResult? compilerResult3 =
            await compilerFromScratch.computeDelta(
                entryPoints: entries,
                trackNeededDillLibraries: modulesToUse != null,
                simulateTransformer: world.simulateTransformer);
        component3 = compilerResult3.component;
        compilerResult3 = null;
        compilerFromScratch = null;
        Result<TestData>? result = performErrorAndWarningCheck(world, data,
            gotError, formattedErrors, gotWarning, formattedWarnings);
        if (result != null) return result;
        util.throwOnEmptyMixinBodies(component3!);
        await util.throwOnInsufficientUriToSource(component3!);
        print("Compile took ${stopwatch.elapsedMilliseconds} ms");

        List<int> thisWholeComponent = util.postProcess(component3!);
        String component3String = componentToStringSdkFiltered(component3!,
            printErrors: world.printErrorsInExpect ? formattedErrors : null);
        print("*****\n\ncomponent3:\n$component3String\n\n\n");
        if (world.compareWithFromScratch) {
          checkIsEqual(newestWholeComponentData, thisWholeComponent);
        }
        checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
            prevFormattedWarnings, formattedWarnings);

        Result<List<int>?> serializationResult = checkIncrementalSerialization(
            incrementalSerialization,
            component3!,
            incrementalSerializer2,
            world);
        if (!serializationResult.isPass) {
          return serializationResult.copyWithOutput(data);
        }
        List<int>? incrementalSerializationBytes3 = serializationResult.output;

        if ((incrementalSerializationBytes == null &&
                incrementalSerializationBytes3 != null) ||
            (incrementalSerializationBytes != null &&
                incrementalSerializationBytes3 == null)) {
          return new Result<TestData>(
              data,
              IncrementalSerializationError,
              "Incremental serialization gave results in one instance, "
              "but not another.");
        }

        if (incrementalSerializationBytes != null) {
          if (world.brandNewIncrementalSerializationAllowDifferent) {
            // Don't check for equality when we allow it to be different
            // (e.g. when the old one contains more, and the new one doesn't).
          } else {
            checkIsEqual(
                incrementalSerializationBytes, incrementalSerializationBytes3!);
          }
          newestWholeComponentData = incrementalSerializationBytes;
        }
      }

      component = null;
      compilerResult = null;
      component2 = null;
      component3 = null;
      // Dummy tree nodes can (currently) leak though the parent pointer.
      // To avoid that (here) (for leak testing) we'll null them out.
      for (TreeNode treeNode in dummyTreeNodes) {
        treeNode.parent = null;
      }

      if (context.breakBetween) {
        debugger();
        print("Continuing after debug break");
      }
    }
    return new Result<TestData>.pass(data);
  }
}

Result<TestData>? checkConstantCoverageReferences(
    List<int> newestWholeComponentData,
    bool omitPlatform,
    List<int> sdkSummaryData,
    TestData data) {
  // Note that this is in a method to avoid "semi-leaks".
  Component loadedComponent = new Component();
  if (omitPlatform) {
    new BinaryBuilder(sdkSummaryData, filename: null)
        .readComponent(loadedComponent);
  }
  new BinaryBuilder(newestWholeComponentData, filename: null)
      .readComponent(loadedComponent);

  for (MapEntry<Uri, Source> source in loadedComponent.uriToSource.entries) {
    Set<Reference>? references = source.value.constantCoverageConstructors;
    if (references != null) {
      for (Reference reference in references) {
        if (reference.node == null) {
          return new Result<TestData>(
              data,
              ConstantCoverageReferenceWithoutNode,
              "Constant coverage reference without node: "
              "${reference.canonicalName} from ${source.value.importUri} "
              "indexed in ${source.key}");
        }
      }
    }
  }
  return null;
}

class Strategy extends EquivalenceStrategy {
  const Strategy();

  @override
  bool checkComponent_libraries(
      EquivalenceVisitor visitor, Component node, Component other) {
    return visitor.checkSets(node.libraries.toSet(), other.libraries.toSet(),
        visitor.matchNamedNodes, visitor.checkNodes, 'libraries');
  }

  @override
  bool checkClass_procedures(
      EquivalenceVisitor visitor, Class node, Class other) {
    // Check procedures as a set instead of a list to allow for reordering.
    return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
        visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
  }

  @override
  bool checkVariableDeclaration_binaryOffsetNoTag(EquivalenceVisitor visitor,
      VariableDeclaration node, VariableDeclaration other) {
    return true;
  }
}

Result? checkNNBDSettings(Component component) {
  NonNullableByDefaultCompiledMode mode = component.mode;
  if (mode == NonNullableByDefaultCompiledMode.Invalid) return null;
  for (Library lib in component.libraries) {
    if (mode == lib.nonNullableByDefaultCompiledMode) continue;

    if (mode == NonNullableByDefaultCompiledMode.Strong ||
        lib.nonNullableByDefaultCompiledMode ==
            NonNullableByDefaultCompiledMode.Strong) {
      // Non agnostic and one (but not both) are strong => error.
      return new Result(
          null,
          NNBDModeMismatch,
          "Component mode was $mode but ${lib.importUri} had mode "
          "${lib.nonNullableByDefaultCompiledMode}.");
    }
  }
  return null;
}

Result<TestData>? checkExpectFile(TestData data, int worldNum,
    String extraUriString, Context context, String actualSerialized) {
  Uri uri = data.loadedFrom.resolve(data.loadedFrom.pathSegments.last +
      ".world.$worldNum${extraUriString}.expect");
  String? expected;
  File file = new File.fromUri(uri);
  if (file.existsSync()) {
    expected = file.readAsStringSync();
  }
  if (expected?.replaceAll("\r\n", "\n") != actualSerialized) {
    if (context.updateExpectations) {
      file.writeAsStringSync(actualSerialized);
    } else {
      String extra = "";
      if (expected == null) extra = "Expect file did not exist.\n";
      return new Result<TestData>(
          data,
          expected == null ? ExpectationFileMissing : ExpectationFileMismatch,
          "${extra}Unexpected serialized representation. "
          "Fix or update $uri to contain the below:\n\n"
          "$actualSerialized",
          autoFixCommand: "updateExpectations=true",
          canBeFixWithUpdateExpectations: true);
    }
  }
  return null;
}

/// Check that the class hierarchy is up-to-date with reality.
///
/// This has the option to do expect files, but it's disabled by default
/// while we're trying to figure out if it's useful or not.
Result<TestData>? checkClassHierarchy(IncrementalCompilerResult compilerResult,
    TestData data, int worldNum, Context context,
    {bool checkExpectFile = false}) {
  ClassHierarchy? classHierarchy = compilerResult.classHierarchy;
  if (classHierarchy is! ClosedWorldClassHierarchy) {
    return new Result<TestData>(
        data,
        ClassHierarchyError,
        "Expected the class hierarchy to be ClosedWorldClassHierarchy "
        "but it wasn't. It was ${classHierarchy.runtimeType}");
  }
  List<ForTestingClassInfo> classHierarchyData =
      classHierarchy.getTestingClassInfo();
  Map<Class, ForTestingClassInfo> classHierarchyMap =
      new Map<Class, ForTestingClassInfo>();
  for (ForTestingClassInfo info in classHierarchyData) {
    if (classHierarchyMap[info.classNode] != null) {
      return new Result<TestData>(
          data, ClassHierarchyError, "Two entries for ${info.classNode}");
    }
    classHierarchyMap[info.classNode] = info;
  }

  Component component = compilerResult.component;
  StringBuffer sb = new StringBuffer();
  for (Library library in component.libraries) {
    if (library.importUri.isScheme("dart")) continue;
    sb.writeln("Library ${library.importUri}");
    for (Class c in library.classes) {
      sb.writeln("  - Class ${c.name}");

      Set<Class> checkedSupertypes = <Class>{};
      Result<TestData>? checkSupertype(Supertype? supertype) {
        if (supertype == null) return null;
        Class superclass = supertype.classNode;
        if (checkedSupertypes.add(superclass)) {
          Supertype? asSuperClass =
              classHierarchy.getClassAsInstanceOf(c, superclass);
          if (asSuperClass == null) {
            return new Result<TestData>(data, ClassHierarchyError,
                "${superclass} not found as a superclass of $c");
          }
          Result<TestData>? result = checkSupertype(superclass.supertype);
          if (result != null) return result;
          result = checkSupertype(superclass.mixedInType);
          if (result != null) return result;
          for (Supertype interface in superclass.implementedTypes) {
            result = checkSupertype(interface);
            if (result != null) return result;
          }
        }
        return null;
      }

      Result<TestData>? result = checkSupertype(c.asThisSupertype);
      if (result != null) return result;

      ForTestingClassInfo? info = classHierarchyMap[c];
      if (info == null) {
        return new Result<TestData>(data, ClassHierarchyError,
            "Didn't find any class hierarchy info for $c");
      }

      if (info.lazyDeclaredGettersAndCalls != null) {
        sb.writeln("    - lazyDeclaredGettersAndCalls:");
        for (Member member in info.lazyDeclaredGettersAndCalls!) {
          sb.writeln("      - ${member.name.text}");
        }

        // Expect these to be the same as in the class.
        Set<Member> members = info.lazyDeclaredGettersAndCalls!.toSet();
        for (Field f in c.fields) {
          if (f.isStatic) continue;
          if (!members.remove(f)) {
            return new Result<TestData>(
                data,
                ClassHierarchyError,
                "Didn't find ${f.name.text} in lazyDeclaredGettersAndCalls "
                "for ${c.name} in ${library.importUri}");
          }
        }
        for (Procedure p in c.procedures) {
          if (p.isStatic) continue;
          if (p.isSetter) continue;
          if (!members.remove(p)) {
            return new Result<TestData>(
                data,
                ClassHierarchyError,
                "Didn't find ${p.name.text} in lazyDeclaredGettersAndCalls "
                "for ${c.name} in ${library.importUri}");
          }
        }
        if (members.isNotEmpty) {
          return new Result<TestData>(
              data,
              ClassHierarchyError,
              "Still have ${members.map((m) => m.name.text)} left "
              "for ${c.name} in ${library.importUri}");
        }
      }
      if (info.lazyDeclaredSetters != null) {
        sb.writeln("    - lazyDeclaredSetters:");
        for (Member member in info.lazyDeclaredSetters!) {
          sb.writeln("      - ${member.name.text}");
        }

        // Expect these to be the same as in the class.
        Set<Member> members = info.lazyDeclaredSetters!.toSet();
        for (Field f in c.fields) {
          if (f.isStatic) continue;
          if (!f.hasSetter) continue;
          if (!members.remove(f)) {
            return new Result<TestData>(data, ClassHierarchyError,
                "Didn't find $f in lazyDeclaredSetters for $c");
          }
        }
        for (Procedure p in c.procedures) {
          if (p.isStatic) continue;
          if (!p.isSetter) continue;
          if (!members.remove(p)) {
            return new Result<TestData>(data, ClassHierarchyError,
                "Didn't find $p in lazyDeclaredSetters for $c");
          }
        }
        if (members.isNotEmpty) {
          return new Result<TestData>(
              data,
              ClassHierarchyError,
              "Still have ${members.map((m) => m.name.text)} left "
              "for ${c.name} in ${library.importUri}");
        }
      }
      if (info.lazyImplementedGettersAndCalls != null) {
        sb.writeln("    - lazyImplementedGettersAndCalls:");
        for (Member member in info.lazyImplementedGettersAndCalls!) {
          sb.writeln("      - ${member.name.text}");
        }
      }
      if (info.lazyImplementedSetters != null) {
        sb.writeln("    - lazyImplementedSetters:");
        for (Member member in info.lazyImplementedSetters!) {
          sb.writeln("      - ${member.name.text}");
        }
      }
      if (info.lazyInterfaceGettersAndCalls != null) {
        sb.writeln("    - lazyInterfaceGettersAndCalls:");
        for (Member member in info.lazyInterfaceGettersAndCalls!) {
          sb.writeln("      - ${member.name.text}");
        }
      }
      if (info.lazyInterfaceSetters != null) {
        sb.writeln("    - lazyInterfaceSetters:");
        for (Member member in info.lazyInterfaceSetters!) {
          sb.writeln("      - ${member.name.text}");
        }
      }
    }
  }
  if (checkExpectFile) {
    String actualClassHierarchy = sb.toString();
    Uri uri = data.loadedFrom.resolve(data.loadedFrom.pathSegments.last +
        ".world.$worldNum.class_hierarchy.expect");
    String? expected;
    File file = new File.fromUri(uri);
    if (file.existsSync()) {
      expected = file.readAsStringSync();
    }
    if (expected != actualClassHierarchy) {
      if (context.updateExpectations) {
        file.writeAsStringSync(actualClassHierarchy);
      } else {
        String extra = "";
        if (expected == null) extra = "Expect file did not exist.\n";
        return new Result<TestData>(
            data,
            ClassHierarchyError,
            "${extra}Unexpected serialized representation. "
            "Fix or update $uri to contain the below:\n\n"
            "$actualClassHierarchy");
      }
    }
  }
  return null;
}

void checkErrorsAndWarnings(
    Set<String> prevFormattedErrors,
    Set<String> formattedErrors,
    Set<String> prevFormattedWarnings,
    Set<String> formattedWarnings) {
  if (prevFormattedErrors.length != formattedErrors.length) {
    Expect.fail("Previously had ${prevFormattedErrors.length} errors, "
        "now had ${formattedErrors.length}.\n\n"
        "Before:\n"
        "${prevFormattedErrors.join("\n")}"
        "\n\n"
        "Now:\n"
        "${formattedErrors.join("\n")}");
  }
  if ((prevFormattedErrors.toSet()..removeAll(formattedErrors)).isNotEmpty) {
    Expect.fail("Previously got error messages $prevFormattedErrors, "
        "now had ${formattedErrors}.");
  }
  if (prevFormattedWarnings.length != formattedWarnings.length) {
    Expect.fail("Previously had ${prevFormattedWarnings.length} errors, "
        "now had ${formattedWarnings.length}.");
  }
  if ((prevFormattedWarnings.toSet()..removeAll(formattedWarnings))
      .isNotEmpty) {
    Expect.fail("Previously got error messages $prevFormattedWarnings, "
        "now had ${formattedWarnings}.");
  }
}

Result<List<int>?> checkIncrementalSerialization(
    bool? incrementalSerialization,
    Component component,
    IncrementalSerializer? incrementalSerializer,
    World world) {
  if (incrementalSerialization == true) {
    Component c = new Component(nameRoot: component.root)
      ..setMainMethodAndMode(null, false, component.mode);
    c.libraries.addAll(component.libraries);
    c.uriToSource.addAll(component.uriToSource);
    Map<String, Set<String>> originalContent = buildMapOfContent(c);
    ByteSink sink = new ByteSink();
    int librariesBefore = c.libraries.length;
    incrementalSerializer!.writePackagesToSinkAndTrimComponent(c, sink);
    int librariesAfter = c.libraries.length;
    if (librariesAfter > librariesBefore) {
      return new Result<List<int>>(null, IncrementalSerializationError,
          "Incremental serialization added libraries!");
    }
    if (librariesBefore == librariesAfter &&
        world.incrementalSerializationDoesWork) {
      return new Result<List<int>>(null, IncrementalSerializationError,
          "Incremental serialization didn't remove any libraries!");
    }
    if (librariesAfter < librariesBefore && sink.builder.isEmpty) {
      return new Result<List<int>>(
          null,
          IncrementalSerializationError,
          "Incremental serialization didn't output any bytes, "
          "but did remove libraries");
    } else if (librariesAfter == librariesBefore && !sink.builder.isEmpty) {
      return new Result<List<int>>(
          null,
          IncrementalSerializationError,
          "Incremental serialization did output bytes, "
          "but didn't remove libraries");
    }
    if (librariesAfter < librariesBefore) {
      // If we actually did incrementally serialize anything, check the output!
      BinaryPrinter printer = new BinaryPrinter(sink);
      printer.writeComponentFile(c);
      List<int> bytes = sink.builder.takeBytes();

      // Load the bytes back in.
      Component loadedComponent = new Component();
      new BinaryBuilder(bytes, filename: null).readComponent(loadedComponent);

      // Check that it doesn't contain anything we said it shouldn't.
      if (world.serializationShouldNotInclude != null) {
        Set<Uri> includedImportUris =
            loadedComponent.libraries.map((l) => l.importUri).toSet();
        for (String uriString in world.serializationShouldNotInclude!) {
          Uri uri = Uri.parse(uriString);
          if (includedImportUris.contains(uri)) {
            return new Result<List<int>>(
                null,
                IncrementalSerializationError,
                "Incremental serialization shouldn't include "
                "$uriString but did.");
          }
        }
      }

      // Check that it contains at least what we want.
      Map<String, Set<String>> afterContent =
          buildMapOfContent(loadedComponent);
      // Remove any keys in afterContent not in the original as the written
      // one is allowed to contain *more*.
      Set<String> newKeys = afterContent.keys.toSet()
        ..removeAll(originalContent.keys);
      for (String key in newKeys) {
        afterContent.remove(key);
      }
      Result? result = checkExpectedContentData(afterContent, originalContent);
      if (result != null) return result.copyWithOutput<List<int>?>(null);

      // Check that the result is self-contained.
      result = checkSelfContained(loadedComponent);
      if (result != null) return result.copyWithOutput<List<int>?>(null);

      return new Result<List<int>>.pass(bytes);
    }
  }
  return new Result<List<int>?>.pass(null);
}

Result? checkSelfContained(Component component) {
  Set<Library> got = new Set<Library>.from(component.libraries);
  for (Library lib in component.libraries) {
    for (LibraryDependency dependency in lib.dependencies) {
      if (dependency.importedLibraryReference.node == null ||
          !got.contains(dependency.targetLibrary)) {
        if (dependency.importedLibraryReference.canonicalName
            .toString()
            .startsWith("root::dart:")) {
          continue;
        }
        return Result(
            null,
            IncrementalSerializationError,
            "Component didn't contain ${dependency.importedLibraryReference} "
            "and it should have.");
      }
    }
  }
  return null;
}

void computeAllReachableLibrariesFor(Library lib, Set<Library> allLibraries) {
  Set<Library> libraries = new Set<Library>();
  List<Library> workList = <Library>[];
  allLibraries.add(lib);
  libraries.add(lib);
  workList.add(lib);
  while (workList.isNotEmpty) {
    Library library = workList.removeLast();
    for (LibraryDependency dependency in library.dependencies) {
      if (dependency.targetLibrary.importUri.isScheme("dart")) continue;
      if (libraries.add(dependency.targetLibrary)) {
        workList.add(dependency.targetLibrary);
        allLibraries.add(dependency.targetLibrary);
      }
    }
  }
}

Result? checkExpectedContent(World world, Component component) {
  if (world.expectedContent != null) {
    Map<String, Set<String>> actualContent = buildMapOfContent(component);
    return checkExpectedContentData(actualContent, world.expectedContent!);
  }
  return null;
}

Result? checkExpectedContentData(Map<String, Set<String>> actualContent,
    Map<String, Iterable<String>> expectedContent) {
  Result<TestData> createFailureResult() {
    return new Result(
        null,
        ContentDataMismatch,
        "Expected and actual content not the same.\n"
        "Expected $expectedContent.\n"
        "Got $actualContent");
  }

  if (actualContent.length != expectedContent.length) {
    return createFailureResult();
  }
  Set<String> missingKeys = actualContent.keys.toSet()
    ..removeAll(expectedContent.keys);
  if (missingKeys.isNotEmpty) {
    return createFailureResult();
  }
  for (MapEntry<String, Iterable<String>> entry in expectedContent.entries) {
    Set<String> expected = new Set<String>.from(entry.value);
    Set<String> actual = actualContent[entry.key]!.toSet();
    if (expected.length != actual.length) {
      return createFailureResult();
    }
    actual.removeAll(expected);
    if (actual.isNotEmpty) {
      return createFailureResult();
    }
  }
  return null;
}

Map<String, Set<String>> buildMapOfContent(Component component) {
  Map<String, Set<String>> actualContent = new Map<String, Set<String>>();
  for (Library lib in component.libraries) {
    Set<String> libContent =
        actualContent[lib.importUri.toString()] = new Set<String>();
    for (Class c in lib.classes) {
      libContent.add("Class ${c.name}");
    }
    for (Procedure p in lib.procedures) {
      libContent.add("Procedure ${p.name.text}");
    }
    for (Field f in lib.fields) {
      libContent.add("Field ${f.name.text}");
    }
  }
  return actualContent;
}

Result<TestData>? checkNeededDillLibraries(
    World world, TestData data, Set<Library>? neededDillLibraries, Uri base) {
  if (world.neededDillLibraries != null) {
    List<Uri> actualContent = <Uri>[];
    for (Library lib in neededDillLibraries!) {
      if (lib.importUri.isScheme("dart")) continue;
      actualContent.add(lib.importUri);
    }

    List<Uri> expectedContent = <Uri>[];
    for (String entry in world.neededDillLibraries!) {
      expectedContent.add(base.resolve(entry));
    }

    Result<TestData> createFailureResult() {
      return new Result<TestData>(
          data,
          NeededDillMismatch,
          "Expected and actual content not the same.\n"
          "Expected $expectedContent.\n"
          "Got $actualContent");
    }

    if (actualContent.length != expectedContent.length) {
      return createFailureResult();
    }
    Set<Uri> notInExpected =
        actualContent.toSet().difference(expectedContent.toSet());
    Set<Uri> notInActual =
        expectedContent.toSet().difference(actualContent.toSet());
    if (notInExpected.isNotEmpty) {
      return createFailureResult();
    }
    if (notInActual.isNotEmpty) {
      return createFailureResult();
    }
  }
  return null;
}

String nodeToString(TreeNode node) {
  StringBuffer buffer = new StringBuffer();
  new Printer(buffer, syntheticNames: new NameSystem()).writeNode(node);
  return '$buffer';
}

String componentToStringSdkFiltered(Component component,
    {required final Set<String>? printErrors}) {
  Component c = new Component();
  List<Uri> dartUris = <Uri>[];
  for (Library lib in component.libraries) {
    if (lib.importUri.isScheme("dart")) {
      dartUris.add(lib.importUri);
    } else {
      if (lib.fileUri.isScheme("holePunch")) {
        // Skip this.
        continue;
      }
      c.libraries.add(lib);
    }
  }
  c.setMainMethodAndMode(component.mainMethodName, true, component.mode);
  c.problemsAsJson = component.problemsAsJson;

  StringBuffer s = new StringBuffer();
  s.write(componentToString(c));

  addConstantCoverageToExpectation(component, s,
      skipImportUri: (Uri? importUri) => importUri?.scheme == "dart");

  if (dartUris.isNotEmpty) {
    s.writeln("");
    s.writeln("And ${dartUris.length} platform libraries:");
    for (Uri uri in dartUris) {
      s.writeln(" - $uri");
    }
  }

  if (printErrors != null && printErrors.isNotEmpty) {
    s.writeln("");
    s.writeln("A total of ${printErrors.length} errors:");
    for (String error in printErrors) {
      // Make the error more readable if it's a json.
      Map<String, dynamic>? decoded;
      try {
        decoded = jsonDecode(error);
      } catch (_) {}
      if (decoded != null && decoded["plainTextFormatted"] is List) {
        List plainTextFormatted = decoded["plainTextFormatted"] as List;
        if (plainTextFormatted.isNotEmpty &&
            plainTextFormatted.first is String) {
          error = plainTextFormatted.first;
        }
      }
      s.writeln(" - $error");
    }
  }

  return s.toString();
}

int countNonSyntheticLibraries(Component c) {
  int result = 0;
  for (Library lib in c.libraries) {
    if (!lib.isSynthetic) result++;
  }
  return result;
}

int countNonSyntheticPlatformLibraries(Component c) {
  int result = 0;
  for (Library lib in c.libraries) {
    if (!lib.isSynthetic && lib.importUri.isScheme("dart")) result++;
  }
  return result;
}

int countSyntheticLibraries(Component c) {
  int result = 0;
  for (Library lib in c.libraries) {
    if (lib.isSynthetic) result++;
  }
  return result;
}

Result<TestData>? performErrorAndWarningCheck(
    World world,
    TestData data,
    bool gotError,
    Set<String> formattedErrors,
    bool gotWarning,
    Set<String> formattedWarnings) {
  if (world.errors && !gotError) {
    return new Result<TestData>(
        data, MissingErrors, "Expected error, but didn't get any.");
  } else if (!world.errors && gotError) {
    return new Result<TestData>(
        data, UnexpectedErrors, "Got unexpected error(s): $formattedErrors.");
  }
  if (world.warnings && !gotWarning) {
    return new Result<TestData>(
        data, MissingWarnings, "Expected warning, but didn't get any.");
  } else if (!world.warnings && gotWarning) {
    return new Result<TestData>(data, UnexpectedWarnings,
        "Got unexpected warnings(s): $formattedWarnings.");
  }
  return null;
}

void checkIsEqual(List<int> a, List<int> b) {
  int length = a.length;
  if (b.length < length) {
    length = b.length;
  }
  for (int i = 0; i < length; ++i) {
    if (a[i] != b[i]) {
      print("Data differs at byte ${i + 1}.");

      StringBuffer message = new StringBuffer();
      message.writeln("Data differs at byte ${i + 1}.");
      message.writeln("");
      message.writeln("Will try to find more useful information:");

      final String repoDir = computeRepoDir();
      File binaryMd = new File("$repoDir/pkg/kernel/binary.md");
      String binaryMdContent = binaryMd.readAsStringSync();

      DillComparer dillComparer = new DillComparer();
      if (dillComparer.compare(a, b, binaryMdContent, message)) {
        message.writeln(
            "Somehow the two different byte-lists compared to the same.");
      }

      Expect.fail(message.toString());
    }
  }
  Expect.equals(a.length, b.length);
}

CompilerOptions getOptions({Target? target, String? sdkSummary}) {
  target ??= new VmTarget(new TargetFlags());
  sdkSummary ??= 'vm_platform_strong.dill';
  final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
  CompilerOptions options = new CompilerOptions()
    ..target = target
    ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
    ..omitPlatform = true
    ..onDiagnostic = (DiagnosticMessage message) {
      if (message.severity == Severity.error ||
          message.severity == Severity.warning) {
        Expect.fail(
            "Unexpected error: ${message.plainTextFormatted.join('\n')}");
      }
    }
    ..sdkSummary = sdkRoot.resolve(sdkSummary)
    ..environmentDefines = const {};
  return options;
}

Future<bool> normalCompile(Uri input, Uri output,
    {CompilerOptions? options}) async {
  options ??= getOptions();
  TestIncrementalCompiler compiler =
      new TestIncrementalCompiler(options, input);
  List<int> bytes =
      await normalCompileToBytes(input, options: options, compiler: compiler);
  new File.fromUri(output).writeAsBytesSync(bytes);
  return compiler.initializedFromDillForTesting;
}

Future<List<int>> normalCompileToBytes(Uri input,
    {CompilerOptions? options, IncrementalCompiler? compiler}) async {
  Component component = await normalCompileToComponent(input,
      options: options, compiler: compiler);
  return util.postProcess(component);
}

Future<Component> normalCompileToComponent(Uri input,
    {CompilerOptions? options, IncrementalCompiler? compiler}) async {
  Component component =
      await normalCompilePlain(input, options: options, compiler: compiler);
  util.throwOnEmptyMixinBodies(component);
  await util.throwOnInsufficientUriToSource(component);
  return component;
}

Future<Component> normalCompilePlain(Uri input,
    {CompilerOptions? options, IncrementalCompiler? compiler}) async {
  options ??= getOptions();
  compiler ??= new TestIncrementalCompiler(options, input);
  return (await compiler.computeDelta()).component;
}

Future<bool> initializedCompile(
    Uri input, Uri output, Uri initializeWith, List<Uri> invalidateUris,
    {CompilerOptions? options}) async {
  options ??= getOptions();
  TestIncrementalCompiler compiler =
      new TestIncrementalCompiler(options, input, initializeWith);
  for (Uri invalidateUri in invalidateUris) {
    compiler.invalidate(invalidateUri);
  }
  IncrementalCompilerResult initializedCompilerResult =
      await compiler.computeDelta();
  Component initializedComponent = initializedCompilerResult.component;
  util.throwOnEmptyMixinBodies(initializedComponent);
  await util.throwOnInsufficientUriToSource(initializedComponent);
  bool result = compiler.initializedFromDillForTesting;
  new File.fromUri(output)
      .writeAsBytesSync(util.postProcess(initializedComponent));
  int actuallyInvalidatedCount = compiler
          .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
          ?.length ??
      0;
  if (result && actuallyInvalidatedCount < invalidateUris.length) {
    Expect.fail("Expected at least ${invalidateUris.length} invalidated uris, "
        "got $actuallyInvalidatedCount");
  }

  IncrementalCompilerResult initializedFullCompilerResult =
      await compiler.computeDelta(fullComponent: true);
  Component initializedFullComponent = initializedFullCompilerResult.component;
  util.throwOnEmptyMixinBodies(initializedFullComponent);
  await util.throwOnInsufficientUriToSource(initializedFullComponent);
  Expect.equals(initializedComponent.libraries.length,
      initializedFullComponent.libraries.length);
  Expect.equals(initializedComponent.uriToSource.length,
      initializedFullComponent.uriToSource.length);

  for (Uri invalidateUri in invalidateUris) {
    compiler.invalidate(invalidateUri);
  }

  IncrementalCompilerResult partialResult = await compiler.computeDelta();
  Component partialComponent = partialResult.component;
  util.throwOnEmptyMixinBodies(partialComponent);
  await util.throwOnInsufficientUriToSource(partialComponent);
  actuallyInvalidatedCount = (compiler
          .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
          ?.length ??
      0);
  if (actuallyInvalidatedCount < invalidateUris.length) {
    Expect.fail("Expected at least ${invalidateUris.length} invalidated uris, "
        "got $actuallyInvalidatedCount");
  }

  IncrementalCompilerResult emptyResult = await compiler.computeDelta();
  Component emptyComponent = emptyResult.component;
  util.throwOnEmptyMixinBodies(emptyComponent);
  await util.throwOnInsufficientUriToSource(emptyComponent);

  List<Uri> fullLibUris =
      initializedComponent.libraries.map((lib) => lib.importUri).toList();
  List<Uri> partialLibUris =
      partialComponent.libraries.map((lib) => lib.importUri).toList();
  List<Uri> emptyLibUris =
      emptyComponent.libraries.map((lib) => lib.importUri).toList();

  Expect.isTrue(fullLibUris.length > partialLibUris.length ||
      partialLibUris.length == invalidateUris.length);
  Expect.isTrue(partialLibUris.isNotEmpty || invalidateUris.isEmpty);

  Expect.isTrue(emptyLibUris.isEmpty);

  return result;
}

class TestIncrementalCompiler extends IncrementalCompiler {
  @override
  final TestRecorderForTesting recorderForTesting =
      new TestRecorderForTesting();
  final Uri entryPoint;

  /// Filter out the automatically added entryPoint, unless it's explicitly
  /// specified as being invalidated.
  /// Also filter out uris with "nonexisting.dart" in the name as synthetic
  /// libraries are invalidated automatically too.
  /// This is not perfect, but works for what it's currently used for.
  Set<Uri>? getFilteredInvalidatedImportUrisForTesting(
      List<Uri> invalidatedUris) {
    if (recorderForTesting.invalidatedImportUrisForTesting == null) return null;

    Set<String> invalidatedFilenames =
        invalidatedUris.map((uri) => uri.pathSegments.last).toSet();
    Set<Uri> result = new Set<Uri>();
    for (Uri uri in recorderForTesting.invalidatedImportUrisForTesting!) {
      if (uri.pathSegments.isNotEmpty &&
          uri.pathSegments.last == "nonexisting.dart") {
        continue;
      }
      if (invalidatedFilenames.contains(entryPoint.pathSegments.last) ||
          invalidatedFilenames.contains(uri.pathSegments.last)) {
        result.add(uri);
      }
    }

    return result.isEmpty ? null : result;
  }

  TestIncrementalCompiler(CompilerOptions options, this.entryPoint,
      [Uri? initializeFrom,
      bool? outlineOnly,
      IncrementalSerializer? incrementalSerializer])
      : super(
            new CompilerContext(
                new ProcessedOptions(options: options, inputs: [entryPoint])),
            initializeFrom,
            outlineOnly,
            incrementalSerializer);

  TestIncrementalCompiler.fromComponent(CompilerOptions options,
      this.entryPoint, Component? componentToInitializeFrom,
      [bool? outlineOnly, IncrementalSerializer? incrementalSerializer])
      : super.fromComponent(
            new CompilerContext(
                new ProcessedOptions(options: options, inputs: [entryPoint])),
            componentToInitializeFrom,
            outlineOnly,
            incrementalSerializer);

  @override
  Future<IncrementalCompilerResult> computeDelta(
      {List<Uri>? entryPoints,
      bool fullComponent = false,
      bool trackNeededDillLibraries = false,
      bool? simulateTransformer}) async {
    IncrementalCompilerResult result = await super.computeDelta(
        entryPoints: entryPoints,
        fullComponent: fullComponent,
        trackNeededDillLibraries: trackNeededDillLibraries);

    // We should at least have the SDK builders available. Slight smoke test.
    if (!dillTargetForTesting!.loader.libraryImportUris
        .map((uri) => uri.toString())
        .contains("dart:core")) {
      throw "Loaders builder should contain the sdk, "
          "but didn't even contain dart:core.";
    }

    if (simulateTransformer == true) {
      doSimulateTransformer(result.component);
    }
    return result;
  }
}

class TestRecorderForTesting extends RecorderForTesting {
  Set<Uri>? invalidatedImportUrisForTesting;
  AdvancedInvalidationResult? advancedInvalidationResult;
  int? rebuildBodiesCount;

  @override
  void recordInvalidatedImportUris(List<Uri> uris) {
    invalidatedImportUrisForTesting = uris.isEmpty ? null : uris.toSet();
  }

  @override
  void recordNonFullComponent(Component component) {
    // It should at least contain the sdk. Slight smoke test.
    if (!component.libraries
        .map((lib) => lib.importUri.toString())
        .contains("dart:core")) {
      throw "Loaders builder should contain the sdk, "
          "but didn't even contain dart:core.";
    }
  }

  @override
  void recordRebuildBodiesCount(int count) {
    rebuildBodiesCount = count;
    assert(
        count == 0 ||
            advancedInvalidationResult == AdvancedInvalidationResult.bodiesOnly,
        "Unexpected successful advanced invalidation: "
        "${advancedInvalidationResult}");
  }

  @override
  void recordAdvancedInvalidationResult(AdvancedInvalidationResult result) {
    advancedInvalidationResult = result;
  }

  @override
  void recordTemporaryFile(Uri uri) {
    File f = new File.fromUri(uri);
    if (f.existsSync()) f.deleteSync();
  }
}

void doSimulateTransformer(Component c) {
  for (Library lib in c.libraries) {
    if (lib.fields
        .where((f) => f.name.text == "unique_SimulateTransformer")
        .toList()
        .isNotEmpty) {
      continue;
    }
    Name fieldName = new Name("unique_SimulateTransformer");
    Field field = new Field.immutable(fieldName,
        isFinal: true,
        fieldReference: lib.reference.canonicalName
            ?.getChildFromFieldWithName(fieldName)
            .reference,
        getterReference: lib.reference.canonicalName
            ?.getChildFromFieldGetterWithName(fieldName)
            .reference,
        fileUri: lib.fileUri);
    lib.addField(field);
    for (Class c in lib.classes) {
      if (c.fields
          .where((f) => f.name.text == "unique_SimulateTransformer")
          .toList()
          .isNotEmpty) {
        continue;
      }
      fieldName = new Name("unique_SimulateTransformer");
      field = new Field.immutable(fieldName,
          isFinal: true,
          fieldReference: lib.reference.canonicalName
              ?.getChildFromFieldWithName(fieldName)
              .reference,
          getterReference: c.reference.canonicalName
              ?.getChildFromFieldGetterWithName(fieldName)
              .reference,
          fileUri: c.fileUri);
      c.addField(field);
    }
  }
}

class TestMemoryFileSystem extends MemoryFileSystem {
  Uri holePunchBase;

  TestMemoryFileSystem(Uri currentDirectory, {required this.holePunchBase})
      : super(currentDirectory);

  @override
  MemoryFileSystemEntity entityForUri(Uri uri) {
    if (uri.isScheme("holePunch")) {
      // "Copy" the file into the memory file system.
      Uri holePunchResolved = holePunchBase.resolve(uri.path);
      File f = new File.fromUri(holePunchResolved);
      MemoryFileSystemEntity entity = super.entityForUri(uri);
      if (f.existsSync()) {
        entity.writeAsBytesSync(f.readAsBytesSync());
      }
      return entity;
    }
    // Try to "sanitize" the uri as a real file system does, namely
    // "a/b.dart" and "a//b.dart" returns the same file.
    if (uri.pathSegments.contains("")) {
      Uri newUri = uri.replace(
          pathSegments: uri.pathSegments.where((element) => element != ""));
      return super.entityForUri(newUri);
    }
    return super.entityForUri(uri);
  }
}
