[flutter_tools] reland: map file URIs to a multiroot scheme (#66405)

If a file scheme and one or more roots is provided, fall back to this mapping before the direct file path if the file path cannot be turned into a package URI.

Use URI representation so that the transformation is resilient to the org-dartlang-app scheme used by the web builds.

Fixes #66095
Fixes #66404
diff --git a/packages/flutter_tools/lib/src/build_system/targets/common.dart b/packages/flutter_tools/lib/src/build_system/targets/common.dart
index c4a8646..7c97865 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/common.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/common.dart
@@ -198,6 +198,8 @@
       logger: environment.logger,
       processManager: environment.processManager,
       artifacts: environment.artifacts,
+      fileSystemRoots: <String>[],
+      fileSystemScheme: null,
     );
     if (environment.defines[kBuildMode] == null) {
       throw MissingDefineException(kBuildMode, 'kernel_snapshot');
diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart
index fee25a2..7bbf091 100644
--- a/packages/flutter_tools/lib/src/commands/attach.dart
+++ b/packages/flutter_tools/lib/src/commands/attach.dart
@@ -385,6 +385,7 @@
       targetModel: TargetModel(stringArg('target-model')),
       buildInfo: getBuildInfo(),
       userIdentifier: userIdentifier,
+      platform: globals.platform,
     );
     flutterDevice.observatoryUris = observatoryUris;
     final List<FlutterDevice> flutterDevices =  <FlutterDevice>[flutterDevice];
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart
index 17f6d85..9735c4b 100644
--- a/packages/flutter_tools/lib/src/commands/daemon.dart
+++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -470,6 +470,7 @@
       flutterProject: flutterProject,
       target: target,
       buildInfo: options.buildInfo,
+      platform: globals.platform,
     );
 
     ResidentRunner runner;
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart
index 08d086e..b086b0e 100644
--- a/packages/flutter_tools/lib/src/commands/drive.dart
+++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -199,6 +199,7 @@
           flutterProject: flutterProject,
           target: targetFile,
           buildInfo: buildInfo,
+          platform: globals.platform,
         );
         residentRunner = webRunnerFactory.createWebRunner(
           flutterDevice,
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index a0a55ad..a18601d 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -531,6 +531,7 @@
           target: stringArg('target'),
           buildInfo: getBuildInfo(),
           userIdentifier: userIdentifier,
+          platform: globals.platform,
         ),
     ];
     // Only support "web mode" with a single web device due to resident runner
diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
index 8085ed0..138fb0e 100644
--- a/packages/flutter_tools/lib/src/compile.dart
+++ b/packages/flutter_tools/lib/src/compile.dart
@@ -11,42 +11,13 @@
 
 import 'artifacts.dart';
 import 'base/common.dart';
-import 'base/context.dart';
 import 'base/file_system.dart';
 import 'base/io.dart';
 import 'base/logger.dart';
+import 'base/platform.dart';
 import 'build_info.dart';
 import 'convert.dart';
 import 'globals.dart' as globals;
-import 'project.dart';
-
-KernelCompilerFactory get kernelCompilerFactory => context.get<KernelCompilerFactory>();
-
-class KernelCompilerFactory {
-  const KernelCompilerFactory({
-    @required FileSystem fileSystem,
-    @required Artifacts artifacts,
-    @required ProcessManager processManager,
-    @required Logger logger,
-  }) : _fileSystem = fileSystem,
-       _artifacts = artifacts,
-       _processManager = processManager,
-       _logger = logger;
-
-  final Logger _logger;
-  final Artifacts _artifacts;
-  final ProcessManager _processManager;
-  final FileSystem _fileSystem;
-
-  Future<KernelCompiler> create(FlutterProject flutterProject) async {
-    return KernelCompiler(
-      logger: _logger,
-      artifacts: _artifacts,
-      fileSystem: _fileSystem,
-      processManager: _processManager,
-    );
-  }
-}
 
 /// The target model describes the set of core libraries that are available within
 /// the SDK.
