Reland filesystem options support with fix for Windows test. (#15655)

* Revert "Revert "Reland pass filesystem options (#15622)" (#15651)"

This reverts commit 0f3eada0664e208bb8c65a5aa02daec38997e8b9.

* Fix for windows failing test

* !isEmpty -> isNotEmpty
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index 4d2d883..4f450e1 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -303,6 +303,10 @@
       command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}');
     if (buildInfo.extraGenSnapshotOptions != null)
       command.add('-Pextra-gen-snapshot-options=${buildInfo.extraGenSnapshotOptions}');
+    if (buildInfo.fileSystemRoots != null && buildInfo.fileSystemRoots.isNotEmpty)
+      command.add('-Pfilesystem-roots=${buildInfo.fileSystemRoots.join('|')}');
+    if (buildInfo.fileSystemScheme != null)
+      command.add('-Pfilesystem-scheme=${buildInfo.fileSystemScheme}');
   }
   if (buildInfo.preferSharedLibrary && androidSdk.ndkCompiler != null) {
     command.add('-Pprefer-shared-library=true');
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart
index c86d5b7..2f9cabf 100644
--- a/packages/flutter_tools/lib/src/build_info.dart
+++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -17,6 +17,8 @@
     this.extraGenSnapshotOptions,
     this.preferSharedLibrary,
     this.targetPlatform,
+    this.fileSystemRoots,
+    this.fileSystemScheme,
   });
 
   final BuildMode mode;
@@ -32,6 +34,9 @@
   /// Whether build should be done using Dart2 Frontend parser.
   final bool previewDart2;
 
+  final List<String> fileSystemRoots;
+  final String fileSystemScheme;
+
   /// Whether the build should track widget creation locations.
   final bool trackWidgetCreation;
 
diff --git a/packages/flutter_tools/lib/src/commands/build_flx.dart b/packages/flutter_tools/lib/src/commands/build_flx.dart
index c763369..8a849ca 100644
--- a/packages/flutter_tools/lib/src/commands/build_flx.dart
+++ b/packages/flutter_tools/lib/src/commands/build_flx.dart
@@ -35,7 +35,18 @@
       ..addFlag('report-licensed-packages',
         help: 'Whether to report the names of all the packages that are included '
               'in the application\'s LICENSE file.',
-        defaultsTo: false);
+        defaultsTo: false)
+      ..addMultiOption('filesystem-root',
+        hide: !verboseHelp,
+        help: 'Specify the path, that is used as root in a virtual file system\n'
+            'for compilation. Input file name should be specified as Uri in\n'
+            'filesystem-scheme scheme. Use only in Dart 2 mode.\n'
+            'Requires --output-dill option to be explicitly specified.\n')
+      ..addOption('filesystem-scheme',
+        defaultsTo: 'org-dartlang-root',
+        hide: !verboseHelp,
+        help: 'Specify the scheme that is used for virtual file system used in\n'
+            'compilation. See more details on filesystem-root option.\n');
     usesPubOption();
   }
 
@@ -67,6 +78,8 @@
       precompiledSnapshot: argResults['precompiled'],
       reportLicensedPackages: argResults['report-licensed-packages'],
       trackWidgetCreation: argResults['track-widget-creation'],
+      fileSystemScheme: argResults['filesystem-scheme'],
+      fileSystemRoots: argResults['filesystem-root'],
     );
   }
 }
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index f4eebbd..cb817a4 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -172,7 +172,18 @@
         help: 'Specify the path to frontend server output kernel file.',
       )
       ..addOption(FlutterOptions.kExtraFrontEndOptions, hide: true)
-      ..addOption(FlutterOptions.kExtraGenSnapshotOptions, hide: true);
+      ..addOption(FlutterOptions.kExtraGenSnapshotOptions, hide: true)
+      ..addMultiOption('filesystem-root',
+        hide: !verboseHelp,
+        help: 'Specify the path, that is used as root in a virtual file system\n'
+            'for compilation. Input file name should be specified as Uri in\n'
+            'filesystem-scheme scheme. Use only in Dart 2 mode.\n'
+            'Requires --output-dill option to be explicitly specified.\n')
+      ..addOption('filesystem-scheme',
+        defaultsTo: 'org-dartlang-root',
+        hide: !verboseHelp,
+        help: 'Specify the scheme that is used for virtual file system used in\n'
+            'compilation. See more details on filesystem-root option.\n');
   }
 
   List<Device> devices;
