| diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart |
| index 12c0770ab..7787bd4ca 100644 |
| --- a/packages/flutter_tools/lib/src/compile.dart |
| +++ b/packages/flutter_tools/lib/src/compile.dart |
| @@ -57,12 +57,15 @@ class TargetModel { |
| } |
| |
| class CompilerOutput { |
| - const CompilerOutput(this.outputFilename, this.errorCount); |
| + const CompilerOutput(this.outputFilename, this.errorCount, this.sources); |
| |
| final String outputFilename; |
| final int errorCount; |
| + final List<Uri> sources; |
| } |
| |
| +enum StdoutState { CollectDiagnostic, CollectDependencies } |
| + |
| /// Handles stdin/stdout communication with the frontend server. |
| class StdoutHandler { |
| StdoutHandler({this.consumer = printError}) { |
| @@ -72,30 +75,54 @@ class StdoutHandler { |
| bool compilerMessageReceived = false; |
| final CompilerMessageConsumer consumer; |
| String boundaryKey; |
| + StdoutState state = StdoutState.CollectDiagnostic; |
| Completer<CompilerOutput> compilerOutput; |
| + final List<Uri> sources = <Uri>[]; |
| |
| bool _suppressCompilerMessages; |
| |
| void handler(String message) { |
| + printTrace('-> $message'); |
| const String kResultPrefix = 'result '; |
| if (boundaryKey == null && message.startsWith(kResultPrefix)) { |
| boundaryKey = message.substring(kResultPrefix.length); |
| } else if (message.startsWith(boundaryKey)) { |
| - if (message.length <= boundaryKey.length) { |
| - compilerOutput.complete(null); |
| - return; |
| + if (state == StdoutState.CollectDiagnostic) { |
| + state = StdoutState.CollectDependencies; |
| + } else { |
| + if (message.length <= boundaryKey.length) { |
| + compilerOutput.complete(null); |
| + return; |
| + } |
| + final int spaceDelimiter = message.lastIndexOf(' '); |
| + compilerOutput.complete( |
| + CompilerOutput( |
| + message.substring(boundaryKey.length + 1, spaceDelimiter), |
| + int.parse(message.substring(spaceDelimiter + 1).trim()), |
| + sources)); |
| } |
| - final int spaceDelimiter = message.lastIndexOf(' '); |
| - compilerOutput.complete( |
| - CompilerOutput( |
| - message.substring(boundaryKey.length + 1, spaceDelimiter), |
| - int.parse(message.substring(spaceDelimiter + 1).trim()))); |
| - } else if (!_suppressCompilerMessages) { |
| - if (compilerMessageReceived == false) { |
| - consumer('\nCompiler message:'); |
| - compilerMessageReceived = true; |
| + } else { |
| + if (state == StdoutState.CollectDiagnostic) { |
| + if (!_suppressCompilerMessages) { |
| + if (compilerMessageReceived == false) { |
| + consumer('\nCompiler message:'); |
| + compilerMessageReceived = true; |
| + } |
| + consumer(message); |
| + } |
| + } else { |
| + assert(state == StdoutState.CollectDependencies); |
| + switch (message[0]) { |
| + case '+': |
| + sources.add(Uri.parse(message.substring(1))); |
| + break; |
| + case '-': |
| + sources.remove(Uri.parse(message.substring(1))); |
| + break; |
| + default: |
| + printTrace('Unexpected prefix for $message uri - ignoring'); |
| + } |
| } |
| - consumer(message); |
| } |
| } |
| |
| @@ -106,6 +133,7 @@ class StdoutHandler { |
| compilerMessageReceived = false; |
| compilerOutput = Completer<CompilerOutput>(); |
| _suppressCompilerMessages = suppressCompilerMessages; |
| + state = StdoutState.CollectDiagnostic; |
| } |
| } |
| |
| @@ -200,7 +228,7 @@ class KernelCompiler { |
| |
| if (await fingerprinter.doesFingerprintMatch()) { |
| printTrace('Skipping kernel compilation. Fingerprint match.'); |
| - return CompilerOutput(outputFilePath, 0); |
| + return CompilerOutput(outputFilePath, 0, /* sources */ null); |
| } |
| } |
| |
| @@ -453,10 +481,13 @@ class ResidentCompiler { |
| ? _mapFilename(request.mainPath, packageUriMapper) + ' ' |
| : ''; |
| _server.stdin.writeln('recompile $mainUri$inputKey'); |
| + printTrace('<- recompile $mainUri$inputKey'); |
| for (String fileUri in request.invalidatedFiles) { |
| _server.stdin.writeln(_mapFileUri(fileUri, packageUriMapper)); |
| + printTrace('<- ${_mapFileUri(fileUri, packageUriMapper)}'); |
| } |
| _server.stdin.writeln(inputKey); |
| + printTrace('<- $inputKey'); |
| |
| return _stdoutHandler.compilerOutput.future; |
| } |
| @@ -545,6 +576,7 @@ class ResidentCompiler { |
| .listen((String message) { printError(message); }); |
| |
| _server.stdin.writeln('compile $scriptUri'); |
| + printTrace('<- compile $scriptUri'); |
| |
| return _stdoutHandler.compilerOutput.future; |
| } |
| @@ -597,6 +629,7 @@ class ResidentCompiler { |
| void accept() { |
| if (_compileRequestNeedsConfirmation) { |
| _server.stdin.writeln('accept'); |
| + printTrace('<- accept'); |
| } |
| _compileRequestNeedsConfirmation = false; |
| } |
| @@ -620,6 +653,7 @@ class ResidentCompiler { |
| } |
| _stdoutHandler.reset(); |
| _server.stdin.writeln('reject'); |
| + printTrace('<- reject'); |
| _compileRequestNeedsConfirmation = false; |
| return _stdoutHandler.compilerOutput.future; |
| } |
| @@ -629,6 +663,7 @@ class ResidentCompiler { |
| /// kernel file. |
| void reset() { |
| _server?.stdin?.writeln('reset'); |
| + printTrace('<- reset'); |
| } |
| |
| String _mapFilename(String filename, PackageUriMapper packageUriMapper) { |
| diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart |
| index 407a51b12..ea63e73c6 100644 |
| --- a/packages/flutter_tools/lib/src/devfs.dart |
| +++ b/packages/flutter_tools/lib/src/devfs.dart |
| @@ -484,6 +484,8 @@ class DevFS { |
| outputPath: dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation), |
| packagesFilePath : _packagesFilePath, |
| ); |
| + // list of sources that needs to be monitored are in [compilerOutput.sources] |
| + // |
| // Don't send full kernel file that would overwrite what VM already |
| // started loading from. |
| if (!bundleFirstUpload) { |
| diff --git a/packages/flutter_tools/test/src/mocks.dart b/packages/flutter_tools/test/src/mocks.dart |
| index 42c9d8f7f..c47b4ff7c 100644 |
| --- a/packages/flutter_tools/test/src/mocks.dart |
| +++ b/packages/flutter_tools/test/src/mocks.dart |
| @@ -490,6 +490,6 @@ class MockResidentCompiler extends BasicMock implements ResidentCompiler { |
| Future<CompilerOutput> recompile(String mainPath, List<String> invalidatedFiles, { String outputPath, String packagesFilePath }) async { |
| fs.file(outputPath).createSync(recursive: true); |
| fs.file(outputPath).writeAsStringSync('compiled_kernel_output'); |
| - return CompilerOutput(outputPath, 0); |
| + return CompilerOutput(outputPath, 0, <Uri>[]); |
| } |
| } |
| diff --git a/packages/flutter_tools/test/tester/flutter_tester_test.dart b/packages/flutter_tools/test/tester/flutter_tester_test.dart |
| index a78f70f4f..b6524bd5d 100644 |
| --- a/packages/flutter_tools/test/tester/flutter_tester_test.dart |
| +++ b/packages/flutter_tools/test/tester/flutter_tester_test.dart |
| @@ -177,7 +177,7 @@ Hello! |
| packagesPath: anyNamed('packagesPath'), |
| )).thenAnswer((_) async { |
| fs.file('$mainPath.dill').createSync(recursive: true); |
| - return CompilerOutput('$mainPath.dill', 0); |
| + return CompilerOutput('$mainPath.dill', 0, <Uri>[]); |
| }); |
| |
| final LaunchResult result = await device.startApp(null, |