@@ -204,19 +175,25 @@
 /// A compiler interface for producing single (non-incremental) kernel files.
 class KernelCompiler {
   KernelCompiler({
-    FileSystem fileSystem, // TODO(jonahwilliams): migrate to @required after google3
-    Logger logger, // TODO(jonahwilliams): migrate to @required after google3
-    ProcessManager processManager, // TODO(jonahwilliams): migrate to @required after google3
-    Artifacts artifacts, // TODO(jonahwilliams): migrate to @required after google3
-  }) : _logger = logger ?? globals.logger,
-       _fileSystem = fileSystem ?? globals.fs,
-       _artifacts = artifacts ?? globals.artifacts,
-       _processManager = processManager ?? globals.processManager;
+    @required FileSystem fileSystem,
+    @required Logger logger,
+    @required ProcessManager processManager,
+    @required Artifacts artifacts,
+    @required List<String> fileSystemRoots,
+    @required String fileSystemScheme,
+  }) : _logger = logger,
+       _fileSystem = fileSystem,
+       _artifacts = artifacts,
+       _processManager = processManager,
+       _fileSystemScheme = fileSystemScheme,
+       _fileSystemRoots = fileSystemRoots;
 
   final FileSystem _fileSystem;
   final Artifacts _artifacts;
   final ProcessManager _processManager;
   final Logger _logger;
+  final String _fileSystemScheme;
+  final List<String> _fileSystemRoots;
 
   Future<CompilerOutput> compile({
     String sdkRoot,
@@ -248,10 +225,12 @@
     if (!_processManager.canRun(engineDartPath)) {
       throwToolExit('Unable to find Dart binary at $engineDartPath');
     }
-    Uri mainUri;
+    String mainUri;
+    final Uri mainFileUri = _fileSystem.file(mainPath).uri;
     if (packagesPath != null) {
-      mainUri = packageConfig.toPackageUri(_fileSystem.file(mainPath).uri);
+      mainUri = packageConfig.toPackageUri(mainFileUri)?.toString();
     }
+    mainUri ??= toMultiRootPath(mainFileUri, _fileSystemScheme, _fileSystemRoots, _fileSystem.path.separator == r'\');
     if (outputFilePath != null && !_fileSystem.isFileSync(outputFilePath)) {
       _fileSystem.file(outputFilePath).createSync(recursive: true);
     }
@@ -302,7 +281,7 @@
         platformDill,
       ],
       ...?extraFrontEndOptions,
-      mainUri?.toString() ?? mainPath,
+      mainUri ?? mainPath,
     ];
 
     _logger.printTrace(command.join(' '));
@@ -436,6 +415,7 @@
     String platformDill,
     List<String> dartDefines,
     String librariesSpec,
+    @required Platform platform,
     // Deprecated
     List<String> experimentalFlags,
   }) = DefaultResidentCompiler;
@@ -522,6 +502,7 @@
   DefaultResidentCompiler(
     String sdkRoot, {
     @required this.buildMode,
+    @required Platform platform,
     Logger logger, // TODO(jonahwilliams): migrate to @required after google3
     ProcessManager processManager, // TODO(jonahwilliams): migrate to @required after google3
     Artifacts artifacts, // TODO(jonahwilliams): migrate to @required after google3
@@ -543,6 +524,7 @@
        _processManager = processManager ?? globals.processManager,
        _artifacts = artifacts ?? globals.artifacts,
        _stdoutHandler = StdoutHandler(logger: logger),
+       _platform = platform,
        dartDefines = dartDefines ?? const <String>[],
        // This is a URI, not a file path, so the forward slash is correct even on Windows.
        sdkRoot = sdkRoot.endsWith('/') ? sdkRoot : '$sdkRoot/';
@@ -550,6 +532,7 @@
   final Logger _logger;
   final ProcessManager _processManager;
   final Artifacts _artifacts;
+  final Platform _platform;
 
   final BuildMode buildMode;
   final bool trackWidgetCreation;
@@ -616,8 +599,9 @@
       );
     }
     final String inputKey = Uuid().generateV4();