@@ -345,6 +356,8 @@
         previewDart2: argResults['preview-dart-2'],
         trackWidgetCreation: argResults['track-widget-creation'],
         dillOutputPath: argResults['output-dill'],
+        fileSystemRoots: argResults['filesystem-root'],
+        fileSystemScheme: argResults['filesystem-scheme'],
       );
     }).toList();
 
diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
index 7c15e91..be66234 100644
--- a/packages/flutter_tools/lib/src/compile.dart
+++ b/packages/flutter_tools/lib/src/compile.dart
@@ -55,7 +55,9 @@
     bool trackWidgetCreation: false,
     List<String> extraFrontEndOptions,
     String incrementalCompilerByteStorePath,
-    String packagesPath}) async {
+    String packagesPath,
+    List<String> fileSystemRoots,
+    String fileSystemScheme}) async {
   final String frontendServer = artifacts.getArtifactPath(
     Artifact.frontendServerSnapshotForEngineDartSdk
   );
@@ -93,9 +95,17 @@
   if (outputFilePath != null) {
     command.addAll(<String>['--output-dill', outputFilePath]);
   }
-  if (depFilePath != null) {
+  if (depFilePath != null && (fileSystemRoots == null || fileSystemRoots.isEmpty)) {
     command.addAll(<String>['--depfile', depFilePath]);
   }
+  if (fileSystemRoots != null) {
+    for (String root in fileSystemRoots) {
+      command.addAll(<String>['--filesystem-root', root]);
+    }
+  }
+  if (fileSystemScheme != null) {
+    command.addAll(<String>['--filesystem-scheme', fileSystemScheme]);
+  }
 
   if (extraFrontEndOptions != null)
     command.addAll(extraFrontEndOptions);
@@ -127,10 +137,13 @@
 /// restarts the Flutter app.
 class ResidentCompiler {
   ResidentCompiler(this._sdkRoot, {bool trackWidgetCreation: false,
-      String packagesPath, CompilerMessageConsumer compilerMessageConsumer: printError})
+      String packagesPath, List<String> fileSystemRoots, String fileSystemScheme ,
+      CompilerMessageConsumer compilerMessageConsumer: printError})
     : assert(_sdkRoot != null),
       _trackWidgetCreation = trackWidgetCreation,
       _packagesPath = packagesPath,
+      _fileSystemRoots = fileSystemRoots,
+      _fileSystemScheme = fileSystemScheme,
       stdoutHandler = new _StdoutHandler(consumer: compilerMessageConsumer) {
     // This is a URI, not a file path, so the forward slash is correct even on Windows.
     if (!_sdkRoot.endsWith('/'))
@@ -139,6 +152,8 @@
 
   final bool _trackWidgetCreation;
   final String _packagesPath;
+  final List<String> _fileSystemRoots;
+  final String _fileSystemScheme;
   String _sdkRoot;
   Process _server;
   final _StdoutHandler stdoutHandler;
@@ -157,11 +172,13 @@
     // First time recompile is called we actually have to compile the app from
     // scratch ignoring list of invalidated files.
     if (_server == null)
-      return _compile(mainPath, outputPath, packagesFilePath);
+      return _compile(_mapFilename(mainPath), outputPath, _mapFilename(packagesFilePath));
 
     final String inputKey = new Uuid().generateV4();
-    _server.stdin.writeln('recompile ${mainPath != null ? mainPath + " ": ""}$inputKey');
-    invalidatedFiles.forEach(_server.stdin.writeln);
+    _server.stdin.writeln('recompile ${mainPath != null ? _mapFilename(mainPath) + " ": ""}$inputKey');
+    for (String filePath in invalidatedFiles) {
+      _server.stdin.writeln(_mapFilename(filePath));
+    }
     _server.stdin.writeln(inputKey);
 
     return stdoutHandler.outputFilename.future;
@@ -192,6 +209,14 @@
     if (_packagesPath != null) {
       args.addAll(<String>['--packages', _packagesPath]);
     }
+    if (_fileSystemRoots != null) {
+      for (String root in _fileSystemRoots) {
+        args.addAll(<String>['--filesystem-root', root]);
+      }
+    }
+    if (_fileSystemScheme != null) {
+      args.addAll(<String>['--filesystem-scheme', _fileSystemScheme]);
+    }
     _server = await processManager.start(args);
     _server.stdout
       .transform(utf8.decoder)
@@ -238,6 +263,19 @@
     _server.stdin.writeln('reset');
   }
 
+  String _mapFilename(String filename) {
+    if (_fileSystemRoots != null) {
+      for (String root in _fileSystemRoots) {
+        if (filename.startsWith(root)) {
+          return new Uri(
+              scheme: _fileSystemScheme, path: filename.substring(root.length))
+              .toString();
+        }
+      }
+    }
+    return filename;
+  }
+
   Future<dynamic> shutdown() {
     _server.kill();
     return _server.exitCode;
diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index 4af38ac..40446d1 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -487,7 +487,7 @@
           final DevFSContent content = dirtyEntries[uri];
           if (content is DevFSFileContent) {
             filesUris.add(uri);
-            invalidatedFiles.add(content.file.uri.toString());
+            invalidatedFiles.add(content.file.path);
             numBytes -= content.size;
           }
         }
diff --git a/packages/flutter_tools/lib/src/flx.dart b/packages/flutter_tools/lib/src/flx.dart
index b7b8236..f02ad9a 100644
--- a/packages/flutter_tools/lib/src/flx.dart
+++ b/packages/flutter_tools/lib/src/flx.dart
@@ -44,6 +44,8 @@
   bool precompiledSnapshot: false,
   bool reportLicensedPackages: false,
   bool trackWidgetCreation: false,
+  List<String> fileSystemRoots,
+  String fileSystemScheme,
 }) async {
   outputPath ??= defaultFlxOutputPath;
   snapshotPath ??= defaultSnapshotPath;
@@ -82,6 +84,9 @@
       outputFilePath: applicationKernelFilePath,
       depFilePath: depfilePath,
       trackWidgetCreation: trackWidgetCreation,
+      fileSystemRoots: fileSystemRoots,
+      fileSystemScheme: fileSystemScheme,
+      packagesPath: packagesPath,
     );
     if (kernelBinaryFilename == null) {
       throwToolExit('Compiler terminated unexpectedly on $mainPath');
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index 3abc152..835fe22 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -36,6 +36,8 @@
   ApplicationPackage package;
   ResidentCompiler generator;
   String dillOutputPath;
+  List<String> fileSystemRoots;
+  String fileSystemScheme;
 
   StreamSubscription<String> _loggingSubscription;
 
@@ -43,11 +45,14 @@
     @required bool previewDart2,
     @required bool trackWidgetCreation,
     this.dillOutputPath,
+    this.fileSystemRoots,
+    this.fileSystemScheme,
   }) {
     if (previewDart2) {
       generator = new ResidentCompiler(
         artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
         trackWidgetCreation: trackWidgetCreation,
+        fileSystemRoots: fileSystemRoots, fileSystemScheme: fileSystemScheme
       );
     }
   }
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index db0e119..a84708c 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -392,7 +392,7 @@
     // We are now running from source.
     _runningFromSnapshot = false;
     final String launchPath = debuggingOptions.buildInfo.previewDart2
