From 3393566b561295d843a5d1a3ef1e8929a31231d4 Mon Sep 17 00:00:00 2001 From: Lau Ching Jun Date: Fri, 16 Oct 2020 10:54:19 -0700 Subject: [PATCH] Use multiroot scheme for initial compilation in ResidentRunner recompile (#68280) --- packages/flutter_tools/lib/src/compile.dart | 12 ++- .../general.shard/compile_batch_test.dart | 2 +- .../compile_incremental_test.dart | 89 +++++++++++++++++-- 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart index 248857c6e75..4058e6785a1 100644 --- a/packages/flutter_tools/lib/src/compile.dart +++ b/packages/flutter_tools/lib/src/compile.dart @@ -584,16 +584,14 @@ class DefaultResidentCompiler implements ResidentCompiler { _compileRequestNeedsConfirmation = true; _stdoutHandler._suppressCompilerMessages = request.suppressErrors; - if (_server == null) { - return _compile( - request.packageConfig.toPackageUri(request.mainUri)?.toString() ?? request.mainUri.toString(), - request.outputPath, - ); - } - final String inputKey = Uuid().generateV4(); final String mainUri = request.packageConfig.toPackageUri(request.mainUri)?.toString() ?? toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots, _platform.isWindows); + if (_server == null) { + return _compile(mainUri, request.outputPath); + } + final String inputKey = Uuid().generateV4(); + _server.stdin.writeln('recompile $mainUri $inputKey'); _logger.printTrace('<- recompile $mainUri $inputKey'); for (final Uri fileUri in request.invalidatedFiles) { 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 c35446e904a..3c0da534748 100644 --- a/packages/flutter_tools/test/general.shard/compile_batch_test.dart +++ b/packages/flutter_tools/test/general.shard/compile_batch_test.dart @@ -240,7 +240,7 @@ void main() { expect(latestCommand, containsAllInOrder(['-DFOO=bar', '-DBAZ=qux'])); }); - testWithoutContext('maps a file to a multiroot scheme if providfed', () async { + testWithoutContext('maps a file to a multiroot scheme if provided', () 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>.fromFuture( 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 f08990c0828..4652cfb54f2 100644 --- a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart +++ b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart @@ -23,6 +23,7 @@ import '../src/mocks.dart'; void main() { ProcessManager mockProcessManager; ResidentCompiler generator; + ResidentCompiler generatorWithScheme; MockProcess mockFrontendServer; MockStdIn mockFrontendServerStdIn; MockStream mockFrontendServerStdErr; @@ -43,6 +44,18 @@ void main() { artifacts: Artifacts.test(), platform: FakePlatform(operatingSystem: 'linux'), ); + generatorWithScheme = ResidentCompiler( + 'sdkroot', + buildMode: BuildMode.debug, + logger: testLogger, + processManager: mockProcessManager, + artifacts: Artifacts.test(), + platform: FakePlatform(operatingSystem: 'linux'), + fileSystemRoots: [ + '/foo/bar/fizz', + ], + fileSystemScheme: 'scheme', + ); when(mockFrontendServer.stdin).thenReturn(mockFrontendServerStdIn); when(mockFrontendServer.stderr) @@ -80,6 +93,26 @@ void main() { expect(output.outputFilename, equals('/path/to/main.dart.dill')); }); + testWithoutContext('incremental compile single dart compile with filesystem scheme', () async { + when(mockFrontendServer.stdout) + .thenAnswer((Invocation invocation) => Stream>.fromFuture( + Future>.value(utf8.encode( + 'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0' + )) + )); + + final CompilerOutput output = await generatorWithScheme.recompile( + Uri.parse('file:///foo/bar/fizz/main.dart'), + null /* invalidatedFiles */, + outputPath: '/build/', + packageConfig: PackageConfig.empty, + ); + expect(mockFrontendServerStdIn.getAndClear(), 'compile scheme:///main.dart\n'); + verifyNoMoreInteractions(mockFrontendServerStdIn); + expect(testLogger.errorText, equals('line1\nline2\n')); + expect(output.outputFilename, equals('/path/to/main.dart.dill')); + }); + testWithoutContext('incremental compile single dart compile abnormally terminates', () async { when(mockFrontendServer.stdout) .thenAnswer((Invocation invocation) => const Stream>.empty() @@ -145,6 +178,47 @@ void main() { )); }); + testWithoutContext('incremental compile and recompile with filesystem scheme', () async { + final StreamController> streamController = StreamController>(); + when(mockFrontendServer.stdout) + .thenAnswer((Invocation invocation) => streamController.stream); + streamController.add(utf8.encode('result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0\n')); + await generatorWithScheme.recompile( + Uri.parse('file:///foo/bar/fizz/main.dart'), + null, /* invalidatedFiles */ + outputPath: '/build/', + packageConfig: PackageConfig.empty, + ); + expect(mockFrontendServerStdIn.getAndClear(), 'compile scheme:///main.dart\n'); + + // No accept or reject commands should be issued until we + // send recompile request. + await _accept(streamController, generatorWithScheme, mockFrontendServerStdIn, ''); + await _reject(streamController, generatorWithScheme, mockFrontendServerStdIn, '', ''); + + await _recompile(streamController, generatorWithScheme, mockFrontendServerStdIn, + 'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n', + mainUri: Uri.parse('file:///foo/bar/fizz/main.dart'), + expectedUri: 'scheme:///main.dart'); + + await _accept(streamController, generatorWithScheme, mockFrontendServerStdIn, r'^accept\n$'); + + await _recompile(streamController, generatorWithScheme, mockFrontendServerStdIn, + 'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n', + mainUri: Uri.parse('file:///foo/bar/fizz/main.dart'), + expectedUri: 'scheme:///main.dart'); + // No sources returned from reject command. + await _reject(streamController, generatorWithScheme, mockFrontendServerStdIn, 'result abc\nabc\n', + r'^reject\n$'); + verifyNoMoreInteractions(mockFrontendServerStdIn); + expect(mockFrontendServerStdIn.getAndClear(), isEmpty); + expect(testLogger.errorText, equals( + 'line0\nline1\n' + 'line1\nline2\n' + 'line1\nline2\n' + )); + }); + testWithoutContext('incremental compile can suppress errors', () async { final StreamController> stdoutController = StreamController>(); when(mockFrontendServer.stdout) @@ -214,17 +288,21 @@ Future _recompile( StreamController> streamController, ResidentCompiler generator, MockStdIn mockFrontendServerStdIn, - String mockCompilerOutput, - { bool suppressErrors = false } -) async { + String mockCompilerOutput, { + bool suppressErrors = false, + Uri mainUri, + String expectedUri = '/path/to/main.dart', +}) async { + mainUri ??= Uri.parse('/path/to/main.dart'); + // Put content into the output stream after generator.recompile gets // going few lines below, resets completer. scheduleMicrotask(() { streamController.add(utf8.encode(mockCompilerOutput)); }); final CompilerOutput output = await generator.recompile( - Uri.parse('/path/to/main.dart'), - [Uri.parse('/path/to/main.dart')], + mainUri, + [mainUri], outputPath: '/build/', packageConfig: PackageConfig.empty, suppressErrors: suppressErrors, @@ -236,6 +314,7 @@ Future _recompile( // Test that uuid matches at beginning and end. expect(parts[2], equals(parts[4])); + expect(parts[1], equals(expectedUri)); mockFrontendServerStdIn.stdInWrites.clear(); }