-    final String mainUri = request.packageConfig.toPackageUri(request.mainUri)?.toString()
-      ?? request.mainUri.toString();
+    final String mainUri = request.packageConfig.toPackageUri(request.mainUri)?.toString() ??
+      toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots, _platform.isWindows);
+
     _server.stdin.writeln('recompile $mainUri $inputKey');
     _logger.printTrace('<- recompile $mainUri $inputKey');
     for (final Uri fileUri in request.invalidatedFiles) {
@@ -625,11 +609,11 @@
       if (fileUri.scheme == 'package') {
         message = fileUri.toString();
       } else {
-        message = request.packageConfig.toPackageUri(fileUri)?.toString()
-          ?? fileUri.toString();
+        message = request.packageConfig.toPackageUri(fileUri)?.toString() ??
+          toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots, _platform.isWindows);
       }
       _server.stdin.writeln(message);
-      _logger.printTrace(message);
+      _logger.printTrace(message.toString());
     }
     _server.stdin.writeln(inputKey);
     _logger.printTrace('<- $inputKey');
@@ -889,3 +873,19 @@
     return _server.exitCode;
   }
 }
+
+/// Convert a file URI into a multiroot scheme URI if provided, otherwise
+/// return unmodified.
+@visibleForTesting
+String toMultiRootPath(Uri fileUri, String scheme, List<String> fileSystemRoots, bool windows) {
+  if (scheme == null || fileSystemRoots.isEmpty || fileUri.scheme != 'file') {
+    return fileUri.toString();
+  }
+  final String filePath = fileUri.toFilePath(windows: windows);
+  for (final String fileSystemRoot in fileSystemRoots) {
+    if (filePath.startsWith(fileSystemRoot)) {
+      return scheme + '://' + filePath.substring(fileSystemRoot.length);
+    }
+  }
+  return fileUri.toString();
+}
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index 4bd5da0..00a85df 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -25,7 +25,6 @@
 import 'build_info.dart';
 import 'build_system/build_system.dart';
 import 'cache.dart';
-import 'compile.dart';
 import 'dart/pub.dart';
 import 'devfs.dart';
 import 'device.dart';
@@ -181,12 +180,6 @@
         xcode: globals.xcode,
         platform: globals.platform,
       ),
-      KernelCompilerFactory: () => KernelCompilerFactory(
-        logger: globals.logger,
-        processManager: globals.processManager,
-        artifacts: globals.artifacts,
-        fileSystem: globals.fs,
-      ),
       Logger: () => globals.platform.isWindows
         ? WindowsStdoutLogger(
             terminal: globals.terminal,
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index 23b388c..28c71613 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -18,6 +18,7 @@
 import 'base/file_system.dart';
 import 'base/io.dart' as io;
 import 'base/logger.dart';
+import 'base/platform.dart';
 import 'base/signals.dart';
 import 'base/utils.dart';
 import 'build_info.dart';
@@ -63,6 +64,7 @@
          artifacts: globals.artifacts,
          processManager: globals.processManager,
          logger: globals.logger,
+         platform: globals.platform,
        );
 
   /// Create a [FlutterDevice] with optional code generation enabled.
@@ -71,6 +73,7 @@
     @required FlutterProject flutterProject,
     @required String target,
     @required BuildInfo buildInfo,
+    @required Platform platform,
     List<String> fileSystemRoots,
     String fileSystemScheme,
     TargetModel targetModel = TargetModel.flutter,
@@ -129,6 +132,7 @@
         artifacts: globals.artifacts,
         processManager: globals.processManager,
         logger: globals.logger,
+        platform: platform,
       );
     } else {
       // The flutter-widget-cache feature only applies to run mode.
@@ -161,6 +165,7 @@
         artifacts: globals.artifacts,
         processManager: globals.processManager,
         logger: globals.logger,
+        platform: platform,
       );
     }
 
