Unverified Commit 4bcf8fb4 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate compile to null safety (#83153)

parent ade6e1f9
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'dart:typed_data';
......@@ -26,8 +24,8 @@ import 'convert.dart';
class TargetModel {
/// Parse a [TargetModel] from a raw string.
///
/// Throws an [AssertionError] if passed a value other than 'flutter' or
/// 'flutter_runner'.
/// Throws an exception if passed a value other than 'flutter',
/// 'flutter_runner', 'vm', or 'dartdevc'.
factory TargetModel(String rawValue) {
switch (rawValue) {
case 'flutter':
......@@ -39,8 +37,7 @@ class TargetModel {
case 'dartdevc':
return dartdevc;
}
assert(false);
return null;
throw Exception('Unexpected target model $rawValue');
}
const TargetModel._(this._value);
......@@ -71,7 +68,7 @@ class CompilerOutput {
final List<Uri> sources;
/// This field is only non-null for expression compilation requests.
final Uint8List expressionData;
final Uint8List? expressionData;
}
enum StdoutState { CollectDiagnostic, CollectDependencies }
......@@ -79,8 +76,8 @@ enum StdoutState { CollectDiagnostic, CollectDependencies }
/// Handles stdin/stdout communication with the frontend server.
class StdoutHandler {
StdoutHandler({
@required Logger logger,
@required FileSystem fileSystem,
required Logger logger,
required FileSystem fileSystem,
}) : _logger = logger,
_fileSystem = fileSystem {
reset();
......@@ -89,14 +86,14 @@ class StdoutHandler {
final Logger _logger;
final FileSystem _fileSystem;
String boundaryKey;
String? boundaryKey;
StdoutState state = StdoutState.CollectDiagnostic;
Completer<CompilerOutput> compilerOutput;
Completer<CompilerOutput?>? compilerOutput;
final List<Uri> sources = <Uri>[];
bool _suppressCompilerMessages;
bool _expectSources;
bool _readFile;
bool _suppressCompilerMessages = false;
bool _expectSources = true;
bool _readFile = false;
void handler(String message) {
const String kResultPrefix = 'result ';
......@@ -104,21 +101,22 @@ class StdoutHandler {
boundaryKey = message.substring(kResultPrefix.length);
return;
}
if (message.startsWith(boundaryKey)) {
final String? messageBoundaryKey = boundaryKey;
if (messageBoundaryKey != null && message.startsWith(messageBoundaryKey)) {
if (_expectSources) {
if (state == StdoutState.CollectDiagnostic) {
state = StdoutState.CollectDependencies;
return;
}
}
if (message.length <= boundaryKey.length) {
compilerOutput.complete(null);
if (message.length <= messageBoundaryKey.length) {
compilerOutput?.complete(null);
return;
}
final int spaceDelimiter = message.lastIndexOf(' ');
final String fileName = message.substring(boundaryKey.length + 1, spaceDelimiter);
final String fileName = message.substring(messageBoundaryKey.length + 1, spaceDelimiter);
final int errorCount = int.parse(message.substring(spaceDelimiter + 1).trim());
Uint8List expressionData;
Uint8List? expressionData;
if (_readFile) {
expressionData = _fileSystem.file(fileName).readAsBytesSync();
}
......@@ -128,7 +126,7 @@ class StdoutHandler {
sources,
expressionData: expressionData,
);
compilerOutput.complete(output);
compilerOutput?.complete(output);
return;
}
if (state == StdoutState.CollectDiagnostic) {
......@@ -156,7 +154,7 @@ class StdoutHandler {
// with its own boundary key and new completer.
void reset({ bool suppressCompilerMessages = false, bool expectSources = true, bool readFile = false }) {
boundaryKey = null;
compilerOutput = Completer<CompilerOutput>();
compilerOutput = Completer<CompilerOutput?>();
_suppressCompilerMessages = suppressCompilerMessages;
_expectSources = expectSources;
_readFile = readFile;
......@@ -193,13 +191,13 @@ List<String> buildModeOptions(BuildMode mode, List<String> dartDefines) {
/// A compiler interface for producing single (non-incremental) kernel files.
class KernelCompiler {
KernelCompiler({
@required FileSystem fileSystem,
@required Logger logger,
@required ProcessManager processManager,
@required Artifacts artifacts,
@required List<String> fileSystemRoots,
@required String fileSystemScheme,
@visibleForTesting StdoutHandler stdoutHandler,
required FileSystem fileSystem,
required Logger logger,
required ProcessManager processManager,
required Artifacts artifacts,
required List<String> fileSystemRoots,
required String fileSystemScheme,
@visibleForTesting StdoutHandler? stdoutHandler,
}) : _logger = logger,
_fileSystem = fileSystem,
_artifacts = artifacts,
......@@ -216,26 +214,26 @@ class KernelCompiler {
final List<String> _fileSystemRoots;
final StdoutHandler _stdoutHandler;
Future<CompilerOutput> compile({
String sdkRoot,
String mainPath,
String outputFilePath,
String depFilePath,
Future<CompilerOutput?> compile({
required String sdkRoot,
String? mainPath,
String? outputFilePath,
String? depFilePath,
TargetModel targetModel = TargetModel.flutter,
bool linkPlatformKernelIn = false,
bool aot = false,
List<String> extraFrontEndOptions,
List<String> fileSystemRoots,
String fileSystemScheme,
String initializeFromDill,
String platformDill,
Directory buildDir,
List<String>? extraFrontEndOptions,
List<String>? fileSystemRoots,
String? fileSystemScheme,
String? initializeFromDill,
String? platformDill,
Directory? buildDir,
bool checkDartPluginRegistry = false,
@required String packagesPath,
@required BuildMode buildMode,
@required bool trackWidgetCreation,
@required List<String> dartDefines,
@required PackageConfig packageConfig,
required String? packagesPath,
required BuildMode buildMode,
required bool trackWidgetCreation,
required List<String> dartDefines,
required PackageConfig packageConfig,
}) async {
final String frontendServer = _artifacts.getArtifactPath(
Artifact.frontendServerSnapshotForEngineDartSdk
......@@ -248,7 +246,7 @@ class KernelCompiler {
if (!_processManager.canRun(engineDartPath)) {
throwToolExit('Unable to find Dart binary at $engineDartPath');
}
String mainUri;
String? mainUri;
final File mainFile = _fileSystem.file(mainPath);
final Uri mainFileUri = mainFile.uri;
if (packagesPath != null) {
......@@ -314,7 +312,7 @@ class KernelCompiler {
platformDill,
],
...?extraFrontEndOptions,
mainUri ?? mainPath,
mainUri,
];
_logger.printTrace(command.join(' '));
......@@ -329,7 +327,7 @@ class KernelCompiler {
.listen(_stdoutHandler.handler);
final int exitCode = await server.exitCode;
if (exitCode == 0) {
return _stdoutHandler.compilerOutput.future;
return _stdoutHandler.compilerOutput?.future;
}
return null;
}
......@@ -339,9 +337,9 @@ class KernelCompiler {
abstract class _CompilationRequest {
_CompilationRequest(this.completer);
Completer<CompilerOutput> completer;
Completer<CompilerOutput?> completer;
Future<CompilerOutput> _run(DefaultResidentCompiler compiler);
Future<CompilerOutput?> _run(DefaultResidentCompiler compiler);
Future<void> run(DefaultResidentCompiler compiler) async {
completer.complete(await _run(compiler));
......@@ -350,7 +348,7 @@ abstract class _CompilationRequest {
class _RecompileRequest extends _CompilationRequest {
_RecompileRequest(
Completer<CompilerOutput> completer,
Completer<CompilerOutput?> completer,
this.mainUri,
this.invalidatedFiles,
this.outputPath,
......@@ -359,19 +357,19 @@ class _RecompileRequest extends _CompilationRequest {
) : super(completer);
Uri mainUri;
List<Uri> invalidatedFiles;
List<Uri>? invalidatedFiles;
String outputPath;
PackageConfig packageConfig;
bool suppressErrors;
@override
Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
compiler._recompile(this);
}
class _CompileExpressionRequest extends _CompilationRequest {
_CompileExpressionRequest(
Completer<CompilerOutput> completer,
Completer<CompilerOutput?> completer,
this.expression,
this.definitions,
this.typeDefinitions,
......@@ -381,20 +379,20 @@ class _CompileExpressionRequest extends _CompilationRequest {
) : super(completer);
String expression;
List<String> definitions;
List<String> typeDefinitions;
String libraryUri;
String klass;
List<String>? definitions;
List<String>? typeDefinitions;
String? libraryUri;
String? klass;
bool isStatic;
@override
Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
compiler._compileExpression(this);
}
class _CompileExpressionToJsRequest extends _CompilationRequest {
_CompileExpressionToJsRequest(
Completer<CompilerOutput> completer,
Completer<CompilerOutput?> completer,
this.libraryUri,
this.line,
this.column,
......@@ -404,24 +402,24 @@ class _CompileExpressionToJsRequest extends _CompilationRequest {
this.expression,
) : super(completer);
final String libraryUri;
final String? libraryUri;
final int line;
final int column;
final Map<String, String> jsModules;
final Map<String, String> jsFrameValues;
final String moduleName;
final String expression;
final Map<String, String>? jsModules;
final Map<String, String>? jsFrameValues;
final String? moduleName;
final String? expression;
@override
Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
compiler._compileExpressionToJs(this);
}
class _RejectRequest extends _CompilationRequest {
_RejectRequest(Completer<CompilerOutput> completer) : super(completer);
_RejectRequest(Completer<CompilerOutput?> completer) : super(completer);
@override
Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
compiler._reject();
}
......@@ -432,23 +430,23 @@ class _RejectRequest extends _CompilationRequest {
/// restarts the Flutter app.
abstract class ResidentCompiler {
factory ResidentCompiler(String sdkRoot, {
@required BuildMode buildMode,
@required Logger logger,
@required ProcessManager processManager,
@required Artifacts artifacts,
@required Platform platform,
@required FileSystem fileSystem,
required BuildMode buildMode,
required Logger logger,
required ProcessManager processManager,
required Artifacts artifacts,
required Platform platform,
required FileSystem fileSystem,
bool testCompilation,
bool trackWidgetCreation,
String packagesPath,
List<String> fileSystemRoots,
String fileSystemScheme,
String? fileSystemScheme,
String initializeFromDill,
TargetModel targetModel,
bool unsafePackageSerialization,
List<String> extraFrontEndOptions,
String platformDill,
List<String> dartDefines,
List<String>? dartDefines,
String librariesSpec,
}) = DefaultResidentCompiler;
......@@ -464,22 +462,22 @@ abstract class ResidentCompiler {
/// point that is used for recompilation.
/// Binary file name is returned if compilation was successful, otherwise
/// null is returned.
Future<CompilerOutput> recompile(
Future<CompilerOutput?> recompile(
Uri mainUri,
List<Uri> invalidatedFiles, {
@required String outputPath,
@required PackageConfig packageConfig,
@required String projectRootPath,
@required FileSystem fs,
List<Uri>? invalidatedFiles, {
required String outputPath,
required PackageConfig packageConfig,
required String projectRootPath,
required FileSystem fs,
bool suppressErrors = false,
});
Future<CompilerOutput> compileExpression(
Future<CompilerOutput?> compileExpression(
String expression,
List<String> definitions,
List<String> typeDefinitions,
String libraryUri,
String klass,
List<String>? definitions,
List<String>? typeDefinitions,
String? libraryUri,
String? klass,
bool isStatic,
);
......@@ -503,7 +501,7 @@ abstract class ResidentCompiler {
/// { 'dart':'dart_sdk', 'main': '/packages/hello_world_main.dart' }
/// Returns a [CompilerOutput] including the name of the file containing the
/// compilation result and a number of errors.
Future<CompilerOutput> compileExpressionToJs(
Future<CompilerOutput?> compileExpressionToJs(
String libraryUri,
int line,
int column,
......@@ -521,39 +519,39 @@ abstract class ResidentCompiler {
/// Should be invoked when results of compilation are rejected by the client.
///
/// Either [accept] or [reject] should be called after every [recompile] call.
Future<CompilerOutput> reject();
Future<CompilerOutput?> reject();
/// Should be invoked when frontend server compiler should forget what was
/// accepted previously so that next call to [recompile] produces complete
/// kernel file.
void reset();
Future<dynamic> shutdown();
Future<Object> shutdown();
}
@visibleForTesting
class DefaultResidentCompiler implements ResidentCompiler {
DefaultResidentCompiler(
String sdkRoot, {
@required this.buildMode,
@required Logger logger,
@required ProcessManager processManager,
@required Artifacts artifacts,
@required Platform platform,
@required FileSystem fileSystem,
required this.buildMode,
required Logger logger,
required ProcessManager processManager,
required Artifacts artifacts,
required Platform platform,
required FileSystem fileSystem,
this.testCompilation = false,
this.trackWidgetCreation = true,
this.packagesPath,
this.fileSystemRoots,
this.fileSystemRoots = const <String>[],
this.fileSystemScheme,
this.initializeFromDill,
this.targetModel = TargetModel.flutter,
this.unsafePackageSerialization,
this.unsafePackageSerialization = false,
this.extraFrontEndOptions,
this.platformDill,
List<String> dartDefines,
List<String>? dartDefines,
this.librariesSpec,
@visibleForTesting StdoutHandler stdoutHandler,
@visibleForTesting StdoutHandler? stdoutHandler,
}) : assert(sdkRoot != null),
_logger = logger,
_processManager = processManager,
......@@ -572,15 +570,15 @@ class DefaultResidentCompiler implements ResidentCompiler {
final bool testCompilation;
final BuildMode buildMode;
final bool trackWidgetCreation;
final String packagesPath;
final String? packagesPath;
final TargetModel targetModel;
final List<String> fileSystemRoots;
final String fileSystemScheme;
final String initializeFromDill;
final String? fileSystemScheme;
final String? initializeFromDill;
final bool unsafePackageSerialization;
final List<String> extraFrontEndOptions;
final List<String>? extraFrontEndOptions;
final List<String> dartDefines;
final String librariesSpec;
final String? librariesSpec;
@override
void addFileSystemRoot(String root) {
......@@ -595,23 +593,23 @@ class DefaultResidentCompiler implements ResidentCompiler {
/// The path to the platform dill file.
///
/// This does not need to be provided for the normal Flutter workflow.
final String platformDill;
final String? platformDill;
Process _server;
Process? _server;
final StdoutHandler _stdoutHandler;
bool _compileRequestNeedsConfirmation = false;
final StreamController<_CompilationRequest> _controller = StreamController<_CompilationRequest>();
@override
Future<CompilerOutput> recompile(
Future<CompilerOutput?> recompile(
Uri mainUri,
List<Uri> invalidatedFiles, {
@required String outputPath,
@required PackageConfig packageConfig,
List<Uri>? invalidatedFiles, {
required String outputPath,
required PackageConfig packageConfig,
bool suppressErrors = false,
String projectRootPath,
FileSystem fs,
String? projectRootPath,
FileSystem? fs,
}) async {
assert(outputPath != null);
if (!_controller.hasListener) {
......@@ -631,14 +629,14 @@ class DefaultResidentCompiler implements ResidentCompiler {
mainUri = generatedMainDart.uri;
}
}
final Completer<CompilerOutput> completer = Completer<CompilerOutput>();
final Completer<CompilerOutput?> completer = Completer<CompilerOutput?>();
_controller.add(
_RecompileRequest(completer, mainUri, invalidatedFiles, outputPath, packageConfig, suppressErrors)
);
return completer.future;
}
Future<CompilerOutput> _recompile(_RecompileRequest request) async {
Future<CompilerOutput?> _recompile(_RecompileRequest request) async {
_stdoutHandler.reset();
_compileRequestNeedsConfirmation = true;
_stdoutHandler._suppressCompilerMessages = request.suppressErrors;
......@@ -646,14 +644,17 @@ class DefaultResidentCompiler implements ResidentCompiler {
final String mainUri = request.packageConfig.toPackageUri(request.mainUri)?.toString() ??
toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots, _platform.isWindows);
if (_server == null) {
final Process? server = _server;
if (server == null) {
return _compile(mainUri, request.outputPath);
}
final String inputKey = Uuid().generateV4();
_server.stdin.writeln('recompile $mainUri $inputKey');
server.stdin.writeln('recompile $mainUri $inputKey');
_logger.printTrace('<- recompile $mainUri $inputKey');
for (final Uri fileUri in request.invalidatedFiles) {
final List<Uri>? invalidatedFiles = request.invalidatedFiles;
if (invalidatedFiles != null) {
for (final Uri fileUri in invalidatedFiles) {
String message;
if (fileUri.scheme == 'package') {
message = fileUri.toString();
......@@ -661,13 +662,14 @@ class DefaultResidentCompiler implements ResidentCompiler {
message = request.packageConfig.toPackageUri(fileUri)?.toString() ??
toMultiRootPath(fileUri, fileSystemScheme, fileSystemRoots, _platform.isWindows);
}
_server.stdin.writeln(message);
server.stdin.writeln(message);
_logger.printTrace(message);
}
_server.stdin.writeln(inputKey);
}
server.stdin.writeln(inputKey);
_logger.printTrace('<- $inputKey');
return _stdoutHandler.compilerOutput.future;
return _stdoutHandler.compilerOutput?.future;
}
final List<_CompilationRequest> _compilationQueue = <_CompilationRequest>[];
......@@ -687,9 +689,9 @@ class DefaultResidentCompiler implements ResidentCompiler {
}
}
Future<CompilerOutput> _compile(
Future<CompilerOutput?> _compile(
String scriptUri,
String outputPath,
String? outputPath,
) async {
final String frontendServer = _artifacts.getArtifactPath(
Artifact.frontendServerSnapshotForEngineDartSdk
......@@ -720,11 +722,11 @@ class DefaultResidentCompiler implements ResidentCompiler {
],
if (librariesSpec != null) ...<String>[
'--libraries-spec',
librariesSpec,
librariesSpec!,
],
if (packagesPath != null) ...<String>[
'--packages',
packagesPath,
packagesPath!,
],
...buildModeOptions(buildMode, dartDefines),
if (trackWidgetCreation) '--track-widget-creation',
......@@ -735,22 +737,22 @@ class DefaultResidentCompiler implements ResidentCompiler {
],
if (fileSystemScheme != null) ...<String>[
'--filesystem-scheme',
fileSystemScheme,
fileSystemScheme!,
],
if (initializeFromDill != null) ...<String>[
'--initialize-from-dill',
initializeFromDill,
initializeFromDill!,
],
if (platformDill != null) ...<String>[
'--platform',
platformDill,
platformDill!,
],
if (unsafePackageSerialization == true) '--unsafe-package-serialization',
...?extraFrontEndOptions,
];
_logger.printTrace(command.join(' '));
_server = await _processManager.start(command);
_server.stdout
_server?.stdout
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter())
.listen(
......@@ -758,76 +760,77 @@ class DefaultResidentCompiler implements ResidentCompiler {
onDone: () {
// when outputFilename future is not completed, but stdout is closed
// process has died unexpectedly.
if (!_stdoutHandler.compilerOutput.isCompleted) {
_stdoutHandler.compilerOutput.complete(null);
if (_stdoutHandler.compilerOutput?.isCompleted == false) {
_stdoutHandler.compilerOutput?.complete(null);
throwToolExit('the Dart compiler exited unexpectedly.');
}
});
_server.stderr
_server?.stderr
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter())
.listen(_logger.printError);
unawaited(_server.exitCode.then((int code) {
unawaited(_server?.exitCode.then((int code) {
if (code != 0) {
throwToolExit('the Dart compiler exited unexpectedly.');
}
}));
_server.stdin.writeln('compile $scriptUri');
_server?.stdin.writeln('compile $scriptUri');
_logger.printTrace('<- compile $scriptUri');
return _stdoutHandler.compilerOutput.future;
return _stdoutHandler.compilerOutput?.future;
}
@override
Future<CompilerOutput> compileExpression(
Future<CompilerOutput?> compileExpression(
String expression,
List<String> definitions,
List<String> typeDefinitions,
String libraryUri,
String klass,
List<String>? definitions,
List<String>? typeDefinitions,
String? libraryUri,
String? klass,
bool isStatic,
) async {
if (!_controller.hasListener) {
_controller.stream.listen(_handleCompilationRequest);
}
final Completer<CompilerOutput> completer = Completer<CompilerOutput>();
final Completer<CompilerOutput?> completer = Completer<CompilerOutput?>();
final _CompileExpressionRequest request = _CompileExpressionRequest(
completer, expression, definitions, typeDefinitions, libraryUri, klass, isStatic);
_controller.add(request);
return completer.future;
}
Future<CompilerOutput> _compileExpression(_CompileExpressionRequest request) async {
Future<CompilerOutput?> _compileExpression(_CompileExpressionRequest request) async {
_stdoutHandler.reset(suppressCompilerMessages: true, expectSources: false, readFile: true);
// 'compile-expression' should be invoked after compiler has been started,
// program was compiled.
if (_server == null) {
final Process? server = _server;
if (server == null) {
return null;
}
final String inputKey = Uuid().generateV4();
_server.stdin
server.stdin
..writeln('compile-expression $inputKey')
..writeln(request.expression);
request.definitions?.forEach(_server.stdin.writeln);
_server.stdin.writeln(inputKey);
request.typeDefinitions?.forEach(_server.stdin.writeln);
_server.stdin
request.definitions?.forEach(server.stdin.writeln);
server.stdin.writeln(inputKey);
request.typeDefinitions?.forEach(server.stdin.writeln);
server.stdin
..writeln(inputKey)
..writeln(request.libraryUri ?? '')
..writeln(request.klass ?? '')
..writeln(request.isStatic ?? false);
..writeln(request.isStatic);
return _stdoutHandler.compilerOutput.future;
return _stdoutHandler.compilerOutput?.future;
}
@override
Future<CompilerOutput> compileExpressionToJs(
Future<CompilerOutput?> compileExpressionToJs(
String libraryUri,
int line,
int column,
......@@ -840,7 +843,7 @@ class DefaultResidentCompiler implements ResidentCompiler {
_controller.stream.listen(_handleCompilationRequest);
}
final Completer<CompilerOutput> completer = Completer<CompilerOutput>();
final Completer<CompilerOutput?> completer = Completer<CompilerOutput?>();
_controller.add(
_CompileExpressionToJsRequest(
completer, libraryUri, line, column, jsModules, jsFrameValues, moduleName, expression)
......@@ -848,85 +851,87 @@ class DefaultResidentCompiler implements ResidentCompiler {
return completer.future;
}
Future<CompilerOutput> _compileExpressionToJs(_CompileExpressionToJsRequest request) async {
Future<CompilerOutput?> _compileExpressionToJs(_CompileExpressionToJsRequest request) async {
_stdoutHandler.reset(suppressCompilerMessages: true, expectSources: false);
// 'compile-expression-to-js' should be invoked after compiler has been started,
// program was compiled.
if (_server == null) {
final Process? server = _server;
if (server == null) {
return null;
}
final String inputKey = Uuid().generateV4();
_server.stdin
server.stdin
..writeln('compile-expression-to-js $inputKey')
..writeln(request.libraryUri ?? '')
..writeln(request.line)
..writeln(request.column);
request.jsModules?.forEach((String k, String v) { _server.stdin.writeln('$k:$v'); });
_server.stdin.writeln(inputKey);
request.jsFrameValues?.forEach((String k, String v) { _server.stdin.writeln('$k:$v'); });
_server.stdin
request.jsModules?.forEach((String k, String v) { server.stdin.writeln('$k:$v'); });
server.stdin.writeln(inputKey);
request.jsFrameValues?.forEach((String k, String v) { server.stdin.writeln('$k:$v'); });
server.stdin
..writeln(inputKey)
..writeln(request.moduleName ?? '')
..writeln(request.expression ?? '');
return _stdoutHandler.compilerOutput.future;
return _stdoutHandler.compilerOutput?.future;
}
@override
void accept() {
if (_compileRequestNeedsConfirmation) {
_server.stdin.writeln('accept');
_server?.stdin.writeln('accept');
_logger.printTrace('<- accept');
}
_compileRequestNeedsConfirmation = false;
}
@override
Future<CompilerOutput> reject() {
Future<CompilerOutput?> reject() {
if (!_controller.hasListener) {
_controller.stream.listen(_handleCompilationRequest);
}
final Completer<CompilerOutput> completer = Completer<CompilerOutput>();
final Completer<CompilerOutput?> completer = Completer<CompilerOutput?>();
_controller.add(_RejectRequest(completer));
return completer.future;
}
Future<CompilerOutput> _reject() {
Future<CompilerOutput?> _reject() async {
if (!_compileRequestNeedsConfirmation) {
return Future<CompilerOutput>.value(null);
return Future<CompilerOutput?>.value(null);
}
_stdoutHandler.reset(expectSources: false);
_server.stdin.writeln('reject');
_server?.stdin.writeln('reject');
_logger.printTrace('<- reject');
_compileRequestNeedsConfirmation = false;
return _stdoutHandler.compilerOutput.future;
return _stdoutHandler.compilerOutput?.future;
}
@override
void reset() {
_server?.stdin?.writeln('reset');
_server?.stdin.writeln('reset');
_logger.printTrace('<- reset');
}
@override
Future<dynamic> shutdown() async {
Future<Object> shutdown() async {
// Server was never successfully created.
if (_server == null) {
final Process? server = _server;
if (server == null) {
return 0;
}
_logger.printTrace('killing pid ${_server.pid}');
_server.kill();
return _server.exitCode;
_logger.printTrace('killing pid ${server.pid}');
server.kill();
return server.exitCode;
}
}
/// Convert a file URI into a multi-root scheme URI if provided, otherwise
/// return unmodified.
@visibleForTesting
String toMultiRootPath(Uri fileUri, String scheme, List<String> fileSystemRoots, bool windows) {
String toMultiRootPath(Uri fileUri, String? scheme, List<String> fileSystemRoots, bool windows) {
if (scheme == null || fileSystemRoots.isEmpty || fileUri.scheme != 'file') {
return fileUri.toString();
}
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'package:file/memory.dart';
......@@ -24,10 +22,10 @@ void main() {
stdoutHandler.reset();
'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0'.split('\n').forEach(stdoutHandler.handler);
final CompilerOutput output = await stdoutHandler.compilerOutput.future;
final CompilerOutput? output = await stdoutHandler.compilerOutput?.future;
expect(logger.errorText, equals('line1\nline2\n'));
expect(output.outputFilename, equals('/path/to/main.dart.dill'));
expect(output?.outputFilename, equals('/path/to/main.dart.dill'));
});
testWithoutContext('StdoutHandler can parse output for failed batch compilation', () async {
......@@ -36,7 +34,7 @@ void main() {
stdoutHandler.reset();
'result abc\nline1\nline2\nabc\nabc'.split('\n').forEach(stdoutHandler.handler);
final CompilerOutput output = await stdoutHandler.compilerOutput.future;
final CompilerOutput? output = await stdoutHandler.compilerOutput?.future;
expect(logger.errorText, equals('line1\nline2\n'));
expect(output, equals(null));
......@@ -73,7 +71,7 @@ void main() {
]),
stdoutHandler: stdoutHandler,
);
final Future<CompilerOutput> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
final Future<CompilerOutput?> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart',
buildMode: BuildMode.debug,
trackWidgetCreation: false,
......@@ -81,10 +79,10 @@ void main() {
packageConfig: PackageConfig.empty,
packagesPath: '.packages',
);
stdoutHandler.compilerOutput.complete(const CompilerOutput('', 0, <Uri>[]));
stdoutHandler.compilerOutput?.complete(const CompilerOutput('', 0, <Uri>[]));
completer.complete();
expect((await output).outputFilename, '');
expect((await output)?.outputFilename, '');
});
testWithoutContext('KernelCompiler returns null if StdoutHandler returns null', () async {
......@@ -118,7 +116,7 @@ void main() {
]),
stdoutHandler: stdoutHandler,
);
final Future<CompilerOutput> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
final Future<CompilerOutput?> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart',
buildMode: BuildMode.debug,
trackWidgetCreation: false,
......@@ -126,7 +124,7 @@ void main() {
packageConfig: PackageConfig.empty,
packagesPath: '.packages',
);
stdoutHandler.compilerOutput.complete(null);
stdoutHandler.compilerOutput?.complete(null);
completer.complete();
expect(await output, null);
......@@ -163,7 +161,7 @@ void main() {
]),
stdoutHandler: stdoutHandler,
);
final Future<CompilerOutput> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
final Future<CompilerOutput?> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart',
buildMode: BuildMode.debug,
trackWidgetCreation: false,
......@@ -171,7 +169,7 @@ void main() {
packageConfig: PackageConfig.empty,
packagesPath: '.packages',
);
stdoutHandler.compilerOutput.complete(const CompilerOutput('', 0, <Uri>[]));
stdoutHandler.compilerOutput?.complete(const CompilerOutput('', 0, <Uri>[]));
completer.complete();
expect(await output, null);
......@@ -209,7 +207,7 @@ void main() {
]),
stdoutHandler: stdoutHandler,
);
final Future<CompilerOutput> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
final Future<CompilerOutput?> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart',
buildMode: BuildMode.profile,
trackWidgetCreation: false,
......@@ -218,10 +216,10 @@ void main() {
packageConfig: PackageConfig.empty,
packagesPath: '.packages',
);
stdoutHandler.compilerOutput.complete(const CompilerOutput('', 0, <Uri>[]));
stdoutHandler.compilerOutput?.complete(const CompilerOutput('', 0, <Uri>[]));
completer.complete();
expect((await output).outputFilename, '');
expect((await output)?.outputFilename, '');
});
testWithoutContext('passes correct AOT config to kernel compiler in aot/release mode', () async {
......@@ -256,7 +254,7 @@ void main() {
]),
stdoutHandler: stdoutHandler,
);
final Future<CompilerOutput> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
final Future<CompilerOutput?> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart',
buildMode: BuildMode.release,
trackWidgetCreation: false,
......@@ -265,10 +263,10 @@ void main() {
packageConfig: PackageConfig.empty,
packagesPath: '.packages',
);
stdoutHandler.compilerOutput.complete(const CompilerOutput('', 0, <Uri>[]));
stdoutHandler.compilerOutput?.complete(const CompilerOutput('', 0, <Uri>[]));
completer.complete();
expect((await output).outputFilename, '');
expect((await output)?.outputFilename, '');
});
testWithoutContext('KernelCompiler passes dartDefines to the frontend_server', () async {
......@@ -305,7 +303,7 @@ void main() {
stdoutHandler: stdoutHandler,
);
final Future<CompilerOutput> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
final Future<CompilerOutput?> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/path/to/main.dart',
buildMode: BuildMode.debug,
trackWidgetCreation: false,
......@@ -314,10 +312,10 @@ void main() {
packagesPath: '.packages',
);
stdoutHandler.compilerOutput.complete(const CompilerOutput('', 0, <Uri>[]));
stdoutHandler.compilerOutput?.complete(const CompilerOutput('', 0, <Uri>[]));
completer.complete();
expect((await output).outputFilename, '');
expect((await output)?.outputFilename, '');
});
testWithoutContext('KernelCompiler maps a file to a multi-root scheme if provided', () async {
......@@ -354,7 +352,7 @@ void main() {
stdoutHandler: stdoutHandler,
);
final Future<CompilerOutput> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
final Future<CompilerOutput?> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/foo/bar/fizz/main.dart',
buildMode: BuildMode.debug,
trackWidgetCreation: false,
......@@ -363,10 +361,10 @@ void main() {
packagesPath: '.packages',
);
stdoutHandler.compilerOutput.complete(const CompilerOutput('', 0, <Uri>[]));
stdoutHandler.compilerOutput?.complete(const CompilerOutput('', 0, <Uri>[]));
completer.complete();
expect((await output).outputFilename, '');
expect((await output)?.outputFilename, '');
});
testWithoutContext('KernelCompiler uses generated entrypoint', () async {
......@@ -409,7 +407,7 @@ void main() {
buildDir.parent.childFile('generated_main.dart').createSync(recursive: true);
final Future<CompilerOutput> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
final Future<CompilerOutput?> output = kernelCompiler.compile(sdkRoot: '/path/to/sdkroot',
mainPath: '/foo/bar/fizz/main.dart',
buildMode: BuildMode.debug,
trackWidgetCreation: false,
......@@ -420,7 +418,7 @@ void main() {
checkDartPluginRegistry: true,
);
stdoutHandler.compilerOutput.complete(const CompilerOutput('', 0, <Uri>[]));
stdoutHandler.compilerOutput?.complete(const CompilerOutput('', 0, <Uri>[]));
completer.complete();
await output;
});
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'package:file/memory.dart';
......@@ -24,12 +22,12 @@ import '../src/fake_process_manager.dart';
import '../src/fakes.dart';
void main() {
FakeProcessManager processManager;
ResidentCompiler generator;
MemoryIOSink frontendServerStdIn;
StreamController<String> stdErrStreamController;
BufferLogger testLogger;
MemoryFileSystem fileSystem;
late FakeProcessManager processManager;
late ResidentCompiler generator;
late MemoryIOSink frontendServerStdIn;
late StreamController<String> stdErrStreamController;
late BufferLogger testLogger;
late MemoryFileSystem fileSystem;
setUp(() {
testLogger = BufferLogger.test();
......@@ -52,7 +50,7 @@ void main() {
});
testWithoutContext('compile expression fails if not previously compiled', () async {
final CompilerOutput result = await generator.compileExpression(
final CompilerOutput? result = await generator.compileExpression(
'2+2', null, null, null, null, false);
expect(result, isNull);
......@@ -82,12 +80,12 @@ void main() {
packageConfig: PackageConfig.empty,
projectRootPath: '',
fs: fileSystem,
).then((CompilerOutput output) {
).then((CompilerOutput? output) {
expect(frontendServerStdIn.getAndClear(),
'compile file:///path/to/main.dart\n');
expect(testLogger.errorText,
equals('line1\nline2\n'));
expect(output.outputFilename, equals('/path/to/main.dart.dill'));
expect(output!.outputFilename, equals('/path/to/main.dart.dill'));
compileExpressionResponseCompleter.complete(
Future<List<int>>.value(utf8.encode(
......@@ -95,9 +93,9 @@ void main() {
)));
generator.compileExpression(
'2+2', null, null, null, null, false).then(
(CompilerOutput outputExpression) {
(CompilerOutput? outputExpression) {
expect(outputExpression, isNotNull);
expect(outputExpression.expressionData, <int>[1, 2, 3, 4]);
expect(outputExpression!.expressionData, <int>[1, 2, 3, 4]);
}
);
});
......@@ -126,10 +124,10 @@ void main() {
packageConfig: PackageConfig.empty,
projectRootPath: '',
fs: MemoryFileSystem(),
).then((CompilerOutput outputCompile) {
).then((CompilerOutput? outputCompile) {
expect(testLogger.errorText,
equals('line1\nline2\n'));
expect(outputCompile.outputFilename, equals('/path/to/main.dart.dill'));
expect(outputCompile!.outputFilename, equals('/path/to/main.dart.dill'));
fileSystem.file('/path/to/main.dart.dill.incremental')
..createSync(recursive: true)
......@@ -144,9 +142,9 @@ void main() {
final Completer<bool> lastExpressionCompleted = Completer<bool>();
unawaited(
generator.compileExpression('0+1', null, null, null, null, false).then(
(CompilerOutput outputExpression) {
(CompilerOutput? outputExpression) {
expect(outputExpression, isNotNull);
expect(outputExpression.expressionData, <int>[0, 1, 2, 3]);
expect(outputExpression!.expressionData, <int>[0, 1, 2, 3]);
fileSystem.file('/path/to/main.dart.dill.incremental')
..createSync(recursive: true)
......@@ -161,9 +159,9 @@ void main() {
// The test manages timing via completers.
unawaited(
generator.compileExpression('1+1', null, null, null, null, false).then(
(CompilerOutput outputExpression) {
(CompilerOutput? outputExpression) {
expect(outputExpression, isNotNull);
expect(outputExpression.expressionData, <int>[4, 5, 6, 7]);
expect(outputExpression!.expressionData, <int>[4, 5, 6, 7]);
lastExpressionCompleted.complete(true);
},
),
......@@ -179,13 +177,13 @@ void main() {
class FakeProcess extends Fake implements Process {
@override
Stream<List<int>> stdout;
Stream<List<int>> stdout = const Stream<List<int>>.empty();
@override
Stream<List<int>> stderr;
Stream<List<int>> stderr = const Stream<List<int>>.empty();
@override
IOSink stdin;
IOSink stdin = IOSink(StreamController<List<int>>().sink);
@override
Future<int> get exitCode => Completer<int>().future;
......@@ -195,12 +193,12 @@ class FakeProcessManager extends Fake implements ProcessManager {
final FakeProcess process = FakeProcess();
@override
bool canRun(dynamic executable, {String workingDirectory}) {
bool canRun(dynamic executable, {String? workingDirectory}) {
return true;
}
@override
Future<Process> start(List<Object> command, {String workingDirectory, Map<String, String> environment, bool includeParentEnvironment = true, bool runInShell = false, ProcessStartMode mode = ProcessStartMode.normal}) async {
Future<Process> start(List<Object> command, {String? workingDirectory, Map<String, String>? environment, bool includeParentEnvironment = true, bool runInShell = false, ProcessStartMode mode = ProcessStartMode.normal}) async {
return process;
}
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'package:file/memory.dart';
......@@ -21,13 +19,13 @@ import '../src/fake_process_manager.dart';
import '../src/fakes.dart';
void main() {
ResidentCompiler generator;
ResidentCompiler generatorWithScheme;
MemoryIOSink frontendServerStdIn;
BufferLogger testLogger;
StdoutHandler generatorStdoutHandler;
StdoutHandler generatorWithSchemeStdoutHandler;
FakeProcessManager fakeProcessManager;
late ResidentCompiler generator;
late ResidentCompiler generatorWithScheme;
late MemoryIOSink frontendServerStdIn;
late BufferLogger testLogger;
late StdoutHandler generatorStdoutHandler;
late StdoutHandler generatorWithSchemeStdoutHandler;
late FakeProcessManager fakeProcessManager;
const List<String> frontendServerCommand = <String>[
'HostArtifact.engineDartBinary',
......@@ -87,7 +85,7 @@ void main() {
stdin: frontendServerStdIn,
));
final CompilerOutput output = await generator.recompile(
final CompilerOutput? output = await generator.recompile(
Uri.parse('/path/to/main.dart'),
null /* invalidatedFiles */,
outputPath: '/build/',
......@@ -97,7 +95,7 @@ void main() {
);
expect(frontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
expect(testLogger.errorText, equals('line1\nline2\n'));
expect(output.outputFilename, equals('/path/to/main.dart.dill'));
expect(output?.outputFilename, equals('/path/to/main.dart.dill'));
expect(fakeProcessManager, hasNoRemainingExpectations);
});
......@@ -114,7 +112,7 @@ void main() {
stdin: frontendServerStdIn,
));
final CompilerOutput output = await generatorWithScheme.recompile(
final CompilerOutput? output = await generatorWithScheme.recompile(
Uri.parse('file:///foo/bar/fizz/main.dart'),
null /* invalidatedFiles */,
outputPath: '/build/',
......@@ -124,7 +122,7 @@ void main() {
);
expect(frontendServerStdIn.getAndClear(), 'compile scheme:///main.dart\n');
expect(testLogger.errorText, equals('line1\nline2\n'));
expect(output.outputFilename, equals('/path/to/main.dart.dill'));
expect(output?.outputFilename, equals('/path/to/main.dart.dill'));
expect(fakeProcessManager, hasNoRemainingExpectations);
});
......@@ -401,16 +399,16 @@ Future<void> _recompile(
MemoryIOSink frontendServerStdIn,
String mockCompilerOutput, {
bool suppressErrors = false,
Uri mainUri,
Uri? mainUri,
String expectedMainUri = '/path/to/main.dart',
List<Uri> updatedUris,
List<String> expectedUpdatedUris,
List<Uri>? updatedUris,
List<String>? expectedUpdatedUris,
}) async {
mainUri ??= Uri.parse('/path/to/main.dart');
updatedUris ??= <Uri>[mainUri];
expectedUpdatedUris ??= <String>[expectedMainUri];
final Future<CompilerOutput> recompileFuture = generator.recompile(
final Future<CompilerOutput?> recompileFuture = generator.recompile(
mainUri,
updatedUris,
outputPath: '/build/',
......@@ -425,8 +423,8 @@ Future<void> _recompile(
scheduleMicrotask(() {
LineSplitter.split(mockCompilerOutput).forEach(stdoutHandler.handler);
});
final CompilerOutput output = await recompileFuture;
expect(output.outputFilename, equals('/path/to/main.dart.dill'));
final CompilerOutput? output = await recompileFuture;
expect(output?.outputFilename, equals('/path/to/main.dart.dill'));
final String commands = frontendServerStdIn.getAndClear();
final RegExp whitespace = RegExp(r'\s+');
final List<String> parts = commands.split(whitespace);
......@@ -459,11 +457,11 @@ Future<void> _reject(
) async {
// Put content into the output stream after generator.recompile gets
// going few lines below, resets completer.
final Future<CompilerOutput> rejectFuture = generator.reject();
final Future<CompilerOutput?> rejectFuture = generator.reject();
scheduleMicrotask(() {
LineSplitter.split(mockCompilerOutput).forEach(stdoutHandler.handler);
});
final CompilerOutput output = await rejectFuture;
final CompilerOutput? output = await rejectFuture;
expect(output, isNull);
final String commands = frontendServerStdIn.getAndClear();
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/logger.dart';
......@@ -19,10 +17,10 @@ void main() {
expect(stdoutHandler.boundaryKey, '12345');
stdoutHandler.handler('12345');
stdoutHandler.handler('12345 message 0');
final CompilerOutput output = await stdoutHandler.compilerOutput.future;
expect(output.errorCount, 0);
expect(output.outputFilename, 'message');
expect(output.expressionData, null);
final CompilerOutput? output = await stdoutHandler.compilerOutput?.future;
expect(output?.errorCount, 0);
expect(output?.outputFilename, 'message');
expect(output?.expressionData, null);
});
testWithoutContext('StdoutHandler can read output bytes', () async {
......@@ -35,11 +33,11 @@ void main() {
expect(stdoutHandler.boundaryKey, '12345');
stdoutHandler.handler('12345');
stdoutHandler.handler('12345 message 0');
final CompilerOutput output = await stdoutHandler.compilerOutput.future;
final CompilerOutput? output = await stdoutHandler.compilerOutput?.future;
expect(output.errorCount, 0);
expect(output.outputFilename, 'message');
expect(output.expressionData, <int>[1, 2, 3, 4]);
expect(output?.errorCount, 0);
expect(output?.outputFilename, 'message');
expect(output?.expressionData, <int>[1, 2, 3, 4]);
});
testWithoutContext('StdoutHandler reads output bytes if errorCount > 0', () async {
......@@ -52,11 +50,11 @@ void main() {
expect(stdoutHandler.boundaryKey, '12345');
stdoutHandler.handler('12345');
stdoutHandler.handler('12345 message 1');
final CompilerOutput output = await stdoutHandler.compilerOutput.future;
final CompilerOutput? output = await stdoutHandler.compilerOutput?.future;
expect(output.errorCount, 1);
expect(output.outputFilename, 'message');
expect(output.expressionData, <int>[1, 2, 3, 4]);
expect(output?.errorCount, 1);
expect(output?.outputFilename, 'message');
expect(output?.expressionData, <int>[1, 2, 3, 4]);
});
testWithoutContext('TargetModel values', () {
......@@ -72,7 +70,7 @@ void main() {
expect(TargetModel('dartdevc'), TargetModel.dartdevc);
expect(TargetModel.dartdevc.toString(), 'dartdevc');
expect(() => TargetModel('foobar'), throwsAssertionError);
expect(() => TargetModel('foobar'), throwsException);
});
testWithoutContext('toMultiRootPath maps different URIs', () async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment