Reland: don't update last compile time when compilation is rejected. (#41580)

* dont update last compiled time when compilation is rejected

* lets try flushing, thats a neat trick

* windows man

* Update hot_reload_test.dart

* Update hot_reload_test.dart

* Update devfs.dart

* Update hot_reload_test.dart

* Update hot_reload_test.dart

* add test that verifies when compile is good that time is updated

* Update devfs_test.dart
diff --git a/packages/flutter_tools/test/general.shard/devfs_test.dart b/packages/flutter_tools/test/general.shard/devfs_test.dart
index a892efa..0a49b42 100644
--- a/packages/flutter_tools/test/general.shard/devfs_test.dart
+++ b/packages/flutter_tools/test/general.shard/devfs_test.dart
@@ -247,12 +247,14 @@
     testUsingContext('reports unsuccessful compile when errors are returned', () async {
       devFS = DevFS(vmService, 'test', tempDir);
       await devFS.create();
+      final DateTime previousCompile = devFS.lastCompiled;
 
       final RealMockResidentCompiler residentCompiler = RealMockResidentCompiler();
       when(residentCompiler.recompile(
         any,
         any,
         outputPath: anyNamed('outputPath'),
+        packagesFilePath: anyNamed('packagesFilePath'),
       )).thenAnswer((Invocation invocation) {
         return Future<CompilerOutput>.value(const CompilerOutput('example', 2, <Uri>[]));
       });
@@ -266,6 +268,40 @@
       );
 
       expect(report.success, false);
+      expect(devFS.lastCompiled, previousCompile);
+    }, overrides: <Type, Generator>{
+      FileSystem: () => fs,
+    });
+
+    testUsingContext('correctly updates last compiled time when compilation does not fail', () async {
+      devFS = DevFS(vmService, 'test', tempDir);
+      // simulate package
+      final File sourceFile = await _createPackage(fs, 'somepkg', 'main.dart');
+
+      await devFS.create();
+      final DateTime previousCompile = devFS.lastCompiled;
+
+      final RealMockResidentCompiler residentCompiler = RealMockResidentCompiler();
+      when(residentCompiler.recompile(
+        any,
+        any,
+        outputPath: anyNamed('outputPath'),
+        packagesFilePath: anyNamed('packagesFilePath'),
+      )).thenAnswer((Invocation invocation) {
+        fs.file('example').createSync();
+        return Future<CompilerOutput>.value(CompilerOutput('example', 0, <Uri>[sourceFile.uri]));
+      });
+
+      final UpdateFSReport report = await devFS.update(
+        mainPath: 'lib/main.dart',
+        generator: residentCompiler,
+        pathToReload: 'lib/foo.txt.dill',
+        trackWidgetCreation: false,
+        invalidatedFiles: <Uri>[],
+      );
+
+      expect(report.success, true);
+      expect(devFS.lastCompiled, isNot(previousCompile));
     }, overrides: <Type, Generator>{
       FileSystem: () => fs,
     });
@@ -375,7 +411,7 @@
   }
 }
 
-Future<void> _createPackage(FileSystem fs, String pkgName, String pkgFileName, { bool doubleSlash = false }) async {
+Future<File> _createPackage(FileSystem fs, String pkgName, String pkgFileName, { bool doubleSlash = false }) async {
   final Directory pkgTempDir = _newTempDir(fs);
   String pkgFilePath = fs.path.join(pkgTempDir.path, pkgName, 'lib', pkgFileName);
   if (doubleSlash) {
@@ -391,7 +427,8 @@
   _packages.forEach((String pkgName, Uri pkgUri) {
     sb.writeln('$pkgName:$pkgUri');
   });
-  fs.file(fs.path.join(_tempDirs[0].path, '.packages')).writeAsStringSync(sb.toString());
+  return fs.file(fs.path.join(_tempDirs[0].path, '.packages'))
+    ..writeAsStringSync(sb.toString());
 }
 
 class RealMockVM extends Mock implements VM {