diff --git a/packages/flutter_tools/lib/src/test/test_compiler.dart b/packages/flutter_tools/lib/src/test/test_compiler.dart
index 9df1ffb..6d0a89d 100644
--- a/packages/flutter_tools/lib/src/test/test_compiler.dart
+++ b/packages/flutter_tools/lib/src/test/test_compiler.dart
@@ -108,6 +108,7 @@
       dartDefines: const <String>[],
       packagesPath: globalPackagesPath,
       extraFrontEndOptions: extraFrontEndOptions,
+      platform: globals.platform,
     );
     return residentCompiler;
   }
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
index 4c36f2f..36d6122 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
@@ -96,7 +96,7 @@
         '$build/app.dill',
         '--depfile',
         '$build/kernel_snapshot.d',
-        '/lib/main.dart',
+        'file:///lib/main.dart',
       ], exitCode: 1),
     ]);
 
@@ -130,7 +130,7 @@
         '$build/app.dill',
         '--depfile',
         '$build/kernel_snapshot.d',
-        '/lib/main.dart',
+        'file:///lib/main.dart',
       ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
     ]);
 
@@ -164,7 +164,7 @@
         '$build/app.dill',
         '--depfile',
         '$build/kernel_snapshot.d',
-        '/lib/main.dart',
+        'file:///lib/main.dart',
       ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
     ]);
 
@@ -201,7 +201,7 @@
         '$build/kernel_snapshot.d',
         'foo',
         'bar',
-        '/lib/main.dart',
+        'file:///lib/main.dart',
       ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
     ]);
 
@@ -235,7 +235,7 @@
         '$build/app.dill',
         '--depfile',
         '$build/kernel_snapshot.d',
-        '/lib/main.dart',
+        'file:///lib/main.dart',
       ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
     ]);
 
@@ -269,7 +269,7 @@
         '$build/app.dill',
         '--depfile',
         '$build/kernel_snapshot.d',
-        '/lib/main.dart',
+        'file:///lib/main.dart',
       ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey $build/app.dill 0\n'),
     ]);
 
@@ -318,7 +318,7 @@
         '$build/app.dill',
         '--depfile',
         '$build/kernel_snapshot.d',
-        '/lib/main.dart',
+        'file:///lib/main.dart',
       ], stdout: 'result $kBoundaryKey\n$kBoundaryKey\n$kBoundaryKey /build/653e11a8e6908714056a57cd6b4f602a/app.dill 0\n'),
     ]);
 
diff --git a/packages/flutter_tools/test/general.shard/compile_batch_test.dart b/packages/flutter_tools/test/general.shard/compile_batch_test.dart
index 6301bdd..34d6706 100644
--- a/packages/flutter_tools/test/general.shard/compile_batch_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_batch_test.dart
@@ -4,10 +4,10 @@
 
 import 'dart:async';
 
+import 'package:file/memory.dart';
 import 'package:flutter_tools/src/artifacts.dart';
 import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/base/platform.dart';
-import 'package:flutter_tools/src/base/terminal.dart';
+import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/compile.dart';
 import 'package:flutter_tools/src/convert.dart';
@@ -47,14 +47,22 @@
     when(mockFrontendServer.exitCode).thenAnswer((_) async => 0);
   });
 
-  testUsingContext('batch compile single dart successful compilation', () async {
+  testWithoutContext('batch compile single dart successful compilation', () async {
     when(mockFrontendServer.stdout)
         .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
           Future<List<int>>.value(utf8.encode(
             'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0'
           ))
         ));
-    final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(null);
+    final BufferLogger logger = BufferLogger.test();
+    final KernelCompiler kernelCompiler = KernelCompiler(
+      artifacts: Artifacts.test(),
+      fileSystem: MemoryFileSystem.test(),
+      fileSystemRoots: <String>[],
+      fileSystemScheme: '',
+      logger: logger,
+      processManager: mockProcessManager
+    );
     final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
       mainPath: '/path/to/main.dart',
       buildMode: BuildMode.debug,
@@ -65,27 +73,29 @@
     );
 
     expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
-    expect(testLogger.errorText, equals('line1\nline2\n'));
+    expect(logger.errorText, equals('line1\nline2\n'));
     expect(output.outputFilename, equals('/path/to/main.dart.dill'));
     final VerificationResult argVerification = verify(mockProcessManager.start(captureAny));
     expect(argVerification.captured.single, containsAll(<String>[
       '-Ddart.developer.causal_async_stacks=true',
     ]));
-  }, overrides: <Type, Generator>{
-    ProcessManager: () => mockProcessManager,
-    OutputPreferences: () => OutputPreferences(showColor: false),
-    Platform: kNoColorTerminalPlatform,
-    Artifacts: () => Artifacts.test(),
   });
 