-        ? dillOutputPath ?? mainPath + '.dill'
+        ? mainPath + '.dill'
         : mainPath;
     await _launchFromDevFS(launchPath);
     restartTimer.stop();
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index cd50e61..c65e9a7 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -61,6 +61,8 @@
 class FlutterOptions {
   static const String kExtraFrontEndOptions = 'extra-front-end-options';
   static const String kExtraGenSnapshotOptions = 'extra-gen-snapshot-options';
+  static const String kFileSystemRoot = 'filesystem-root';
+  static const String kFileSystemScheme = 'filesystem-scheme';
 }
 
 abstract class FlutterCommand extends Command<Null> {
@@ -194,7 +196,12 @@
       preferSharedLibrary: argParser.options.containsKey('prefer-shared-library')
         ? argResults['prefer-shared-library']
         : false,
-      targetPlatform: targetPlatform);
+      targetPlatform: targetPlatform,
+      fileSystemRoots: argParser.options.containsKey(FlutterOptions.kFileSystemRoot)
+          ? argResults[FlutterOptions.kFileSystemRoot] : null,
+      fileSystemScheme: argParser.options.containsKey(FlutterOptions.kFileSystemScheme)
+          ? argResults[FlutterOptions.kFileSystemScheme] : null,
+    );
   }
 
   void setupApplicationPackages() {