-  testUsingContext('passes correct AOT config to kernel compiler in aot/profile mode', () async {
+  testWithoutContext('passes correct AOT config to kernel compiler in aot/profile mode', () async {
     when(mockFrontendServer.stdout)
       .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
         Future<List<int>>.value(utf8.encode(
           'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0'
         ))
       ));
-    final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(null);
+    final KernelCompiler kernelCompiler = KernelCompiler(
+      artifacts: Artifacts.test(),
+      fileSystem: MemoryFileSystem.test(),
+      fileSystemRoots: <String>[],
+      fileSystemScheme: '',
+      logger: BufferLogger.test(),
+      processManager: mockProcessManager
+    );
     await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
       mainPath: '/path/to/main.dart',
       buildMode: BuildMode.profile,
@@ -106,22 +116,23 @@
       '--bytecode-options=source-positions',
       '-Ddart.developer.causal_async_stacks=false',
     ]));
-  }, overrides: <Type, Generator>{
-    ProcessManager: () => mockProcessManager,
-    OutputPreferences: () => OutputPreferences(showColor: false),
-    Platform: kNoColorTerminalPlatform,
-    Artifacts: () => Artifacts.test(),
   });
 
-
-  testUsingContext('passes correct AOT config to kernel compiler in aot/release mode', () async {
+  testWithoutContext('passes correct AOT config to kernel compiler in aot/release mode', () async {
     when(mockFrontendServer.stdout)
       .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
         Future<List<int>>.value(utf8.encode(
           'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0'
         ))
       ));
-    final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(null);
+    final KernelCompiler kernelCompiler = KernelCompiler(
+      artifacts: Artifacts.test(),
+      fileSystem: MemoryFileSystem.test(),
+      fileSystemRoots: <String>[],
+      fileSystemScheme: '',
+      logger: BufferLogger.test(),
+      processManager: mockProcessManager
+    );
     await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
       mainPath: '/path/to/main.dart',
       buildMode: BuildMode.release,
@@ -142,21 +153,24 @@
       '--bytecode-options=source-positions',
       '-Ddart.developer.causal_async_stacks=false',
     ]));
-  }, overrides: <Type, Generator>{
-    ProcessManager: () => mockProcessManager,
-    OutputPreferences: () => OutputPreferences(showColor: false),
-    Platform: kNoColorTerminalPlatform,
-    Artifacts: () => Artifacts.test(),
   });
 
-  testUsingContext('batch compile single dart failed compilation', () async {
+  testWithoutContext('batch compile single dart failed compilation', () async {
     when(mockFrontendServer.stdout)
         .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
           Future<List<int>>.value(utf8.encode(
             'result abc\nline1\nline2\nabc\nabc'
           ))
         ));
-    final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(null);
+    final BufferLogger logger = BufferLogger.test();
+    final KernelCompiler kernelCompiler = KernelCompiler(
+      artifacts: Artifacts.test(),
+      fileSystem: MemoryFileSystem.test(),
+      fileSystemRoots: <String>[],
+      fileSystemScheme: '',
+      logger: logger,
+      processManager: mockProcessManager
+    );
     final CompilerOutput output = await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
       mainPath: '/path/to/main.dart',
       buildMode: BuildMode.debug,
@@ -167,25 +181,27 @@
     );
 
     expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
-    expect(testLogger.errorText, equals('line1\nline2\n'));
+    expect(logger.errorText, equals('line1\nline2\n'));
     expect(output, equals(null));
-  }, overrides: <Type, Generator>{
-    ProcessManager: () => mockProcessManager,
-    OutputPreferences: () => OutputPreferences(showColor: false),
-    Platform: kNoColorTerminalPlatform,
-    Artifacts: () => Artifacts.test(),
   });
 
-  testUsingContext('batch compile single dart abnormal compiler termination', () async {
+  testWithoutContext('batch compile single dart abnormal compiler termination', () async {
     when(mockFrontendServer.exitCode).thenAnswer((_) async => 255);
-
     when(mockFrontendServer.stdout)
         .thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
         Future<List<int>>.value(utf8.encode(
             'result abc\nline1\nline2\nabc\nabc'
         ))
     ));
-    final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(null);
+    final BufferLogger logger = BufferLogger.test();
+    final KernelCompiler kernelCompiler = KernelCompiler(
+      artifacts: Artifacts.test(),
+      fileSystem: MemoryFileSystem.test(),
+      fileSystemRoots: <String>[],
+      fileSystemScheme: '',
+      logger: logger,
+      processManager: mockProcessManager
+    );
     final CompilerOutput output = await kernelCompiler.compile(
       sdkRoot: '/path/to/sdkroot',
       mainPath: '/path/to/main.dart',
@@ -196,22 +212,24 @@
       packagesPath: '.packages',
     );
     expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
-    expect(testLogger.errorText, equals('line1\nline2\n'));
+    expect(logger.errorText, equals('line1\nline2\n'));
     expect(output, equals(null));
-  }, overrides: <Type, Generator>{
-    ProcessManager: () => mockProcessManager,
-    OutputPreferences: () => OutputPreferences(showColor: false),
-    Platform: kNoColorTerminalPlatform,
-    Artifacts: () => Artifacts.test(),
   });
 
-  testUsingContext('passes dartDefines to the kernel compiler', () async {
+  testWithoutContext('passes dartDefines to the kernel compiler', () async {
     // Use unsuccessful result because it's easier to setup in test. We only care about arguments passed to the compiler.
     when(mockFrontendServer.exitCode).thenAnswer((_) async => 255);
     when(mockFrontendServer.stdout).thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
       Future<List<int>>.value(<int>[])
     ));
-    final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(null);
+    final KernelCompiler kernelCompiler = KernelCompiler(
+      artifacts: Artifacts.test(),
+      fileSystem: MemoryFileSystem.test(),
+      fileSystemRoots: <String>[],
+      fileSystemScheme: '',
+      logger: BufferLogger.test(),
+      processManager: mockProcessManager
+    );
     await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
       mainPath: '/path/to/main.dart',
       buildMode: BuildMode.debug,
@@ -222,11 +240,34 @@
     );
 
     expect(latestCommand, containsAllInOrder(<String>['-DFOO=bar', '-DBAZ=qux']));
-  }, overrides: <Type, Generator>{
-    ProcessManager: () => mockProcessManager,
-    OutputPreferences: () => OutputPreferences(showColor: false),
-    Platform: kNoColorTerminalPlatform,
-    Artifacts: () => Artifacts.test(),
+  });
+
+  testWithoutContext('maps a file to a multiroot scheme if providfed', () async {
+    // Use unsuccessful result because it's easier to setup in test. We only care about arguments passed to the compiler.
+    when(mockFrontendServer.exitCode).thenAnswer((_) async => 255);
+    when(mockFrontendServer.stdout).thenAnswer((Invocation invocation) => Stream<List<int>>.fromFuture(
+      Future<List<int>>.value(<int>[])
+    ));
+    final KernelCompiler kernelCompiler = KernelCompiler(
+      artifacts: Artifacts.test(),
+      fileSystem: MemoryFileSystem.test(),
+      fileSystemRoots: <String>[
+        '/foo/bar/fizz',
+      ],
+      fileSystemScheme: 'scheme',
+      logger: BufferLogger.test(),
+      processManager: mockProcessManager
+    );
+    await kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
+      mainPath: '/foo/bar/fizz/main.dart',
+      buildMode: BuildMode.debug,
+      trackWidgetCreation: false,
+      dartDefines: const <String>[],
+      packageConfig: PackageConfig.empty,
+      packagesPath: '.packages',
+    );
+
+    expect(latestCommand, containsAll(<String>['scheme:///main.dart']));
   });
 }
 
diff --git a/packages/flutter_tools/test/general.shard/compile_expression_test.dart b/packages/flutter_tools/test/general.shard/compile_expression_test.dart
index 809be97..41a34a2 100644
--- a/packages/flutter_tools/test/general.shard/compile_expression_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_expression_test.dart
@@ -8,6 +8,7 @@
 import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/logger.dart';
+import 'package:flutter_tools/src/base/platform.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/compile.dart';
 import 'package:flutter_tools/src/convert.dart';
@@ -40,6 +41,7 @@
       artifacts: Artifacts.test(),
       processManager: mockProcessManager,
       logger: testLogger,
+      platform: FakePlatform(operatingSystem: 'linux'),
     );
 
     when(mockFrontendServer.stdin).thenReturn(mockFrontendServerStdIn);
diff --git a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
index 19bea90..f08990c 100644
--- a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
@@ -8,6 +8,7 @@
 import 'package:flutter_tools/src/base/async_guard.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/logger.dart';
+import 'package:flutter_tools/src/base/platform.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/compile.dart';
 import 'package:flutter_tools/src/convert.dart';
@@ -40,6 +41,7 @@
       logger: testLogger,
       processManager: mockProcessManager,
       artifacts: Artifacts.test(),
+      platform: FakePlatform(operatingSystem: 'linux'),
     );
 
     when(mockFrontendServer.stdin).thenReturn(mockFrontendServerStdIn);
diff --git a/packages/flutter_tools/test/general.shard/compile_test.dart b/packages/flutter_tools/test/general.shard/compile_test.dart
index eccc2ad..ac91c61 100644
--- a/packages/flutter_tools/test/general.shard/compile_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_test.dart
@@ -34,4 +34,13 @@
 
     expect(() => TargetModel('foobar'), throwsAssertionError);
   });
+
+  testWithoutContext('toMultiRootPath maps different URIs', () async {
+    expect(toMultiRootPath(Uri.parse('file:///a/b/c'), 'scheme', <String>['/a/b'], false), 'scheme:///c');
+    expect(toMultiRootPath(Uri.parse('file:///d/b/c'), 'scheme', <String>['/a/b'], false), 'file:///d/b/c');
+    expect(toMultiRootPath(Uri.parse('file:///a/b/c'), 'scheme', <String>['/d/b', '/a/b'], false), 'scheme:///c');
+    expect(toMultiRootPath(Uri.parse('file:///a/b/c'), null, <String>[], false), 'file:///a/b/c');
+    expect(toMultiRootPath(Uri.parse('org-dartlang-app:///a/b/c'), null, <String>[], false), 'org-dartlang-app:///a/b/c');
+    expect(toMultiRootPath(Uri.parse('org-dartlang-app:///a/b/c'), 'scheme', <String>['/d/b'], false), 'org-dartlang-app:///a/b/c');
+  });
 }
diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
index d206d8d..03a0802 100644
--- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
@@ -2059,6 +2059,7 @@
       ),
       flutterProject: FlutterProject.current(),
       target: null,
+      platform: FakePlatform(operatingSystem: 'linux'),
     )).generator as DefaultResidentCompiler;
 
     expect(residentCompiler.initializeFromDill,
@@ -2093,6 +2094,7 @@
       ),
       flutterProject: FlutterProject.current(),
       target: null,
+      platform: FakePlatform(operatingSystem: 'linux'),
     )).generator as DefaultResidentCompiler;
 
     expect(residentCompiler.initializeFromDill,
@@ -2126,7 +2128,7 @@
         extraFrontEndOptions: <String>[],
       ),
       flutterProject: FlutterProject.current(),
-      target: null,
+      target: null, platform: null,
     )).generator as DefaultResidentCompiler;
 
     expect(residentCompiler.extraFrontEndOptions,