[flutter_tool] partial null safety migration of tool source code (#105798)

This commit is contained in:
Jonah Williams 2022-06-15 13:02:07 -07:00 committed by GitHub
parent a7ddb9b64e
commit 92034482f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 1932 additions and 2025 deletions

View File

@ -339,6 +339,7 @@ Future<void> _runGeneralToolTests() async {
_toolsPath,
testPaths: <String>[path.join('test', 'general.shard')],
enableFlutterToolAsserts: false,
// Detect unit test time regressions (poor time delay handling, etc).
// This overrides the 15 minute default for tools tests.
// See the README.md and dart_test.yaml files in the flutter_tools package.

View File

@ -2,10 +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:meta/meta.dart';
import 'runner.dart' as runner;
import 'src/artifacts.dart';
import 'src/base/context.dart';
@ -110,7 +106,7 @@ Future<void> main(List<String> args) async {
// devtools source code.
DevtoolsLauncher: () => DevtoolsServerLauncher(
processManager: globals.processManager,
dartExecutable: globals.artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
dartExecutable: globals.artifacts!.getHostArtifact(HostArtifact.engineDartBinary).path,
logger: globals.logger,
botDetector: globals.botDetector,
),
@ -134,8 +130,8 @@ Future<void> main(List<String> args) async {
}
List<FlutterCommand> generateCommands({
@required bool verboseHelp,
@required bool verbose,
required bool verboseHelp,
required bool verbose,
}) => <FlutterCommand>[
AnalyzeCommand(
verboseHelp: verboseHelp,
@ -144,7 +140,7 @@ List<FlutterCommand> generateCommands({
processManager: globals.processManager,
logger: globals.logger,
terminal: globals.terminal,
artifacts: globals.artifacts,
artifacts: globals.artifacts!,
),
AssembleCommand(verboseHelp: verboseHelp, buildSystem: globals.buildSystem),
AttachCommand(verboseHelp: verboseHelp),
@ -210,9 +206,9 @@ List<FlutterCommand> generateCommands({
/// Our logger class hierarchy and runtime requirements are overly complicated.
class LoggerFactory {
LoggerFactory({
@required Terminal terminal,
@required Stdio stdio,
@required OutputPreferences outputPreferences,
required Terminal terminal,
required Stdio stdio,
required OutputPreferences outputPreferences,
StopwatchFactory stopwatchFactory = const StopwatchFactory(),
}) : _terminal = terminal,
_stdio = stdio,
@ -226,11 +222,11 @@ class LoggerFactory {
/// Create the appropriate logger for the current platform and configuration.
Logger createLogger({
@required bool verbose,
@required bool prefixedErrors,
@required bool machine,
@required bool daemon,
@required bool windows,
required bool verbose,
required bool prefixedErrors,
required bool machine,
required bool daemon,
required bool windows,
}) {
Logger logger;
if (windows) {

View File

@ -2,7 +2,7 @@
// 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';
@ -31,9 +31,9 @@ Future<int> run(
bool muteCommandLogging = false,
bool verbose = false,
bool verboseHelp = false,
bool reportCrashes,
String flutterVersion,
Map<Type, Generator> overrides,
bool? reportCrashes,
String? flutterVersion,
Map<Type, Generator>? overrides,
}) async {
if (muteCommandLogging) {
// Remove the verbose option; for help and doctor, users don't need to see
@ -55,8 +55,8 @@ Future<int> run(
);
String getVersion() => flutterVersion ?? globals.flutterVersion.getVersionString(redactUnknownBranches: true);
Object firstError;
StackTrace firstStackTrace;
Object? firstError;
StackTrace? firstStackTrace;
return runZoned<Future<int>>(() async {
try {
await runner.run(args);
@ -74,7 +74,7 @@ Future<int> run(
// This catches all exceptions to send to crash logging, etc.
firstError = error;
firstStackTrace = stackTrace;
return _handleToolError(error, stackTrace, verbose, args, reportCrashes, getVersion);
return _handleToolError(error, stackTrace, verbose, args, reportCrashes!, getVersion);
}
}, onError: (Object error, StackTrace stackTrace) async { // ignore: deprecated_member_use
// If sending a crash report throws an error into the zone, we don't want
@ -82,14 +82,14 @@ Future<int> run(
// to send the original error that triggered the crash report.
firstError ??= error;
firstStackTrace ??= stackTrace;
await _handleToolError(firstError, firstStackTrace, verbose, args, reportCrashes, getVersion);
await _handleToolError(firstError!, firstStackTrace, verbose, args, reportCrashes!, getVersion);
});
}, overrides: overrides);
}
Future<int> _handleToolError(
dynamic error,
StackTrace stackTrace,
Object error,
StackTrace? stackTrace,
bool verbose,
List<String> args,
bool reportCrashes,
@ -102,7 +102,7 @@ Future<int> _handleToolError(
return _exit(64);
} else if (error is ToolExit) {
if (error.message != null) {
globals.printError(error.message);
globals.printError(error.message!);
}
if (verbose) {
globals.printError('\n$stackTrace\n');
@ -138,7 +138,7 @@ Future<int> _handleToolError(
);
await crashReportSender.sendReport(
error: error,
stackTrace: stackTrace,
stackTrace: stackTrace!,
getFlutterVersion: getFlutterVersion,
command: args.join(' '),
);
@ -159,17 +159,17 @@ Future<int> _handleToolError(
final CrashDetails details = CrashDetails(
command: _crashCommand(args),
error: error,
stackTrace: stackTrace,
stackTrace: stackTrace!,
doctorText: doctorText,
);
final File file = await _createLocalCrashReport(details);
await globals.crashReporter.informUser(details, file);
await globals.crashReporter!.informUser(details, file);
return _exit(1);
// This catch catches all exceptions to ensure the message below is printed.
} catch (error) { // ignore: avoid_catches_without_on_clauses
} catch (error, st) { // ignore: avoid_catches_without_on_clauses
globals.stdio.stderrWrite(
'Unable to generate crash report due to secondary error: $error\n'
'Unable to generate crash report due to secondary error: $error\n$st\n'
'${globals.userMessages.flutterToolBugInstructions}\n',
);
// Any exception thrown here (including one thrown by `_exit()`) will
@ -241,7 +241,7 @@ Future<int> _exit(int code) async {
}
// Run shutdown hooks before flushing logs
await globals.shutdownHooks.runShutdownHooks();
await globals.shutdownHooks!.runShutdownHooks();
final Completer<void> completer = Completer<void>();

View File

@ -271,7 +271,7 @@ class AndroidValidator extends DoctorValidator {
/// SDK have been accepted.
class AndroidLicenseValidator extends DoctorValidator {
AndroidLicenseValidator({
required AndroidSdk androidSdk,
required AndroidSdk? androidSdk,
required Platform platform,
required OperatingSystemUtils operatingSystemUtils,
required FileSystem fileSystem,
@ -291,7 +291,7 @@ class AndroidLicenseValidator extends DoctorValidator {
_userMessages = userMessages,
super('Android license subvalidator');
final AndroidSdk _androidSdk;
final AndroidSdk? _androidSdk;
final AndroidStudio? _androidStudio;
final Stdio _stdio;
final OperatingSystemUtils _operatingSystemUtils;
@ -309,13 +309,13 @@ class AndroidLicenseValidator extends DoctorValidator {
final List<ValidationMessage> messages = <ValidationMessage>[];
// Match pre-existing early termination behavior
if (_androidSdk == null || _androidSdk.latestVersion == null ||
_androidSdk.validateSdkWellFormed().isNotEmpty ||
if (_androidSdk == null || _androidSdk?.latestVersion == null ||
_androidSdk!.validateSdkWellFormed().isNotEmpty ||
! await _checkJavaVersionNoOutput()) {
return ValidationResult(ValidationType.missing, messages);
}
final String sdkVersionText = _userMessages.androidStatusInfo(_androidSdk.latestVersion!.buildToolsVersionName);
final String sdkVersionText = _userMessages.androidStatusInfo(_androidSdk!.latestVersion!.buildToolsVersionName);
// Check for licenses.
switch (await licensesAccepted) {
@ -392,8 +392,8 @@ class AndroidLicenseValidator extends DoctorValidator {
try {
final Process process = await _processManager.start(
<String>[_androidSdk.sdkManagerPath!, '--licenses'],
environment: _androidSdk.sdkManagerEnv,
<String>[_androidSdk!.sdkManagerPath!, '--licenses'],
environment: _androidSdk!.sdkManagerEnv,
);
process.stdin.write('n\n');
// We expect logcat streams to occasionally contain invalid utf-8,
@ -432,8 +432,8 @@ class AndroidLicenseValidator extends DoctorValidator {
try {
final Process process = await _processManager.start(
<String>[_androidSdk.sdkManagerPath!, '--licenses'],
environment: _androidSdk.sdkManagerEnv,
<String>[_androidSdk!.sdkManagerPath!, '--licenses'],
environment: _androidSdk!.sdkManagerEnv,
);
// The real stdin will never finish streaming. Pipe until the child process
@ -463,7 +463,7 @@ class AndroidLicenseValidator extends DoctorValidator {
return exitCode == 0;
} on ProcessException catch (e) {
throwToolExit(_userMessages.androidCannotRunSdkManager(
_androidSdk.sdkManagerPath ?? '',
_androidSdk?.sdkManagerPath ?? '',
e.toString(),
_platform,
));
@ -471,7 +471,7 @@ class AndroidLicenseValidator extends DoctorValidator {
}
bool _canRunSdkManager() {
final String? sdkManagerPath = _androidSdk.sdkManagerPath;
final String? sdkManagerPath = _androidSdk?.sdkManagerPath;
if (sdkManagerPath == null) {
return false;
}

View File

@ -97,7 +97,7 @@ class AndroidApk extends ApplicationPackage implements PrebuiltApplicationPackag
/// Creates a new AndroidApk based on the information in the Android manifest.
static Future<AndroidApk?> fromAndroidProject(
AndroidProject androidProject, {
required AndroidSdk androidSdk,
required AndroidSdk? androidSdk,
required ProcessManager processManager,
required UserMessages userMessages,
required ProcessUtils processUtils,
@ -113,7 +113,7 @@ class AndroidApk extends ApplicationPackage implements PrebuiltApplicationPackag
// the application Id, so we need to look at what was actually built.
return AndroidApk.fromApk(
apkFile,
androidSdk: androidSdk,
androidSdk: androidSdk!,
processManager: processManager,
logger: logger,
userMessages: userMessages,

View File

@ -157,9 +157,9 @@ class SettingsFile {
/// Given a data structure which is a Map of String to dynamic values, return
/// the same structure (`Map<String, dynamic>`) with the correct runtime types.
Map<String, dynamic>? castStringKeyedMap(dynamic untyped) {
Map<String, Object?>? castStringKeyedMap(Object? untyped) {
final Map<dynamic, dynamic>? map = untyped as Map<dynamic, dynamic>?;
return map?.cast<String, dynamic>();
return map?.cast<String, Object?>();
}
/// Smallest column that will be used for text wrapping. If the requested column

View File

@ -2,11 +2,8 @@
// 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:meta/meta.dart';
import 'package:vm_service/vm_service.dart';
import '../android/android_device.dart';
@ -123,7 +120,7 @@ class AttachCommand extends FlutterCommand {
hotRunnerFactory ??= HotRunnerFactory();
}
HotRunnerFactory hotRunnerFactory;
HotRunnerFactory? hotRunnerFactory;
@override
final String name = 'attach';
@ -148,22 +145,22 @@ known, it can be explicitly provided to attach via the command-line, e.g.
@override
final String category = FlutterCommandCategory.tools;
int get debugPort {
if (argResults['debug-port'] == null) {
int? get debugPort {
if (argResults!['debug-port'] == null) {
return null;
}
try {
return int.parse(stringArgDeprecated('debug-port'));
return int.parse(stringArgDeprecated('debug-port')!);
} on Exception catch (error) {
throwToolExit('Invalid port for `--debug-port`: $error');
}
}
Uri get debugUri {
if (argResults['debug-url'] == null) {
Uri? get debugUri {
if (argResults!['debug-url'] == null) {
return null;
}
final Uri uri = Uri.tryParse(stringArgDeprecated('debug-url'));
final Uri? uri = Uri.tryParse(stringArgDeprecated('debug-url')!);
if (uri == null) {
throwToolExit('Invalid `--debug-url`: ${stringArgDeprecated('debug-url')}');
}
@ -173,11 +170,11 @@ known, it can be explicitly provided to attach via the command-line, e.g.
return uri;
}
String get appId {
String? get appId {
return stringArgDeprecated('app-id');
}
String get userIdentifier => stringArgDeprecated(FlutterOptions.kDeviceUser);
String? get userIdentifier => stringArgDeprecated(FlutterOptions.kDeviceUser);
@override
Future<void> validateCommand() async {
@ -189,13 +186,13 @@ known, it can be explicitly provided to attach via the command-line, e.g.
throwToolExit(null);
}
debugPort;
if (debugPort == null && debugUri == null && argResults.wasParsed(FlutterCommand.ipv6Flag)) {
if (debugPort == null && debugUri == null && argResults!.wasParsed(FlutterCommand.ipv6Flag)) {
throwToolExit(
'When the --debug-port or --debug-url is unknown, this command determines '
'the value of --ipv6 on its own.',
);
}
if (debugPort == null && debugUri == null && argResults.wasParsed(FlutterCommand.observatoryPortOption)) {
if (debugPort == null && debugUri == null && argResults!.wasParsed(FlutterCommand.observatoryPortOption)) {
throwToolExit(
'When the --debug-port or --debug-url is unknown, this command does not use '
'the value of --observatory-port.',
@ -207,7 +204,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
}
if (userIdentifier != null) {
final Device device = await findTargetDevice();
final Device? device = await findTargetDevice();
if (device is! AndroidDevice) {
throwToolExit('--${FlutterOptions.kDeviceUser} is only supported for Android');
}
@ -218,9 +215,9 @@ known, it can be explicitly provided to attach via the command-line, e.g.
Future<FlutterCommandResult> runCommand() async {
await _validateArguments();
final Device device = await findTargetDevice();
final Device device = await (findTargetDevice() as FutureOr<Device>);
final Artifacts overrideArtifacts = device.artifactOverrides ?? globals.artifacts;
final Artifacts? overrideArtifacts = device.artifactOverrides ?? globals.artifacts;
await context.run<void>(
body: () => _attachToDevice(device),
overrides: <Type, Generator>{
@ -234,7 +231,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
Future<void> _attachToDevice(Device device) async {
final FlutterProject flutterProject = FlutterProject.current();
final Daemon daemon = boolArgDeprecated('machine')
final Daemon? daemon = boolArgDeprecated('machine')
? Daemon(
DaemonConnection(
daemonStreams: DaemonStreams.fromStdio(globals.stdio, logger: globals.logger),
@ -247,20 +244,20 @@ known, it can be explicitly provided to attach via the command-line, e.g.
)
: null;
Stream<Uri> observatoryUri;
bool usesIpv6 = ipv6;
Stream<Uri>? observatoryUri;
bool usesIpv6 = ipv6!;
final String ipv6Loopback = InternetAddress.loopbackIPv6.address;
final String ipv4Loopback = InternetAddress.loopbackIPv4.address;
final String hostname = usesIpv6 ? ipv6Loopback : ipv4Loopback;
if (debugPort == null && debugUri == null) {
if (device is FuchsiaDevice) {
final String module = stringArgDeprecated('module');
final String module = stringArgDeprecated('module')!;
if (module == null) {
throwToolExit("'--module' is required for attaching to a Fuchsia device");
}
usesIpv6 = device.ipv6;
FuchsiaIsolateDiscoveryProtocol isolateDiscoveryProtocol;
FuchsiaIsolateDiscoveryProtocol? isolateDiscoveryProtocol;
try {
isolateDiscoveryProtocol = device.getIsolateDiscoveryProtocol(module);
observatoryUri = Stream<Uri>.value(await isolateDiscoveryProtocol.uri).asBroadcastStream();
@ -273,9 +270,9 @@ known, it can be explicitly provided to attach via the command-line, e.g.
rethrow;
}
} else if ((device is IOSDevice) || (device is IOSSimulator) || (device is MacOSDesignedForIPadDevice)) {
final Uri uriFromMdns =
await MDnsObservatoryDiscovery.instance.getObservatoryUri(
appId,
final Uri? uriFromMdns =
await MDnsObservatoryDiscovery.instance!.getObservatoryUri(
appId!,
device,
usesIpv6: usesIpv6,
deviceVmservicePort: deviceVmservicePort,
@ -292,7 +289,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
// to find the service protocol.
await device.getLogReader(includePastLogs: device is AndroidDevice),
portForwarder: device.portForwarder,
ipv6: ipv6,
ipv6: ipv6!,
devicePort: deviceVmservicePort,
hostPort: hostVmservicePort,
logger: globals.logger,
@ -308,7 +305,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
buildObservatoryUri(
device,
debugUri?.host ?? hostname,
debugPort ?? debugUri.port,
debugPort ?? debugUri!.port,
hostVmservicePort,
debugUri?.path,
)
@ -318,20 +315,20 @@ known, it can be explicitly provided to attach via the command-line, e.g.
globals.terminal.usesTerminalUi = daemon == null;
try {
int result;
int? result;
if (daemon != null) {
final ResidentRunner runner = await createResidentRunner(
final ResidentRunner runner = await (createResidentRunner(
observatoryUris: observatoryUri,
device: device,
flutterProject: flutterProject,
usesIpv6: usesIpv6,
);
AppInstance app;
) as FutureOr<ResidentRunner>);
late AppInstance app;
try {
app = await daemon.appDomain.launch(
runner,
({Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<void> appStartedCompleter}) {
({Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter}) {
return runner.attach(
connectionInfoCompleter: connectionInfoCompleter,
appStartedCompleter: appStartedCompleter,
@ -349,19 +346,19 @@ known, it can be explicitly provided to attach via the command-line, e.g.
} on Exception catch (error) {
throwToolExit(error.toString());
}
result = await app.runner.waitForAppToFinish();
result = await app.runner!.waitForAppToFinish();
assert(result != null);
return;
}
while (true) {
final ResidentRunner runner = await createResidentRunner(
final ResidentRunner runner = await (createResidentRunner(
observatoryUris: observatoryUri,
device: device,
flutterProject: flutterProject,
usesIpv6: usesIpv6,
);
) as FutureOr<ResidentRunner>);
final Completer<void> onAppStart = Completer<void>.sync();
TerminalHandler terminalHandler;
TerminalHandler? terminalHandler;
unawaited(onAppStart.future.whenComplete(() {
terminalHandler = TerminalHandler(
runner,
@ -396,18 +393,18 @@ known, it can be explicitly provided to attach via the command-line, e.g.
}
rethrow;
} finally {
final List<ForwardedPort> ports = device.portForwarder.forwardedPorts.toList();
final List<ForwardedPort> ports = device.portForwarder!.forwardedPorts.toList();
for (final ForwardedPort port in ports) {
await device.portForwarder.unforward(port);
await device.portForwarder!.unforward(port);
}
}
}
Future<ResidentRunner> createResidentRunner({
@required Stream<Uri> observatoryUris,
@required Device device,
@required FlutterProject flutterProject,
@required bool usesIpv6,
Future<ResidentRunner?> createResidentRunner({
required Stream<Uri> observatoryUris,
required Device device,
required FlutterProject flutterProject,
required bool usesIpv6,
}) async {
assert(observatoryUris != null);
assert(device != null);
@ -418,7 +415,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
final FlutterDevice flutterDevice = await FlutterDevice.create(
device,
target: targetFile,
targetModel: TargetModel(stringArgDeprecated('target-model')),
targetModel: TargetModel(stringArgDeprecated('target-model')!),
buildInfo: buildInfo,
userIdentifier: userIdentifier,
platform: globals.platform,
@ -433,11 +430,11 @@ known, it can be explicitly provided to attach via the command-line, e.g.
);
return buildInfo.isDebug
? hotRunnerFactory.build(
? hotRunnerFactory!.build(
flutterDevices,
target: targetFile,
debuggingOptions: debuggingOptions,
packagesFilePath: globalResults['packages'] as String,
packagesFilePath: globalResults!['packages'] as String?,
projectRootPath: stringArgDeprecated('project-root'),
dillOutputPath: stringArgDeprecated('output-dill'),
ipv6: usesIpv6,
@ -455,19 +452,19 @@ known, it can be explicitly provided to attach via the command-line, e.g.
}
class HotRunnerFactory {
HotRunner build(
HotRunner? build(
List<FlutterDevice> devices, {
String target,
DebuggingOptions debuggingOptions,
required String target,
required DebuggingOptions debuggingOptions,
bool benchmarkMode = false,
File applicationBinary,
File? applicationBinary,
bool hostIsIde = false,
String projectRootPath,
String packagesFilePath,
String dillOutputPath,
String? projectRootPath,
String? packagesFilePath,
String? dillOutputPath,
bool stayResident = true,
bool ipv6 = false,
FlutterProject flutterProject,
FlutterProject? flutterProject,
}) => HotRunner(
devices,
target: target,

View File

@ -2,7 +2,7 @@
// 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';
@ -32,14 +32,14 @@ typedef PrintFn = void Function(Object);
class CustomDevicesCommand extends FlutterCommand {
factory CustomDevicesCommand({
@required CustomDevicesConfig customDevicesConfig,
@required OperatingSystemUtils operatingSystemUtils,
@required Terminal terminal,
@required Platform platform,
@required ProcessManager processManager,
@required FileSystem fileSystem,
@required Logger logger,
@required FeatureFlags featureFlags,
required CustomDevicesConfig customDevicesConfig,
required OperatingSystemUtils operatingSystemUtils,
required Terminal terminal,
required Platform platform,
required ProcessManager processManager,
required FileSystem fileSystem,
required Logger logger,
required FeatureFlags featureFlags,
}) {
return CustomDevicesCommand._common(
customDevicesConfig: customDevicesConfig,
@ -55,14 +55,14 @@ class CustomDevicesCommand extends FlutterCommand {
@visibleForTesting
factory CustomDevicesCommand.test({
@required CustomDevicesConfig customDevicesConfig,
@required OperatingSystemUtils operatingSystemUtils,
@required Terminal terminal,
@required Platform platform,
@required ProcessManager processManager,
@required FileSystem fileSystem,
@required Logger logger,
@required FeatureFlags featureFlags,
required CustomDevicesConfig customDevicesConfig,
required OperatingSystemUtils operatingSystemUtils,
required Terminal terminal,
required Platform platform,
required ProcessManager processManager,
required FileSystem fileSystem,
required Logger logger,
required FeatureFlags featureFlags,
PrintFn usagePrintFn = print
}) {
return CustomDevicesCommand._common(
@ -79,14 +79,14 @@ class CustomDevicesCommand extends FlutterCommand {
}
CustomDevicesCommand._common({
@required CustomDevicesConfig customDevicesConfig,
@required OperatingSystemUtils operatingSystemUtils,
@required Terminal terminal,
@required Platform platform,
@required ProcessManager processManager,
@required FileSystem fileSystem,
@required Logger logger,
@required FeatureFlags featureFlags,
required CustomDevicesConfig customDevicesConfig,
required OperatingSystemUtils operatingSystemUtils,
required Terminal terminal,
required Platform platform,
required ProcessManager processManager,
required FileSystem fileSystem,
required Logger logger,
required FeatureFlags featureFlags,
PrintFn usagePrintFn = print,
}) : assert(customDevicesConfig != null),
assert(operatingSystemUtils != null),
@ -162,7 +162,9 @@ Requires the custom devices feature to be enabled. You can enable it using "flut
String get category => FlutterCommandCategory.tools;
@override
Future<FlutterCommandResult> runCommand() async => null;
Future<FlutterCommandResult> runCommand() async {
return FlutterCommandResult.success();
}
@override
void printUsage() {
@ -175,15 +177,15 @@ Requires the custom devices feature to be enabled. You can enable it using "flut
/// feature is enabled.
abstract class CustomDevicesCommandBase extends FlutterCommand {
CustomDevicesCommandBase({
@required this.customDevicesConfig,
@required this.featureFlags,
@required this.fileSystem,
@required this.logger,
required this.customDevicesConfig,
required this.featureFlags,
required this.fileSystem,
required this.logger,
});
@protected final CustomDevicesConfig customDevicesConfig;
@protected final FeatureFlags featureFlags;
@protected final FileSystem fileSystem;
@protected final FileSystem? fileSystem;
@protected final Logger logger;
/// The path to the (potentially non-existing) backup of the config file.
@ -195,7 +197,7 @@ abstract class CustomDevicesCommandBase extends FlutterCommand {
/// doesn't exist. (True otherwise)
@protected
bool backup() {
final File configFile = fileSystem.file(customDevicesConfig.configPath);
final File configFile = fileSystem!.file(customDevicesConfig.configPath);
if (configFile.existsSync()) {
configFile.copySync(configBackupPath);
return true;
@ -219,14 +221,11 @@ abstract class CustomDevicesCommandBase extends FlutterCommand {
class CustomDevicesListCommand extends CustomDevicesCommandBase {
CustomDevicesListCommand({
@required CustomDevicesConfig customDevicesConfig,
@required FeatureFlags featureFlags,
@required Logger logger,
required super.customDevicesConfig,
required super.featureFlags,
required super.logger,
}) : super(
customDevicesConfig: customDevicesConfig,
featureFlags: featureFlags,
fileSystem: null,
logger: logger
fileSystem: null
);
@override
@ -241,7 +240,7 @@ List the currently configured custom devices, both enabled and disabled, reachab
Future<FlutterCommandResult> runCommand() async {
checkFeatureEnabled();
List<CustomDeviceConfig> devices;
late List<CustomDeviceConfig> devices;
try {
devices = customDevicesConfig.devices;
} on Exception {
@ -263,16 +262,11 @@ List the currently configured custom devices, both enabled and disabled, reachab
class CustomDevicesResetCommand extends CustomDevicesCommandBase {
CustomDevicesResetCommand({
@required CustomDevicesConfig customDevicesConfig,
@required FeatureFlags featureFlags,
@required FileSystem fileSystem,
@required Logger logger,
}) : super(
customDevicesConfig: customDevicesConfig,
featureFlags: featureFlags,
fileSystem: fileSystem,
logger: logger
);
required super.customDevicesConfig,
required super.featureFlags,
required FileSystem super.fileSystem,
required super.logger,
});
@override
String get description => '''
@ -291,7 +285,7 @@ If a file already exists at the backup location, it will be overwritten.
final bool wasBackedUp = backup();
ErrorHandlingFileSystem.deleteIfExists(fileSystem.file(customDevicesConfig.configPath));
ErrorHandlingFileSystem.deleteIfExists(fileSystem!.file(customDevicesConfig.configPath));
customDevicesConfig.ensureFileExists();
logger.printStatus(
@ -306,24 +300,18 @@ If a file already exists at the backup location, it will be overwritten.
class CustomDevicesAddCommand extends CustomDevicesCommandBase {
CustomDevicesAddCommand({
@required CustomDevicesConfig customDevicesConfig,
@required OperatingSystemUtils operatingSystemUtils,
@required Terminal terminal,
@required Platform platform,
@required FeatureFlags featureFlags,
@required ProcessManager processManager,
@required FileSystem fileSystem,
@required Logger logger,
required super.customDevicesConfig,
required OperatingSystemUtils operatingSystemUtils,
required Terminal terminal,
required Platform platform,
required super.featureFlags,
required ProcessManager processManager,
required FileSystem super.fileSystem,
required super.logger,
}) : _operatingSystemUtils = operatingSystemUtils,
_terminal = terminal,
_platform = platform,
_processManager = processManager,
super(
customDevicesConfig: customDevicesConfig,
featureFlags: featureFlags,
fileSystem: fileSystem,
logger: logger
)
_processManager = processManager
{
argParser.addFlag(
_kCheck,
@ -379,7 +367,7 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
final Terminal _terminal;
final Platform _platform;
final ProcessManager _processManager;
StreamQueue<String> inputs;
late StreamQueue<String> inputs;
@override
String get description => 'Add a new device the custom devices config file.';
@ -413,7 +401,7 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
result = false;
}
final Directory temp = await fileSystem.systemTempDirectory.createTemp();
final Directory temp = await fileSystem!.systemTempDirectory.createTemp();
try {
final bool ok = await device.tryInstall(
@ -445,8 +433,8 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
if (config.usesPortForwarding) {
final CustomDevicePortForwarder portForwarder = CustomDevicePortForwarder(
deviceName: device.name,
forwardPortCommand: config.forwardPortCommand,
forwardPortSuccessRegex: config.forwardPortSuccessRegex,
forwardPortCommand: config.forwardPortCommand!,
forwardPortSuccessRegex: config.forwardPortSuccessRegex!,
processManager: _processManager,
logger: logger,
);
@ -455,7 +443,7 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
// find a random port we can forward
final int port = await _operatingSystemUtils.findFreePort();
final ForwardedPort forwardedPort = await portForwarder.tryForward(port, port);
final ForwardedPort forwardedPort = await (portForwarder.tryForward(port, port) as FutureOr<ForwardedPort>);
if (forwardedPort == null) {
_printConfigCheckingError("Couldn't forward test port $port from device.",);
result = false;
@ -482,8 +470,8 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
///
/// Only check if `--check` is explicitly specified. (Don't check by default)
Future<FlutterCommandResult> runNonInteractively() async {
final String jsonStr = stringArgDeprecated(_kJson);
final bool shouldCheck = boolArgDeprecated(_kCheck) ?? false;
final String jsonStr = stringArgDeprecated(_kJson)!;
final bool shouldCheck = boolArgDeprecated(_kCheck);
dynamic json;
try {
@ -492,7 +480,7 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
throwToolExit('Could not decode json: $e');
}
CustomDeviceConfig config;
late CustomDeviceConfig config;
try {
config = CustomDeviceConfig.fromJson(json);
} on CustomDeviceRevivalException catch (e) {
@ -518,12 +506,12 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
bool _isValidIpAddr(String s) => InternetAddress.tryParse(s) != null;
/// Ask the user to input a string.
Future<String> askForString(
Future<String?> askForString(
String name, {
String description,
String example,
String defaultsTo,
Future<bool> Function(String) validator,
String? description,
String? example,
String? defaultsTo,
Future<bool> Function(String)? validator,
}) async {
String msg = description ?? name;
@ -555,7 +543,7 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
/// Ask the user for a y(es) / n(o) or empty input.
Future<bool> askForBool(
String name, {
String description,
String? description,
bool defaultsTo = true,
}) async {
final String defaultsToStr = defaultsTo == true ? '[Y/n]' : '[y/N]';
@ -591,7 +579,7 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
/// Run interactively (with user prompts), the target device should be
/// connected to via ssh.
Future<FlutterCommandResult> runInteractivelySsh() async {
final bool shouldCheck = boolArgDeprecated(_kCheck) ?? true;
final bool shouldCheck = boolArgDeprecated(_kCheck);
// Listen to the keystrokes stream as late as possible, since it's a
// single-subscription stream apparently.
@ -610,61 +598,61 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
inputs = StreamQueue<String>(nonClosingKeystrokes.stream);
final String id = await askForString(
final String id = await (askForString(
'id',
description:
'Please enter the id you want to device to have. Must contain only '
'alphanumeric or underscore characters.',
example: 'pi',
validator: (String s) async => RegExp(r'^\w+$').hasMatch(s),
);
) as FutureOr<String>);
final String label = await askForString(
final String label = await (askForString(
'label',
description:
'Please enter the label of the device, which is a slightly more verbose '
'name for the device.',
example: 'Raspberry Pi',
);
) as FutureOr<String>);
final String sdkNameAndVersion = await askForString(
final String sdkNameAndVersion = await (askForString(
'SDK name and version',
example: 'Raspberry Pi 4 Model B+',
);
) as FutureOr<String>);
final bool enabled = await askForBool(
'enabled',
description: 'Should the device be enabled?',
);
final String targetStr = await askForString(
final String targetStr = await (askForString(
'target',
description: 'Please enter the hostname or IPv4/v6 address of the device.',
example: 'raspberrypi',
validator: (String s) async => _isValidHostname(s) || _isValidIpAddr(s)
);
) as FutureOr<String>);
final InternetAddress targetIp = InternetAddress.tryParse(targetStr);
final InternetAddress? targetIp = InternetAddress.tryParse(targetStr);
final bool useIp = targetIp != null;
final bool ipv6 = useIp && targetIp.type == InternetAddressType.IPv6;
final InternetAddress loopbackIp = ipv6
? InternetAddress.loopbackIPv6
: InternetAddress.loopbackIPv4;
final String username = await askForString(
final String username = await (askForString(
'username',
description: 'Please enter the username used for ssh-ing into the remote device.',
example: 'pi',
defaultsTo: 'no username',
);
) as FutureOr<String>);
final String remoteRunDebugCommand = await askForString(
final String remoteRunDebugCommand = await (askForString(
'run command',
description:
'Please enter the command executed on the remote device for starting '
r'the app. "/tmp/${appName}" is the path to the asset bundle.',
example: r'flutter-pi /tmp/${appName}'
);
) as FutureOr<String>);
final bool usePortForwarding = await askForBool(
'use port forwarding',
@ -675,12 +663,12 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
'not using port forwarding.',
);
final String screenshotCommand = await askForString(
final String screenshotCommand = await (askForString(
'screenshot command',
description: 'Enter the command executed on the remote device for taking a screenshot.',
example: r"fbgrab /tmp/screenshot.png && cat /tmp/screenshot.png | base64 | tr -d ' \n\t'",
defaultsTo: 'no screenshotting support',
);
) as FutureOr<String>);
// SSH expects IPv6 addresses to use the bracket syntax like URIs do too,
// but the IPv6 the user enters is a raw IPv6 address, so we need to wrap it.
@ -777,7 +765,6 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
targetStr,
],
explicitPingSuccessRegex: true,
pingSuccessRegex: null
);
} else {
throw UnsupportedError('Unsupported operating system');
@ -815,16 +802,11 @@ class CustomDevicesAddCommand extends CustomDevicesCommandBase {
class CustomDevicesDeleteCommand extends CustomDevicesCommandBase {
CustomDevicesDeleteCommand({
@required CustomDevicesConfig customDevicesConfig,
@required FeatureFlags featureFlags,
@required FileSystem fileSystem,
@required Logger logger,
}) : super(
customDevicesConfig: customDevicesConfig,
featureFlags: featureFlags,
fileSystem: fileSystem,
logger: logger
);
required super.customDevicesConfig,
required super.featureFlags,
required FileSystem super.fileSystem,
required super.logger,
});
@override
String get description => '''
@ -838,7 +820,7 @@ Delete a device from the config file.
Future<FlutterCommandResult> runCommand() async {
checkFeatureEnabled();
final String id = globalResults['device-id'] as String;
final String id = globalResults!['device-id'] as String;
if (!customDevicesConfig.contains(id)) {
throwToolExit('Couldn\'t find device with id "$id" in config at "${customDevicesConfig.configPath}"');
}

View File

@ -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:async/async.dart';
@ -66,10 +64,10 @@ class DaemonCommand extends FlutterCommand {
@override
Future<FlutterCommandResult> runCommand() async {
if (argResults['listen-on-tcp-port'] != null) {
int port;
if (argResults!['listen-on-tcp-port'] != null) {
int? port;
try {
port = int.parse(stringArgDeprecated('listen-on-tcp-port'));
port = int.parse(stringArgDeprecated('listen-on-tcp-port')!);
} on FormatException catch (error) {
throwToolExit('Invalid port for `--listen-on-tcp-port`: $error');
}
@ -108,17 +106,17 @@ class _DaemonServer {
this.notifyingLogger,
});
final int port;
final int? port;
/// Stdout logger used to print general server-related errors.
final Logger logger;
final Logger? logger;
// Logger that sends the message to the other end of daemon connection.
final NotifyingLogger notifyingLogger;
final NotifyingLogger? notifyingLogger;
Future<void> run() async {
final ServerSocket serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, port);
logger.printStatus('Daemon server listening on ${serverSocket.port}');
final ServerSocket serverSocket = await ServerSocket.bind(InternetAddress.loopbackIPv4, port!);
logger!.printStatus('Daemon server listening on ${serverSocket.port}');
final StreamSubscription<Socket> subscription = serverSocket.listen(
(Socket socket) async {
@ -126,13 +124,13 @@ class _DaemonServer {
// reset, we will receive an uncatchable exception.
// https://github.com/dart-lang/sdk/issues/25518
final Future<void> socketDone = socket.done.catchError((dynamic error, StackTrace stackTrace) {
logger.printError('Socket error: $error');
logger.printTrace('$stackTrace');
logger!.printError('Socket error: $error');
logger!.printTrace('$stackTrace');
});
final Daemon daemon = Daemon(
DaemonConnection(
daemonStreams: DaemonStreams.fromSocket(socket, logger: logger),
logger: logger,
daemonStreams: DaemonStreams.fromSocket(socket, logger: logger!),
logger: logger!,
),
notifyingLogger: notifyingLogger,
);
@ -147,8 +145,8 @@ class _DaemonServer {
}
}
typedef CommandHandler = Future<dynamic> Function(Map<String, dynamic> args);
typedef CommandHandlerWithBinary = Future<dynamic> Function(Map<String, dynamic> args, Stream<List<int>> binary);
typedef CommandHandler = Future<dynamic>? Function(Map<String, dynamic> args);
typedef CommandHandlerWithBinary = Future<dynamic> Function(Map<String, dynamic> args, Stream<List<int>>? binary);
class Daemon {
Daemon(
@ -178,15 +176,15 @@ class Daemon {
final DaemonConnection connection;
DaemonDomain daemonDomain;
AppDomain appDomain;
DeviceDomain deviceDomain;
EmulatorDomain emulatorDomain;
DevToolsDomain devToolsDomain;
ProxyDomain proxyDomain;
StreamSubscription<DaemonMessage> _commandSubscription;
late DaemonDomain daemonDomain;
late AppDomain appDomain;
late DeviceDomain deviceDomain;
EmulatorDomain? emulatorDomain;
DevToolsDomain? devToolsDomain;
late ProxyDomain proxyDomain;
StreamSubscription<DaemonMessage>? _commandSubscription;
final NotifyingLogger notifyingLogger;
final NotifyingLogger? notifyingLogger;
final bool logToStdout;
final Completer<int> _onExitCompleter = Completer<int>();
@ -203,7 +201,7 @@ class Daemon {
// {id, method, params}
// [id] is an opaque type to us.
final dynamic id = request.data['id'];
final Object? id = request.data['id'];
if (id == null) {
globals.stdio.stderrWrite('no id for request: $request\n');
@ -211,7 +209,7 @@ class Daemon {
}
try {
final String method = request.data['method'] as String;
final String method = request.data['method']! as String;
assert(method != null);
if (!method.contains('.')) {
throw DaemonException('method not understood: $method');
@ -223,13 +221,13 @@ class Daemon {
throw DaemonException('no domain for method: $method');
}
_domainMap[prefix].handleCommand(name, id, castStringKeyedMap(request.data['params']) ?? const <String, dynamic>{}, request.binary);
_domainMap[prefix]!.handleCommand(name, id, castStringKeyedMap(request.data['params']) ?? const <String, dynamic>{}, request.binary);
} on Exception catch (error, trace) {
connection.sendErrorResponse(id, _toJsonable(error), trace);
}
}
Future<void> shutdown({ dynamic error }) async {
Future<void> shutdown({ Object? error }) async {
await devToolsDomain?.dispose();
await _commandSubscription?.cancel();
await connection.dispose();
@ -270,12 +268,12 @@ abstract class Domain {
@override
String toString() => name;
void handleCommand(String command, dynamic id, Map<String, dynamic> args, Stream<List<int>> binary) {
void handleCommand(String command, Object id, Map<String, dynamic> args, Stream<List<int>>? binary) {
Future<dynamic>.sync(() {
if (_handlers.containsKey(command)) {
return _handlers[command](args);
return _handlers[command]!(args);
} else if (_handlersWithBinary.containsKey(command)) {
return _handlersWithBinary[command](args, binary);
return _handlersWithBinary[command]!(args, binary);
}
throw DaemonException('command not understood: $name.$command');
}).then<dynamic>((dynamic result) {
@ -285,11 +283,11 @@ abstract class Domain {
});
}
void sendEvent(String name, [ dynamic args, List<int> binary ]) {
void sendEvent(String name, [ dynamic args, List<int>? binary ]) {
daemon.connection.sendEvent(name, _toJsonable(args), binary);
}
String _getStringArg(Map<String, dynamic> args, String name, { bool required = false }) {
String? _getStringArg(Map<String, dynamic> args, String name, { bool required = false }) {
if (required && !args.containsKey(name)) {
throw DaemonException('$name is required');
}
@ -297,10 +295,10 @@ abstract class Domain {
if (val != null && val is! String) {
throw DaemonException('$name is not a String');
}
return val as String;
return val as String?;
}
bool _getBoolArg(Map<String, dynamic> args, String name, { bool required = false }) {
bool? _getBoolArg(Map<String, dynamic> args, String name, { bool required = false }) {
if (required && !args.containsKey(name)) {
throw DaemonException('$name is required');
}
@ -308,10 +306,10 @@ abstract class Domain {
if (val != null && val is! bool) {
throw DaemonException('$name is not a bool');
}
return val as bool;
return val as bool?;
}
int _getIntArg(Map<String, dynamic> args, String name, { bool required = false }) {
int? _getIntArg(Map<String, dynamic> args, String name, { bool required = false }) {
if (required && !args.containsKey(name)) {
throw DaemonException('$name is required');
}
@ -319,7 +317,7 @@ abstract class Domain {
if (val != null && val is! int) {
throw DaemonException('$name is not an int');
}
return val as int;
return val as int?;
}
Future<void> dispose() async { }
@ -342,7 +340,7 @@ class DaemonDomain extends Domain {
},
);
_subscription = daemon.notifyingLogger.onMessage.listen((LogMessage message) {
_subscription = daemon.notifyingLogger!.onMessage.listen((LogMessage message) {
if (daemon.logToStdout) {
if (message.level == 'status') {
// We use `print()` here instead of `stdout.writeln()` in order to
@ -374,7 +372,7 @@ class DaemonDomain extends Domain {
});
}
StreamSubscription<LogMessage> _subscription;
StreamSubscription<LogMessage>? _subscription;
Future<String> version(Map<String, dynamic> args) {
return Future<String>.value(protocolVersion);
@ -411,7 +409,7 @@ class DaemonDomain extends Domain {
/// as whether command line tools are installed or whether the host platform
/// is correct.
Future<Map<String, Object>> getSupportedPlatforms(Map<String, dynamic> args) async {
final String projectRoot = _getStringArg(args, 'projectRoot', required: true);
final String? projectRoot = _getStringArg(args, 'projectRoot', required: true);
final List<String> result = <String>[];
try {
final FlutterProject flutterProject = FlutterProject.fromDirectory(globals.fs.directory(projectRoot));
@ -461,8 +459,8 @@ class DaemonDomain extends Domain {
}
typedef RunOrAttach = Future<void> Function({
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<void> appStartedCompleter,
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
});
/// This domain responds to methods like [start] and [stop].
@ -488,17 +486,17 @@ class AppDomain extends Domain {
Device device,
String projectDirectory,
String target,
String route,
String? route,
DebuggingOptions options,
bool enableHotReload, {
File applicationBinary,
@required bool trackWidgetCreation,
String projectRootPath,
String packagesFilePath,
String dillOutputPath,
File? applicationBinary,
required bool trackWidgetCreation,
String? projectRootPath,
String? packagesFilePath,
String? dillOutputPath,
bool ipv6 = false,
bool multidexEnabled = false,
String isolateFilter,
String? isolateFilter,
bool machine = true,
}) async {
if (!await device.supportsRuntimeMode(options.buildInfo.mode)) {
@ -523,14 +521,14 @@ class AppDomain extends Domain {
ResidentRunner runner;
if (await device.targetPlatform == TargetPlatform.web_javascript) {
runner = webRunnerFactory.createWebRunner(
runner = webRunnerFactory!.createWebRunner(
flutterDevice,
flutterProject: flutterProject,
target: target,
debuggingOptions: options,
ipv6: ipv6,
stayResident: true,
urlTunneller: options.webEnableExposeUrl ? daemon.daemonDomain.exposeUrl : null,
urlTunneller: options.webEnableExposeUrl! ? daemon.daemonDomain.exposeUrl : null,
machine: machine,
usage: globals.flutterUsage,
systemClock: globals.systemClock,
@ -565,8 +563,8 @@ class AppDomain extends Domain {
return launch(
runner,
({
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<void> appStartedCompleter,
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
}) {
return runner.run(
connectionInfoCompleter: connectionInfoCompleter,
@ -588,7 +586,7 @@ class AppDomain extends Domain {
ResidentRunner runner,
RunOrAttach runOrAttach,
Device device,
String projectDirectory,
String? projectDirectory,
bool enableHotReload,
Directory cwd,
LaunchMode launchMode,
@ -610,7 +608,7 @@ class AppDomain extends Domain {
'launchMode': launchMode.toString(),
});
Completer<DebugConnectionInfo> connectionInfoCompleter;
Completer<DebugConnectionInfo>? connectionInfoCompleter;
if (runner.debuggingEnabled) {
connectionInfoCompleter = Completer<DebugConnectionInfo>();
@ -620,7 +618,7 @@ class AppDomain extends Domain {
(DebugConnectionInfo info) {
final Map<String, dynamic> params = <String, dynamic>{
// The web vmservice proxy does not have an http address.
'port': info.httpUri?.port ?? info.wsUri.port,
'port': info.httpUri?.port ?? info.wsUri!.port,
'wsUri': info.wsUri.toString(),
};
if (info.baseUri != null) {
@ -664,16 +662,16 @@ class AppDomain extends Domain {
final int _hotReloadDebounceDurationMs = 50;
Future<OperationResult> restart(Map<String, dynamic> args) async {
final String appId = _getStringArg(args, 'appId', required: true);
Future<OperationResult>? restart(Map<String, dynamic> args) async {
final String? appId = _getStringArg(args, 'appId', required: true);
final bool fullRestart = _getBoolArg(args, 'fullRestart') ?? false;
final bool pauseAfterRestart = _getBoolArg(args, 'pause') ?? false;
final String restartReason = _getStringArg(args, 'reason');
final String? restartReason = _getStringArg(args, 'reason');
final bool debounce = _getBoolArg(args, 'debounce') ?? false;
// This is an undocumented parameter used for integration tests.
final int debounceDurationOverrideMs = _getIntArg(args, 'debounceDurationOverrideMs');
final int? debounceDurationOverrideMs = _getIntArg(args, 'debounceDurationOverrideMs');
final AppInstance app = _getApp(appId);
final AppInstance? app = _getApp(appId);
if (app == null) {
throw DaemonException("app '$appId' not found");
}
@ -689,7 +687,7 @@ class AppDomain extends Domain {
pause: pauseAfterRestart,
reason: restartReason);
},
);
)!;
}
/// Debounce and queue reload actions.
@ -699,11 +697,11 @@ class AppDomain extends Domain {
/// and all return the same result. If an action is requested after an identical
/// action has already started, it will be queued and run again once the first
/// action completes.
Future<OperationResult> _queueAndDebounceReloadAction(
Future<OperationResult>? _queueAndDebounceReloadAction(
AppInstance app,
OperationType operationType,
bool debounce,
int debounceDurationOverrideMs,
int? debounceDurationOverrideMs,
Future<OperationResult> Function() action,
) {
final Duration debounceDuration = debounce
@ -727,39 +725,40 @@ class AppDomain extends Domain {
/// "method":"ext.flutter.platformOverride"
/// }
Future<Map<String, dynamic>> callServiceExtension(Map<String, dynamic> args) async {
final String appId = _getStringArg(args, 'appId', required: true);
final String methodName = _getStringArg(args, 'methodName');
final Map<String, dynamic> params = args['params'] == null ? <String, dynamic>{} : castStringKeyedMap(args['params']);
final String? appId = _getStringArg(args, 'appId', required: true);
final String methodName = _getStringArg(args, 'methodName')!;
final Map<String, dynamic>? params = args['params'] == null ? <String, dynamic>{} : castStringKeyedMap(args['params']);
final AppInstance app = _getApp(appId);
final AppInstance? app = _getApp(appId);
if (app == null) {
throw DaemonException("app '$appId' not found");
}
final FlutterDevice device = app.runner.flutterDevices.first;
final List<FlutterView> views = await device.vmService.getFlutterViews();
final Map<String, dynamic> result = await device
.vmService
final FlutterDevice device = app.runner!.flutterDevices.first!;
final List<FlutterView> views = await device.vmService!.getFlutterViews();
final Map<String, dynamic>? result = await device
.vmService!
.invokeFlutterExtensionRpcRaw(
methodName,
args: params,
isolateId: views
.first.uiIsolate.id
.first.uiIsolate!.id!
);
if (result == null) {
throw DaemonException('method not available: $methodName');
}
if (result.containsKey('error')) {
throw result['error'];
// ignore: only_throw_errors
throw result['error']! as Object;
}
return result;
}
Future<bool> stop(Map<String, dynamic> args) async {
final String appId = _getStringArg(args, 'appId', required: true);
final String? appId = _getStringArg(args, 'appId', required: true);
final AppInstance app = _getApp(appId);
final AppInstance? app = _getApp(appId);
if (app == null) {
throw DaemonException("app '$appId' not found");
}
@ -776,9 +775,9 @@ class AppDomain extends Domain {
}
Future<bool> detach(Map<String, dynamic> args) async {
final String appId = _getStringArg(args, 'appId', required: true);
final String? appId = _getStringArg(args, 'appId', required: true);
final AppInstance app = _getApp(appId);
final AppInstance? app = _getApp(appId);
if (app == null) {
throw DaemonException("app '$appId' not found");
}
@ -794,11 +793,16 @@ class AppDomain extends Domain {
);
}
AppInstance _getApp(String id) {
return _apps.firstWhere((AppInstance app) => app.id == id, orElse: () => null);
AppInstance? _getApp(String? id) {
for (final AppInstance app in _apps) {
if (app.id == id) {
return app;
}
}
return null;
}
void _sendAppEvent(AppInstance app, String name, [ Map<String, dynamic> args ]) {
void _sendAppEvent(AppInstance app, String name, [ Map<String, dynamic>? args ]) {
sendEvent('app.$name', <String, dynamic>{
'appId': app.id,
...?args,
@ -830,12 +834,12 @@ class DeviceDomain extends Domain {
// Use the device manager discovery so that client provided device types
// are usable via the daemon protocol.
globals.deviceManager.deviceDiscoverers.forEach(addDeviceDiscoverer);
globals.deviceManager!.deviceDiscoverers.forEach(addDeviceDiscoverer);
}
/// An incrementing number used to generate unique ids.
int _id = 0;
final Map<String, ApplicationPackage> _applicationPackages = <String, ApplicationPackage>{};
final Map<String, ApplicationPackage?> _applicationPackages = <String, ApplicationPackage?>{};
final Map<String, DeviceLogReader> _logReaders = <String, DeviceLogReader>{};
void addDeviceDiscoverer(DeviceDiscovery discoverer) {
@ -856,7 +860,7 @@ class DeviceDomain extends Domain {
return (Device device) {
_serializeDeviceEvents = _serializeDeviceEvents.then<void>((_) async {
try {
final Map<String, Object> response = await _deviceToMap(device);
final Map<String, Object?> response = await _deviceToMap(device);
sendEvent(eventName, response);
} on Exception catch (err) {
globals.printError('$err');
@ -869,7 +873,7 @@ class DeviceDomain extends Domain {
/// Return a list of the current devices, with each device represented as a map
/// of properties (id, name, platform, ...).
Future<List<Map<String, dynamic>>> getDevices([ Map<String, dynamic> args ]) async {
Future<List<Map<String, dynamic>>> getDevices([ Map<String, dynamic>? args ]) async {
return <Map<String, dynamic>>[
for (final PollingDeviceDiscovery discoverer in _discoverers)
for (final Device device in await discoverer.devices)
@ -878,7 +882,7 @@ class DeviceDomain extends Domain {
}
/// Return a list of the current devices, discarding existing cache of devices.
Future<List<Map<String, dynamic>>> discoverDevices([ Map<String, dynamic> args ]) async {
Future<List<Map<String, dynamic>>> discoverDevices([ Map<String, dynamic>? args ]) async {
return <Map<String, dynamic>>[
for (final PollingDeviceDiscovery discoverer in _discoverers)
for (final Device device in await discoverer.discoverDevices())
@ -902,50 +906,50 @@ class DeviceDomain extends Domain {
/// Forward a host port to a device port.
Future<Map<String, dynamic>> forward(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final int devicePort = _getIntArg(args, 'devicePort', required: true);
int hostPort = _getIntArg(args, 'hostPort');
final String? deviceId = _getStringArg(args, 'deviceId', required: true);
final int devicePort = _getIntArg(args, 'devicePort', required: true)!;
int? hostPort = _getIntArg(args, 'hostPort');
final Device device = await daemon.deviceDomain._getDevice(deviceId);
final Device? device = await daemon.deviceDomain._getDevice(deviceId);
if (device == null) {
throw DaemonException("device '$deviceId' not found");
}
hostPort = await device.portForwarder.forward(devicePort, hostPort: hostPort);
hostPort = await device.portForwarder!.forward(devicePort, hostPort: hostPort);
return <String, dynamic>{'hostPort': hostPort};
}
/// Removes a forwarded port.
Future<void> unforward(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final int devicePort = _getIntArg(args, 'devicePort', required: true);
final int hostPort = _getIntArg(args, 'hostPort', required: true);
final String? deviceId = _getStringArg(args, 'deviceId', required: true);
final int devicePort = _getIntArg(args, 'devicePort', required: true)!;
final int hostPort = _getIntArg(args, 'hostPort', required: true)!;
final Device device = await daemon.deviceDomain._getDevice(deviceId);
final Device? device = await daemon.deviceDomain._getDevice(deviceId);
if (device == null) {
throw DaemonException("device '$deviceId' not found");
}
return device.portForwarder.unforward(ForwardedPort(hostPort, devicePort));
return device.portForwarder!.unforward(ForwardedPort(hostPort, devicePort));
}
/// Returns whether a device supports runtime mode.
Future<bool> supportsRuntimeMode(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final Device device = await daemon.deviceDomain._getDevice(deviceId);
final String? deviceId = _getStringArg(args, 'deviceId', required: true);
final Device? device = await daemon.deviceDomain._getDevice(deviceId);
if (device == null) {
throw DaemonException("device '$deviceId' not found");
}
final String buildMode = _getStringArg(args, 'buildMode', required: true);
final String buildMode = _getStringArg(args, 'buildMode', required: true)!;
return await device.supportsRuntimeMode(getBuildModeForName(buildMode));
}
/// Creates an application package from a file in the temp directory.
Future<String> uploadApplicationPackage(Map<String, dynamic> args) async {
final TargetPlatform targetPlatform = getTargetPlatformForName(_getStringArg(args, 'targetPlatform', required: true));
final File applicationBinary = daemon.proxyDomain.tempDirectory.childFile(_getStringArg(args, 'applicationBinary', required: true));
final ApplicationPackage applicationPackage = await ApplicationPackageFactory.instance.getPackageForPlatform(
final TargetPlatform targetPlatform = getTargetPlatformForName(_getStringArg(args, 'targetPlatform', required: true)!);
final File applicationBinary = daemon.proxyDomain.tempDirectory.childFile(_getStringArg(args, 'applicationBinary', required: true)!);
final ApplicationPackage? applicationPackage = await ApplicationPackageFactory.instance!.getPackageForPlatform(
targetPlatform,
applicationBinary: applicationBinary,
);
@ -956,13 +960,13 @@ class DeviceDomain extends Domain {
/// Starts the log reader on the device.
Future<String> startLogReader(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final Device device = await daemon.deviceDomain._getDevice(deviceId);
final String? deviceId = _getStringArg(args, 'deviceId', required: true);
final Device? device = await daemon.deviceDomain._getDevice(deviceId);
if (device == null) {
throw DaemonException("device '$deviceId' not found");
}
final String applicationPackageId = _getStringArg(args, 'applicationPackageId');
final ApplicationPackage applicationPackage = applicationPackageId != null ? _applicationPackages[applicationPackageId] : null;
final String? applicationPackageId = _getStringArg(args, 'applicationPackageId');
final ApplicationPackage? applicationPackage = applicationPackageId != null ? _applicationPackages[applicationPackageId] : null;
final String id = '${deviceId}_${_id++}';
final DeviceLogReader logReader = await device.getLogReader(app: applicationPackage);
@ -975,32 +979,32 @@ class DeviceDomain extends Domain {
/// Stops a log reader that was previously started.
Future<void> stopLogReader(Map<String, dynamic> args) async {
final String id = _getStringArg(args, 'id', required: true);
final String? id = _getStringArg(args, 'id', required: true);
_logReaders.remove(id)?.dispose();
}
/// Starts an app on a device.
Future<Map<String, dynamic>> startApp(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final Device device = await daemon.deviceDomain._getDevice(deviceId);
final String? deviceId = _getStringArg(args, 'deviceId', required: true);
final Device? device = await daemon.deviceDomain._getDevice(deviceId);
if (device == null) {
throw DaemonException("device '$deviceId' not found");
}
final String applicationPackageId = _getStringArg(args, 'applicationPackageId', required: true);
final ApplicationPackage applicationPackage = _applicationPackages[applicationPackageId];
final String? applicationPackageId = _getStringArg(args, 'applicationPackageId', required: true);
final ApplicationPackage applicationPackage = _applicationPackages[applicationPackageId!]!;
final LaunchResult result = await device.startApp(
applicationPackage,
debuggingOptions: DebuggingOptions.fromJson(
castStringKeyedMap(args['debuggingOptions']),
castStringKeyedMap(args['debuggingOptions'])!,
// We are using prebuilts, build info does not matter here.
BuildInfo.debug,
),
mainPath: _getStringArg(args, 'mainPath'),
route: _getStringArg(args, 'route'),
platformArgs: castStringKeyedMap(args['platformArgs']),
prebuiltApplication: _getBoolArg(args, 'prebuiltApplication'),
ipv6: _getBoolArg(args, 'ipv6'),
platformArgs: castStringKeyedMap(args['platformArgs']) ?? const <String, Object>{},
prebuiltApplication: _getBoolArg(args, 'prebuiltApplication') ?? false,
ipv6: _getBoolArg(args, 'ipv6') ?? false,
userIdentifier: _getStringArg(args, 'userIdentifier'),
);
return <String, dynamic>{
@ -1011,13 +1015,13 @@ class DeviceDomain extends Domain {
/// Stops an app.
Future<bool> stopApp(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final Device device = await daemon.deviceDomain._getDevice(deviceId);
final String? deviceId = _getStringArg(args, 'deviceId', required: true);
final Device? device = await daemon.deviceDomain._getDevice(deviceId);
if (device == null) {
throw DaemonException("device '$deviceId' not found");
}
final String applicationPackageId = _getStringArg(args, 'applicationPackageId', required: true);
final ApplicationPackage applicationPackage = _applicationPackages[applicationPackageId];
final String? applicationPackageId = _getStringArg(args, 'applicationPackageId', required: true);
final ApplicationPackage applicationPackage = _applicationPackages[applicationPackageId!]!;
return device.stopApp(
applicationPackage,
userIdentifier: _getStringArg(args, 'userIdentifier'),
@ -1025,9 +1029,9 @@ class DeviceDomain extends Domain {
}
/// Takes a screenshot.
Future<String> takeScreenshot(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final Device device = await daemon.deviceDomain._getDevice(deviceId);
Future<String?> takeScreenshot(Map<String, dynamic> args) async {
final String? deviceId = _getStringArg(args, 'deviceId', required: true);
final Device? device = await daemon.deviceDomain._getDevice(deviceId);
if (device == null) {
throw DaemonException("device '$deviceId' not found");
}
@ -1051,9 +1055,15 @@ class DeviceDomain extends Domain {
}
/// Return the device matching the deviceId field in the args.
Future<Device> _getDevice(String deviceId) async {
Future<Device?> _getDevice(String? deviceId) async {
for (final PollingDeviceDiscovery discoverer in _discoverers) {
final Device device = (await discoverer.devices).firstWhere((Device device) => device.id == deviceId, orElse: () => null);
final List<Device> devices = await discoverer.devices;
Device? device;
for (final Device localDevice in devices) {
if (localDevice.id == deviceId) {
device = localDevice;
}
}
if (device != null) {
return device;
}
@ -1067,11 +1077,11 @@ class DevToolsDomain extends Domain {
registerHandler('serve', serve);
}
DevtoolsLauncher _devtoolsLauncher;
DevtoolsLauncher? _devtoolsLauncher;
Future<Map<String, dynamic>> serve([ Map<String, dynamic> args ]) async {
Future<Map<String, dynamic>> serve([ Map<String, dynamic>? args ]) async {
_devtoolsLauncher ??= DevtoolsLauncher.instance;
final DevToolsServerAddress server = await _devtoolsLauncher.serve();
final DevToolsServerAddress? server = await _devtoolsLauncher?.serve();
return<String, dynamic>{
'host': server?.host,
'port': server?.port,
@ -1111,8 +1121,8 @@ Map<String, dynamic> _emulatorToMap(Emulator emulator) {
return <String, dynamic>{
'id': emulator.id,
'name': emulator.name,
'category': emulator.category?.toString(),
'platformType': emulator.platformType?.toString(),
'category': emulator.category.toString(),
'platformType': emulator.platformType.toString(),
};
}
@ -1123,7 +1133,7 @@ Map<String, dynamic> _operationResultToMap(OperationResult result) {
};
}
dynamic _toJsonable(dynamic obj) {
Object? _toJsonable(dynamic obj) {
if (obj is String || obj is int || obj is bool || obj is Map<dynamic, dynamic> || obj is List<dynamic> || obj == null) {
return obj;
}
@ -1137,7 +1147,7 @@ dynamic _toJsonable(dynamic obj) {
}
class NotifyingLogger extends DelegatingLogger {
NotifyingLogger({ @required this.verbose, @required Logger parent }) : super(parent) {
NotifyingLogger({ required this.verbose, required Logger parent }) : super(parent) {
_messageController = StreamController<LogMessage>.broadcast(
onListen: _onListen,
);
@ -1145,7 +1155,7 @@ class NotifyingLogger extends DelegatingLogger {
final bool verbose;
final List<LogMessage> messageBuffer = <LogMessage>[];
StreamController<LogMessage> _messageController;
late StreamController<LogMessage> _messageController;
void _onListen() {
if (messageBuffer.isNotEmpty) {
@ -1159,12 +1169,12 @@ class NotifyingLogger extends DelegatingLogger {
@override
void printError(
String message, {
StackTrace stackTrace,
bool emphasis = false,
TerminalColor color,
int indent,
int hangingIndent,
bool wrap,
StackTrace? stackTrace,
bool? emphasis = false,
TerminalColor? color,
int? indent,
int? hangingIndent,
bool? wrap,
}) {
_sendMessage(LogMessage('error', message, stackTrace));
}
@ -1172,11 +1182,11 @@ class NotifyingLogger extends DelegatingLogger {
@override
void printWarning(
String message, {
bool emphasis = false,
TerminalColor color,
int indent,
int hangingIndent,
bool wrap,
bool? emphasis = false,
TerminalColor? color,
int? indent,
int? hangingIndent,
bool? wrap,
}) {
_sendMessage(LogMessage('warning', message));
}
@ -1184,19 +1194,19 @@ class NotifyingLogger extends DelegatingLogger {
@override
void printStatus(
String message, {
bool emphasis = false,
TerminalColor color,
bool newline = true,
int indent,
int hangingIndent,
bool wrap,
bool? emphasis = false,
TerminalColor? color,
bool? newline = true,
int? indent,
int? hangingIndent,
bool? wrap,
}) {
_sendMessage(LogMessage('status', message));
}
@override
void printBox(String message, {
String title,
String? title,
}) {
_sendMessage(LogMessage('status', title == null ? message : '$title: $message'));
}
@ -1212,8 +1222,8 @@ class NotifyingLogger extends DelegatingLogger {
@override
Status startProgress(
String message, {
@required Duration timeout,
String progressId,
Duration? timeout,
String? progressId,
bool multilineOutput = false,
bool includeTiming = true,
int progressIndicatorPadding = kDefaultStatusPadding,
@ -1237,7 +1247,7 @@ class NotifyingLogger extends DelegatingLogger {
}
@override
void sendEvent(String name, [Map<String, dynamic> args]) { }
void sendEvent(String name, [Map<String, dynamic>? args]) { }
@override
bool get supportsColor => throw UnimplementedError();
@ -1252,20 +1262,20 @@ class NotifyingLogger extends DelegatingLogger {
/// A running application, started by this daemon.
class AppInstance {
AppInstance(this.id, { this.runner, this.logToStdout = false, @required AppRunLogger logger })
AppInstance(this.id, { this.runner, this.logToStdout = false, required AppRunLogger logger })
: _logger = logger;
final String id;
final ResidentRunner runner;
final ResidentRunner? runner;
final bool logToStdout;
final AppRunLogger _logger;
Future<OperationResult> restart({ bool fullRestart = false, bool pause = false, String reason }) {
return runner.restart(fullRestart: fullRestart, pause: pause, reason: reason);
Future<OperationResult> restart({ bool fullRestart = false, bool pause = false, String? reason }) {
return runner!.restart(fullRestart: fullRestart, pause: pause, reason: reason);
}
Future<void> stop() => runner.exit();
Future<void> detach() => runner.detach();
Future<void> stop() => runner!.exit();
Future<void> detach() => runner!.detach();
void closeLogger() {
_logger.close();
@ -1289,16 +1299,16 @@ class EmulatorDomain extends Domain {
logger: globals.logger,
androidSdk: globals.androidSdk,
processManager: globals.processManager,
androidWorkflow: androidWorkflow,
androidWorkflow: androidWorkflow!,
);
Future<List<Map<String, dynamic>>> getEmulators([ Map<String, dynamic> args ]) async {
Future<List<Map<String, dynamic>>> getEmulators([ Map<String, dynamic>? args ]) async {
final List<Emulator> list = await emulators.getAllAvailableEmulators();
return list.map<Map<String, dynamic>>(_emulatorToMap).toList();
}
Future<void> launch(Map<String, dynamic> args) async {
final String emulatorId = _getStringArg(args, 'emulatorId', required: true);
final String emulatorId = _getStringArg(args, 'emulatorId', required: true)!;
final bool coldBoot = _getBoolArg(args, 'coldBoot') ?? false;
final List<Emulator> matches =
await emulators.getEmulatorsMatching(emulatorId);
@ -1312,7 +1322,7 @@ class EmulatorDomain extends Domain {
}
Future<Map<String, dynamic>> create(Map<String, dynamic> args) async {
final String name = _getStringArg(args, 'name');
final String? name = _getStringArg(args, 'name');
final CreateEmulatorResult res = await emulators.createEmulator(name: name);
return <String, dynamic>{
'success': res.success,
@ -1336,16 +1346,16 @@ class ProxyDomain extends Domain {
int _id = 0;
/// Writes to a file in a local temporary directory.
Future<void> writeTempFile(Map<String, dynamic> args, Stream<List<int>> binary) async {
final String path = _getStringArg(args, 'path', required: true);
Future<void> writeTempFile(Map<String, dynamic> args, Stream<List<int>>? binary) async {
final String path = _getStringArg(args, 'path', required: true)!;
final File file = tempDirectory.childFile(path);
await file.parent.create(recursive: true);
await file.openWrite().addStream(binary);
await file.openWrite().addStream(binary!);
}
/// Calculate rolling hashes for a file in the local temporary directory.
Future<Map<String, dynamic>> calculateFileHashes(Map<String, dynamic> args) async {
final String path = _getStringArg(args, 'path', required: true);
Future<Map<String, dynamic>?> calculateFileHashes(Map<String, dynamic> args) async {
final String path = _getStringArg(args, 'path', required: true)!;
final File file = tempDirectory.childFile(path);
if (!await file.exists()) {
return null;
@ -1354,24 +1364,24 @@ class ProxyDomain extends Domain {
return result.toJson();
}
Future<bool> updateFile(Map<String, dynamic> args, Stream<List<int>> binary) async {
final String path = _getStringArg(args, 'path', required: true);
Future<bool?> updateFile(Map<String, dynamic> args, Stream<List<int>>? binary) async {
final String path = _getStringArg(args, 'path', required: true)!;
final File file = tempDirectory.childFile(path);
if (!await file.exists()) {
return null;
}
final List<Map<String, dynamic>> deltaJson = (args['delta'] as List<dynamic>).cast<Map<String, dynamic>>();
final List<FileDeltaBlock> delta = FileDeltaBlock.fromJsonList(deltaJson);
final bool result = await FileTransfer().rebuildFile(file, delta, binary);
final bool result = await FileTransfer().rebuildFile(file, delta, binary!);
return result;
}
/// Opens a connection to a local port, and returns the connection id.
Future<String> connect(Map<String, dynamic> args) async {
final int targetPort = _getIntArg(args, 'port', required: true);
final int targetPort = _getIntArg(args, 'port', required: true)!;
final String id = 'portForwarder_${targetPort}_${_id++}';
Socket socket;
Socket? socket;
try {
socket = await Socket.connect(InternetAddress.loopbackIPv4, targetPort);
@ -1409,7 +1419,7 @@ class ProxyDomain extends Domain {
/// Disconnects from a previously established connection.
Future<bool> disconnect(Map<String, dynamic> args) async {
final String id = _getStringArg(args, 'id', required: true);
final String? id = _getStringArg(args, 'id', required: true);
if (_forwardedConnections.containsKey(id)) {
await _forwardedConnections.remove(id)?.close();
return true;
@ -1418,10 +1428,10 @@ class ProxyDomain extends Domain {
}
/// Writes to a previously established connection.
Future<bool> write(Map<String, dynamic> args, Stream<List<int>> binary) async {
final String id = _getStringArg(args, 'id', required: true);
Future<bool> write(Map<String, dynamic> args, Stream<List<int>>? binary) async {
final String? id = _getStringArg(args, 'id', required: true);
if (_forwardedConnections.containsKey(id)) {
final StreamSubscription<List<int>> subscription = binary.listen(_forwardedConnections[id].add);
final StreamSubscription<List<int>> subscription = binary!.listen(_forwardedConnections[id!]!.add);
await subscription.asFuture<void>();
await subscription.cancel();
return true;
@ -1439,7 +1449,7 @@ class ProxyDomain extends Domain {
// to be reused on any subsequent runs.
}
Directory _tempDirectory;
Directory? _tempDirectory;
Directory get tempDirectory => _tempDirectory ??= globals.fs.systemTempDirectory.childDirectory('flutter_tool_daemon')..createSync();
}
@ -1452,19 +1462,19 @@ class ProxyDomain extends Domain {
// TODO(devoncarew): To simplify this code a bit, we could choose to specialize
// this class into two, one for each of the above use cases.
class AppRunLogger extends DelegatingLogger {
AppRunLogger({ @required Logger parent }) : super(parent);
AppRunLogger({ required Logger parent }) : super(parent);
AppDomain domain;
AppInstance app;
AppDomain? domain;
late AppInstance app;
int _nextProgressId = 0;
Status _status;
Status? _status;
@override
Status startProgress(
String message, {
@required Duration timeout,
String progressId,
Duration? timeout,
String? progressId,
bool multilineOutput = false,
bool includeTiming = true,
int progressIndicatorPadding = kDefaultStatusPadding,
@ -1486,7 +1496,7 @@ class AppRunLogger extends DelegatingLogger {
finished: true,
);
}, stopwatch: Stopwatch())..start();
return _status;
return _status!;
}
void close() {
@ -1494,10 +1504,10 @@ class AppRunLogger extends DelegatingLogger {
}
void _sendProgressEvent({
@required String eventId,
@required String eventType,
required String eventId,
required String? eventType,
bool finished = false,
String message,
String? message,
}) {
if (domain == null) {
// If we're sending progress events before an app has started, send the
@ -1513,16 +1523,16 @@ class AppRunLogger extends DelegatingLogger {
if (finished != null) 'finished': finished,
};
domain._sendAppEvent(app, 'progress', event);
domain!._sendAppEvent(app, 'progress', event);
}
}
@override
void sendEvent(String name, [Map<String, dynamic> args, List<int> binary]) {
void sendEvent(String name, [Map<String, dynamic>? args, List<int>? binary]) {
if (domain == null) {
printStatus('event sent after app closed: $name');
} else {
domain.sendEvent(name, args, binary);
domain!.sendEvent(name, args, binary);
}
}
@ -1542,7 +1552,7 @@ class LogMessage {
final String level;
final String message;
final StackTrace stackTrace;
final StackTrace? stackTrace;
}
/// The method by which the Flutter app was launched.
@ -1574,9 +1584,9 @@ enum OperationType {
class DebounceOperationQueue<T, K> {
final Map<K, RestartableTimer> _debounceTimers = <K, RestartableTimer>{};
final Map<K, Future<T>> _operationQueue = <K, Future<T>>{};
Future<void> _inProgressAction;
Future<void>? _inProgressAction;
Future<T> queueAndDebounce(
Future<T>? queueAndDebounce(
K operationType,
Duration debounceDuration,
Future<T> Function() action,

View File

@ -2,7 +2,7 @@
// 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';
@ -49,10 +49,10 @@ import 'run.dart';
class DriveCommand extends RunCommandBase {
DriveCommand({
bool verboseHelp = false,
@visibleForTesting FlutterDriverFactory flutterDriverFactory,
@required FileSystem fileSystem,
@required Logger logger,
@required Platform platform,
@visibleForTesting FlutterDriverFactory? flutterDriverFactory,
required FileSystem fileSystem,
required Logger? logger,
required Platform platform,
}) : _flutterDriverFactory = flutterDriverFactory,
_fileSystem = fileSystem,
_logger = logger,
@ -156,15 +156,15 @@ class DriveCommand extends RunCommandBase {
// specified not to.
@override
bool get shouldRunPub {
if (argResults.wasParsed('pub') && !boolArgDeprecated('pub')) {
if (argResults!.wasParsed('pub') && !boolArgDeprecated('pub')) {
return false;
}
return true;
}
FlutterDriverFactory _flutterDriverFactory;
FlutterDriverFactory? _flutterDriverFactory;
final FileSystem _fileSystem;
final Logger _logger;
final Logger? _logger;
final FileSystemUtils _fsUtils;
@override
@ -179,9 +179,9 @@ class DriveCommand extends RunCommandBase {
@override
final List<String> aliases = <String>['driver'];
String get userIdentifier => stringArgDeprecated(FlutterOptions.kDeviceUser);
String? get userIdentifier => stringArgDeprecated(FlutterOptions.kDeviceUser);
String get screenshot => stringArgDeprecated('screenshot');
String? get screenshot => stringArgDeprecated('screenshot');
@override
bool get startPausedDefault => true;
@ -192,7 +192,7 @@ class DriveCommand extends RunCommandBase {
@override
Future<void> validateCommand() async {
if (userIdentifier != null) {
final Device device = await findTargetDevice();
final Device? device = await findTargetDevice();
if (device is! AndroidDevice) {
throwToolExit('--${FlutterOptions.kDeviceUser} is only supported for Android');
}
@ -202,39 +202,39 @@ class DriveCommand extends RunCommandBase {
@override
Future<FlutterCommandResult> runCommand() async {
final String testFile = _getTestFile();
final String testFile = _getTestFile()!;
if (testFile == null) {
throwToolExit(null);
}
if (await _fileSystem.type(testFile) != FileSystemEntityType.file) {
throwToolExit('Test file not found: $testFile');
}
final String applicationBinaryPath = stringArgDeprecated(FlutterOptions.kUseApplicationBinary);
final Device device = await findTargetDevice(includeUnsupportedDevices: applicationBinaryPath == null);
final String? applicationBinaryPath = stringArgDeprecated(FlutterOptions.kUseApplicationBinary);
final Device? device = await findTargetDevice(includeUnsupportedDevices: applicationBinaryPath == null);
if (device == null) {
throwToolExit(null);
}
if (screenshot != null && !device.supportsScreenshot) {
_logger.printError('Screenshot not supported for ${device.name}.');
_logger!.printError('Screenshot not supported for ${device.name}.');
}
final bool web = device is WebServerDevice || device is ChromiumDevice;
_flutterDriverFactory ??= FlutterDriverFactory(
applicationPackageFactory: ApplicationPackageFactory.instance,
logger: _logger,
applicationPackageFactory: ApplicationPackageFactory.instance!,
logger: _logger!,
processUtils: globals.processUtils,
dartSdkPath: globals.artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
devtoolsLauncher: DevtoolsLauncher.instance,
dartSdkPath: globals.artifacts!.getHostArtifact(HostArtifact.engineDartBinary).path,
devtoolsLauncher: DevtoolsLauncher.instance!,
);
final PackageConfig packageConfig = await loadPackageConfigWithLogging(
_fileSystem.file('.packages'),
logger: _logger,
logger: _logger!,
throwOnError: false,
) ?? PackageConfig.empty;
final DriverService driverService = _flutterDriverFactory.createDriverService(web);
);
final DriverService driverService = _flutterDriverFactory!.createDriverService(web);
final BuildInfo buildInfo = await getBuildInfo();
final DebuggingOptions debuggingOptions = await createDebuggingOptions(web);
final File applicationBinary = applicationBinaryPath == null
final File? applicationBinary = applicationBinaryPath == null
? null
: _fileSystem.file(applicationBinaryPath);
@ -245,7 +245,7 @@ class DriveCommand extends RunCommandBase {
buildInfo,
device,
debuggingOptions,
ipv6,
ipv6 ?? false,
applicationBinary: applicationBinary,
route: route,
userIdentifier: userIdentifier,
@ -260,7 +260,7 @@ class DriveCommand extends RunCommandBase {
}
);
} else {
final Uri uri = Uri.tryParse(stringArgDeprecated('use-existing-app'));
final Uri? uri = Uri.tryParse(stringArgDeprecated('use-existing-app')!);
if (uri == null) {
throwToolExit('Invalid VM Service URI: ${stringArgDeprecated('use-existing-app')}');
}
@ -268,7 +268,7 @@ class DriveCommand extends RunCommandBase {
uri,
device,
debuggingOptions,
ipv6,
ipv6 ?? false,
);
}
@ -279,10 +279,10 @@ class DriveCommand extends RunCommandBase {
packageConfig,
chromeBinary: stringArgDeprecated('chrome-binary'),
headless: boolArgDeprecated('headless'),
browserDimension: stringArgDeprecated('browser-dimension').split(','),
browserDimension: stringArgDeprecated('browser-dimension')!.split(','),
browserName: stringArgDeprecated('browser-name'),
driverPort: stringArgDeprecated('driver-port') != null
? int.tryParse(stringArgDeprecated('driver-port'))
? int.tryParse(stringArgDeprecated('driver-port')!)
: null,
androidEmulator: boolArgDeprecated('android-emulator'),
profileMemory: stringArgDeprecated('profile-memory'),
@ -293,10 +293,10 @@ class DriveCommand extends RunCommandBase {
screenshotTaken = true;
}
if (boolArgDeprecated('keep-app-running') ?? (argResults['use-existing-app'] != null)) {
_logger.printStatus('Leaving the application running.');
if (boolArgDeprecated('keep-app-running')) {
_logger!.printStatus('Leaving the application running.');
} else {
final File skslFile = stringArgDeprecated('write-sksl-on-exit') != null
final File? skslFile = stringArgDeprecated('write-sksl-on-exit') != null
? _fileSystem.file(stringArgDeprecated('write-sksl-on-exit'))
: null;
await driverService.stop(userIdentifier: userIdentifier, writeSkslOnExit: skslFile);
@ -316,8 +316,8 @@ class DriveCommand extends RunCommandBase {
return FlutterCommandResult.success();
}
String _getTestFile() {
if (argResults['driver'] != null) {
String? _getTestFile() {
if (argResults!['driver'] != null) {
return stringArgDeprecated('driver');
}
@ -332,7 +332,7 @@ class DriveCommand extends RunCommandBase {
// for the corresponding test file relative to it.
if (!_fileSystem.path.isRelative(appFile)) {
if (!_fileSystem.path.isWithin(packageDir, appFile)) {
_logger.printError(
_logger!.printError(
'Application file $appFile is outside the package directory $packageDir'
);
return null;
@ -344,7 +344,7 @@ class DriveCommand extends RunCommandBase {
final List<String> parts = _fileSystem.path.split(appFile);
if (parts.length < 2) {
_logger.printError(
_logger!.printError(
'Application file $appFile must reside in one of the sub-directories '
'of the package structure, not in the root directory.'
);
@ -372,9 +372,9 @@ class DriveCommand extends RunCommandBase {
'png',
);
await device.takeScreenshot(outputFile);
_logger.printStatus('Screenshot written to ${outputFile.path}');
_logger!.printStatus('Screenshot written to ${outputFile.path}');
} on Exception catch (error) {
_logger.printError('Error taking screenshot: $error');
_logger!.printError('Error taking screenshot: $error');
}
}
}

View File

@ -2,10 +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:meta/meta.dart';
import '../base/common.dart';
import '../base/logger.dart';
import '../base/platform.dart';
@ -18,10 +14,10 @@ import '../runner/flutter_command.dart';
class PrecacheCommand extends FlutterCommand {
PrecacheCommand({
bool verboseHelp = false,
@required Cache cache,
@required Platform platform,
@required Logger logger,
@required FeatureFlags featureFlags,
required Cache? cache,
required Platform platform,
required Logger logger,
required FeatureFlags featureFlags,
}) : _cache = cache,
_platform = platform,
_logger = logger,
@ -30,39 +26,39 @@ class PrecacheCommand extends FlutterCommand {
help: 'Precache artifacts for all host platforms.');
argParser.addFlag('force', abbr: 'f', negatable: false,
help: 'Force re-downloading of artifacts.');
argParser.addFlag('android', negatable: true, defaultsTo: false,
argParser.addFlag('android',
help: 'Precache artifacts for Android development.',
hide: !verboseHelp);
argParser.addFlag('android_gen_snapshot', negatable: true, defaultsTo: false,
argParser.addFlag('android_gen_snapshot',
help: 'Precache gen_snapshot for Android development.',
hide: !verboseHelp);
argParser.addFlag('android_maven', negatable: true, defaultsTo: false,
argParser.addFlag('android_maven',
help: 'Precache Gradle dependencies for Android development.',
hide: !verboseHelp);
argParser.addFlag('android_internal_build', negatable: true, defaultsTo: false,
argParser.addFlag('android_internal_build',
help: 'Precache dependencies for internal Android development.',
hide: !verboseHelp);
argParser.addFlag('ios', negatable: true, defaultsTo: false,
argParser.addFlag('ios',
help: 'Precache artifacts for iOS development.');
argParser.addFlag('web', negatable: true, defaultsTo: false,
argParser.addFlag('web',
help: 'Precache artifacts for web development.');
argParser.addFlag('linux', negatable: true, defaultsTo: false,
argParser.addFlag('linux',
help: 'Precache artifacts for Linux desktop development.');
argParser.addFlag('windows', negatable: true, defaultsTo: false,
argParser.addFlag('windows',
help: 'Precache artifacts for Windows desktop development.');
argParser.addFlag('macos', negatable: true, defaultsTo: false,
argParser.addFlag('macos',
help: 'Precache artifacts for macOS desktop development.');
argParser.addFlag('fuchsia', negatable: true, defaultsTo: false,
argParser.addFlag('fuchsia',
help: 'Precache artifacts for Fuchsia development.');
argParser.addFlag('universal', negatable: true, defaultsTo: true,
argParser.addFlag('universal', defaultsTo: true,
help: 'Precache artifacts required for any development platform.');
argParser.addFlag('flutter_runner', negatable: true, defaultsTo: false,
argParser.addFlag('flutter_runner',
help: 'Precache the flutter runner artifacts.', hide: !verboseHelp);
argParser.addFlag('use-unsigned-mac-binaries', negatable: true, defaultsTo: false,
argParser.addFlag('use-unsigned-mac-binaries',
help: 'Precache the unsigned macOS binaries when available.', hide: !verboseHelp);
}
final Cache _cache;
final Cache? _cache;
final Logger _logger;
final Platform _platform;
final FeatureFlags _featureFlags;
@ -106,9 +102,9 @@ class PrecacheCommand extends FlutterCommand {
Set<String> _explicitArtifactSelections() {
final Map<String, String> umbrellaForArtifact = _umbrellaForArtifactMap();
final Set<String> selections = <String>{};
bool explicitlySelected(String name) => boolArgDeprecated(name) && argResults.wasParsed(name);
bool explicitlySelected(String name) => boolArgDeprecated(name) && argResults!.wasParsed(name);
for (final DevelopmentArtifact artifact in DevelopmentArtifact.values) {
final String umbrellaName = umbrellaForArtifact[artifact.name];
final String? umbrellaName = umbrellaForArtifact[artifact.name];
if (explicitlySelected(artifact.name) ||
(umbrellaName != null && explicitlySelected(umbrellaName))) {
selections.add(artifact.name);
@ -120,11 +116,11 @@ class PrecacheCommand extends FlutterCommand {
@override
Future<void> validateCommand() {
_expandedArtifacts.forEach((String umbrellaName, List<String> childArtifactNames) {
if (!argResults.arguments.contains('--no-$umbrellaName')) {
if (!argResults!.arguments.contains('--no-$umbrellaName')) {
return;
}
for (final String childArtifactName in childArtifactNames) {
if (argResults.arguments.contains('--$childArtifactName')) {
if (argResults!.arguments.contains('--$childArtifactName')) {
throwToolExit('--$childArtifactName requires --$umbrellaName');
}
}
@ -137,21 +133,21 @@ class PrecacheCommand extends FlutterCommand {
Future<FlutterCommandResult> runCommand() async {
// Re-lock the cache.
if (_platform.environment['FLUTTER_ALREADY_LOCKED'] != 'true') {
await _cache.lock();
await _cache!.lock();
}
if (boolArgDeprecated('force')) {
_cache.clearStampFiles();
_cache!.clearStampFiles();
}
final bool includeAllPlatforms = boolArgDeprecated('all-platforms');
if (includeAllPlatforms) {
_cache.includeAllPlatforms = true;
_cache!.includeAllPlatforms = true;
}
if (boolArgDeprecated('use-unsigned-mac-binaries')) {
_cache.useUnsignedMacBinaries = true;
_cache!.useUnsignedMacBinaries = true;
}
final Set<String> explicitlyEnabled = _explicitArtifactSelections();
_cache.platformOverrideArtifacts = explicitlyEnabled;
_cache!.platformOverrideArtifacts = explicitlyEnabled;
// If the user did not provide any artifact flags, then download
// all artifacts that correspond to an enabled platform.
@ -159,7 +155,7 @@ class PrecacheCommand extends FlutterCommand {
final Map<String, String> umbrellaForArtifact = _umbrellaForArtifactMap();
final Set<DevelopmentArtifact> requiredArtifacts = <DevelopmentArtifact>{};
for (final DevelopmentArtifact artifact in DevelopmentArtifact.values) {
if (artifact.feature != null && !_featureFlags.isEnabled(artifact.feature)) {
if (artifact.feature != null && !_featureFlags.isEnabled(artifact.feature!)) {
continue;
}
@ -168,8 +164,8 @@ class PrecacheCommand extends FlutterCommand {
requiredArtifacts.add(artifact);
}
}
if (!await _cache.isUpToDate()) {
await _cache.updateAll(requiredArtifacts);
if (!await _cache!.isUpToDate()) {
await _cache!.updateAll(requiredArtifacts);
} else {
_logger.printStatus('Already up-to-date.');
}

View File

@ -2,7 +2,7 @@
// 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';
@ -31,7 +31,7 @@ import 'daemon.dart';
/// Shared logic between `flutter run` and `flutter drive` commands.
abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
RunCommandBase({ @required bool verboseHelp }) {
RunCommandBase({ required bool verboseHelp }) {
addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false);
usesDartDefineOption();
usesFlavorOption();
@ -182,7 +182,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
bool get purgePersistentCache => boolArgDeprecated('purge-persistent-cache');
bool get disableServiceAuthCodes => boolArgDeprecated('disable-service-auth-codes');
bool get cacheStartupProfile => boolArgDeprecated('cache-startup-profile');
bool get runningWithPrebuiltApplication => argResults[FlutterOptions.kUseApplicationBinary] != null;
bool get runningWithPrebuiltApplication => argResults![FlutterOptions.kUseApplicationBinary] != null;
bool get trackWidgetCreation => boolArgDeprecated('track-widget-creation');
bool get enableImpeller => boolArgDeprecated('enable-impeller');
bool get uninstallFirst => boolArgDeprecated('uninstall-first');
@ -193,17 +193,17 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
/// Whether to start the application paused by default.
bool get startPausedDefault;
String get route => stringArgDeprecated('route');
String? get route => stringArgDeprecated('route');
String get traceAllowlist => stringArgDeprecated('trace-allowlist');
String? get traceAllowlist => stringArgDeprecated('trace-allowlist');
/// Create a debugging options instance for the current `run` or `drive` invocation.
@visibleForTesting
@protected
Future<DebuggingOptions> createDebuggingOptions(bool webMode) async {
final BuildInfo buildInfo = await getBuildInfo();
final int browserDebugPort = featureFlags.isWebEnabled && argResults.wasParsed('web-browser-debug-port')
? int.parse(stringArgDeprecated('web-browser-debug-port'))
final int? browserDebugPort = featureFlags.isWebEnabled && argResults!.wasParsed('web-browser-debug-port')
? int.parse(stringArgDeprecated('web-browser-debug-port')!)
: null;
if (buildInfo.mode.isRelease) {
return DebuggingOptions.disabled(
@ -293,7 +293,6 @@ class RunCommand extends RunCommandBase {
"By default, the widgets library's binding takes care of sending this event.",
)
..addFlag('use-test-fonts',
negatable: true,
help: 'Enable (and default to) the "Ahem" font. This is a special font '
'used in tests to remove any dependencies on the font metrics. It '
'is enabled when you use "flutter test". Set this flag when running '
@ -315,12 +314,10 @@ class RunCommand extends RunCommandBase {
'and progress in machine friendly format.',
)
..addFlag('hot',
negatable: true,
defaultsTo: kHotReloadDefault,
help: 'Run with support for hot reloading. Only available for debug mode. Not available with "--trace-startup".',
)
..addFlag('resident',
negatable: true,
defaultsTo: true,
hide: !verboseHelp,
help: 'Stay resident after launching the application. Not available with "--trace-startup".',
@ -349,8 +346,6 @@ class RunCommand extends RunCommandBase {
// is slower for certain use cases.
// See: https://github.com/flutter/flutter/issues/49499
..addFlag('fast-start',
negatable: true,
defaultsTo: false,
help: 'Whether to quickly bootstrap applications with a minimal app. '
'Currently this is only supported on Android devices. This option '
'cannot be paired with "--${FlutterOptions.kUseApplicationBinary}".',
@ -371,25 +366,25 @@ class RunCommand extends RunCommandBase {
@override
String get category => FlutterCommandCategory.project;
List<Device> devices;
List<Device>? devices;
bool webMode = false;
String get userIdentifier => stringArgDeprecated(FlutterOptions.kDeviceUser);
String? get userIdentifier => stringArgDeprecated(FlutterOptions.kDeviceUser);
@override
bool get startPausedDefault => false;
@override
Future<String> get usagePath async {
final String command = await super.usagePath;
Future<String?> get usagePath async {
final String? command = await super.usagePath;
if (devices == null) {
return command;
}
if (devices.length > 1) {
if (devices!.length > 1) {
return '$command/all';
}
return '$command/${getNameForTargetPlatform(await devices[0].targetPlatform)}';
return '$command/${getNameForTargetPlatform(await devices![0].targetPlatform)}';
}
@override
@ -399,22 +394,22 @@ class RunCommand extends RunCommandBase {
bool anyAndroidDevices = false;
bool anyIOSDevices = false;
if (devices == null || devices.isEmpty) {
if (devices == null || devices!.isEmpty) {
deviceType = 'none';
deviceOsVersion = 'none';
isEmulator = false;
} else if (devices.length == 1) {
final TargetPlatform platform = await devices[0].targetPlatform;
} else if (devices!.length == 1) {
final TargetPlatform platform = await devices![0].targetPlatform;
anyAndroidDevices = platform == TargetPlatform.android;
anyIOSDevices = platform == TargetPlatform.ios;
deviceType = getNameForTargetPlatform(platform);
deviceOsVersion = await devices[0].sdkNameAndVersion;
isEmulator = await devices[0].isLocalEmulator;
deviceOsVersion = await devices![0].sdkNameAndVersion;
isEmulator = await devices![0].isLocalEmulator;
} else {
deviceType = 'multiple';
deviceOsVersion = 'multiple';
isEmulator = false;
for (final Device device in devices) {
for (final Device device in devices!) {
final TargetPlatform platform = await device.targetPlatform;
anyAndroidDevices = anyAndroidDevices || (platform == TargetPlatform.android);
anyIOSDevices = anyIOSDevices || (platform == TargetPlatform.ios);
@ -424,7 +419,7 @@ class RunCommand extends RunCommandBase {
}
}
String androidEmbeddingVersion;
String? androidEmbeddingVersion;
final List<String> hostLanguage = <String>[];
if (anyAndroidDevices) {
final AndroidProject androidProject = FlutterProject.current().android;
@ -469,7 +464,7 @@ class RunCommand extends RunCommandBase {
}
bool shouldUseHotMode(BuildInfo buildInfo) {
final bool hotArg = boolArgDeprecated('hot') ?? false;
final bool hotArg = boolArgDeprecated('hot');
final bool shouldUseHotMode = hotArg && !traceStartup;
return buildInfo.isDebug && shouldUseHotMode;
}
@ -489,33 +484,33 @@ class RunCommand extends RunCommandBase {
if (devices == null) {
throwToolExit(null);
}
if (globals.deviceManager.hasSpecifiedAllDevices && runningWithPrebuiltApplication) {
if (globals.deviceManager!.hasSpecifiedAllDevices && runningWithPrebuiltApplication) {
throwToolExit('Using "-d all" with "--${FlutterOptions.kUseApplicationBinary}" is not supported');
}
if (userIdentifier != null
&& devices.every((Device device) => device is! AndroidDevice)) {
&& devices!.every((Device device) => device is! AndroidDevice)) {
throwToolExit(
'--${FlutterOptions.kDeviceUser} is only supported for Android. At least one Android device is required.'
);
}
if (devices.any((Device device) => device is AndroidDevice)) {
if (devices!.any((Device device) => device is AndroidDevice)) {
_deviceDeprecationBehavior = DeprecationBehavior.exit;
}
// Only support "web mode" with a single web device due to resident runner
// refactoring required otherwise.
webMode = featureFlags.isWebEnabled &&
devices.length == 1 &&
await devices.single.targetPlatform == TargetPlatform.web_javascript;
devices!.length == 1 &&
await devices!.single.targetPlatform == TargetPlatform.web_javascript;
}
@visibleForTesting
Future<ResidentRunner> createRunner({
@required bool hotMode,
@required List<FlutterDevice> flutterDevices,
@required String applicationBinaryPath,
@required FlutterProject flutterProject,
Future<ResidentRunner?> createRunner({
required bool hotMode,
required List<FlutterDevice> flutterDevices,
required String? applicationBinaryPath,
required FlutterProject flutterProject,
}) async {
if (hotMode && !webMode) {
return HotRunner(
@ -529,11 +524,11 @@ class RunCommand extends RunCommandBase {
projectRootPath: stringArgDeprecated('project-root'),
dillOutputPath: stringArgDeprecated('output-dill'),
stayResident: stayResident,
ipv6: ipv6,
ipv6: ipv6 ?? false,
multidexEnabled: boolArgDeprecated('multidex'),
);
} else if (webMode) {
return webRunnerFactory.createWebRunner(
return webRunnerFactory!.createWebRunner(
flutterDevices.single,
target: targetFile,
flutterProject: flutterProject,
@ -556,7 +551,7 @@ class RunCommand extends RunCommandBase {
applicationBinary: applicationBinaryPath == null
? null
: globals.fs.file(applicationBinaryPath),
ipv6: ipv6,
ipv6: ipv6 ?? false,
stayResident: stayResident,
multidexEnabled: boolArgDeprecated('multidex'),
);
@ -583,33 +578,33 @@ class RunCommand extends RunCommandBase {
// debug mode.
final BuildInfo buildInfo = await getBuildInfo();
final bool hotMode = shouldUseHotMode(buildInfo);
final String applicationBinaryPath = stringArgDeprecated(FlutterOptions.kUseApplicationBinary);
final String? applicationBinaryPath = stringArgDeprecated(FlutterOptions.kUseApplicationBinary);
if (boolArgDeprecated('machine')) {
if (devices.length > 1) {
if (devices!.length > 1) {
throwToolExit('"--machine" does not support "-d all".');
}
final Daemon daemon = createMachineDaemon();
AppInstance app;
late AppInstance app;
try {
app = await daemon.appDomain.startApp(
devices.first, globals.fs.currentDirectory.path, targetFile, route,
devices!.first, globals.fs.currentDirectory.path, targetFile, route,
await createDebuggingOptions(webMode), hotMode,
applicationBinary: applicationBinaryPath == null
? null
: globals.fs.file(applicationBinaryPath),
trackWidgetCreation: trackWidgetCreation,
projectRootPath: stringArgDeprecated('project-root'),
packagesFilePath: globalResults['packages'] as String,
packagesFilePath: globalResults!['packages'] as String?,
dillOutputPath: stringArgDeprecated('output-dill'),
ipv6: ipv6,
ipv6: ipv6 ?? false,
multidexEnabled: boolArgDeprecated('multidex'),
);
} on Exception catch (error) {
throwToolExit(error.toString());
}
final DateTime appStartedTime = globals.systemClock.now();
final int result = await app.runner.waitForAppToFinish();
final int result = await app.runner!.waitForAppToFinish();
if (result != 0) {
throwToolExit(null, exitCode: result);
}
@ -622,7 +617,7 @@ class RunCommand extends RunCommandBase {
globals.terminal.usesTerminalUi = true;
final BuildMode buildMode = getBuildMode();
for (final Device device in devices) {
for (final Device device in devices!) {
if (!await device.supportsRuntimeMode(buildMode)) {
throwToolExit(
'${sentenceCase(getFriendlyModeName(buildMode))} '
@ -649,14 +644,14 @@ class RunCommand extends RunCommandBase {
}
}
List<String> expFlags;
List<String>? expFlags;
if (argParser.options.containsKey(FlutterOptions.kEnableExperiment) &&
stringsArg(FlutterOptions.kEnableExperiment).isNotEmpty) {
expFlags = stringsArg(FlutterOptions.kEnableExperiment);
}
final FlutterProject flutterProject = FlutterProject.current();
final List<FlutterDevice> flutterDevices = <FlutterDevice>[
for (final Device device in devices)
for (final Device device in devices!)
await FlutterDevice.create(
device,
experimentalFlags: expFlags,
@ -667,21 +662,21 @@ class RunCommand extends RunCommandBase {
),
];
final ResidentRunner runner = await createRunner(
final ResidentRunner runner = await (createRunner(
applicationBinaryPath: applicationBinaryPath,
flutterDevices: flutterDevices,
flutterProject: flutterProject,
hotMode: hotMode,
);
) as FutureOr<ResidentRunner>);
DateTime appStartedTime;
DateTime? appStartedTime;
// Sync completer so the completing agent attaching to the resident doesn't
// need to know about analytics.
//
// Do not add more operations to the future.
final Completer<void> appStartedTimeRecorder = Completer<void>.sync();
TerminalHandler handler;
TerminalHandler? handler;
// This callback can't throw.
unawaited(appStartedTimeRecorder.future.then<void>(
(_) {
@ -702,7 +697,7 @@ class RunCommand extends RunCommandBase {
}
));
try {
final int result = await runner.run(
final int? result = await runner.run(
appStartedCompleter: appStartedTimeRecorder,
enableDevTools: stayResident && boolArgDeprecated(FlutterCommand.kEnableDevTools),
route: route,
@ -723,14 +718,14 @@ class RunCommand extends RunCommandBase {
}
return FlutterCommandResult(
ExitStatus.success,
timingLabelParts: <String>[
timingLabelParts: <String?>[
if (hotMode) 'hot' else 'cold',
getModeName(getBuildMode()),
if (devices.length == 1)
getNameForTargetPlatform(await devices[0].targetPlatform)
if (devices!.length == 1)
getNameForTargetPlatform(await devices![0].targetPlatform)
else
'multiple',
if (devices.length == 1 && await devices[0].isLocalEmulator)
if (devices!.length == 1 && await devices![0].isLocalEmulator)
'emulator'
else
null,

View File

@ -2,7 +2,7 @@
// 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:math' as math;
@ -95,7 +95,6 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
help: 'Run only tests that do not have the specified tags. See: https://pub.dev/packages/test#tagging-tests',
)
..addFlag('start-paused',
defaultsTo: false,
negatable: false,
help: 'Start in a paused mode and wait for a debugger to connect.\n'
'You must specify a single test file to run, explicitly.\n'
@ -103,23 +102,19 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
'console once the test has started.',
)
..addFlag('run-skipped',
defaultsTo: false,
help: 'Run skipped tests instead of skipping them.',
)
..addFlag('disable-service-auth-codes',
defaultsTo: false,
negatable: false,
hide: !verboseHelp,
help: '(deprecated) Allow connections to the VM service without using authentication codes. '
'(Not recommended! This can open your device to remote code execution attacks!)'
)
..addFlag('coverage',
defaultsTo: false,
negatable: false,
help: 'Whether to collect coverage information.',
)
..addFlag('merge-coverage',
defaultsTo: false,
negatable: false,
help: 'Whether to merge coverage data with "coverage/lcov.base.info".\n'
'Implies collecting coverage data. (Requires lcov.)',
@ -153,7 +148,6 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
)
..addFlag('test-assets',
defaultsTo: true,
negatable: true,
help: 'Whether to build the assets bundle for testing. '
'This takes additional time before running the tests. '
'Consider using "--no-test-assets" if assets are not required.',
@ -191,7 +185,6 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
'them separately.'
)
..addFlag('enable-vmservice',
defaultsTo: false,
hide: !verboseHelp,
help: 'Enables the VM service without "--start-paused". This flag is '
'intended for use with tests that will use "dart:developer" to '
@ -255,8 +248,8 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
String get category => FlutterCommandCategory.project;
@override
Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) {
_testFiles = argResults.rest.map<String>(globals.fs.path.absolute).toList();
Future<FlutterCommandResult> verifyThenRunCommand(String? commandPath) {
_testFiles = argResults!.rest.map<String>(globals.fs.path.absolute).toList();
if (_testFiles.isEmpty) {
// We don't scan the entire package, only the test/ subdirectory, so that
// files with names like "hit_test.dart" don't get run.
@ -305,8 +298,8 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
final bool buildTestAssets = boolArgDeprecated('test-assets');
final List<String> names = stringsArg('name');
final List<String> plainNames = stringsArg('plain-name');
final String tags = stringArgDeprecated('tags');
final String excludeTags = stringArgDeprecated('exclude-tags');
final String? tags = stringArgDeprecated('tags');
final String? excludeTags = stringArgDeprecated('exclude-tags');
final BuildInfo buildInfo = await getBuildInfo(forcedBuildMode: BuildMode.debug);
if (buildInfo.packageConfig['test_api'] == null) {
@ -320,11 +313,11 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
);
}
String testAssetDirectory;
String? testAssetDirectory;
if (buildTestAssets) {
await _buildTestAsset();
testAssetDirectory = globals.fs.path.
join(flutterProject?.directory?.path ?? '', 'build', 'unit_test_assets');
join(flutterProject.directory.path, 'build', 'unit_test_assets');
}
final bool startPaused = boolArgDeprecated('start-paused');
@ -335,14 +328,14 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
);
}
int jobs = int.tryParse(stringArgDeprecated('concurrency'));
int? jobs = int.tryParse(stringArgDeprecated('concurrency')!);
if (jobs == null || jobs <= 0 || !jobs.isFinite) {
throwToolExit(
'Could not parse -j/--concurrency argument. It must be an integer greater than zero.'
);
}
if (_isIntegrationTest) {
if (argResults.wasParsed('concurrency')) {
if (argResults!.wasParsed('concurrency')) {
globals.printStatus(
'-j/--concurrency was parsed but will be ignored, this option is not '
'supported when running Integration Tests.',
@ -353,13 +346,13 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
jobs = 1;
}
final int shardIndex = int.tryParse(stringArgDeprecated('shard-index') ?? '');
final int? shardIndex = int.tryParse(stringArgDeprecated('shard-index') ?? '');
if (shardIndex != null && (shardIndex < 0 || !shardIndex.isFinite)) {
throwToolExit(
'Could not parse --shard-index=$shardIndex argument. It must be an integer greater than -1.');
}
final int totalShards = int.tryParse(stringArgDeprecated('total-shards') ?? '');
final int? totalShards = int.tryParse(stringArgDeprecated('total-shards') ?? '');
if (totalShards != null && (totalShards <= 0 || !totalShards.isFinite)) {
throwToolExit(
'Could not parse --total-shards=$totalShards argument. It must be an integer greater than zero.');
@ -375,7 +368,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
}
final bool machine = boolArgDeprecated('machine');
CoverageCollector collector;
CoverageCollector? collector;
if (boolArgDeprecated('coverage') || boolArgDeprecated('merge-coverage')) {
final String projectName = flutterProject.manifest.appName;
collector = CoverageCollector(
@ -385,7 +378,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
);
}
TestWatcher watcher;
TestWatcher? watcher;
if (machine) {
watcher = EventPrinter(parent: collector, out: globals.stdio.stdout);
} else if (collector != null) {
@ -402,7 +395,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
nullAssertions: boolArgDeprecated(FlutterOptions.kNullAssertions),
);
Device integrationTestDevice;
Device? integrationTestDevice;
if (_isIntegrationTest) {
integrationTestDevice = await findTargetDevice();

View File

@ -2,7 +2,7 @@
// 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';
@ -70,12 +70,12 @@ import 'windows/windows_workflow.dart';
Future<T> runInContext<T>(
FutureOr<T> Function() runner, {
Map<Type, Generator> overrides,
Map<Type, Generator>? overrides,
}) async {
// Wrap runner with any asynchronous initialization that should run with the
// overrides and callbacks.
bool runningOnBot;
late bool runningOnBot;
FutureOr<T> runnerWrapper() async {
runningOnBot = await globals.isRunningOnBot;
return runner();
@ -90,9 +90,9 @@ Future<T> runInContext<T>(
logger: globals.logger,
processManager: globals.processManager,
fileSystem: globals.fs,
artifacts: globals.artifacts,
artifacts: globals.artifacts!,
usage: globals.flutterUsage,
gradleUtils: globals.gradleUtils,
gradleUtils: globals.gradleUtils!,
platform: globals.platform,
),
AndroidLicenseValidator: () => AndroidLicenseValidator(
@ -158,11 +158,11 @@ Future<T> runInContext<T>(
processManager: globals.processManager,
logger: globals.logger,
platform: globals.platform,
xcodeProjectInterpreter: globals.xcodeProjectInterpreter,
xcodeProjectInterpreter: globals.xcodeProjectInterpreter!,
usage: globals.flutterUsage,
),
CocoaPodsValidator: () => CocoaPodsValidator(
globals.cocoaPods,
globals.cocoaPods!,
globals.userMessages,
),
Config: () => Config(
@ -187,29 +187,29 @@ Future<T> runInContext<T>(
processManager: globals.processManager,
platform: globals.platform,
androidSdk: globals.androidSdk,
iosSimulatorUtils: globals.iosSimulatorUtils,
iosSimulatorUtils: globals.iosSimulatorUtils!,
featureFlags: featureFlags,
fileSystem: globals.fs,
iosWorkflow: globals.iosWorkflow,
artifacts: globals.artifacts,
iosWorkflow: globals.iosWorkflow!,
artifacts: globals.artifacts!,
flutterVersion: globals.flutterVersion,
androidWorkflow: androidWorkflow,
fuchsiaWorkflow: fuchsiaWorkflow,
xcDevice: globals.xcdevice,
androidWorkflow: androidWorkflow!,
fuchsiaWorkflow: fuchsiaWorkflow!,
xcDevice: globals.xcdevice!,
userMessages: globals.userMessages,
windowsWorkflow: windowsWorkflow,
windowsWorkflow: windowsWorkflow!,
macOSWorkflow: MacOSWorkflow(
platform: globals.platform,
featureFlags: featureFlags,
),
fuchsiaSdk: globals.fuchsiaSdk,
fuchsiaSdk: globals.fuchsiaSdk!,
operatingSystemUtils: globals.os,
terminal: globals.terminal,
customDevicesConfig: globals.customDevicesConfig,
),
DevtoolsLauncher: () => DevtoolsServerLauncher(
processManager: globals.processManager,
dartExecutable: globals.artifacts.getHostArtifact(HostArtifact.engineDartBinary).path,
dartExecutable: globals.artifacts!.getHostArtifact(HostArtifact.engineDartBinary).path,
logger: globals.logger,
botDetector: globals.botDetector,
),
@ -220,7 +220,7 @@ Future<T> runInContext<T>(
processManager: globals.processManager,
logger: globals.logger,
fileSystem: globals.fs,
androidWorkflow: androidWorkflow,
androidWorkflow: androidWorkflow!,
),
FeatureFlags: () => FlutterFeatureFlags(
flutterVersion: globals.flutterVersion,
@ -234,7 +234,7 @@ Future<T> runInContext<T>(
FuchsiaWorkflow: () => FuchsiaWorkflow(
featureFlags: featureFlags,
platform: globals.platform,
fuchsiaArtifacts: globals.fuchsiaArtifacts,
fuchsiaArtifacts: globals.fuchsiaArtifacts!,
),
GradleUtils: () => GradleUtils(
fileSystem: globals.fs,
@ -247,11 +247,11 @@ Future<T> runInContext<T>(
IOSSimulatorUtils: () => IOSSimulatorUtils(
logger: globals.logger,
processManager: globals.processManager,
xcode: globals.xcode,
xcode: globals.xcode!,
),
IOSWorkflow: () => IOSWorkflow(
featureFlags: featureFlags,
xcode: globals.xcode,
xcode: globals.xcode!,
platform: globals.platform,
),
LocalEngineLocator: () => LocalEngineLocator(
@ -259,7 +259,7 @@ Future<T> runInContext<T>(
logger: globals.logger,
platform: globals.platform,
fileSystem: globals.fs,
flutterRoot: Cache.flutterRoot,
flutterRoot: Cache.flutterRoot!,
),
Logger: () => globals.platform.isWindows
? WindowsStdoutLogger(
@ -287,7 +287,7 @@ Future<T> runInContext<T>(
processManager: globals.processManager,
),
OutputPreferences: () => OutputPreferences(
wrapText: globals.stdio.hasTerminal ?? false,
wrapText: globals.stdio.hasTerminal,
showColor: globals.platform.stdoutSupportsAnsi,
stdio: globals.stdio,
),
@ -318,7 +318,7 @@ Future<T> runInContext<T>(
SystemClock: () => const SystemClock(),
Usage: () => Usage(
runningOnBot: runningOnBot,
firstRunMessenger: FirstRunMessenger(persistentToolState: globals.persistentToolState),
firstRunMessenger: FirstRunMessenger(persistentToolState: globals.persistentToolState!),
),
UserMessages: () => UserMessages(),
VisualStudioValidator: () => VisualStudioValidator(
@ -343,17 +343,17 @@ Future<T> runInContext<T>(
processManager: globals.processManager,
platform: globals.platform,
fileSystem: globals.fs,
xcodeProjectInterpreter: globals.xcodeProjectInterpreter,
xcodeProjectInterpreter: globals.xcodeProjectInterpreter!,
),
XCDevice: () => XCDevice(
processManager: globals.processManager,
logger: globals.logger,
artifacts: globals.artifacts,
artifacts: globals.artifacts!,
cache: globals.cache,
platform: globals.platform,
xcode: globals.xcode,
xcode: globals.xcode!,
iproxy: IProxy(
iproxyPath: globals.artifacts.getHostArtifact(
iproxyPath: globals.artifacts!.getHostArtifact(
HostArtifact.iproxy,
).path,
logger: globals.logger,

View File

@ -301,7 +301,7 @@ class DaemonConnection {
}
/// Sends an error response to the other end of the connection.
void sendErrorResponse(Object id, Object error, StackTrace trace) {
void sendErrorResponse(Object id, Object? error, StackTrace trace) {
_daemonStreams.send(<String, Object?>{
'id': id,
'error': error,

View File

@ -44,7 +44,7 @@ abstract class DesktopDevice extends Device {
final DesktopLogReader _deviceLogReader = DesktopLogReader();
@override
DevFSWriter createDevFSWriter(covariant ApplicationPackage app, String userIdentifier) {
DevFSWriter createDevFSWriter(covariant ApplicationPackage? app, String? userIdentifier) {
return LocalDevFSWriter(fileSystem: _fileSystem);
}

View File

@ -477,7 +477,7 @@ class DevFS {
final StopwatchFactory _stopwatchFactory;
final String fsName;
final Directory rootDirectory;
final Directory? rootDirectory;
final Set<String> assetPathsToEvict = <String>{};
// A flag to indicate whether we have called `setAssetDirectory` on the target device.
@ -497,7 +497,7 @@ class DevFS {
final String baseUriString = baseUri.toString();
if (deviceUriString.startsWith(baseUriString)) {
final String deviceUriSuffix = deviceUriString.substring(baseUriString.length);
return rootDirectory.uri.resolve(deviceUriSuffix);
return rootDirectory!.uri.resolve(deviceUriSuffix);
}
return deviceUri;
}

View File

@ -557,8 +557,8 @@ abstract class Device {
/// For example, the desktop device classes can use a writer which
/// copies the files across the local file system.
DevFSWriter? createDevFSWriter(
covariant ApplicationPackage app,
String userIdentifier,
covariant ApplicationPackage? app,
String? userIdentifier,
) {
return null;
}
@ -593,7 +593,7 @@ abstract class Device {
/// [platformArgs] allows callers to pass platform-specific arguments to the
/// start call. The build mode is not used by all platforms.
Future<LaunchResult> startApp(
covariant ApplicationPackage package, {
covariant ApplicationPackage? package, {
String? mainPath,
String? route,
required DebuggingOptions debuggingOptions,
@ -624,7 +624,7 @@ abstract class Device {
///
/// Specify [userIdentifier] to stop app installed to a profile (Android only).
Future<bool> stopApp(
covariant ApplicationPackage app, {
covariant ApplicationPackage? app, {
String? userIdentifier,
});

View File

@ -2,7 +2,7 @@
// 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';
@ -20,10 +20,10 @@ import 'resident_runner.dart';
/// start a server instance.
class DevtoolsServerLauncher extends DevtoolsLauncher {
DevtoolsServerLauncher({
@required ProcessManager processManager,
@required String dartExecutable,
@required Logger logger,
@required BotDetector botDetector,
required ProcessManager processManager,
required String dartExecutable,
required Logger? logger,
required BotDetector botDetector,
}) : _processManager = processManager,
_dartExecutable = dartExecutable,
_logger = logger,
@ -31,14 +31,14 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
final ProcessManager _processManager;
final String _dartExecutable;
final Logger _logger;
final Logger? _logger;
final BotDetector _botDetector;
final Completer<void> _processStartCompleter = Completer<void>();
io.Process _devToolsProcess;
io.Process? _devToolsProcess;
bool _devToolsProcessKilled = false;
@visibleForTesting
Future<void> devToolsProcessExit;
Future<void>? devToolsProcessExit;
static final RegExp _serveDevToolsPattern =
RegExp(r'Serving DevTools at ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+?)\.?$');
@ -47,7 +47,7 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
Future<void> get processStart => _processStartCompleter.future;
@override
Future<void> launch(Uri vmServiceUri, {List<String> additionalArguments}) async {
Future<void> launch(Uri? vmServiceUri, {List<String>? additionalArguments}) async {
// Place this entire method in a try/catch that swallows exceptions because
// this method is guaranteed not to return a Future that throws.
try {
@ -60,23 +60,23 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
]);
_processStartCompleter.complete();
final Completer<Uri> completer = Completer<Uri>();
_devToolsProcess.stdout
_devToolsProcess!.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen((String line) {
final Match match = _serveDevToolsPattern.firstMatch(line);
final Match? match = _serveDevToolsPattern.firstMatch(line);
if (match != null) {
final String url = match[1];
final String url = match[1]!;
completer.complete(Uri.parse(url));
}
});
_devToolsProcess.stderr
_devToolsProcess!.stderr
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen(_logger.printError);
.listen(_logger!.printError);
final bool runningOnBot = await _botDetector.isRunningOnBot;
devToolsProcessExit = _devToolsProcess.exitCode.then(
devToolsProcessExit = _devToolsProcess!.exitCode.then(
(int exitCode) {
if (!_devToolsProcessKilled && runningOnBot) {
throwToolExit('DevTools process failed: exitCode=$exitCode');
@ -86,12 +86,12 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
devToolsUrl = await completer.future;
} on Exception catch (e, st) {
_logger.printError('Failed to launch DevTools: $e', stackTrace: st);
_logger!.printError('Failed to launch DevTools: $e', stackTrace: st);
}
}
@override
Future<DevToolsServerAddress> serve() async {
Future<DevToolsServerAddress?> serve() async {
if (activeDevToolsServer == null) {
await launch(null);
}
@ -105,7 +105,7 @@ class DevtoolsServerLauncher extends DevtoolsLauncher {
}
if (_devToolsProcess != null) {
_devToolsProcessKilled = true;
_devToolsProcess.kill();
_devToolsProcess!.kill();
}
}
}

View File

@ -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:dds/dds.dart' as dds;
@ -25,11 +23,11 @@ import 'web_driver_service.dart';
class FlutterDriverFactory {
FlutterDriverFactory({
@required ApplicationPackageFactory applicationPackageFactory,
@required Logger logger,
@required ProcessUtils processUtils,
@required String dartSdkPath,
@required DevtoolsLauncher devtoolsLauncher,
required ApplicationPackageFactory applicationPackageFactory,
required Logger logger,
required ProcessUtils processUtils,
required String dartSdkPath,
required DevtoolsLauncher devtoolsLauncher,
}) : _applicationPackageFactory = applicationPackageFactory,
_logger = logger,
_processUtils = processUtils,
@ -69,10 +67,10 @@ abstract class DriverService {
Device device,
DebuggingOptions debuggingOptions,
bool ipv6, {
File applicationBinary,
String route,
String userIdentifier,
String mainPath,
File? applicationBinary,
String? route,
String? userIdentifier,
String? mainPath,
Map<String, Object> platformArgs = const <String, Object>{},
});
@ -94,13 +92,13 @@ abstract class DriverService {
List<String> arguments,
Map<String, String> environment,
PackageConfig packageConfig, {
bool headless,
String chromeBinary,
String browserName,
bool androidEmulator,
int driverPort,
List<String> browserDimension,
String profileMemory,
bool? headless,
String? chromeBinary,
String? browserName,
bool? androidEmulator,
int? driverPort,
List<String>? browserDimension,
String? profileMemory,
});
/// Stop the running application and uninstall it from the device.
@ -109,8 +107,8 @@ abstract class DriverService {
/// and write SkSL to the file. This is only supported on mobile and
/// desktop devices.
Future<void> stop({
File writeSkslOnExit,
String userIdentifier,
File? writeSkslOnExit,
String? userIdentifier,
});
}
@ -118,11 +116,11 @@ abstract class DriverService {
/// applications.
class FlutterDriverService extends DriverService {
FlutterDriverService({
@required ApplicationPackageFactory applicationPackageFactory,
@required Logger logger,
@required ProcessUtils processUtils,
@required String dartSdkPath,
@required DevtoolsLauncher devtoolsLauncher,
required ApplicationPackageFactory applicationPackageFactory,
required Logger logger,
required ProcessUtils processUtils,
required String dartSdkPath,
required DevtoolsLauncher devtoolsLauncher,
@visibleForTesting VMServiceConnector vmServiceConnector = connectToVmService,
}) : _applicationPackageFactory = applicationPackageFactory,
_logger = logger,
@ -140,10 +138,10 @@ class FlutterDriverService extends DriverService {
final VMServiceConnector _vmServiceConnector;
final DevtoolsLauncher _devtoolsLauncher;
Device _device;
ApplicationPackage _applicationPackage;
String _vmServiceUri;
FlutterVmService _vmService;
Device? _device;
ApplicationPackage? _applicationPackage;
late String _vmServiceUri;
late FlutterVmService _vmService;
@override
Future<void> start(
@ -151,11 +149,11 @@ class FlutterDriverService extends DriverService {
Device device,
DebuggingOptions debuggingOptions,
bool ipv6, {
File applicationBinary,
String route,
String userIdentifier,
File? applicationBinary,
String? route,
String? userIdentifier,
Map<String, Object> platformArgs = const <String, Object>{},
String mainPath,
String? mainPath,
}) async {
if (buildInfo.isRelease) {
throwToolExit(
@ -173,7 +171,7 @@ class FlutterDriverService extends DriverService {
applicationBinary: applicationBinary,
);
int attempt = 0;
LaunchResult result;
LaunchResult? result;
bool prebuiltApplication = applicationBinary != null;
while (attempt < _kLaunchAttempts) {
result = await device.startApp(
@ -197,7 +195,7 @@ class FlutterDriverService extends DriverService {
throwToolExit('Application failed to start. Will not run test. Quitting.', exitCode: 1);
}
return reuseApplication(
result.observatoryUri,
result.observatoryUri!,
device,
debuggingOptions,
ipv6,
@ -251,13 +249,13 @@ class FlutterDriverService extends DriverService {
List<String> arguments,
Map<String, String> environment,
PackageConfig packageConfig, {
bool headless,
String chromeBinary,
String browserName,
bool androidEmulator,
int driverPort,
List<String> browserDimension,
String profileMemory,
bool? headless,
String? chromeBinary,
String? browserName,
bool? androidEmulator,
int? driverPort,
List<String>? browserDimension,
String? profileMemory,
}) async {
if (profileMemory != null) {
unawaited(_devtoolsLauncher.launch(
@ -285,35 +283,35 @@ class FlutterDriverService extends DriverService {
@override
Future<void> stop({
File writeSkslOnExit,
String userIdentifier,
File? writeSkslOnExit,
String? userIdentifier,
}) async {
if (writeSkslOnExit != null) {
final FlutterView flutterView = (await _vmService.getFlutterViews()).first;
final Map<String, Object> result = await _vmService.getSkSLs(
final Map<String, Object> result = await (_vmService.getSkSLs(
viewId: flutterView.id
);
await sharedSkSlWriter(_device, result, outputFile: writeSkslOnExit, logger: _logger);
) as FutureOr<Map<String, Object>>);
await sharedSkSlWriter(_device!, result, outputFile: writeSkslOnExit, logger: _logger);
}
// If the application package is available, stop and uninstall.
if (_applicationPackage != null) {
if (!await _device.stopApp(_applicationPackage, userIdentifier: userIdentifier)) {
if (!await _device!.stopApp(_applicationPackage, userIdentifier: userIdentifier)) {
_logger.printError('Failed to stop app');
}
if (!await _device.uninstallApp(_applicationPackage, userIdentifier: userIdentifier)) {
if (!await _device!.uninstallApp(_applicationPackage!, userIdentifier: userIdentifier)) {
_logger.printError('Failed to uninstall app');
}
} else if (_device.supportsFlutterExit) {
} else if (_device!.supportsFlutterExit) {
// Otherwise use the VM Service URI to stop the app as a best effort approach.
final vm_service.VM vm = await _vmService.service.getVM();
final vm_service.IsolateRef isolateRef = vm.isolates
final vm_service.IsolateRef isolateRef = vm.isolates!
.firstWhere((vm_service.IsolateRef element) {
return !element.isSystemIsolate;
}, orElse: () => null);
unawaited(_vmService.flutterExit(isolateId: isolateRef.id));
return !element.isSystemIsolate!;
});
unawaited(_vmService.flutterExit(isolateId: isolateRef.id!));
} else {
_logger.printTrace('No application package for $_device, leaving app running');
}
await _device.dispose();
await _device!.dispose();
}
}

View File

@ -2,7 +2,7 @@
// 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:math' as math;
@ -28,9 +28,9 @@ import 'drive_service.dart';
/// An implementation of the driver service for web debug and release applications.
class WebDriverService extends DriverService {
WebDriverService({
@required ProcessUtils processUtils,
@required String dartSdkPath,
@required Logger logger,
required ProcessUtils processUtils,
required String dartSdkPath,
required Logger logger,
}) : _processUtils = processUtils,
_dartSdkPath = dartSdkPath,
_logger = logger;
@ -39,15 +39,15 @@ class WebDriverService extends DriverService {
final String _dartSdkPath;
final Logger _logger;
ResidentRunner _residentRunner;
Uri _webUri;
late ResidentRunner _residentRunner;
Uri? _webUri;
/// The result of [ResidentRunner.run].
///
/// This is expected to stay `null` throughout the test, as the application
/// must be running until [stop] is called. If it becomes non-null, it likely
/// indicates a bug.
int _runResult;
int? _runResult;
@override
Future<void> start(
@ -55,10 +55,10 @@ class WebDriverService extends DriverService {
Device device,
DebuggingOptions debuggingOptions,
bool ipv6, {
File applicationBinary,
String route,
String userIdentifier,
String mainPath,
File? applicationBinary,
String? route,
String? userIdentifier,
String? mainPath,
Map<String, Object> platformArgs = const <String, Object>{},
}) async {
final FlutterDevice flutterDevice = await FlutterDevice.create(
@ -67,7 +67,7 @@ class WebDriverService extends DriverService {
buildInfo: buildInfo,
platform: globals.platform,
);
_residentRunner = webRunnerFactory.createWebRunner(
_residentRunner = webRunnerFactory!.createWebRunner(
flutterDevice,
target: mainPath,
ipv6: ipv6,
@ -90,21 +90,21 @@ class WebDriverService extends DriverService {
systemClock: globals.systemClock,
);
final Completer<void> appStartedCompleter = Completer<void>.sync();
final Future<int> runFuture = _residentRunner.run(
final Future<int?> runFuture = _residentRunner.run(
appStartedCompleter: appStartedCompleter,
route: route,
);
bool isAppStarted = false;
await Future.any<Object>(<Future<Object>>[
runFuture.then((int result) {
runFuture.then((int? result) {
_runResult = result;
return null;
}),
} as FutureOr<Object> Function(int?)),
appStartedCompleter.future.then((_) {
isAppStarted = true;
return null;
}),
} as FutureOr<Object> Function(void)),
]);
if (_runResult != null) {
@ -126,22 +126,25 @@ class WebDriverService extends DriverService {
}
@override
Future<int> startTest(String testFile, List<String> arguments, Map<String, String> environment, PackageConfig packageConfig, {
@required bool headless,
String chromeBinary,
@required String browserName,
bool androidEmulator,
int driverPort,
List<String> browserDimension,
String profileMemory,
Future<int> startTest(
String testFile,
List<String> arguments,
Map<String, String> environment,
PackageConfig packageConfig, {
bool? headless,
String? chromeBinary,
String? browserName,
bool? androidEmulator,
int? driverPort,
List<String>? browserDimension,
String? profileMemory,
}) async {
async_io.WebDriver webDriver;
late async_io.WebDriver webDriver;
final Browser browser = _browserNameToEnum(browserName);
try {
webDriver = await async_io.createDriver(
uri: Uri.parse('http://localhost:$driverPort/'),
desired: getDesiredCapabilities(browser, headless, chromeBinary),
spec: async_io.WebDriverSpec.Auto
);
} on SocketException catch (error) {
_logger.printTrace('$error');
@ -156,11 +159,11 @@ class WebDriverService extends DriverService {
final bool isAndroidChrome = browser == Browser.androidChrome;
// Do not set the window size for android chrome browser.
if (!isAndroidChrome) {
assert(browserDimension.length == 2);
int x;
int y;
assert(browserDimension!.length == 2);
late int x;
late int y;
try {
x = int.parse(browserDimension[0]);
x = int.parse(browserDimension![0]);
y = int.parse(browserDimension[1]);
} on FormatException catch (ex) {
throwToolExit('Dimension provided to --browser-dimension is invalid: $ex');
@ -184,7 +187,7 @@ class WebDriverService extends DriverService {
}
@override
Future<void> stop({File writeSkslOnExit, String userIdentifier}) async {
Future<void> stop({File? writeSkslOnExit, String? userIdentifier}) async {
final bool appDidFinishPrematurely = _runResult != null;
await _residentRunner.exitApp();
await _residentRunner.cleanupAtFinish();
@ -197,7 +200,7 @@ class WebDriverService extends DriverService {
}
}
Map<String, String> _additionalDriverEnvironment(async_io.WebDriver webDriver, String browserName, bool androidEmulator) {
Map<String, String> _additionalDriverEnvironment(async_io.WebDriver webDriver, String? browserName, bool? androidEmulator) {
return <String, String>{
'DRIVER_SESSION_ID': webDriver.id,
'DRIVER_SESSION_URI': webDriver.uri.toString(),
@ -205,7 +208,7 @@ class WebDriverService extends DriverService {
'DRIVER_SESSION_CAPABILITIES': json.encode(webDriver.capabilities),
'SUPPORT_TIMELINE_ACTION': (_browserNameToEnum(browserName) == Browser.chrome).toString(),
'FLUTTER_WEB_TEST': 'true',
'ANDROID_CHROME_ON_EMULATOR': (_browserNameToEnum(browserName) == Browser.androidChrome && androidEmulator).toString(),
'ANDROID_CHROME_ON_EMULATOR': (_browserNameToEnum(browserName) == Browser.androidChrome && androidEmulator!).toString(),
};
}
@ -234,7 +237,7 @@ enum Browser {
/// Returns desired capabilities for given [browser], [headless] and
/// [chromeBinary].
@visibleForTesting
Map<String, dynamic> getDesiredCapabilities(Browser browser, bool headless, [String chromeBinary]) {
Map<String, dynamic> getDesiredCapabilities(Browser browser, bool? headless, [String? chromeBinary]) {
switch (browser) {
case Browser.chrome:
return <String, dynamic>{
@ -258,7 +261,7 @@ Map<String, dynamic> getDesiredCapabilities(Browser browser, bool headless, [Str
'--no-default-browser-check',
'--no-sandbox',
'--no-first-run',
if (headless) '--headless',
if (headless!) '--headless',
],
'perfLoggingPrefs': <String, String>{
'traceCategories':
@ -268,14 +271,13 @@ Map<String, dynamic> getDesiredCapabilities(Browser browser, bool headless, [Str
},
},
};
break;
case Browser.firefox:
return <String, dynamic>{
'acceptInsecureCerts': true,
'browserName': 'firefox',
'moz:firefoxOptions' : <String, dynamic>{
'args': <String>[
if (headless) '-headless',
if (headless!) '-headless',
],
'prefs': <String, dynamic>{
'dom.file.createInChild': true,
@ -290,18 +292,15 @@ Map<String, dynamic> getDesiredCapabilities(Browser browser, bool headless, [Str
'log': <String, String>{'level': 'trace'},
},
};
break;
case Browser.edge:
return <String, dynamic>{
'acceptInsecureCerts': true,
'browserName': 'edge',
};
break;
case Browser.safari:
return <String, dynamic>{
'browserName': 'safari',
};
break;
case Browser.iosSafari:
return <String, dynamic>{
'platformName': 'ios',
@ -318,11 +317,10 @@ Map<String, dynamic> getDesiredCapabilities(Browser browser, bool headless, [Str
},
};
}
throw UnsupportedError('Browser $browser not supported.'); // dead code; remove with null safety migration
}
/// Converts [browserName] string to [Browser]
Browser _browserNameToEnum(String browserName) {
Browser _browserNameToEnum(String? browserName) {
switch (browserName) {
case 'android-chrome': return Browser.androidChrome;
case 'chrome': return Browser.chrome;

View File

@ -25,7 +25,7 @@ import 'windows/application_package.dart';
/// A package factory that supports all Flutter target platforms.
class FlutterApplicationPackageFactory extends ApplicationPackageFactory {
FlutterApplicationPackageFactory({
required AndroidSdk androidSdk,
required AndroidSdk? androidSdk,
required ProcessManager processManager,
required Logger logger,
required UserMessages userMessages,
@ -38,7 +38,7 @@ class FlutterApplicationPackageFactory extends ApplicationPackageFactory {
_processUtils = ProcessUtils(logger: logger, processManager: processManager);
final AndroidSdk _androidSdk;
final AndroidSdk? _androidSdk;
final ProcessManager _processManager;
final Logger _logger;
final ProcessUtils _processUtils;
@ -72,7 +72,7 @@ class FlutterApplicationPackageFactory extends ApplicationPackageFactory {
applicationBinary,
processManager: _processManager,
logger: _logger,
androidSdk: _androidSdk,
androidSdk: _androidSdk!,
userMessages: _userMessages,
processUtils: _processUtils,
);

View File

@ -40,7 +40,7 @@ class FlutterDeviceManager extends DeviceManager {
required Platform platform,
required ProcessManager processManager,
required FileSystem fileSystem,
required AndroidSdk androidSdk,
required AndroidSdk? androidSdk,
required FeatureFlags featureFlags,
required IOSSimulatorUtils iosSimulatorUtils,
required XCDevice xcDevice,

View File

@ -338,7 +338,7 @@ class IOSSimulator extends Device {
final SimControl _simControl;
@override
DevFSWriter createDevFSWriter(covariant ApplicationPackage app, String userIdentifier) {
DevFSWriter createDevFSWriter(covariant ApplicationPackage? app, String? userIdentifier) {
return LocalDevFSWriter(fileSystem: globals.fs);
}

View File

@ -2,12 +2,11 @@
// 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';
import 'package:dwds/data/build_result.dart';
// ignore: import_of_legacy_library_into_null_safe
import 'package:dwds/dwds.dart';
import 'package:html/dom.dart';
import 'package:html/parser.dart';
@ -46,24 +45,24 @@ import '../web/memory_fs.dart';
import 'sdk_web_configuration.dart';
typedef DwdsLauncher = Future<Dwds> Function({
@required AssetReader assetReader,
@required Stream<BuildResult> buildResults,
@required ConnectionProvider chromeConnection,
@required LoadStrategy loadStrategy,
@required bool enableDebugging,
ExpressionCompiler expressionCompiler,
bool enableDebugExtension,
String hostname,
bool useSseForDebugProxy,
bool useSseForDebugBackend,
bool useSseForInjectedClient,
UrlEncoder urlEncoder,
bool spawnDds,
bool enableDevtoolsLaunch,
DevtoolsLauncher devtoolsLauncher,
bool launchDevToolsInNewWindow,
SdkConfigurationProvider sdkConfigurationProvider,
bool emitDebugEvents,
required AssetReader assetReader,
required Stream<BuildResult> buildResults,
required ConnectionProvider chromeConnection,
required LoadStrategy loadStrategy,
required bool enableDebugging,
ExpressionCompiler? expressionCompiler,
bool? enableDebugExtension,
String? hostname,
bool? useSseForDebugProxy,
bool? useSseForDebugBackend,
bool? useSseForInjectedClient,
UrlEncoder? urlEncoder,
bool? spawnDds,
bool? enableDevtoolsLaunch,
DevtoolsLauncher? devtoolsLauncher,
bool? launchDevToolsInNewWindow,
SdkConfigurationProvider? sdkConfigurationProvider,
bool? emitDebugEvents,
});
// A minimal index for projects that do not yet support web.
@ -83,11 +82,11 @@ const String _kDefaultIndex = '''
/// This is only used in development mode.
class WebExpressionCompiler implements ExpressionCompiler {
WebExpressionCompiler(this._generator, {
@required FileSystem fileSystem,
required FileSystem? fileSystem,
}) : _fileSystem = fileSystem;
final ResidentCompiler _generator;
final FileSystem _fileSystem;
final FileSystem? _fileSystem;
@override
Future<ExpressionCompilationResult> compileExpressionToJs(
@ -100,13 +99,13 @@ class WebExpressionCompiler implements ExpressionCompiler {
String moduleName,
String expression,
) async {
final CompilerOutput compilerOutput =
final CompilerOutput? compilerOutput =
await _generator.compileExpressionToJs(libraryUri, line, column,
jsModules, jsFrameValues, moduleName, expression);
if (compilerOutput != null && compilerOutput.outputFilename != null) {
final String content = utf8.decode(
_fileSystem.file(compilerOutput.outputFilename).readAsBytesSync());
_fileSystem!.file(compilerOutput.outputFilename).readAsBytesSync());
return ExpressionCompilationResult(
content, compilerOutput.errorCount > 0);
}
@ -117,7 +116,7 @@ class WebExpressionCompiler implements ExpressionCompiler {
}
@override
Future<void> initialize({String moduleFormat, bool soundNullSafety}) async {}
Future<void> initialize({String? moduleFormat, bool? soundNullSafety}) async {}
@override
Future<bool> updateDependencies(Map<String, ModuleInfo> modules) async => true;
@ -180,10 +179,10 @@ class WebAssetServer implements AssetReader {
/// Unhandled exceptions will throw a [ToolExit] with the error and stack
/// trace.
static Future<WebAssetServer> start(
ChromiumLauncher chromiumLauncher,
ChromiumLauncher? chromiumLauncher,
String hostname,
int port,
UrlTunneller urlTunneller,
int? port,
UrlTunneller? urlTunneller,
bool useSseForDebugProxy,
bool useSseForDebugBackend,
bool useSseForInjectedClient,
@ -191,7 +190,7 @@ class WebAssetServer implements AssetReader {
bool enableDwds,
bool enableDds,
Uri entrypoint,
ExpressionCompiler expressionCompiler,
ExpressionCompiler? expressionCompiler,
NullSafetyMode nullSafetyMode, {
bool testMode = false,
DwdsLauncher dwdsLauncher = Dwds.start,
@ -202,7 +201,7 @@ class WebAssetServer implements AssetReader {
} else {
address = (await InternetAddress.lookup(hostname)).first;
}
HttpServer httpServer;
HttpServer? httpServer;
const int kMaxRetries = 4;
for (int i = 0; i <= kMaxRetries; i++) {
try {
@ -218,7 +217,7 @@ class WebAssetServer implements AssetReader {
}
// Allow rendering in a iframe.
httpServer.defaultResponseHeaders.remove('x-frame-options', 'SAMEORIGIN');
httpServer!.defaultResponseHeaders.remove('x-frame-options', 'SAMEORIGIN');
final PackageConfig packageConfig = buildInfo.packageConfig;
final Map<String, String> digests = <String, String>{};
@ -246,7 +245,7 @@ class WebAssetServer implements AssetReader {
basePath: server.basePath,
);
runZonedGuarded(() {
shelf.serveRequests(httpServer, releaseAssetServer.handle);
shelf.serveRequests(httpServer!, releaseAssetServer.handle);
}, (Object e, StackTrace s) {
globals.printTrace('Release asset server: error serving requests: $e:$s');
});
@ -284,7 +283,7 @@ class WebAssetServer implements AssetReader {
enableDebugExtension: true,
buildResults: const Stream<BuildResult>.empty(),
chromeConnection: () async {
final Chromium chromium = await chromiumLauncher.connectedInstance;
final Chromium chromium = await chromiumLauncher!.connectedInstance;
return chromium.chromeConnection;
},
hostname: hostname,
@ -297,11 +296,11 @@ class WebAssetServer implements AssetReader {
ReloadConfiguration.none,
server,
digestProvider,
server.basePath,
server.basePath!,
).strategy,
expressionCompiler: expressionCompiler,
spawnDds: enableDds,
sdkConfigurationProvider: SdkWebConfigurationProvider(globals.artifacts),
sdkConfigurationProvider: SdkWebConfigurationProvider(globals.artifacts!),
);
shelf.Pipeline pipeline = const shelf.Pipeline();
if (enableDwds) {
@ -313,42 +312,42 @@ class WebAssetServer implements AssetReader {
final shelf.Cascade cascade =
shelf.Cascade().add(dwds.handler).add(dwdsHandler);
runZonedGuarded(() {
shelf.serveRequests(httpServer, cascade.handler);
shelf.serveRequests(httpServer!, cascade.handler);
}, (Object e, StackTrace s) {
globals.printTrace('Dwds server: error serving requests: $e:$s');
});
server.dwds = dwds;
server._dwdsInit = true;
return server;
}
final NullSafetyMode _nullSafetyMode;
final HttpServer _httpServer;
final WebMemoryFS _webMemoryFS = WebMemoryFS();
final PackageConfig _packages;
final InternetAddress internetAddress;
/* late final */ Dwds dwds;
Directory entrypointCacheDirectory;
late final Dwds dwds;
late Directory entrypointCacheDirectory;
bool _dwdsInit = false;
@visibleForTesting
HttpHeaders get defaultResponseHeaders => _httpServer.defaultResponseHeaders;
@visibleForTesting
Uint8List getFile(String path) => _webMemoryFS.files[path];
Uint8List? getFile(String path) => _webMemoryFS.files[path];
@visibleForTesting
Uint8List getSourceMap(String path) => _webMemoryFS.sourcemaps[path];
Uint8List? getSourceMap(String path) => _webMemoryFS.sourcemaps[path];
@visibleForTesting
Uint8List getMetadata(String path) => _webMemoryFS.metadataFiles[path];
Uint8List? getMetadata(String path) => _webMemoryFS.metadataFiles[path];
@visibleForTesting
/// The base path to serve from.
///
/// It should have no leading or trailing slashes.
String basePath = '';
String? basePath = '';
// handle requests for JavaScript source, dart sources maps, or asset files.
@visibleForTesting
@ -358,7 +357,7 @@ class WebAssetServer implements AssetReader {
return shelf.Response.notFound('');
}
final String requestPath = _stripBasePath(request.url.path, basePath);
final String? requestPath = _stripBasePath(request.url.path, basePath);
if (requestPath == null) {
return shelf.Response.notFound('');
@ -372,7 +371,7 @@ class WebAssetServer implements AssetReader {
final Map<String, String> headers = <String, String>{};
// Track etag headers for better caching of resources.
final String ifNoneMatch = request.headers[HttpHeaders.ifNoneMatchHeader];
final String? ifNoneMatch = request.headers[HttpHeaders.ifNoneMatchHeader];
headers[HttpHeaders.cacheControlHeader] = 'max-age=0, must-revalidate';
// If this is a JavaScript file, it must be in the in-memory cache.
@ -380,7 +379,7 @@ class WebAssetServer implements AssetReader {
final String webServerPath =
requestPath.replaceFirst('.dart.js', '.dart.lib.js');
if (_webMemoryFS.files.containsKey(requestPath) || _webMemoryFS.files.containsKey(webServerPath)) {
final List<int> bytes = getFile(requestPath) ?? getFile(webServerPath);
final List<int>? bytes = getFile(requestPath) ?? getFile(webServerPath);
// Use the underlying buffer hashCode as a revision string. This buffer is
// replaced whenever the frontend_server produces new output files, which
// will also change the hashCode.
@ -388,7 +387,7 @@ class WebAssetServer implements AssetReader {
if (ifNoneMatch == etag) {
return shelf.Response.notModified();
}
headers[HttpHeaders.contentLengthHeader] = bytes.length.toString();
headers[HttpHeaders.contentLengthHeader] = bytes!.length.toString();
headers[HttpHeaders.contentTypeHeader] = 'application/javascript';
headers[HttpHeaders.etagHeader] = etag;
return shelf.Response.ok(bytes, headers: headers);
@ -396,12 +395,12 @@ class WebAssetServer implements AssetReader {
// If this is a sourcemap file, then it might be in the in-memory cache.
// Attempt to lookup the file by URI.
if (_webMemoryFS.sourcemaps.containsKey(requestPath)) {
final List<int> bytes = getSourceMap(requestPath);
final List<int>? bytes = getSourceMap(requestPath);
final String etag = bytes.hashCode.toString();
if (ifNoneMatch == etag) {
return shelf.Response.notModified();
}
headers[HttpHeaders.contentLengthHeader] = bytes.length.toString();
headers[HttpHeaders.contentLengthHeader] = bytes!.length.toString();
headers[HttpHeaders.contentTypeHeader] = 'application/json';
headers[HttpHeaders.etagHeader] = etag;
return shelf.Response.ok(bytes, headers: headers);
@ -410,12 +409,12 @@ class WebAssetServer implements AssetReader {
// If this is a metadata file, then it might be in the in-memory cache.
// Attempt to lookup the file by URI.
if (_webMemoryFS.metadataFiles.containsKey(requestPath)) {
final List<int> bytes = getMetadata(requestPath);
final List<int>? bytes = getMetadata(requestPath);
final String etag = bytes.hashCode.toString();
if (ifNoneMatch == etag) {
return shelf.Response.notModified();
}
headers[HttpHeaders.contentLengthHeader] = bytes.length.toString();
headers[HttpHeaders.contentLengthHeader] = bytes!.length.toString();
headers[HttpHeaders.contentTypeHeader] = 'application/json';
headers[HttpHeaders.etagHeader] = etag;
return shelf.Response.ok(bytes, headers: headers);
@ -475,7 +474,9 @@ class WebAssetServer implements AssetReader {
/// Tear down the http server running.
Future<void> dispose() async {
await dwds?.stop();
if (_dwdsInit) {
await dwds.stop();
}
return _httpServer.close();
}
@ -546,7 +547,7 @@ class WebAssetServer implements AssetReader {
// The file might have been a package file which is signaled by a
// `/packages/<package>/<path>` request.
if (segments.first == 'packages') {
final Uri filePath = _packages
final Uri? filePath = _packages
.resolve(Uri(scheme: 'package', pathSegments: segments.skip(1)));
if (filePath != null) {
final File packageFile = globals.fs.file(filePath);
@ -559,7 +560,7 @@ class WebAssetServer implements AssetReader {
// Otherwise it must be a Dart SDK source or a Flutter Web SDK source.
final Directory dartSdkParent = globals.fs
.directory(
globals.artifacts.getHostArtifact(HostArtifact.engineDartSdkPath))
globals.artifacts!.getHostArtifact(HostArtifact.engineDartSdkPath))
.parent;
final File dartSdkFile = globals.fs.file(dartSdkParent.uri.resolve(path));
if (dartSdkFile.existsSync()) {
@ -567,25 +568,25 @@ class WebAssetServer implements AssetReader {
}
final Directory flutterWebSdk = globals.fs
.directory(globals.artifacts.getHostArtifact(HostArtifact.flutterWebSdk));
.directory(globals.artifacts!.getHostArtifact(HostArtifact.flutterWebSdk));
final File webSdkFile = globals.fs.file(flutterWebSdk.uri.resolve(path));
return webSdkFile;
}
File get _resolveDartSdkJsFile =>
globals.fs.file(globals.artifacts.getHostArtifact(
kDartSdkJsArtifactMap[webRenderer][_nullSafetyMode]
globals.fs.file(globals.artifacts!.getHostArtifact(
kDartSdkJsArtifactMap[webRenderer]![_nullSafetyMode]!
));
File get _resolveDartSdkJsMapFile =>
globals.fs.file(globals.artifacts.getHostArtifact(
kDartSdkJsMapArtifactMap[webRenderer][_nullSafetyMode]
globals.fs.file(globals.artifacts!.getHostArtifact(
kDartSdkJsMapArtifactMap[webRenderer]![_nullSafetyMode]!
));
@override
Future<String> dartSourceContents(String serverPath) async {
serverPath = _stripBasePath(serverPath, basePath);
Future<String?> dartSourceContents(String serverPath) async {
serverPath = _stripBasePath(serverPath, basePath)!;
final File result = _resolveDartFile(serverPath);
if (result.existsSync()) {
return result.readAsString();
@ -595,18 +596,18 @@ class WebAssetServer implements AssetReader {
@override
Future<String> sourceMapContents(String serverPath) async {
serverPath = _stripBasePath(serverPath, basePath);
return utf8.decode(_webMemoryFS.sourcemaps[serverPath]);
serverPath = _stripBasePath(serverPath, basePath)!;
return utf8.decode(_webMemoryFS.sourcemaps[serverPath]!);
}
@override
Future<String> metadataContents(String serverPath) async {
serverPath = _stripBasePath(serverPath, basePath);
if (serverPath == 'main_module.ddc_merged_metadata') {
Future<String?> metadataContents(String serverPath) async {
final String? resultPath = _stripBasePath(serverPath, basePath);
if (resultPath == 'main_module.ddc_merged_metadata') {
return _webMemoryFS.mergedMetadata;
}
if (_webMemoryFS.metadataFiles.containsKey(serverPath)) {
return utf8.decode(_webMemoryFS.metadataFiles[serverPath]);
if (_webMemoryFS.metadataFiles.containsKey(resultPath)) {
return utf8.decode(_webMemoryFS.metadataFiles[resultPath]!);
}
throw Exception('Could not find metadata contents for $serverPath');
}
@ -618,8 +619,8 @@ class WebAssetServer implements AssetReader {
class ConnectionResult {
ConnectionResult(this.appConnection, this.debugConnection, this.vmService);
final AppConnection appConnection;
final DebugConnection debugConnection;
final AppConnection? appConnection;
final DebugConnection? debugConnection;
final vm_service.VmService vmService;
}
@ -630,29 +631,29 @@ class WebDevFS implements DevFS {
/// [testMode] is true, do not actually initialize dwds or the shelf static
/// server.
WebDevFS({
@required this.hostname,
@required int port,
@required this.packagesFilePath,
@required this.urlTunneller,
@required this.useSseForDebugProxy,
@required this.useSseForDebugBackend,
@required this.useSseForInjectedClient,
@required this.buildInfo,
@required this.enableDwds,
@required this.enableDds,
@required this.entrypoint,
@required this.expressionCompiler,
@required this.chromiumLauncher,
@required this.nullAssertions,
@required this.nativeNullAssertions,
@required this.nullSafetyMode,
required this.hostname,
required int? port,
required this.packagesFilePath,
required this.urlTunneller,
required this.useSseForDebugProxy,
required this.useSseForDebugBackend,
required this.useSseForInjectedClient,
required this.buildInfo,
required this.enableDwds,
required this.enableDds,
required this.entrypoint,
required this.expressionCompiler,
required this.chromiumLauncher,
required this.nullAssertions,
required this.nativeNullAssertions,
required this.nullSafetyMode,
this.testMode = false,
}) : _port = port;
final Uri entrypoint;
final String hostname;
final String packagesFilePath;
final UrlTunneller urlTunneller;
final UrlTunneller? urlTunneller;
final bool useSseForDebugProxy;
final bool useSseForDebugBackend;
final bool useSseForInjectedClient;
@ -660,14 +661,14 @@ class WebDevFS implements DevFS {
final bool enableDwds;
final bool enableDds;
final bool testMode;
final ExpressionCompiler expressionCompiler;
final ChromiumLauncher chromiumLauncher;
final ExpressionCompiler? expressionCompiler;
final ChromiumLauncher? chromiumLauncher;
final bool nullAssertions;
final bool nativeNullAssertions;
final int _port;
final int? _port;
final NullSafetyMode nullSafetyMode;
WebAssetServer webAssetServer;
late WebAssetServer webAssetServer;
Dwds get dwds => webAssetServer.dwds;
@ -675,13 +676,13 @@ class WebDevFS implements DevFS {
@override
bool hasSetAssetDirectory = false;
Future<DebugConnection> _cachedExtensionFuture;
StreamSubscription<void> _connectedApps;
Future<DebugConnection>? _cachedExtensionFuture;
StreamSubscription<void>? _connectedApps;
/// Connect and retrieve the [DebugConnection] for the current application.
///
/// Only calls [AppConnection.runMain] on the subsequent connections.
Future<ConnectionResult> connect(bool useDebugExtension) {
Future<ConnectionResult?> connect(bool useDebugExtension) {
final Completer<ConnectionResult> firstConnection =
Completer<ConnectionResult>();
_connectedApps =
@ -706,7 +707,7 @@ class WebDevFS implements DevFS {
firstConnection.completeError(error, stackTrace);
}
}
}, onError: (dynamic error, StackTrace stackTrace) {
}, onError: (Object error, StackTrace stackTrace) {
globals.printError(
'Unknown error while waiting for debug connection:$error\n$stackTrace');
if (!firstConnection.isCompleted) {
@ -720,18 +721,18 @@ class WebDevFS implements DevFS {
List<Uri> sources = <Uri>[];
@override
DateTime lastCompiled;
DateTime? lastCompiled;
@override
PackageConfig lastPackageConfig;
PackageConfig? lastPackageConfig;
// We do not evict assets on the web.
@override
Set<String> get assetPathsToEvict => const <String>{};
@override
Uri get baseUri => _baseUri;
Uri _baseUri;
Uri? get baseUri => _baseUri;
Uri? _baseUri;
@override
Future<Uri> create() async {
@ -758,11 +759,11 @@ class WebDevFS implements DevFS {
webAssetServer.webRenderer = WebRendererMode.canvaskit;
}
if (hostname == 'any') {
_baseUri = Uri.http('localhost:$selectedPort', webAssetServer.basePath);
_baseUri = Uri.http('localhost:$selectedPort', webAssetServer.basePath!);
} else {
_baseUri = Uri.http('$hostname:$selectedPort', webAssetServer.basePath);
_baseUri = Uri.http('$hostname:$selectedPort', webAssetServer.basePath!);
}
return _baseUri;
return _baseUri!;
}
@override
@ -780,24 +781,24 @@ class WebDevFS implements DevFS {
String get fsName => 'web_asset';
@override
Directory get rootDirectory => null;
Directory? get rootDirectory => null;
@override
Future<UpdateFSReport> update({
@required Uri mainUri,
@required ResidentCompiler generator,
@required bool trackWidgetCreation,
@required String pathToReload,
@required List<Uri> invalidatedFiles,
@required PackageConfig packageConfig,
@required String dillOutputPath,
DevFSWriter devFSWriter,
String target,
AssetBundle bundle,
DateTime firstBuildTime,
required Uri mainUri,
required ResidentCompiler generator,
required bool trackWidgetCreation,
required String pathToReload,
required List<Uri> invalidatedFiles,
required PackageConfig packageConfig,
required String dillOutputPath,
DevFSWriter? devFSWriter,
String? target,
AssetBundle? bundle,
DateTime? firstBuildTime,
bool bundleFirstUpload = false,
bool fullRestart = false,
String projectRootPath,
String? projectRootPath,
}) async {
assert(trackWidgetCreation != null);
assert(generator != null);
@ -854,7 +855,7 @@ class WebDevFS implements DevFS {
// the web specific bootstrap logic. To make it easier for DWDS to handle
// mapping the file name, this is done via an additional file root and
// special hard-coded scheme.
final CompilerOutput compilerOutput = await generator.recompile(
final CompilerOutput? compilerOutput = await generator.recompile(
Uri(
scheme: 'org-dartlang-app',
path: '/${mainUri.pathSegments.last}',
@ -873,11 +874,11 @@ class WebDevFS implements DevFS {
lastCompiled = candidateCompileTime;
// list of sources that needs to be monitored are in [compilerOutput.sources]
sources = compilerOutput.sources;
File codeFile;
late File codeFile;
File manifestFile;
File sourcemapFile;
File metadataFile;
List<String> modules;
late List<String> modules;
try {
final Directory parentDirectory = globals.fs.directory(outputDirectoryPath);
codeFile = parentDirectory.childFile('${compilerOutput.outputFilename}.sources');
@ -898,7 +899,7 @@ class WebDevFS implements DevFS {
@visibleForTesting
final File requireJS = globals.fs.file(globals.fs.path.join(
globals.artifacts.getHostArtifact(HostArtifact.engineDartSdkPath).path,
globals.artifacts!.getHostArtifact(HostArtifact.engineDartSdkPath).path,
'lib',
'dev_compiler',
'kernel',
@ -908,7 +909,7 @@ class WebDevFS implements DevFS {
@visibleForTesting
final File stackTraceMapper = globals.fs.file(globals.fs.path.join(
globals.artifacts.getHostArtifact(HostArtifact.engineDartSdkPath).path,
globals.artifacts!.getHostArtifact(HostArtifact.engineDartSdkPath).path,
'lib',
'dev_compiler',
'web',
@ -924,10 +925,10 @@ class WebDevFS implements DevFS {
class ReleaseAssetServer {
ReleaseAssetServer(
this.entrypoint, {
@required FileSystem fileSystem,
@required String webBuildDirectory,
@required String flutterRoot,
@required Platform platform,
required FileSystem fileSystem,
required String? webBuildDirectory,
required String? flutterRoot,
required Platform platform,
this.basePath = '',
}) : _fileSystem = fileSystem,
_platform = platform,
@ -937,8 +938,8 @@ class ReleaseAssetServer {
FileSystemUtils(fileSystem: fileSystem, platform: platform);
final Uri entrypoint;
final String _flutterRoot;
final String _webBuildDirectory;
final String? _flutterRoot;
final String? _webBuildDirectory;
final FileSystem _fileSystem;
final FileSystemUtils _fileSystemUtils;
final Platform _platform;
@ -948,7 +949,7 @@ class ReleaseAssetServer {
/// The base path to serve from.
///
/// It should have no leading or trailing slashes.
final String basePath;
final String? basePath;
// Locations where source files, assets, or source maps may be located.
List<Uri> _searchPaths() => <Uri>[
@ -965,8 +966,8 @@ class ReleaseAssetServer {
return shelf.Response.notFound('');
}
Uri fileUri;
final String requestPath = _stripBasePath(request.url.path, basePath);
Uri? fileUri;
final String? requestPath = _stripBasePath(request.url.path, basePath);
if (requestPath == null) {
return shelf.Response.notFound('');
@ -1000,7 +1001,7 @@ class ReleaseAssetServer {
}
final File file = _fileSystem
.file(_fileSystem.path.join(_webBuildDirectory, 'index.html'));
.file(_fileSystem.path.join(_webBuildDirectory!, 'index.html'));
return shelf.Response.ok(file.readAsBytesSync(), headers: <String, String>{
'Content-Type': 'text/html',
});
@ -1022,19 +1023,19 @@ void log(logging.LogRecord event) {
Future<Directory> _loadDwdsDirectory(
FileSystem fileSystem, Logger logger) async {
final String toolPackagePath =
fileSystem.path.join(Cache.flutterRoot, 'packages', 'flutter_tools');
fileSystem.path.join(Cache.flutterRoot!, 'packages', 'flutter_tools');
final String packageFilePath =
fileSystem.path.join(toolPackagePath, '.dart_tool', 'package_config.json');
final PackageConfig packageConfig = await loadPackageConfigWithLogging(
fileSystem.file(packageFilePath),
logger: logger,
);
return fileSystem.directory(packageConfig['dwds'].packageUriRoot);
return fileSystem.directory(packageConfig['dwds']!.packageUriRoot);
}
String _stripBasePath(String path, String basePath) {
String? _stripBasePath(String path, String? basePath) {
path = _stripLeadingSlashes(path);
if (path.startsWith(basePath)) {
if (basePath != null && path.startsWith(basePath)) {
path = path.substring(basePath.length);
} else {
// The given path isn't under base path, return null to indicate that.
@ -1057,25 +1058,25 @@ String _stripTrailingSlashes(String path) {
return path;
}
String _parseBasePathFromIndexHtml(File indexHtml) {
String? _parseBasePathFromIndexHtml(File indexHtml) {
final String htmlContent =
indexHtml.existsSync() ? indexHtml.readAsStringSync() : _kDefaultIndex;
final Document document = parse(htmlContent);
final Element baseElement = document.querySelector('base');
String baseHref =
baseElement?.attributes == null ? null : baseElement.attributes['href'];
final Element? baseElement = document.querySelector('base');
String? baseHref =
baseElement?.attributes == null ? null : baseElement!.attributes['href'];
if (baseHref == null || baseHref == kBaseHrefPlaceholder) {
baseHref = '';
} else if (!baseHref.startsWith('/')) {
throw ToolExit(
'Error: The base href in "web/index.html" must be absolute (i.e. start '
'with a "/"), but found: `${baseElement.outerHtml}`.\n'
'with a "/"), but found: `${baseElement!.outerHtml}`.\n'
'$basePathExample',
);
} else if (!baseHref.endsWith('/')) {
throw ToolExit(
'Error: The base href in "web/index.html" must end with a "/", but found: `${baseElement.outerHtml}`.\n'
'Error: The base href in "web/index.html" must end with a "/", but found: `${baseElement!.outerHtml}`.\n'
'$basePathExample',
);
} else {

View File

@ -2,12 +2,10 @@
// 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';
// ignore: import_of_legacy_library_into_null_safe
import 'package:dwds/dwds.dart';
import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:vm_service/vm_service.dart' as vmservice;
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
@ -48,16 +46,16 @@ class DwdsWebRunnerFactory extends WebRunnerFactory {
@override
ResidentRunner createWebRunner(
FlutterDevice device, {
String target,
@required bool stayResident,
@required FlutterProject flutterProject,
@required bool ipv6,
@required DebuggingOptions debuggingOptions,
@required UrlTunneller urlTunneller,
@required Logger logger,
@required FileSystem fileSystem,
@required SystemClock systemClock,
@required Usage usage,
String? target,
required bool stayResident,
required FlutterProject flutterProject,
required bool? ipv6,
required DebuggingOptions debuggingOptions,
required UrlTunneller? urlTunneller,
required Logger? logger,
required FileSystem fileSystem,
required SystemClock systemClock,
required Usage usage,
bool machine = false,
}) {
return ResidentWebRunner(
@ -83,18 +81,18 @@ const String kExitMessage = 'Failed to establish connection with the application
class ResidentWebRunner extends ResidentRunner {
ResidentWebRunner(
FlutterDevice device, {
String target,
FlutterDevice? device, {
String? target,
bool stayResident = true,
bool machine = false,
@required this.flutterProject,
@required bool ipv6,
@required DebuggingOptions debuggingOptions,
@required FileSystem fileSystem,
@required Logger logger,
@required SystemClock systemClock,
@required Usage usage,
@required UrlTunneller urlTunneller,
required this.flutterProject,
required bool? ipv6,
required DebuggingOptions debuggingOptions,
required FileSystem? fileSystem,
required Logger? logger,
required SystemClock systemClock,
required Usage usage,
UrlTunneller? urlTunneller,
ResidentDevtoolsHandlerFactory devtoolsHandler = createDefaultHandler,
}) : _fileSystem = fileSystem,
_logger = logger,
@ -102,8 +100,8 @@ class ResidentWebRunner extends ResidentRunner {
_usage = usage,
_urlTunneller = urlTunneller,
super(
<FlutterDevice>[device],
target: target ?? fileSystem.path.join('lib', 'main.dart'),
<FlutterDevice?>[device],
target: target ?? fileSystem!.path.join('lib', 'main.dart'),
debuggingOptions: debuggingOptions,
ipv6: ipv6,
stayResident: stayResident,
@ -111,25 +109,25 @@ class ResidentWebRunner extends ResidentRunner {
devtoolsHandler: devtoolsHandler,
);
final FileSystem _fileSystem;
final Logger _logger;
final FileSystem? _fileSystem;
final Logger? _logger;
final SystemClock _systemClock;
final Usage _usage;
final UrlTunneller _urlTunneller;
final UrlTunneller? _urlTunneller;
@override
Logger get logger => _logger;
Logger? get logger => _logger;
@override
FileSystem get fileSystem => _fileSystem;
FileSystem? get fileSystem => _fileSystem;
FlutterDevice get device => flutterDevices.first;
FlutterDevice? get device => flutterDevices.first;
final FlutterProject flutterProject;
DateTime firstBuildTime;
DateTime? firstBuildTime;
// Used with the new compiler to generate a bootstrap file containing plugins
// and platform initialization.
Directory _generatedEntrypointDirectory;
Directory? _generatedEntrypointDirectory;
// Only the debug builds of the web support the service protocol.
@override
@ -139,7 +137,7 @@ class ResidentWebRunner extends ResidentRunner {
bool get debuggingEnabled => isRunningDebug && deviceIsDebuggable;
/// WebServer device is debuggable when running with --start-paused.
bool get deviceIsDebuggable => device.device is! WebServerDevice || debuggingOptions.startPaused;
bool get deviceIsDebuggable => device!.device is! WebServerDevice || debuggingOptions.startPaused;
@override
bool get supportsWriteSkSL => false;
@ -150,24 +148,24 @@ class ResidentWebRunner extends ResidentRunner {
bool get _enableDwds => debuggingEnabled;
ConnectionResult _connectionResult;
StreamSubscription<vmservice.Event> _stdOutSub;
StreamSubscription<vmservice.Event> _stdErrSub;
StreamSubscription<vmservice.Event> _extensionEventSub;
ConnectionResult? _connectionResult;
StreamSubscription<vmservice.Event>? _stdOutSub;
StreamSubscription<vmservice.Event>? _stdErrSub;
StreamSubscription<vmservice.Event>? _extensionEventSub;
bool _exited = false;
WipConnection _wipConnection;
ChromiumLauncher _chromiumLauncher;
WipConnection? _wipConnection;
ChromiumLauncher? _chromiumLauncher;
FlutterVmService get _vmService {
if (_instance != null) {
return _instance;
return _instance!;
}
final vmservice.VmService service =_connectionResult?.vmService;
final Uri websocketUri = Uri.parse(_connectionResult.debugConnection.uri);
final vmservice.VmService? service =_connectionResult?.vmService;
final Uri websocketUri = Uri.parse(_connectionResult!.debugConnection!.uri);
final Uri httpUri = _httpUriFromWebsocketUri(websocketUri);
return _instance ??= FlutterVmService(service, wsAddress: websocketUri, httpAddress: httpUri);
return _instance ??= FlutterVmService(service!, wsAddress: websocketUri, httpAddress: httpUri);
}
FlutterVmService _instance;
FlutterVmService? _instance;
@override
Future<void> cleanupAfterSignal() async {
@ -183,17 +181,17 @@ class ResidentWebRunner extends ResidentRunner {
if (_exited) {
return;
}
await residentDevtoolsHandler.shutdown();
await residentDevtoolsHandler!.shutdown();
await _stdOutSub?.cancel();
await _stdErrSub?.cancel();
await _extensionEventSub?.cancel();
await device.device.stopApp(null);
await device!.device!.stopApp(null);
try {
_generatedEntrypointDirectory?.deleteSync(recursive: true);
} on FileSystemException {
// Best effort to clean up temp dirs.
_logger.printTrace(
'Failed to clean up temp directory: ${_generatedEntrypointDirectory.path}',
_logger!.printTrace(
'Failed to clean up temp directory: ${_generatedEntrypointDirectory!.path}',
);
}
_exited = true;
@ -212,59 +210,58 @@ class ResidentWebRunner extends ResidentRunner {
const String fire = '🔥';
const String rawMessage =
' To hot restart changes while running, press "r" or "R".';
final String message = _logger.terminal.color(
fire + _logger.terminal.bolden(rawMessage),
final String message = _logger!.terminal.color(
fire + _logger!.terminal.bolden(rawMessage),
TerminalColor.red,
);
_logger.printStatus(message);
_logger!.printStatus(message);
const String quitMessage = 'To quit, press "q".';
_logger.printStatus('For a more detailed help message, press "h". $quitMessage');
_logger.printStatus('');
_logger!.printStatus('For a more detailed help message, press "h". $quitMessage');
_logger!.printStatus('');
printDebuggerList();
}
@override
Future<void> stopEchoingDeviceLog() async {
// Do nothing for ResidentWebRunner
await device.stopEchoingDeviceLog();
await device!.stopEchoingDeviceLog();
}
@override
Future<int> run({
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<void> appStartedCompleter,
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool enableDevTools = false, // ignored, we don't yet support devtools for web
String route,
String? route,
}) async {
firstBuildTime = DateTime.now();
final ApplicationPackage package = await ApplicationPackageFactory.instance.getPackageForPlatform(
final ApplicationPackage? package = await ApplicationPackageFactory.instance!.getPackageForPlatform(
TargetPlatform.web_javascript,
buildInfo: debuggingOptions.buildInfo,
applicationBinary: null,
);
if (package == null) {
_logger.printStatus('This application is not configured to build on the web.');
_logger.printStatus('To add web support to a project, run `flutter create .`.');
_logger!.printStatus('This application is not configured to build on the web.');
_logger!.printStatus('To add web support to a project, run `flutter create .`.');
}
final String modeName = debuggingOptions.buildInfo.friendlyModeName;
_logger.printStatus(
'Launching ${getDisplayPath(target, _fileSystem)} '
'on ${device.device.name} in $modeName mode...',
_logger!.printStatus(
'Launching ${getDisplayPath(target, _fileSystem!)} '
'on ${device!.device!.name} in $modeName mode...',
);
if (device.device is ChromiumDevice) {
_chromiumLauncher = (device.device as ChromiumDevice).chromeLauncher;
if (device!.device is ChromiumDevice) {
_chromiumLauncher = (device!.device! as ChromiumDevice).chromeLauncher;
}
try {
return await asyncGuard(() async {
final ExpressionCompiler expressionCompiler =
final ExpressionCompiler? expressionCompiler =
debuggingOptions.webEnableExpressionEvaluation
? WebExpressionCompiler(device.generator, fileSystem: _fileSystem)
? WebExpressionCompiler(device!.generator!, fileSystem: _fileSystem)
: null;
device.devFS = WebDevFS(
device!.devFS = WebDevFS(
hostname: debuggingOptions.hostname ?? 'localhost',
port: debuggingOptions.port != null
? int.tryParse(debuggingOptions.port)
? int.tryParse(debuggingOptions.port!)
: null,
packagesFilePath: packagesFilePath,
urlTunneller: _urlTunneller,
@ -274,22 +271,22 @@ class ResidentWebRunner extends ResidentRunner {
buildInfo: debuggingOptions.buildInfo,
enableDwds: _enableDwds,
enableDds: debuggingOptions.enableDds,
entrypoint: _fileSystem.file(target).uri,
entrypoint: _fileSystem!.file(target).uri,
expressionCompiler: expressionCompiler,
chromiumLauncher: _chromiumLauncher,
nullAssertions: debuggingOptions.nullAssertions,
nullSafetyMode: debuggingOptions.buildInfo.nullSafetyMode,
nativeNullAssertions: debuggingOptions.nativeNullAssertions,
);
final Uri url = await device.devFS.create();
final Uri url = await device!.devFS!.create();
if (debuggingOptions.buildInfo.isDebug) {
final UpdateFSReport report = await _updateDevFS(fullRestart: true);
if (!report.success) {
_logger.printError('Failed to compile application.');
_logger!.printError('Failed to compile application.');
appFailedToStart();
return 1;
}
device.generator.accept();
device!.generator!.accept();
cacheInitialDillCompilation();
} else {
await buildWeb(
@ -304,7 +301,7 @@ class ResidentWebRunner extends ResidentRunner {
null,
);
}
await device.device.startApp(
await device!.device!.startApp(
package,
mainPath: target,
debuggingOptions: debuggingOptions,
@ -320,19 +317,19 @@ class ResidentWebRunner extends ResidentRunner {
});
} on WebSocketException catch (error, stackTrace) {
appFailedToStart();
_logger.printError('$error', stackTrace: stackTrace);
_logger!.printError('$error', stackTrace: stackTrace);
throwToolExit(kExitMessage);
} on ChromeDebugException catch (error, stackTrace) {
appFailedToStart();
_logger.printError('$error', stackTrace: stackTrace);
_logger!.printError('$error', stackTrace: stackTrace);
throwToolExit(kExitMessage);
} on AppConnectionException catch (error, stackTrace) {
appFailedToStart();
_logger.printError('$error', stackTrace: stackTrace);
_logger!.printError('$error', stackTrace: stackTrace);
throwToolExit(kExitMessage);
} on SocketException catch (error, stackTrace) {
appFailedToStart();
_logger.printError('$error', stackTrace: stackTrace);
_logger!.printError('$error', stackTrace: stackTrace);
throwToolExit(kExitMessage);
} on Exception {
appFailedToStart();
@ -343,12 +340,12 @@ class ResidentWebRunner extends ResidentRunner {
@override
Future<OperationResult> restart({
bool fullRestart = false,
bool pause = false,
String reason,
bool? pause = false,
String? reason,
bool benchmarkMode = false,
}) async {
final DateTime start = _systemClock.now();
final Status status = _logger.startProgress(
final Status status = _logger!.startProgress(
'Performing hot restart...',
progressId: 'hot.restart',
);
@ -358,10 +355,10 @@ class ResidentWebRunner extends ResidentRunner {
// Full restart is always false for web, since the extra recompile is wasteful.
final UpdateFSReport report = await _updateDevFS();
if (report.success) {
device.generator.accept();
device!.generator!.accept();
} else {
status.stop();
await device.generator.reject();
await device!.generator!.reject();
return OperationResult(1, 'Failed to recompile application.');
}
} else {
@ -384,7 +381,7 @@ class ResidentWebRunner extends ResidentRunner {
try {
if (!deviceIsDebuggable) {
_logger.printStatus('Recompile complete. Page requires refresh.');
_logger!.printStatus('Recompile complete. Page requires refresh.');
} else if (isRunningDebug) {
await _vmService.service.callMethod('hotRestart');
} else {
@ -402,8 +399,8 @@ class ResidentWebRunner extends ResidentRunner {
final Duration elapsed = _systemClock.now().difference(start);
final String elapsedMS = getElapsedAsMilliseconds(elapsed);
_logger.printStatus('Restarted application in $elapsedMS.');
unawaited(residentDevtoolsHandler.hotRestart(flutterDevices));
_logger!.printStatus('Restarted application in $elapsedMS.');
unawaited(residentDevtoolsHandler!.hotRestart(flutterDevices));
// Don't track restart times for dart2js builds or web-server devices.
if (debuggingOptions.buildInfo.isDebug && deviceIsDebuggable) {
@ -411,7 +408,7 @@ class ResidentWebRunner extends ResidentRunner {
HotEvent(
'restart',
targetPlatform: getNameForTargetPlatform(TargetPlatform.web_javascript),
sdkName: await device.device.sdkNameAndVersion,
sdkName: await device!.device!.sdkNameAndVersion,
emulator: false,
fullRestart: true,
reason: reason,
@ -425,34 +422,34 @@ class ResidentWebRunner extends ResidentRunner {
// Flutter web projects need to include a generated main entrypoint to call the
// appropriate bootstrap method and inject plugins.
// Keep this in sync with build_system/targets/web.dart.
Future<Uri> _generateEntrypoint(Uri mainUri, PackageConfig packageConfig) async {
File result = _generatedEntrypointDirectory?.childFile('web_entrypoint.dart');
Future<Uri> _generateEntrypoint(Uri mainUri, PackageConfig? packageConfig) async {
File? result = _generatedEntrypointDirectory?.childFile('web_entrypoint.dart');
if (_generatedEntrypointDirectory == null) {
_generatedEntrypointDirectory ??= _fileSystem.systemTempDirectory.createTempSync('flutter_tools.')
_generatedEntrypointDirectory ??= _fileSystem!.systemTempDirectory.createTempSync('flutter_tools.')
..createSync();
result = _generatedEntrypointDirectory.childFile('web_entrypoint.dart');
result = _generatedEntrypointDirectory!.childFile('web_entrypoint.dart');
// Generates the generated_plugin_registrar
await injectBuildTimePluginFiles(flutterProject, webPlatform: true, destination: _generatedEntrypointDirectory);
await injectBuildTimePluginFiles(flutterProject, webPlatform: true, destination: _generatedEntrypointDirectory!);
// The below works because `injectBuildTimePluginFiles` is configured to write
// the web_plugin_registrant.dart file alongside the generated main.dart
const String/*?*/ generatedImport = 'web_plugin_registrant.dart';
const String generatedImport = 'web_plugin_registrant.dart';
Uri importedEntrypoint = packageConfig.toPackageUri(mainUri);
Uri? importedEntrypoint = packageConfig!.toPackageUri(mainUri);
// Special handling for entrypoints that are not under lib, such as test scripts.
if (importedEntrypoint == null) {
final String parent = _fileSystem.file(mainUri).parent.path;
flutterDevices.first.generator.addFileSystemRoot(parent);
flutterDevices.first.generator.addFileSystemRoot(_fileSystem.directory('test').absolute.path);
final String parent = _fileSystem!.file(mainUri).parent.path;
flutterDevices.first!.generator!.addFileSystemRoot(parent);
flutterDevices.first!.generator!.addFileSystemRoot(_fileSystem!.directory('test').absolute.path);
importedEntrypoint = Uri(
scheme: 'org-dartlang-app',
path: '/${mainUri.pathSegments.last}',
);
}
final LanguageVersion languageVersion = determineLanguageVersion(
_fileSystem.file(mainUri),
_fileSystem!.file(mainUri),
packageConfig[flutterProject.manifest.appName],
Cache.flutterRoot,
Cache.flutterRoot!,
);
final String entrypoint = main_dart.generateMainDartFile(importedEntrypoint.toString(),
@ -462,14 +459,14 @@ class ResidentWebRunner extends ResidentRunner {
result.writeAsStringSync(entrypoint);
}
return result.absolute.uri;
return result!.absolute.uri;
}
Future<UpdateFSReport> _updateDevFS({bool fullRestart = false}) async {
final bool isFirstUpload = !assetBundle.wasBuiltOnce();
final bool rebuildBundle = assetBundle.needsBuild();
if (rebuildBundle) {
_logger.printTrace('Updating assets');
_logger!.printTrace('Updating assets');
final int result = await assetBundle.build(
packagesPath: debuggingOptions.buildInfo.packagesPath,
targetPlatform: TargetPlatform.web_javascript,
@ -479,67 +476,66 @@ class ResidentWebRunner extends ResidentRunner {
}
}
final InvalidationResult invalidationResult = await projectFileInvalidator.findInvalidated(
lastCompiled: device.devFS.lastCompiled,
urisToMonitor: device.devFS.sources,
lastCompiled: device!.devFS!.lastCompiled,
urisToMonitor: device!.devFS!.sources,
packagesPath: packagesFilePath,
packageConfig: device.devFS.lastPackageConfig
packageConfig: device!.devFS!.lastPackageConfig
?? debuggingOptions.buildInfo.packageConfig,
);
final Status devFSStatus = _logger.startProgress(
'Waiting for connection from debug service on ${device.device.name}...',
final Status devFSStatus = _logger!.startProgress(
'Waiting for connection from debug service on ${device!.device!.name}...',
);
final UpdateFSReport report = await device.devFS.update(
final UpdateFSReport report = await device!.devFS!.update(
mainUri: await _generateEntrypoint(
_fileSystem.file(mainPath).absolute.uri,
_fileSystem!.file(mainPath).absolute.uri,
invalidationResult.packageConfig,
),
target: target,
bundle: assetBundle,
firstBuildTime: firstBuildTime,
bundleFirstUpload: isFirstUpload,
generator: device.generator,
generator: device!.generator!,
fullRestart: fullRestart,
dillOutputPath: dillOutputPath,
projectRootPath: projectRootPath,
pathToReload: getReloadPath(fullRestart: fullRestart, swap: false),
invalidatedFiles: invalidationResult.uris,
packageConfig: invalidationResult.packageConfig,
invalidatedFiles: invalidationResult.uris!,
packageConfig: invalidationResult.packageConfig!,
trackWidgetCreation: debuggingOptions.buildInfo.trackWidgetCreation,
devFSWriter: null,
);
devFSStatus.stop();
_logger.printTrace('Synced ${getSizeAsMB(report.syncedBytes)}.');
_logger!.printTrace('Synced ${getSizeAsMB(report.syncedBytes)}.');
return report;
}
@override
Future<int> attach({
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<void> appStartedCompleter,
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool allowExistingDdsInstance = false,
bool enableDevTools = false, // ignored, we don't yet support devtools for web
bool needsFullRestart = true,
}) async {
if (_chromiumLauncher != null) {
final Chromium chrome = await _chromiumLauncher.connectedInstance;
final ChromeTab chromeTab = await chrome.chromeConnection.getTab((ChromeTab chromeTab) {
final Chromium chrome = await _chromiumLauncher!.connectedInstance;
final ChromeTab chromeTab = await (chrome.chromeConnection.getTab((ChromeTab chromeTab) {
return !chromeTab.url.startsWith('chrome-extension');
});
}) as FutureOr<ChromeTab>);
if (chromeTab == null) {
throwToolExit('Failed to connect to Chrome instance.');
}
_wipConnection = await chromeTab.connect();
}
Uri websocketUri;
Uri? websocketUri;
if (supportsServiceProtocol) {
final WebDevFS webDevFS = device.devFS as WebDevFS;
final bool useDebugExtension = device.device is WebServerDevice && debuggingOptions.startPaused;
final WebDevFS webDevFS = device!.devFS! as WebDevFS;
final bool useDebugExtension = device!.device is WebServerDevice && debuggingOptions.startPaused;
_connectionResult = await webDevFS.connect(useDebugExtension);
unawaited(_connectionResult.debugConnection.onDone.whenComplete(_cleanupAndExit));
unawaited(_connectionResult!.debugConnection!.onDone.whenComplete(_cleanupAndExit));
void onLogEvent(vmservice.Event event) {
final String message = processVmServiceMessage(event);
_logger.printStatus(message);
_logger!.printStatus(message);
}
_stdOutSub = _vmService.service.onStdoutEvent.listen(onLogEvent);
@ -564,41 +560,41 @@ class ResidentWebRunner extends ResidentRunner {
}
await setUpVmService(
(String isolateId, {
bool force,
bool pause,
bool? force,
bool? pause,
}) async {
await restart(pause: pause);
},
null,
null,
device.device,
device!.device,
null,
printStructuredErrorLog,
_vmService.service,
);
websocketUri = Uri.parse(_connectionResult.debugConnection.uri);
device.vmService = _vmService;
websocketUri = Uri.parse(_connectionResult!.debugConnection!.uri);
device!.vmService = _vmService;
// Run main immediately if the app is not started paused or if there
// is no debugger attached. Otherwise, runMain when a resume event
// is received.
if (!debuggingOptions.startPaused || !supportsServiceProtocol) {
_connectionResult.appConnection.runMain();
_connectionResult!.appConnection!.runMain();
} else {
StreamSubscription<void> resumeSub;
late StreamSubscription<void> resumeSub;
resumeSub = _vmService.service.onDebugEvent
.listen((vmservice.Event event) {
if (event.type == vmservice.EventKind.kResume) {
_connectionResult.appConnection.runMain();
_connectionResult!.appConnection!.runMain();
resumeSub.cancel();
}
});
}
if (enableDevTools) {
// The method below is guaranteed never to return a failing future.
unawaited(residentDevtoolsHandler.serveAndAnnounceDevTools(
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
));
@ -606,20 +602,20 @@ class ResidentWebRunner extends ResidentRunner {
}
if (websocketUri != null) {
if (debuggingOptions.vmserviceOutFile != null) {
_fileSystem.file(debuggingOptions.vmserviceOutFile)
_fileSystem!.file(debuggingOptions.vmserviceOutFile)
..createSync(recursive: true)
..writeAsStringSync(websocketUri.toString());
}
_logger.printStatus('Debug service listening on $websocketUri');
_logger.printStatus('');
_logger!.printStatus('Debug service listening on $websocketUri');
_logger!.printStatus('');
if (debuggingOptions.buildInfo.nullSafetyMode == NullSafetyMode.sound) {
_logger.printStatus('💪 Running with sound null safety 💪', emphasis: true);
_logger!.printStatus('💪 Running with sound null safety 💪', emphasis: true);
} else {
_logger.printStatus(
_logger!.printStatus(
'Running with unsound null safety',
emphasis: true,
);
_logger.printStatus(
_logger!.printStatus(
'For more information see https://dart.dev/null-safety/unsound-null-safety',
);
}
@ -638,7 +634,7 @@ class ResidentWebRunner extends ResidentRunner {
@override
Future<void> exitApp() async {
await device.exitApps();
await device!.exitApps();
appFinished();
}
}

View File

@ -2,10 +2,9 @@
// 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';
// ignore: import_of_legacy_library_into_null_safe
import 'package:dwds/dwds.dart';
import '../artifacts.dart';
@ -17,12 +16,12 @@ class SdkWebConfigurationProvider extends SdkConfigurationProvider {
SdkWebConfigurationProvider(this._artifacts);
final Artifacts _artifacts;
SdkConfiguration _configuration;
SdkConfiguration? _configuration;
/// Create and validate configuration matching the default SDK layout.
/// Create configuration matching the default SDK layout.
@override
Future<SdkConfiguration> get configuration async {
Future<SdkConfiguration?> get configuration async {
if (_configuration == null) {
final String sdkDir = _artifacts.getHostArtifact(HostArtifact.flutterWebSdk).path;
final String unsoundSdkSummaryPath = _artifacts.getHostArtifact(HostArtifact.webPlatformKernelDill).path;
@ -40,7 +39,7 @@ class SdkWebConfigurationProvider extends SdkConfigurationProvider {
}
/// Validate that SDK configuration exists on disk.
static void validate(SdkConfiguration configuration, { FileSystem fileSystem }) {
static void validate(SdkConfiguration configuration, { required FileSystem fileSystem }) {
configuration.validateSdkDir(fileSystem: fileSystem);
configuration.validateSummaries(fileSystem: fileSystem);
configuration.validateLibrariesSpec(fileSystem: fileSystem);

View File

@ -181,7 +181,7 @@ class PreviewDevice extends Device {
}
@override
DevFSWriter createDevFSWriter(covariant ApplicationPackage app, String userIdentifier) {
DevFSWriter createDevFSWriter(covariant ApplicationPackage? app, String? userIdentifier) {
return LocalDevFSWriter(fileSystem: _fileSystem);
}
}

View File

@ -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:browser_launcher/browser_launcher.dart';
@ -14,9 +12,9 @@ import 'build_info.dart';
import 'resident_runner.dart';
import 'vmservice.dart';
typedef ResidentDevtoolsHandlerFactory = ResidentDevtoolsHandler Function(DevtoolsLauncher, ResidentRunner, Logger);
typedef ResidentDevtoolsHandlerFactory = ResidentDevtoolsHandler Function(DevtoolsLauncher?, ResidentRunner, Logger);
ResidentDevtoolsHandler createDefaultHandler(DevtoolsLauncher launcher, ResidentRunner runner, Logger logger) {
ResidentDevtoolsHandler createDefaultHandler(DevtoolsLauncher? launcher, ResidentRunner runner, Logger logger) {
return FlutterResidentDevtoolsHandler(launcher, runner, logger);
}
@ -24,7 +22,7 @@ ResidentDevtoolsHandler createDefaultHandler(DevtoolsLauncher launcher, Resident
/// the resident runner.
abstract class ResidentDevtoolsHandler {
/// The current devtools server, or null if one is not running.
DevToolsServerAddress get activeDevToolsServer;
DevToolsServerAddress? get activeDevToolsServer;
/// Whether it's ok to announce the [activeDevToolsServer].
///
@ -32,14 +30,14 @@ abstract class ResidentDevtoolsHandler {
/// of the DevTools.
bool get readyToAnnounce;
Future<void> hotRestart(List<FlutterDevice> flutterDevices);
Future<void> hotRestart(List<FlutterDevice?> flutterDevices);
Future<void> serveAndAnnounceDevTools({
Uri devToolsServerAddress,
@required List<FlutterDevice> flutterDevices,
Uri? devToolsServerAddress,
required List<FlutterDevice?> flutterDevices,
});
bool launchDevToolsInBrowser({@required List<FlutterDevice> flutterDevices});
bool launchDevToolsInBrowser({required List<FlutterDevice?> flutterDevices});
Future<void> shutdown();
}
@ -49,7 +47,7 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
static const Duration launchInBrowserTimeout = Duration(seconds: 15);
final DevtoolsLauncher _devToolsLauncher;
final DevtoolsLauncher? _devToolsLauncher;
final ResidentRunner _residentRunner;
final Logger _logger;
bool _shutdown = false;
@ -59,7 +57,7 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
bool launchedInBrowser = false;
@override
DevToolsServerAddress get activeDevToolsServer {
DevToolsServerAddress? get activeDevToolsServer {
assert(!_readyToAnnounce || _devToolsLauncher?.activeDevToolsServer != null);
return _devToolsLauncher?.activeDevToolsServer;
}
@ -71,26 +69,26 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
// This must be guaranteed not to return a Future that fails.
@override
Future<void> serveAndAnnounceDevTools({
Uri devToolsServerAddress,
@required List<FlutterDevice> flutterDevices,
Uri? devToolsServerAddress,
required List<FlutterDevice?> flutterDevices,
}) async {
assert(!_readyToAnnounce);
if (!_residentRunner.supportsServiceProtocol || _devToolsLauncher == null) {
return;
}
if (devToolsServerAddress != null) {
_devToolsLauncher.devToolsUrl = devToolsServerAddress;
_devToolsLauncher!.devToolsUrl = devToolsServerAddress;
} else {
await _devToolsLauncher.serve();
await _devToolsLauncher!.serve();
_served = true;
}
await _devToolsLauncher.ready;
await _devToolsLauncher!.ready;
// Do not attempt to print debugger list if the connection has failed or if we're shutting down.
if (_devToolsLauncher.activeDevToolsServer == null || _shutdown) {
if (_devToolsLauncher!.activeDevToolsServer == null || _shutdown) {
assert(!_readyToAnnounce);
return;
}
final List<FlutterDevice> devicesWithExtension = await _devicesWithExtensions(flutterDevices);
final List<FlutterDevice?> devicesWithExtension = await _devicesWithExtensions(flutterDevices);
await _maybeCallDevToolsUriServiceExtension(devicesWithExtension);
await _callConnectedVmServiceUriExtension(devicesWithExtension);
if (_shutdown) {
@ -98,7 +96,7 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
return;
}
_readyToAnnounce = true;
assert(_devToolsLauncher.activeDevToolsServer != null);
assert(_devToolsLauncher!.activeDevToolsServer != null);
if (_residentRunner.reportedDebuggers) {
// Since the DevTools only just became available, we haven't had a chance to
// report their URLs yet. Do so now.
@ -108,13 +106,13 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
// This must be guaranteed not to return a Future that fails.
@override
bool launchDevToolsInBrowser({@required List<FlutterDevice> flutterDevices}) {
bool launchDevToolsInBrowser({required List<FlutterDevice?> flutterDevices}) {
if (!_residentRunner.supportsServiceProtocol || _devToolsLauncher == null) {
return false;
}
if (_devToolsLauncher.devToolsUrl == null) {
if (_devToolsLauncher!.devToolsUrl == null) {
_logger.startProgress('Waiting for Flutter DevTools to be served...');
unawaited(_devToolsLauncher.ready.then((_) {
unawaited(_devToolsLauncher!.ready.then((_) {
_launchDevToolsForDevices(flutterDevices);
}));
} else {
@ -123,27 +121,27 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
return true;
}
void _launchDevToolsForDevices(List<FlutterDevice> flutterDevices) {
void _launchDevToolsForDevices(List<FlutterDevice?> flutterDevices) {
assert(activeDevToolsServer != null);
for (final FlutterDevice device in flutterDevices) {
final String devToolsUrl = activeDevToolsServer.uri?.replace(
queryParameters: <String, dynamic>{'uri': '${device.vmService.httpAddress}'},
for (final FlutterDevice? device in flutterDevices) {
final String devToolsUrl = activeDevToolsServer!.uri!.replace(
queryParameters: <String, dynamic>{'uri': '${device!.vmService!.httpAddress}'},
).toString();
_logger.printStatus('Launching Flutter DevTools for ${device.device.name} at $devToolsUrl');
_logger.printStatus('Launching Flutter DevTools for ${device.device!.name} at $devToolsUrl');
unawaited(Chrome.start(<String>[devToolsUrl]));
}
launchedInBrowser = true;
}
Future<void> _maybeCallDevToolsUriServiceExtension(
List<FlutterDevice> flutterDevices,
List<FlutterDevice?> flutterDevices,
) async {
if (_devToolsLauncher?.activeDevToolsServer == null) {
return;
}
await Future.wait(<Future<void>>[
for (final FlutterDevice device in flutterDevices)
if (device.vmService != null) _callDevToolsUriExtension(device),
for (final FlutterDevice? device in flutterDevices)
if (device?.vmService != null) _callDevToolsUriExtension(device!),
]);
}
@ -155,7 +153,7 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
'ext.flutter.activeDevToolsServerAddress',
device: device,
params: <String, dynamic>{
'value': _devToolsLauncher.activeDevToolsServer.uri.toString(),
'value': _devToolsLauncher!.activeDevToolsServer!.uri.toString(),
},
);
} on Exception catch (e) {
@ -166,15 +164,14 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
}
}
Future<List<FlutterDevice>> _devicesWithExtensions(List<FlutterDevice> flutterDevices) async {
final List<FlutterDevice> devices = await Future.wait(<Future<FlutterDevice>>[
for (final FlutterDevice device in flutterDevices) _waitForExtensionsForDevice(device),
Future<List<FlutterDevice?>> _devicesWithExtensions(List<FlutterDevice?> flutterDevices) async {
return Future.wait(<Future<FlutterDevice?>>[
for (final FlutterDevice? device in flutterDevices) _waitForExtensionsForDevice(device!),
]);
return devices.where((FlutterDevice device) => device != null).toList();
}
/// Returns null if the service extension cannot be found on the device.
Future<FlutterDevice> _waitForExtensionsForDevice(FlutterDevice flutterDevice) async {
Future<FlutterDevice?> _waitForExtensionsForDevice(FlutterDevice flutterDevice) async {
const String extension = 'ext.flutter.connectedVmServiceUri';
try {
await flutterDevice.vmService?.findExtensionIsolate(
@ -191,15 +188,15 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
}
}
Future<void> _callConnectedVmServiceUriExtension(List<FlutterDevice> flutterDevices) async {
Future<void> _callConnectedVmServiceUriExtension(List<FlutterDevice?> flutterDevices) async {
await Future.wait(<Future<void>>[
for (final FlutterDevice device in flutterDevices)
if (device.vmService != null) _callConnectedVmServiceExtension(device),
for (final FlutterDevice? device in flutterDevices)
if (device?.vmService != null) _callConnectedVmServiceExtension(device!),
]);
}
Future<void> _callConnectedVmServiceExtension(FlutterDevice device) async {
final Uri uri = device.vmService.httpAddress ?? device.vmService.wsAddress;
final Uri? uri = device.vmService!.httpAddress ?? device.vmService!.wsAddress;
if (uri == null) {
return;
}
@ -222,29 +219,30 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
Future<void> _invokeRpcOnFirstView(
String method, {
@required FlutterDevice device,
@required Map<String, dynamic> params,
required FlutterDevice device,
required Map<String, dynamic> params,
}) async {
if (device.targetPlatform == TargetPlatform.web_javascript) {
return device.vmService.callMethodWrapper(
await device.vmService!.callMethodWrapper(
method,
args: params,
);
return;
}
final List<FlutterView> views = await device.vmService.getFlutterViews();
final List<FlutterView> views = await device.vmService!.getFlutterViews();
if (views.isEmpty) {
return;
}
await device.vmService.invokeFlutterExtensionRpcRaw(
await device.vmService!.invokeFlutterExtensionRpcRaw(
method,
args: params,
isolateId: views.first.uiIsolate.id,
isolateId: views.first.uiIsolate!.id!,
);
}
@override
Future<void> hotRestart(List<FlutterDevice> flutterDevices) async {
final List<FlutterDevice> devicesWithExtension = await _devicesWithExtensions(flutterDevices);
Future<void> hotRestart(List<FlutterDevice?> flutterDevices) async {
final List<FlutterDevice?> devicesWithExtension = await _devicesWithExtensions(flutterDevices);
await Future.wait(<Future<void>>[
_maybeCallDevToolsUriServiceExtension(devicesWithExtension),
_callConnectedVmServiceUriExtension(devicesWithExtension),
@ -258,12 +256,12 @@ class FlutterResidentDevtoolsHandler implements ResidentDevtoolsHandler {
}
_shutdown = true;
_readyToAnnounce = false;
await _devToolsLauncher.close();
await _devToolsLauncher!.close();
}
}
@visibleForTesting
NoOpDevtoolsHandler createNoOpHandler(DevtoolsLauncher launcher, ResidentRunner runner, Logger logger) {
NoOpDevtoolsHandler createNoOpHandler(DevtoolsLauncher? launcher, ResidentRunner runner, Logger logger) {
return NoOpDevtoolsHandler();
}
@ -272,23 +270,23 @@ class NoOpDevtoolsHandler implements ResidentDevtoolsHandler {
bool wasShutdown = false;
@override
DevToolsServerAddress get activeDevToolsServer => null;
DevToolsServerAddress? get activeDevToolsServer => null;
@override
bool get readyToAnnounce => false;
@override
Future<void> hotRestart(List<FlutterDevice> flutterDevices) async {
Future<void> hotRestart(List<FlutterDevice?> flutterDevices) async {
return;
}
@override
Future<void> serveAndAnnounceDevTools({Uri devToolsServerAddress, List<FlutterDevice> flutterDevices}) async {
Future<void> serveAndAnnounceDevTools({Uri? devToolsServerAddress, List<FlutterDevice?>? flutterDevices}) async {
return;
}
@override
bool launchDevToolsInBrowser({List<FlutterDevice> flutterDevices}) {
bool launchDevToolsInBrowser({List<FlutterDevice?>? flutterDevices}) {
return false;
}

File diff suppressed because it is too large Load Diff

View File

@ -2,18 +2,12 @@
// 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:meta/meta.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'build_info.dart';
import 'device.dart';
import 'globals.dart' as globals;
import 'resident_devtools_handler.dart';
import 'resident_runner.dart';
import 'tracing.dart';
import 'vmservice.dart';
@ -21,31 +15,24 @@ import 'vmservice.dart';
const String kFlutterTestOutputsDirEnvName = 'FLUTTER_TEST_OUTPUTS_DIR';
class ColdRunner extends ResidentRunner {
ColdRunner(
List<FlutterDevice> devices, {
@required String target,
@required DebuggingOptions debuggingOptions,
super.devices, {
required super.target,
required super.debuggingOptions,
this.traceStartup = false,
this.awaitFirstFrameWhenTracing = true,
this.applicationBinary,
this.multidexEnabled = false,
bool ipv6 = false,
bool stayResident = true,
bool machine = false,
ResidentDevtoolsHandlerFactory devtoolsHandler = createDefaultHandler,
bool super.ipv6 = false,
super.stayResident,
super.machine,
super.devtoolsHandler,
}) : super(
devices,
target: target,
debuggingOptions: debuggingOptions,
hotMode: false,
stayResident: stayResident,
ipv6: ipv6,
machine: machine,
devtoolsHandler: devtoolsHandler,
);
final bool traceStartup;
final bool awaitFirstFrameWhenTracing;
final File applicationBinary;
final File? applicationBinary;
final bool multidexEnabled;
bool _didAttach = false;
@ -60,14 +47,14 @@ class ColdRunner extends ResidentRunner {
@override
Future<int> run({
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<void> appStartedCompleter,
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool enableDevTools = false,
String route,
String? route,
}) async {
try {
for (final FlutterDevice device in flutterDevices) {
final int result = await device.runCold(
for (final FlutterDevice? device in flutterDevices) {
final int result = await device!.runCold(
coldRunner: this,
route: route,
);
@ -95,38 +82,38 @@ class ColdRunner extends ResidentRunner {
if (enableDevTools && debuggingEnabled) {
// The method below is guaranteed never to return a failing future.
unawaited(residentDevtoolsHandler.serveAndAnnounceDevTools(
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
));
}
if (flutterDevices.first.observatoryUris != null) {
if (flutterDevices.first!.observatoryUris != null) {
// For now, only support one debugger connection.
connectionInfoCompleter?.complete(DebugConnectionInfo(
httpUri: flutterDevices.first.vmService.httpAddress,
wsUri: flutterDevices.first.vmService.wsAddress,
httpUri: flutterDevices.first!.vmService!.httpAddress,
wsUri: flutterDevices.first!.vmService!.wsAddress,
));
}
globals.printTrace('Application running.');
for (final FlutterDevice device in flutterDevices) {
if (device.vmService == null) {
for (final FlutterDevice? device in flutterDevices) {
if (device!.vmService == null) {
continue;
}
await device.initLogReader();
globals.printTrace('Connected to ${device.device.name}');
globals.printTrace('Connected to ${device.device!.name}');
}
if (traceStartup) {
// Only trace startup for the first device.
final FlutterDevice device = flutterDevices.first;
final FlutterDevice device = flutterDevices.first!;
if (device.vmService != null) {
globals.printStatus('Tracing startup on ${device.device.name}.');
globals.printStatus('Tracing startup on ${device.device!.name}.');
final String outputPath = globals.platform.environment[kFlutterTestOutputsDirEnvName] ?? getBuildDirectory();
await downloadStartupTrace(
device.vmService,
device.vmService!,
awaitFirstFrame: awaitFirstFrameWhenTracing,
logger: globals.logger,
output: globals.fs.directory(outputPath),
@ -148,8 +135,8 @@ class ColdRunner extends ResidentRunner {
@override
Future<int> attach({
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<void> appStartedCompleter,
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool allowExistingDdsInstance = false,
bool enableDevTools = false,
bool needsFullRestart = true,
@ -165,11 +152,11 @@ class ColdRunner extends ResidentRunner {
return 2;
}
for (final FlutterDevice device in flutterDevices) {
await device.initLogReader();
for (final FlutterDevice? device in flutterDevices) {
await device!.initLogReader();
}
for (final FlutterDevice device in flutterDevices) {
final List<FlutterView> views = await device.vmService.getFlutterViews();
for (final FlutterDevice? device in flutterDevices) {
final List<FlutterView> views = await device!.vmService!.getFlutterViews();
for (final FlutterView view in views) {
globals.printTrace('Connected to $view.');
}
@ -177,7 +164,7 @@ class ColdRunner extends ResidentRunner {
if (enableDevTools && debuggingEnabled) {
// The method below is guaranteed never to return a failing future.
unawaited(residentDevtoolsHandler.serveAndAnnounceDevTools(
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
));
@ -202,16 +189,16 @@ class ColdRunner extends ResidentRunner {
@override
Future<void> cleanupAtFinish() async {
for (final FlutterDevice flutterDevice in flutterDevices) {
await flutterDevice.device.dispose();
for (final FlutterDevice? flutterDevice in flutterDevices) {
await flutterDevice!.device!.dispose();
}
await residentDevtoolsHandler.shutdown();
await residentDevtoolsHandler!.shutdown();
await stopEchoingDeviceLog();
}
@override
void printHelp({ @required bool details }) {
void printHelp({ required bool details }) {
globals.printStatus('Flutter run key commands.');
if (details) {
printHelpDetails();
@ -229,10 +216,10 @@ class ColdRunner extends ResidentRunner {
@override
Future<void> preExit() async {
for (final FlutterDevice device in flutterDevices) {
for (final FlutterDevice? device in flutterDevices) {
// If we're running in release mode, stop the app using the device logic.
if (device.vmService == null) {
await device.device.stopApp(device.package, userIdentifier: device.userIdentifier);
if (device!.vmService == null) {
await device.device!.stopApp(device.package, userIdentifier: device.userIdentifier);
}
}
await super.preExit();

File diff suppressed because it is too large Load Diff

View File

@ -69,7 +69,7 @@ class FlutterCommandResult {
/// Optional data that can be appended to the timing event.
/// https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#timingLabel
/// Do not add PII.
final List<String>? timingLabelParts;
final List<String?>? timingLabelParts;
/// Optional epoch time when the command's non-interactive wait time is
/// complete during the command's execution. Use to measure user perceivable
@ -1265,7 +1265,7 @@ abstract class FlutterCommand extends Command<void> {
CommandResultEvent(commandPath, commandResult.toString()).send();
// Send timing.
final List<String> labels = <String>[
final List<String?> labels = <String?>[
if (commandResult.exitStatus != null)
getEnumName(commandResult.exitStatus),
if (commandResult.timingLabelParts?.isNotEmpty ?? false)
@ -1273,7 +1273,7 @@ abstract class FlutterCommand extends Command<void> {
];
final String label = labels
.where((String label) => !_isBlank(label))
.where((String? label) => label != null && !_isBlank(label))
.join('-');
globals.flutterUsage.sendTiming(
'flutter',

View File

@ -2,7 +2,7 @@
// 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:coverage/coverage.dart' as coverage;
import 'package:meta/meta.dart';
@ -19,7 +19,7 @@ import 'watcher.dart';
/// A class that collects code coverage data during test runs.
class CoverageCollector extends TestWatcher {
CoverageCollector({this.libraryNames, this.verbose = true, @required this.packagesPath});
CoverageCollector({this.libraryNames, this.verbose = true, required this.packagesPath});
/// True when log messages should be emitted.
final bool verbose;
@ -29,11 +29,11 @@ class CoverageCollector extends TestWatcher {
final String packagesPath;
/// Map of file path to coverage hit map for that file.
Map<String, coverage.HitMap> _globalHitmap;
Map<String, coverage.HitMap>? _globalHitmap;
/// The names of the libraries to gather coverage for. If null, all libraries
/// will be accepted.
Set<String> libraryNames;
Set<String>? libraryNames;
@override
Future<void> handleFinishedTest(TestDevice testDevice) async {
@ -56,7 +56,7 @@ class CoverageCollector extends TestWatcher {
if (_globalHitmap == null) {
_globalHitmap = hitmap;
} else {
_globalHitmap.merge(hitmap);
_globalHitmap!.merge(hitmap);
}
}
@ -107,7 +107,7 @@ class CoverageCollector extends TestWatcher {
Future<void> collectCoverage(TestDevice testDevice) async {
assert(testDevice != null);
Map<String, dynamic> data;
Map<String, dynamic>? data;
final Future<void> processComplete = testDevice.finished.catchError(
(Object error) => throw Exception(
@ -134,7 +134,7 @@ class CoverageCollector extends TestWatcher {
_logMessage('Merging coverage data...');
_addHitmap(await coverage.HitMap.parseJson(
data['coverage'] as List<Map<String, dynamic>>,
data!['coverage'] as List<Map<String, dynamic>>,
packagePath: packageDirectory,
checkIgnoredLines: true,
));
@ -145,10 +145,10 @@ class CoverageCollector extends TestWatcher {
///
/// This will not start any collection tasks. It us up to the caller of to
/// call [collectCoverage] for each process first.
Future<String> finalizeCoverage({
String Function(Map<String, coverage.HitMap> hitmap) formatter,
coverage.Resolver resolver,
Directory coverageDirectory,
Future<String?> finalizeCoverage({
String Function(Map<String, coverage.HitMap> hitmap)? formatter,
coverage.Resolver? resolver,
Directory? coverageDirectory,
}) async {
if (_globalHitmap == null) {
return null;
@ -160,15 +160,15 @@ class CoverageCollector extends TestWatcher {
? <String>[globals.fs.path.join(packagePath, 'lib')]
: <String>[coverageDirectory.path];
formatter = (Map<String, coverage.HitMap> hitmap) => hitmap
.formatLcov(resolver, reportOn: reportOn, basePath: packagePath);
.formatLcov(resolver!, reportOn: reportOn, basePath: packagePath);
}
final String result = formatter(_globalHitmap);
final String result = formatter(_globalHitmap!);
_globalHitmap = null;
return result;
}
Future<bool> collectCoverageData(String coveragePath, { bool mergeCoverageData = false, Directory coverageDirectory }) async {
final String coverageData = await finalizeCoverage(
Future<bool> collectCoverageData(String? coveragePath, { bool mergeCoverageData = false, Directory? coverageDirectory }) async {
final String? coverageData = await finalizeCoverage(
coverageDirectory: coverageDirectory,
);
_logMessage('coverage information collection complete');
@ -225,15 +225,15 @@ class CoverageCollector extends TestWatcher {
Future<void> handleTestTimedOut(TestDevice testDevice) async { }
}
Future<FlutterVmService> _defaultConnect(Uri serviceUri) {
Future<FlutterVmService> _defaultConnect(Uri? serviceUri) {
return connectToVmService(
serviceUri, compression: CompressionOptions.compressionOff, logger: globals.logger,);
serviceUri!, compression: CompressionOptions.compressionOff, logger: globals.logger,);
}
Future<Map<String, dynamic>> collect(Uri serviceUri, Set<String> libraryNames, {
Future<Map<String, dynamic>> collect(Uri? serviceUri, Set<String>? libraryNames, {
bool waitPaused = false,
String debugName,
Future<FlutterVmService> Function(Uri) connector = _defaultConnect,
String? debugName,
Future<FlutterVmService> Function(Uri?) connector = _defaultConnect,
@visibleForTesting bool forceSequential = false,
}) async {
final FlutterVmService vmService = await connector(serviceUri);
@ -244,31 +244,31 @@ Future<Map<String, dynamic>> collect(Uri serviceUri, Set<String> libraryNames, {
Future<Map<String, dynamic>> _getAllCoverage(
vm_service.VmService service,
Set<String> libraryNames,
Set<String>? libraryNames,
bool forceSequential,
) async {
final vm_service.Version version = await service.getVersion();
final bool libraryFilters = (version.major == 3 && version.minor >= 57) || version.major > 3;
final bool libraryFilters = (version.major == 3 && version.minor! >= 57) || version.major! > 3;
final vm_service.VM vm = await service.getVM();
final List<Map<String, dynamic>> coverage = <Map<String, dynamic>>[];
bool libraryPredicate(String libraryName) {
bool libraryPredicate(String? libraryName) {
if (libraryNames == null) {
return true;
}
final Uri uri = Uri.parse(libraryName);
final Uri uri = Uri.parse(libraryName!);
if (uri.scheme != 'package') {
return false;
}
final String scope = uri.path.split('/').first;
return libraryNames.contains(scope);
}
for (final vm_service.IsolateRef isolateRef in vm.isolates) {
if (isolateRef.isSystemIsolate) {
for (final vm_service.IsolateRef isolateRef in vm.isolates!) {
if (isolateRef.isSystemIsolate!) {
continue;
}
if (libraryFilters) {
final vm_service.SourceReport sourceReport = await service.getSourceReport(
isolateRef.id,
isolateRef.id!,
<String>['Coverage'],
forceCompile: true,
reportLines: true,
@ -283,7 +283,7 @@ Future<Map<String, dynamic>> _getAllCoverage(
} else {
vm_service.ScriptList scriptList;
try {
scriptList = await service.getScripts(isolateRef.id);
scriptList = await service.getScripts(isolateRef.id!);
} on vm_service.SentinelException {
continue;
}
@ -294,14 +294,14 @@ Future<Map<String, dynamic>> _getAllCoverage(
// For each ScriptRef loaded into the VM, load the corresponding Script
// and SourceReport object.
for (final vm_service.ScriptRef script in scriptList.scripts) {
final String libraryUri = script.uri;
for (final vm_service.ScriptRef script in scriptList.scripts!) {
final String? libraryUri = script.uri;
if (!libraryPredicate(libraryUri)) {
continue;
}
final String scriptId = script.id;
final String? scriptId = script.id;
final Future<void> getSourceReport = service.getSourceReport(
isolateRef.id,
isolateRef.id!,
<String>['Coverage'],
scriptId: scriptId,
forceCompile: true,
@ -328,36 +328,36 @@ void _buildCoverageMap(
List<vm_service.SourceReport> sourceReports,
List<Map<String, dynamic>> coverage,
) {
final Map<String, Map<int, int>> hitMaps = <String, Map<int, int>>{};
final Map<String?, Map<int, int>> hitMaps = <String?, Map<int, int>>{};
for (final vm_service.SourceReport sourceReport in sourceReports) {
for (final vm_service.SourceReportRange range in sourceReport.ranges) {
final vm_service.SourceReportCoverage coverage = range.coverage;
for (final vm_service.SourceReportRange range in sourceReport.ranges!) {
final vm_service.SourceReportCoverage? coverage = range.coverage;
// Coverage reports may sometimes be null for a Script.
if (coverage == null) {
continue;
}
final vm_service.ScriptRef scriptRef = sourceReport.scripts[range.scriptIndex];
final String uri = scriptRef.uri;
final vm_service.ScriptRef scriptRef = sourceReport.scripts![range.scriptIndex!];
final String? uri = scriptRef.uri;
hitMaps[uri] ??= <int, int>{};
final Map<int, int> hitMap = hitMaps[uri];
final List<int> hits = coverage.hits;
final List<int> misses = coverage.misses;
final Map<int, int>? hitMap = hitMaps[uri];
final List<int>? hits = coverage.hits;
final List<int>? misses = coverage.misses;
if (hits != null) {
for (final int line in hits) {
final int current = hitMap[line] ?? 0;
final int current = hitMap![line] ?? 0;
hitMap[line] = current + 1;
}
}
if (misses != null) {
for (final int line in misses) {
hitMap[line] ??= 0;
hitMap![line] ??= 0;
}
}
}
}
hitMaps.forEach((String uri, Map<int, int> hitMap) {
coverage.add(_toScriptCoverageJson(uri, hitMap));
hitMaps.forEach((String? uri, Map<int, int> hitMap) {
coverage.add(_toScriptCoverageJson(uri!, hitMap));
});
}

View File

@ -2,7 +2,7 @@
// 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';
@ -47,22 +47,22 @@ typedef PlatformPluginRegistration = void Function(FlutterPlatform platform);
/// main()`), you can set an observatory port explicitly.
FlutterPlatform installHook({
TestWrapper testWrapper = const TestWrapper(),
@required String shellPath,
@required DebuggingOptions debuggingOptions,
TestWatcher watcher,
required String shellPath,
required DebuggingOptions debuggingOptions,
TestWatcher? watcher,
bool enableObservatory = false,
bool machine = false,
String precompiledDillPath,
Map<String, String> precompiledDillFiles,
String? precompiledDillPath,
Map<String, String>? precompiledDillFiles,
bool updateGoldens = false,
String testAssetDirectory,
String? testAssetDirectory,
InternetAddressType serverType = InternetAddressType.IPv4,
Uri projectRootDirectory,
FlutterProject flutterProject,
String icudtlPath,
PlatformPluginRegistration platformPluginRegistration,
Device integrationTestDevice,
String integrationTestUserIdentifier,
Uri? projectRootDirectory,
FlutterProject? flutterProject,
String? icudtlPath,
PlatformPluginRegistration? platformPluginRegistration,
Device? integrationTestDevice,
String? integrationTestUserIdentifier,
}) {
assert(testWrapper != null);
assert(enableObservatory || (!debuggingOptions.startPaused && debuggingOptions.hostVmServicePort == null));
@ -119,9 +119,9 @@ FlutterPlatform installHook({
// NOTE: this API is used by the fuchsia source tree, do not add new
// required or position parameters.
String generateTestBootstrap({
@required Uri testUrl,
@required InternetAddress host,
File testConfigFile,
required Uri testUrl,
required InternetAddress host,
File? testConfigFile,
bool updateGoldens = false,
String languageVersionHeader = '',
bool nullSafety = false,
@ -271,8 +271,8 @@ typedef Finalizer = Future<void> Function();
/// The flutter test platform used to integrate with package:test.
class FlutterPlatform extends PlatformPlugin {
FlutterPlatform({
@required this.shellPath,
@required this.debuggingOptions,
required this.shellPath,
required this.debuggingOptions,
this.watcher,
this.enableObservatory,
this.machine,
@ -290,26 +290,26 @@ class FlutterPlatform extends PlatformPlugin {
final String shellPath;
final DebuggingOptions debuggingOptions;
final TestWatcher watcher;
final bool enableObservatory;
final bool machine;
final InternetAddress host;
final String precompiledDillPath;
final Map<String, String> precompiledDillFiles;
final bool updateGoldens;
final String testAssetDirectory;
final Uri projectRootDirectory;
final FlutterProject flutterProject;
final String icudtlPath;
final TestWatcher? watcher;
final bool? enableObservatory;
final bool? machine;
final InternetAddress? host;
final String? precompiledDillPath;
final Map<String, String>? precompiledDillFiles;
final bool? updateGoldens;
final String? testAssetDirectory;
final Uri? projectRootDirectory;
final FlutterProject? flutterProject;
final String? icudtlPath;
/// The device to run the test on for Integration Tests.
///
/// If this is null, the test will run as a regular test with the Flutter
/// Tester; otherwise it will run as a Integration Test on this device.
final Device integrationTestDevice;
final Device? integrationTestDevice;
bool get _isIntegrationTest => integrationTestDevice != null;
final String integrationTestUserIdentifier;
final String? integrationTestUserIdentifier;
final FontConfigManager _fontConfigManager = FontConfigManager();
@ -317,7 +317,7 @@ class FlutterPlatform extends PlatformPlugin {
///
/// To speed up compilation, each compile is initialized from an existing
/// dill file from previous runs, if possible.
TestCompiler compiler;
TestCompiler? compiler;
// Each time loadChannel() is called, we spin up a local WebSocket server,
// then spin up the engine in a subprocess. We pass the engine a Dart file
@ -361,7 +361,7 @@ class FlutterPlatform extends PlatformPlugin {
_testCount += 1;
final StreamController<dynamic> localController = StreamController<dynamic>();
final StreamController<dynamic> remoteController = StreamController<dynamic>();
final Completer<_AsyncError> testCompleteCompleter = Completer<_AsyncError>();
final Completer<_AsyncError?> testCompleteCompleter = Completer<_AsyncError?>();
final _FlutterPlatformStreamSinkWrapper<dynamic> remoteSink = _FlutterPlatformStreamSinkWrapper<dynamic>(
remoteController.sink,
testCompleteCompleter.future,
@ -384,17 +384,17 @@ class FlutterPlatform extends PlatformPlugin {
List<String> definitions,
List<String> typeDefinitions,
String libraryUri,
String klass,
String? klass,
bool isStatic,
) async {
if (compiler == null || compiler.compiler == null) {
if (compiler == null || compiler!.compiler == null) {
throw Exception('Compiler is not set up properly to compile $expression');
}
final CompilerOutput compilerOutput =
await compiler.compiler.compileExpression(expression, definitions,
final CompilerOutput? compilerOutput =
await compiler!.compiler!.compileExpression(expression, definitions,
typeDefinitions, libraryUri, klass, isStatic);
if (compilerOutput != null && compilerOutput.expressionData != null) {
return base64.encode(compilerOutput.expressionData);
return base64.encode(compilerOutput.expressionData!);
}
throw Exception('Failed to compile $expression');
}
@ -404,7 +404,7 @@ class FlutterPlatform extends PlatformPlugin {
return IntegrationTestTestDevice(
id: ourTestCount,
debuggingOptions: debuggingOptions,
device: integrationTestDevice,
device: integrationTestDevice!,
userIdentifier: integrationTestUserIdentifier,
);
}
@ -415,7 +415,7 @@ class FlutterPlatform extends PlatformPlugin {
processManager: globals.processManager,
logger: globals.logger,
shellPath: shellPath,
enableObservatory: enableObservatory,
enableObservatory: enableObservatory!,
machine: machine,
debuggingOptions: debuggingOptions,
host: host,
@ -427,14 +427,14 @@ class FlutterPlatform extends PlatformPlugin {
);
}
Future<_AsyncError> _startTest(
Future<_AsyncError?> _startTest(
String testPath,
StreamChannel<dynamic> testHarnessChannel,
int ourTestCount,
) async {
globals.printTrace('test $ourTestCount: starting test $testPath');
_AsyncError outOfBandError; // error that we couldn't send to the harness that we need to send via our future
_AsyncError? outOfBandError; // error that we couldn't send to the harness that we need to send via our future
final List<Finalizer> finalizers = <Finalizer>[]; // Will be run in reverse order.
bool controllerSinkClosed = false;
@ -447,7 +447,7 @@ class FlutterPlatform extends PlatformPlugin {
// If a kernel file is given, then use that to launch the test.
// If mapping is provided, look kernel file from mapping.
// If all fails, create a "listener" dart that invokes actual test.
String mainDart;
String? mainDart;
if (precompiledDillPath != null) {
mainDart = precompiledDillPath;
// When start paused is specified, it means that the user is likely
@ -457,10 +457,10 @@ class FlutterPlatform extends PlatformPlugin {
compiler ??= TestCompiler(debuggingOptions.buildInfo, flutterProject, precompiledDillPath: precompiledDillPath);
final Uri testUri = globals.fs.file(testPath).uri;
// Trigger a compilation to initialize the resident compiler.
unawaited(compiler.compile(testUri));
unawaited(compiler!.compile(testUri));
}
} else if (precompiledDillFiles != null) {
mainDart = precompiledDillFiles[testPath];
mainDart = precompiledDillFiles![testPath];
} else {
mainDart = _createListenerDart(finalizers, ourTestCount, testPath);
@ -468,7 +468,7 @@ class FlutterPlatform extends PlatformPlugin {
if (integrationTestDevice == null) {
// Lazily instantiate compiler so it is built only if it is actually used.
compiler ??= TestCompiler(debuggingOptions.buildInfo, flutterProject);
mainDart = await compiler.compile(globals.fs.file(mainDart).uri);
mainDart = await compiler!.compile(globals.fs.file(mainDart).uri);
if (mainDart == null) {
testHarnessChannel.sink.addError('Compilation failed for testPath=$testPath');
@ -479,7 +479,7 @@ class FlutterPlatform extends PlatformPlugin {
globals.printTrace('test $ourTestCount: starting test device');
final TestDevice testDevice = _createTestDevice(ourTestCount);
final Future<StreamChannel<String>> remoteChannelFuture = testDevice.start(mainDart);
final Future<StreamChannel<String>> remoteChannelFuture = testDevice.start(mainDart!);
finalizers.add(() async {
globals.printTrace('test $ourTestCount: ensuring test device is terminated.');
await testDevice.kill();
@ -584,7 +584,7 @@ class FlutterPlatform extends PlatformPlugin {
}
String _generateTestMain({
Uri testUrl,
required Uri testUrl,
}) {
assert(testUrl.scheme == 'file');
final File file = globals.fs.file(testUrl);
@ -592,14 +592,14 @@ class FlutterPlatform extends PlatformPlugin {
final LanguageVersion languageVersion = determineLanguageVersion(
file,
packageConfig[flutterProject?.manifest?.appName],
Cache.flutterRoot,
packageConfig[flutterProject!.manifest.appName],
Cache.flutterRoot!,
);
return generateTestBootstrap(
testUrl: testUrl,
testConfigFile: findTestConfigFile(globals.fs.file(testUrl), globals.logger),
host: host,
updateGoldens: updateGoldens,
host: host!,
updateGoldens: updateGoldens!,
flutterTestDep: packageConfig['flutter_test'] != null,
languageVersionHeader: '// @dart=${languageVersion.major}.${languageVersion.minor}',
integrationTest: _isIntegrationTest,
@ -609,7 +609,7 @@ class FlutterPlatform extends PlatformPlugin {
@override
Future<dynamic> close() async {
if (compiler != null) {
await compiler.dispose();
await compiler!.dispose();
compiler = null;
}
await _fontConfigManager.dispose();
@ -633,7 +633,7 @@ class _FlutterPlatformStreamSinkWrapper<S> implements StreamSink<S> {
_FlutterPlatformStreamSinkWrapper(this._parent, this._shellProcessClosed);
final StreamSink<S> _parent;
final Future<_AsyncError> _shellProcessClosed;
final Future<_AsyncError?> _shellProcessClosed;
@override
Future<void> get done => _done.future;
@ -650,7 +650,7 @@ class _FlutterPlatformStreamSinkWrapper<S> implements StreamSink<S> {
assert(futureResults.first == null);
final dynamic lastResult = futureResults.last;
if (lastResult is _AsyncError) {
_done.completeError(lastResult.error, lastResult.stack);
_done.completeError(lastResult.error as Object, lastResult.stack);
} else {
assert(lastResult == null);
_done.complete();
@ -664,7 +664,7 @@ class _FlutterPlatformStreamSinkWrapper<S> implements StreamSink<S> {
@override
void add(S event) => _parent.add(event);
@override
void addError(dynamic errorEvent, [ StackTrace stackTrace ]) => _parent.addError(errorEvent, stackTrace);
void addError(Object errorEvent, [ StackTrace? stackTrace ]) => _parent.addError(errorEvent, stackTrace);
@override
Future<dynamic> addStream(Stream<S> stream) => _parent.addStream(stream);
}
@ -681,9 +681,9 @@ class _AsyncError {
/// The returned future completes when either side is closed, which also
/// indicates when the tests have finished.
Future<void> _pipeHarnessToRemote({
@required int id,
@required StreamChannel<dynamic> harnessChannel,
@required StreamChannel<String> remoteChannel,
required int id,
required StreamChannel<dynamic> harnessChannel,
required StreamChannel<String> remoteChannel,
}) async {
globals.printTrace('test $id: Waiting for test harness or tests to finish');

View File

@ -2,7 +2,7 @@
// 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:io' as io; // flutter_ignore: dart_io_import;
@ -29,25 +29,26 @@ import 'test_device.dart';
/// Implementation of [TestDevice] with the Flutter Tester over a [Process].
class FlutterTesterTestDevice extends TestDevice {
FlutterTesterTestDevice({
@required this.id,
@required this.platform,
@required this.fileSystem,
@required this.processManager,
@required this.logger,
@required this.shellPath,
@required this.debuggingOptions,
@required this.enableObservatory,
@required this.machine,
@required this.host,
@required this.testAssetDirectory,
@required this.flutterProject,
@required this.icudtlPath,
@required this.compileExpression,
@required this.fontConfigManager,
required this.id,
required this.platform,
required this.fileSystem,
required this.processManager,
required this.logger,
required this.shellPath,
required this.debuggingOptions,
required this.enableObservatory,
required this.machine,
required this.host,
required this.testAssetDirectory,
required this.flutterProject,
required this.icudtlPath,
required this.compileExpression,
required this.fontConfigManager,
}) : assert(shellPath != null), // Please provide the path to the shell in the SKY_SHELL environment variable.
assert(!debuggingOptions.startPaused || enableObservatory),
_gotProcessObservatoryUri = enableObservatory
? Completer<Uri>() : (Completer<Uri>()..complete(null)),
// ignore: null_argument_to_non_null_type
? Completer<Uri>() : (Completer<Uri>()..complete()),
_operatingSystemUtils = OperatingSystemUtils(
fileSystem: fileSystem,
logger: logger,
@ -64,19 +65,19 @@ class FlutterTesterTestDevice extends TestDevice {
final String shellPath;
final DebuggingOptions debuggingOptions;
final bool enableObservatory;
final bool machine;
final InternetAddress host;
final String testAssetDirectory;
final FlutterProject flutterProject;
final String icudtlPath;
final CompileExpression compileExpression;
final bool? machine;
final InternetAddress? host;
final String? testAssetDirectory;
final FlutterProject? flutterProject;
final String? icudtlPath;
final CompileExpression? compileExpression;
final FontConfigManager fontConfigManager;
final Completer<Uri> _gotProcessObservatoryUri;
final Completer<int> _exitCode = Completer<int>();
Process _process;
HttpServer _server;
Process? _process;
HttpServer? _server;
final OperatingSystemUtils _operatingSystemUtils;
/// Starts the device.
@ -92,7 +93,7 @@ class FlutterTesterTestDevice extends TestDevice {
// Prepare our WebSocket server to talk to the engine subprocess.
// Let the server choose an unused port.
_server = await bind(host, /*port*/ 0);
logger.printTrace('test $id: test harness socket server is running at port:${_server.port}');
logger.printTrace('test $id: test harness socket server is running at port:${_server!.port}');
final List<String> command = <String>[
// Until an arm64 flutter tester binary is available, force to run in Rosetta
// to avoid "unexpectedly got a signal in sigtramp" crash.
@ -118,7 +119,7 @@ class FlutterTesterTestDevice extends TestDevice {
]
else
'--disable-observatory',
if (host.type == InternetAddressType.IPv6) '--ipv6',
if (host!.type == InternetAddressType.IPv6) '--ipv6',
if (icudtlPath != null) '--icu-data-file-path=$icudtlPath',
'--enable-checked-mode',
'--verify-entry-points',
@ -143,38 +144,38 @@ class FlutterTesterTestDevice extends TestDevice {
// If FLUTTER_TEST has not been set, assume from this context that this
// call was invoked by the command 'flutter test'.
final String flutterTest = platform.environment.containsKey('FLUTTER_TEST')
? platform.environment['FLUTTER_TEST']
? platform.environment['FLUTTER_TEST']!
: 'true';
final Map<String, String> environment = <String, String>{
'FLUTTER_TEST': flutterTest,
'FONTCONFIG_FILE': fontConfigManager.fontConfigFile.path,
'SERVER_PORT': _server.port.toString(),
'APP_NAME': flutterProject?.manifest?.appName ?? '',
'SERVER_PORT': _server!.port.toString(),
'APP_NAME': flutterProject?.manifest.appName ?? '',
if (testAssetDirectory != null)
'UNIT_TEST_ASSETS': testAssetDirectory,
'UNIT_TEST_ASSETS': testAssetDirectory!,
};
logger.printTrace('test $id: Starting flutter_tester process with command=$command, environment=$environment');
_process = await processManager.start(command, environment: environment);
// Unawaited to update state.
unawaited(_process.exitCode.then((int exitCode) {
logger.printTrace('test $id: flutter_tester process at pid ${_process.pid} exited with code=$exitCode');
unawaited(_process!.exitCode.then((int exitCode) {
logger.printTrace('test $id: flutter_tester process at pid ${_process!.pid} exited with code=$exitCode');
_exitCode.complete(exitCode);
}));
logger.printTrace('test $id: Started flutter_tester process at pid ${_process.pid}');
logger.printTrace('test $id: Started flutter_tester process at pid ${_process!.pid}');
// Pipe stdout and stderr from the subprocess to our printStatus console.
// We also keep track of what observatory port the engine used, if any.
_pipeStandardStreamsToConsole(
process: _process,
process: _process!,
reportObservatoryUri: (Uri detectedUri) async {
assert(!_gotProcessObservatoryUri.isCompleted);
assert(debuggingOptions.hostVmServicePort == null ||
debuggingOptions.hostVmServicePort == detectedUri.port);
Uri forwardingUri;
Uri? forwardingUri;
if (debuggingOptions.enableDds) {
logger.printTrace('test $id: Starting Dart Development Service');
final DartDevelopmentService dds = await startDds(detectedUri);
@ -186,7 +187,7 @@ class FlutterTesterTestDevice extends TestDevice {
logger.printTrace('Connecting to service protocol: $forwardingUri');
final Future<FlutterVmService> localVmService = connectToVmService(
forwardingUri,
forwardingUri!,
compileExpression: compileExpression,
logger: logger,
);
@ -194,7 +195,7 @@ class FlutterTesterTestDevice extends TestDevice {
logger.printTrace('test $id: Successfully connected to service protocol: $forwardingUri');
}));
if (debuggingOptions.startPaused && !machine) {
if (debuggingOptions.startPaused && !machine!) {
logger.printStatus('The test process has been started.');
logger.printStatus('You can now connect to it using observatory. To connect, load the following Web site in your browser:');
logger.printStatus(' $forwardingUri');
@ -244,7 +245,7 @@ class FlutterTesterTestDevice extends TestDevice {
Uri get _ddsServiceUri {
return Uri(
scheme: 'http',
host: (host.type == InternetAddressType.IPv6 ?
host: (host!.type == InternetAddressType.IPv6 ?
InternetAddress.loopbackIPv6 :
InternetAddress.loopbackIPv4
).host,
@ -259,7 +260,7 @@ class FlutterTesterTestDevice extends TestDevice {
uri,
serviceUri: _ddsServiceUri,
enableAuthCodes: !debuggingOptions.disableServiceAuthCodes,
ipv6: host.type == InternetAddressType.IPv6,
ipv6: host!.type == InternetAddressType.IPv6,
);
}
@ -268,7 +269,7 @@ class FlutterTesterTestDevice extends TestDevice {
/// Only intended to be overridden in tests.
@protected
@visibleForTesting
Future<HttpServer> bind(InternetAddress host, int port) => HttpServer.bind(host, port);
Future<HttpServer> bind(InternetAddress? host, int port) => HttpServer.bind(host, port);
@protected
@visibleForTesting
@ -276,7 +277,7 @@ class FlutterTesterTestDevice extends TestDevice {
assert(_server != null);
try {
final HttpRequest firstRequest = await _server.first;
final HttpRequest firstRequest = await _server!.first;
final WebSocket webSocket = await WebSocketTransformer.upgrade(firstRequest);
return _webSocketToStreamChannel(webSocket);
} on Exception catch (error, stackTrace) {
@ -287,14 +288,14 @@ class FlutterTesterTestDevice extends TestDevice {
@override
String toString() {
final String status = _process != null
? 'pid: ${_process.pid}, ${_exitCode.isCompleted ? 'exited' : 'running'}'
? 'pid: ${_process!.pid}, ${_exitCode.isCompleted ? 'exited' : 'running'}'
: 'not started';
return 'Flutter Tester ($status) for test $id';
}
void _pipeStandardStreamsToConsole({
@required Process process,
@required Future<void> Function(Uri uri) reportObservatoryUri,
required Process process,
required Future<void> Function(Uri uri) reportObservatoryUri,
}) {
for (final Stream<List<int>> stream in <Stream<List<int>>>[
process.stderr,
@ -307,10 +308,10 @@ class FlutterTesterTestDevice extends TestDevice {
(String line) async {
logger.printTrace('test $id: Shell: $line');
final Match match = globals.kVMServiceMessageRegExp.firstMatch(line);
final Match? match = globals.kVMServiceMessageRegExp.firstMatch(line);
if (match != null) {
try {
final Uri uri = Uri.parse(match[1]);
final Uri uri = Uri.parse(match[1]!);
if (reportObservatoryUri != null) {
await reportObservatoryUri(uri);
}
@ -357,7 +358,7 @@ StreamChannel<String> _webSocketToStreamChannel(WebSocket webSocket) {
.pipe(webSocket);
webSocket
// We're only communicating with string encoded JSON.
.map<String>((dynamic message) => message as String)
.map<String?>((dynamic message) => message as String?)
.pipe(controller.local.sink);
return controller.foreign;

View File

@ -2,12 +2,9 @@
// 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';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import '../base/file_system.dart';
@ -28,26 +25,26 @@ import 'test_config.dart';
class TestGoldenComparator {
/// Creates a [TestGoldenComparator] instance.
TestGoldenComparator(this.shellPath, this.compilerFactory, {
@required Logger logger,
@required FileSystem fileSystem,
@required ProcessManager processManager,
@required this.webRenderer,
required Logger logger,
required FileSystem fileSystem,
required ProcessManager? processManager,
required this.webRenderer,
}) : tempDir = fileSystem.systemTempDirectory.createTempSync('flutter_web_platform.'),
_logger = logger,
_fileSystem = fileSystem,
_processManager = processManager;
final String shellPath;
final String? shellPath;
final Directory tempDir;
final TestCompiler Function() compilerFactory;
final Logger _logger;
final FileSystem _fileSystem;
final ProcessManager _processManager;
final ProcessManager? _processManager;
final WebRendererMode webRenderer;
TestCompiler _compiler;
TestGoldenComparatorProcess _previousComparator;
Uri _previousTestUri;
TestCompiler? _compiler;
TestGoldenComparatorProcess? _previousComparator;
Uri? _previousTestUri;
Future<void> close() async {
tempDir.deleteSync(recursive: true);
@ -57,13 +54,16 @@ class TestGoldenComparator {
/// Start golden comparator in a separate process. Start one file per test file
/// to reduce the overhead of starting `flutter_tester`.
Future<TestGoldenComparatorProcess> _processForTestFile(Uri testUri) async {
Future<TestGoldenComparatorProcess?> _processForTestFile(Uri testUri) async {
if (testUri == _previousTestUri) {
return _previousComparator;
}
final String bootstrap = TestGoldenComparatorProcess.generateBootstrap(_fileSystem.file(testUri), testUri, logger: _logger);
final Process process = await _startProcess(bootstrap);
final Process? process = await _startProcess(bootstrap);
if (process == null) {
return null;
}
unawaited(_previousComparator?.close());
_previousComparator = TestGoldenComparatorProcess(process, logger: _logger);
_previousTestUri = testUri;
@ -71,16 +71,19 @@ class TestGoldenComparator {
return _previousComparator;
}
Future<Process> _startProcess(String testBootstrap) async {
Future<Process?> _startProcess(String testBootstrap) async {
// Prepare the Dart file that will talk to us and start the test.
final File listenerFile = (await tempDir.createTemp('listener')).childFile('listener.dart');
await listenerFile.writeAsString(testBootstrap);
// Lazily create the compiler
_compiler = _compiler ?? compilerFactory();
final String output = await _compiler.compile(listenerFile.uri);
final String? output = await _compiler!.compile(listenerFile.uri);
if (output == null) {
return null;
}
final List<String> command = <String>[
shellPath,
shellPath!,
'--disable-observatory',
'--non-interactive',
'--packages=${_fileSystem.path.join('.dart_tool', 'package_config.json')}',
@ -92,12 +95,12 @@ class TestGoldenComparator {
'FLUTTER_TEST_BROWSER': 'chrome',
'FLUTTER_WEB_RENDERER': webRenderer == WebRendererMode.html ? 'html' : 'canvaskit',
};
return _processManager.start(command, environment: environment);
return _processManager!.start(command, environment: environment);
}
Future<String> compareGoldens(Uri testUri, Uint8List bytes, Uri goldenKey, bool updateGoldens) async {
Future<String?> compareGoldens(Uri testUri, Uint8List bytes, Uri goldenKey, bool? updateGoldens) async {
final File imageFile = await (await tempDir.createTemp('image')).childFile('image').writeAsBytes(bytes);
final TestGoldenComparatorProcess process = await _processForTestFile(testUri);
final TestGoldenComparatorProcess process = await (_processForTestFile(testUri) as FutureOr<TestGoldenComparatorProcess>);
process.sendCommand(imageFile, goldenKey, updateGoldens);
final Map<String, dynamic> result = await process.getResponse();
@ -105,7 +108,7 @@ class TestGoldenComparator {
if (result == null) {
return 'unknown error';
} else {
return (result['success'] as bool) ? null : ((result['message'] as String) ?? 'does not match');
return (result['success'] as bool) ? null : ((result['message'] as String?) ?? 'does not match');
}
}
}
@ -114,7 +117,7 @@ class TestGoldenComparator {
/// handles communication with the child process.
class TestGoldenComparatorProcess {
/// Creates a [TestGoldenComparatorProcess] backed by [process].
TestGoldenComparatorProcess(this.process, {@required Logger logger}) : _logger = logger {
TestGoldenComparatorProcess(this.process, {required Logger logger}) : _logger = logger {
// Pipe stdout and stderr to printTrace and printError.
// Also parse stdout as a stream of JSON objects.
streamIterator = StreamIterator<Map<String, dynamic>>(
@ -138,14 +141,14 @@ class TestGoldenComparatorProcess {
final Logger _logger;
final Process process;
StreamIterator<Map<String, dynamic>> streamIterator;
late StreamIterator<Map<String, dynamic>> streamIterator;
Future<void> close() async {
process.kill();
await process.exitCode;
}
void sendCommand(File imageFile, Uri goldenKey, bool updateGoldens) {
void sendCommand(File imageFile, Uri? goldenKey, bool? updateGoldens) {
final Object command = jsonEncode(<String, dynamic>{
'imageFile': imageFile.path,
'key': goldenKey.toString(),
@ -161,8 +164,8 @@ class TestGoldenComparatorProcess {
return streamIterator.current;
}
static String generateBootstrap(File testFile, Uri testUri, {@required Logger logger}) {
final File testConfigFile = findTestConfigFile(testFile, logger);
static String generateBootstrap(File testFile, Uri testUri, {required Logger logger}) {
final File? testConfigFile = findTestConfigFile(testFile, logger);
// Generate comparator process for the file.
return '''
import 'dart:convert'; // flutter_ignore: dart_convert_import

View File

@ -2,14 +2,11 @@
// 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';
import 'package:async/async.dart';
import 'package:http_multi_server/http_multi_server.dart';
import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:pool/pool.dart';
import 'package:process/process.dart';
@ -41,19 +38,19 @@ import 'test_compiler.dart';
class FlutterWebPlatform extends PlatformPlugin {
FlutterWebPlatform._(this._server, this._config, this._root, {
FlutterProject flutterProject,
String shellPath,
FlutterProject? flutterProject,
String? shellPath,
this.updateGoldens,
this.nullAssertions,
@required this.buildInfo,
@required this.webMemoryFS,
@required FileSystem fileSystem,
@required PackageConfig flutterToolPackageConfig,
@required ChromiumLauncher chromiumLauncher,
@required Logger logger,
@required Artifacts artifacts,
@required ProcessManager processManager,
@required Cache cache,
required this.buildInfo,
required this.webMemoryFS,
required FileSystem fileSystem,
required PackageConfig flutterToolPackageConfig,
required ChromiumLauncher chromiumLauncher,
required Logger logger,
required Artifacts? artifacts,
required ProcessManager processManager,
required Cache cache,
}) : _fileSystem = fileSystem,
_flutterToolPackageConfig = flutterToolPackageConfig,
_chromiumLauncher = chromiumLauncher,
@ -63,7 +60,7 @@ class FlutterWebPlatform extends PlatformPlugin {
final shelf.Cascade cascade = shelf.Cascade()
.add(_webSocketHandler.handler)
.add(createStaticHandler(
fileSystem.path.join(Cache.flutterRoot, 'packages', 'flutter_tools'),
fileSystem.path.join(Cache.flutterRoot!, 'packages', 'flutter_tools'),
serveFilesOutsidePath: true,
))
.add(_handleStaticArtifact)
@ -93,9 +90,9 @@ class FlutterWebPlatform extends PlatformPlugin {
final PackageConfig _flutterToolPackageConfig;
final ChromiumLauncher _chromiumLauncher;
final Logger _logger;
final Artifacts _artifacts;
final bool updateGoldens;
final bool nullAssertions;
final Artifacts? _artifacts;
final bool? updateGoldens;
final bool? nullAssertions;
final OneOffHandler _webSocketHandler = OneOffHandler();
final AsyncMemoizer<void> _closeMemo = AsyncMemoizer<void>();
final String _root;
@ -106,28 +103,28 @@ class FlutterWebPlatform extends PlatformPlugin {
/// to lead to flaky tests.
final Pool _suiteLock = Pool(1);
BrowserManager _browserManager;
TestGoldenComparator _testGoldenComparator;
BrowserManager? _browserManager;
late TestGoldenComparator _testGoldenComparator;
static Future<FlutterWebPlatform> start(String root, {
FlutterProject flutterProject,
String shellPath,
FlutterProject? flutterProject,
String? shellPath,
bool updateGoldens = false,
bool pauseAfterLoad = false,
bool nullAssertions = false,
@required BuildInfo buildInfo,
@required WebMemoryFS webMemoryFS,
@required FileSystem fileSystem,
@required Logger logger,
@required ChromiumLauncher chromiumLauncher,
@required Artifacts artifacts,
@required ProcessManager processManager,
@required Cache cache,
required BuildInfo buildInfo,
required WebMemoryFS webMemoryFS,
required FileSystem fileSystem,
required Logger logger,
required ChromiumLauncher chromiumLauncher,
required Artifacts? artifacts,
required ProcessManager processManager,
required Cache cache,
}) async {
final shelf_io.IOServer server = shelf_io.IOServer(await HttpMultiServer.loopback(0));
final PackageConfig packageConfig = await loadPackageConfigWithLogging(
fileSystem.file(fileSystem.path.join(
Cache.flutterRoot,
Cache.flutterRoot!,
'packages',
'flutter_tools',
'.dart_tool',
@ -158,7 +155,7 @@ class FlutterWebPlatform extends PlatformPlugin {
bool get _closed => _closeMemo.hasRun;
/// Uri of the test package.
Uri get testUri => _flutterToolPackageConfig['test'].packageUriRoot;
Uri get testUri => _flutterToolPackageConfig['test']!.packageUriRoot;
WebRendererMode get _rendererMode {
return buildInfo.dartDefines.contains('FLUTTER_WEB_USE_SKIA=true')
@ -178,7 +175,7 @@ class FlutterWebPlatform extends PlatformPlugin {
/// The ahem text file.
File get _ahem => _fileSystem.file(_fileSystem.path.join(
Cache.flutterRoot,
Cache.flutterRoot!,
'packages',
'flutter_tools',
'static',
@ -187,7 +184,7 @@ class FlutterWebPlatform extends PlatformPlugin {
/// The require js binary.
File get _requireJs => _fileSystem.file(_fileSystem.path.join(
_artifacts.getHostArtifact(HostArtifact.engineDartSdkPath).path,
_artifacts!.getHostArtifact(HostArtifact.engineDartSdkPath).path,
'lib',
'dev_compiler',
'kernel',
@ -197,7 +194,7 @@ class FlutterWebPlatform extends PlatformPlugin {
/// The ddc to dart stack trace mapper.
File get _stackTraceMapper => _fileSystem.file(_fileSystem.path.join(
_artifacts.getHostArtifact(HostArtifact.engineDartSdkPath).path,
_artifacts!.getHostArtifact(HostArtifact.engineDartSdkPath).path,
'lib',
'dev_compiler',
'web',
@ -205,10 +202,10 @@ class FlutterWebPlatform extends PlatformPlugin {
));
File get _dartSdk => _fileSystem.file(
_artifacts.getHostArtifact(kDartSdkJsArtifactMap[_rendererMode][_nullSafetyMode]));
_artifacts!.getHostArtifact(kDartSdkJsArtifactMap[_rendererMode]![_nullSafetyMode]!));
File get _dartSdkSourcemaps => _fileSystem.file(
_artifacts.getHostArtifact(kDartSdkJsMapArtifactMap[_rendererMode][_nullSafetyMode]));
_artifacts!.getHostArtifact(kDartSdkJsMapArtifactMap[_rendererMode]![_nullSafetyMode]!));
/// The precompiled test javascript.
File get _testDartJs => _fileSystem.file(_fileSystem.path.join(
@ -254,7 +251,7 @@ class FlutterWebPlatform extends PlatformPlugin {
final String leadingPath = request.url.path.split('.dart.bootstrap.js')[0];
final String generatedFile = '${_fileSystem.path.split(leadingPath).join('_')}.dart.test.dart.js';
return shelf.Response.ok(generateMainModule(
nullAssertions: nullAssertions,
nullAssertions: nullAssertions!,
nativeNullAssertions: true,
bootstrapModule: '${_fileSystem.path.basename(leadingPath)}.dart.bootstrap',
entrypoint: '/$generatedFile'
@ -317,7 +314,7 @@ class FlutterWebPlatform extends PlatformPlugin {
FutureOr<shelf.Response> _packageFilesHandler(shelf.Request request) async {
if (request.requestedUri.pathSegments.first == 'packages') {
final Uri fileUri = buildInfo.packageConfig.resolve(Uri(
final Uri? fileUri = buildInfo.packageConfig.resolve(Uri(
scheme: 'package',
pathSegments: request.requestedUri.pathSegments.skip(1),
));
@ -344,16 +341,16 @@ class FlutterWebPlatform extends PlatformPlugin {
Future<shelf.Response> _goldenFileHandler(shelf.Request request) async {
if (request.url.path.contains('flutter_goldens')) {
final Map<String, Object> body = json.decode(await request.readAsString()) as Map<String, Object>;
final Uri goldenKey = Uri.parse(body['key'] as String);
final Uri testUri = Uri.parse(body['testUri'] as String);
final num width = body['width'] as num;
final num height = body['height'] as num;
final Uri goldenKey = Uri.parse(body['key']! as String);
final Uri testUri = Uri.parse(body['testUri']! as String);
final num width = body['width']! as num;
final num height = body['height']! as num;
Uint8List bytes;
try {
final ChromeTab chromeTab = await _browserManager._browser.chromeConnection.getTab((ChromeTab tab) {
return tab.url.contains(_browserManager._browser.url);
});
final ChromeTab chromeTab = await (_browserManager!._browser.chromeConnection.getTab((ChromeTab tab) {
return tab.url.contains(_browserManager!._browser.url!);
}) as FutureOr<ChromeTab>);
final WipConnection connection = await chromeTab.connect();
final WipResponse response = await connection.sendCommand('Page.captureScreenshot', <String, Object>{
// Clip the screenshot to include only the element.
@ -369,7 +366,7 @@ class FlutterWebPlatform extends PlatformPlugin {
'scale': 1.0,
},
});
bytes = base64.decode(response.result['data'] as String);
bytes = base64.decode(response.result!['data'] as String);
} on WipError catch (ex) {
_logger.printError('Caught WIPError: $ex');
return shelf.Response.ok('WIP error: $ex');
@ -382,7 +379,7 @@ class FlutterWebPlatform extends PlatformPlugin {
return shelf.Response.ok('Unknown error, bytes is null');
}
final String errorMessage = await _testGoldenComparator.compareGoldens(testUri, bytes, goldenKey, updateGoldens);
final String? errorMessage = await _testGoldenComparator.compareGoldens(testUri, bytes, goldenKey, updateGoldens);
return shelf.Response.ok(errorMessage ?? 'true');
} else {
return shelf.Response.notFound('Not Found');
@ -473,8 +470,8 @@ class FlutterWebPlatform extends PlatformPlugin {
final String pathFromTest = _fileSystem.path.relative(path, from: _fileSystem.path.join(_root, 'test'));
final Uri suiteUrl = url.resolveUri(_fileSystem.path.toUri('${_fileSystem.path.withoutExtension(pathFromTest)}.html'));
final String relativePath = _fileSystem.path.relative(_fileSystem.path.normalize(path), from: _fileSystem.currentDirectory.path);
final RunnerSuite suite = await _browserManager.load(relativePath, suiteUrl, suiteConfig, message, onDone: () async {
await _browserManager.close();
final RunnerSuite suite = await _browserManager!.load(relativePath, suiteUrl, suiteConfig, message, onDone: () async {
await _browserManager!.close();
_browserManager = null;
lockResource.release();
});
@ -516,7 +513,7 @@ class FlutterWebPlatform extends PlatformPlugin {
@override
Future<void> closeEphemeral() async {
if (_browserManager != null) {
await _browserManager.close();
await _browserManager!.close();
}
}
@ -524,7 +521,7 @@ class FlutterWebPlatform extends PlatformPlugin {
Future<void> close() => _closeMemo.runOnce(() async {
await Future.wait<void>(<Future<dynamic>>[
if (_browserManager != null)
_browserManager.close(),
_browserManager!.close(),
_server.close(),
_testGoldenComparator.close(),
]);
@ -561,7 +558,7 @@ class OneOffHandler {
return shelf.Response.notFound(null);
}
final String path = components.removeAt(0);
final FutureOr<shelf.Response> Function(shelf.Request) handler =
final FutureOr<shelf.Response> Function(shelf.Request)? handler =
_handlers.remove(path);
if (handler == null) {
return shelf.Response.notFound(null);
@ -590,8 +587,8 @@ class BrowserManager {
// Whenever we get a message, no matter which child channel it's for, we know
// the browser is still running code which means the user isn't debugging.
_channel = MultiChannel<dynamic>(
webSocket.cast<String>().transform(jsonDocument).changeStream((Stream<Object> stream) {
return stream.map((Object message) {
webSocket.cast<String>().transform(jsonDocument).changeStream((Stream<Object?> stream) {
return stream.map((Object? message) {
if (!_closed) {
_timer.reset();
}
@ -615,7 +612,7 @@ class BrowserManager {
/// The channel used to communicate with the browser.
///
/// This is connected to a page running `static/host.dart`.
MultiChannel<dynamic> _channel;
late MultiChannel<dynamic> _channel;
/// The ID of the next suite to be loaded.
///
@ -630,14 +627,14 @@ class BrowserManager {
///
/// This will be `null` as long as the browser isn't displaying a pause
/// screen.
CancelableCompleter<dynamic> _pauseCompleter;
CancelableCompleter<dynamic>? _pauseCompleter;
/// The controller for [_BrowserEnvironment.onRestart].
final StreamController<dynamic> _onRestartController =
StreamController<dynamic>.broadcast();
/// The environment to attach to each suite.
Future<_BrowserEnvironment> _environment;
late Future<_BrowserEnvironment> _environment;
/// Controllers for every suite in this browser.
///
@ -649,7 +646,7 @@ class BrowserManager {
//
// Because the browser stops running code when the user is actively debugging,
// this lets us detect whether they're debugging reasonably accurately.
RestartableTimer _timer;
late RestartableTimer _timer;
final AsyncMemoizer<dynamic> _closeMemoizer = AsyncMemoizer<dynamic>();
@ -677,25 +674,23 @@ class BrowserManager {
final Chromium chrome = await chromiumLauncher.launch(url.toString(), headless: headless);
final Completer<BrowserManager> completer = Completer<BrowserManager>();
unawaited(chrome.onExit.then((int browserExitCode) {
unawaited(chrome.onExit.then((int? browserExitCode) {
throwToolExit('${runtime.name} exited with code $browserExitCode before connecting.');
}).catchError((dynamic error, StackTrace stackTrace) {
if (completer.isCompleted) {
return null;
}).catchError((Object error, StackTrace stackTrace) {
if (!completer.isCompleted) {
completer.completeError(error, stackTrace);
}
completer.completeError(error, stackTrace);
}));
unawaited(future.then((WebSocketChannel webSocket) {
if (completer.isCompleted) {
return;
}
completer.complete(BrowserManager._(chrome, runtime, webSocket));
}).catchError((dynamic error, StackTrace stackTrace) {
}).catchError((Object error, StackTrace stackTrace) {
chrome.close();
if (completer.isCompleted) {
return null;
if (!completer.isCompleted) {
completer.completeError(error, stackTrace);
}
completer.completeError(error, stackTrace);
}));
return completer.future;
@ -720,7 +715,7 @@ class BrowserManager {
Uri url,
SuiteConfiguration suiteConfig,
Object message, {
Future<void> Function() onDone,
Future<void> Function()? onDone,
}
) async {
url = url.replace(fragment: Uri.encodeFull(jsonEncode(<String, Object>{
@ -729,7 +724,7 @@ class BrowserManager {
})));
final int suiteID = _suiteID++;
RunnerSuiteController controller;
RunnerSuiteController? controller;
void closeIframe() {
if (_closed) {
return;
@ -747,7 +742,7 @@ class BrowserManager {
StreamTransformer<dynamic, dynamic>.fromHandlers(handleDone: (EventSink<dynamic> sink) {
closeIframe();
sink.close();
onDone();
onDone!();
}),
);
@ -774,25 +769,25 @@ class BrowserManager {
/// An implementation of [Environment.displayPause].
CancelableOperation<dynamic> _displayPause() {
if (_pauseCompleter != null) {
return _pauseCompleter.operation;
return _pauseCompleter!.operation;
}
_pauseCompleter = CancelableCompleter<dynamic>(onCancel: () {
_channel.sink.add(<String, String>{'command': 'resume'});
_pauseCompleter = null;
});
_pauseCompleter.operation.value.whenComplete(() {
_pauseCompleter!.operation.value.whenComplete(() {
_pauseCompleter = null;
});
_channel.sink.add(<String, String>{'command': 'displayPause'});
return _pauseCompleter.operation;
return _pauseCompleter!.operation;
}
/// The callback for handling messages received from the host page.
void _onMessage(dynamic message) {
assert(message is Map<String, dynamic>);
if (message is Map<String, dynamic>) {
switch (message['command'] as String) {
switch (message['command'] as String?) {
case 'ping':
break;
case 'restart':
@ -800,7 +795,7 @@ class BrowserManager {
break;
case 'resume':
if (_pauseCompleter != null) {
_pauseCompleter.complete();
_pauseCompleter!.complete();
}
break;
default:
@ -818,7 +813,7 @@ class BrowserManager {
_closed = true;
_timer.cancel();
if (_pauseCompleter != null) {
_pauseCompleter.complete();
_pauseCompleter!.complete();
}
_pauseCompleter = null;
_controllers.clear();
@ -844,7 +839,7 @@ class _BrowserEnvironment implements Environment {
final bool supportsDebugging = true;
@override
final Uri observatoryUrl;
final Uri? observatoryUrl;
@override
final Uri remoteDebuggerUrl;

View File

@ -29,7 +29,7 @@ class IntegrationTestTestDevice implements TestDevice {
final int id;
final Device device;
final DebuggingOptions debuggingOptions;
final String userIdentifier;
final String? userIdentifier;
ApplicationPackage? _applicationPackage;
final Completer<void> _finished = Completer<void>();
@ -50,7 +50,7 @@ class IntegrationTestTestDevice implements TestDevice {
}
final LaunchResult launchResult = await device.startApp(
_applicationPackage!,
_applicationPackage,
mainPath: entrypointPath,
platformArgs: <String, dynamic>{},
debuggingOptions: debuggingOptions,

View File

@ -2,10 +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:meta/meta.dart';
import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
@ -29,32 +25,32 @@ abstract class FlutterTestRunner {
Future<int> runTests(
TestWrapper testWrapper,
List<String> testFiles, {
@required DebuggingOptions debuggingOptions,
required DebuggingOptions debuggingOptions,
List<String> names = const <String>[],
List<String> plainNames = const <String>[],
String tags,
String excludeTags,
String? tags,
String? excludeTags,
bool enableObservatory = false,
bool ipv6 = false,
bool machine = false,
String precompiledDillPath,
Map<String, String> precompiledDillFiles,
String? precompiledDillPath,
Map<String, String>? precompiledDillFiles,
bool updateGoldens = false,
TestWatcher watcher,
@required int concurrency,
String testAssetDirectory,
FlutterProject flutterProject,
String icudtlPath,
Directory coverageDirectory,
TestWatcher? watcher,
required int? concurrency,
String? testAssetDirectory,
FlutterProject? flutterProject,
String? icudtlPath,
Directory? coverageDirectory,
bool web = false,
String randomSeed,
String reporter,
String timeout,
String? randomSeed,
String? reporter,
String? timeout,
bool runSkipped = false,
int shardIndex,
int totalShards,
Device integrationTestDevice,
String integrationTestUserIdentifier,
int? shardIndex,
int? totalShards,
Device? integrationTestDevice,
String? integrationTestUserIdentifier,
});
}
@ -65,35 +61,35 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
Future<int> runTests(
TestWrapper testWrapper,
List<String> testFiles, {
@required DebuggingOptions debuggingOptions,
required DebuggingOptions debuggingOptions,
List<String> names = const <String>[],
List<String> plainNames = const <String>[],
String tags,
String excludeTags,
String? tags,
String? excludeTags,
bool enableObservatory = false,
bool ipv6 = false,
bool machine = false,
String precompiledDillPath,
Map<String, String> precompiledDillFiles,
String? precompiledDillPath,
Map<String, String>? precompiledDillFiles,
bool updateGoldens = false,
TestWatcher watcher,
@required int concurrency,
String testAssetDirectory,
FlutterProject flutterProject,
String icudtlPath,
Directory coverageDirectory,
TestWatcher? watcher,
required int? concurrency,
String? testAssetDirectory,
FlutterProject? flutterProject,
String? icudtlPath,
Directory? coverageDirectory,
bool web = false,
String randomSeed,
String reporter,
String timeout,
String? randomSeed,
String? reporter,
String? timeout,
bool runSkipped = false,
int shardIndex,
int totalShards,
Device integrationTestDevice,
String integrationTestUserIdentifier,
int? shardIndex,
int? totalShards,
Device? integrationTestDevice,
String? integrationTestUserIdentifier,
}) async {
// Configure package:test to use the Flutter engine for child processes.
final String shellPath = globals.artifacts.getArtifactPath(Artifact.flutterTester);
final String shellPath = globals.artifacts!.getArtifactPath(Artifact.flutterTester);
// Compute the command-line arguments for package:test.
final List<String> testArgs = <String>[
@ -136,11 +132,11 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
logger: globals.logger,
fileSystem: globals.fs,
platform: globals.platform,
artifacts: globals.artifacts,
artifacts: globals.artifacts!,
processManager: globals.processManager,
config: globals.config,
).initialize(
projectDirectory: flutterProject.directory,
projectDirectory: flutterProject!.directory,
testOutputDir: tempBuildDir,
testFiles: testFiles,
buildInfo: debuggingOptions.buildInfo,

View File

@ -2,7 +2,7 @@
// 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';
@ -22,7 +22,7 @@ class CompilationRequest {
CompilationRequest(this.mainUri, this.result);
Uri mainUri;
Completer<String> result;
Completer<String?> result;
}
/// A frontend_server wrapper for the flutter test runner.
@ -43,9 +43,9 @@ class TestCompiler {
TestCompiler(
this.buildInfo,
this.flutterProject,
{ String precompiledDillPath }
{ String? precompiledDillPath }
) : testFilePath = precompiledDillPath ?? globals.fs.path.join(
flutterProject.directory.path,
flutterProject!.directory.path,
getBuildDirectory(),
'test_cache',
getDefaultCachedKernelPath(
@ -69,19 +69,19 @@ class TestCompiler {
final StreamController<CompilationRequest> compilerController = StreamController<CompilationRequest>();
final List<CompilationRequest> compilationQueue = <CompilationRequest>[];
final FlutterProject flutterProject;
final FlutterProject? flutterProject;
final BuildInfo buildInfo;
final String testFilePath;
final bool shouldCopyDillFile;
ResidentCompiler compiler;
File outputDill;
ResidentCompiler? compiler;
late File outputDill;
Future<String> compile(Uri mainDart) {
Future<String?> compile(Uri mainDart) {
final Completer<String> completer = Completer<String>();
if (compilerController.isClosed) {
return Future<String>.value();
return Future<String?>.value();
}
compilerController.add(CompilationRequest(mainDart, completer));
return completer.future;
@ -91,7 +91,7 @@ class TestCompiler {
// Check for null in case this instance is shut down before the
// lazily-created compiler has been created.
if (compiler != null) {
await compiler.shutdown();
await compiler!.shutdown();
compiler = null;
}
}
@ -103,10 +103,10 @@ class TestCompiler {
/// Create the resident compiler used to compile the test.
@visibleForTesting
Future<ResidentCompiler> createCompiler() async {
Future<ResidentCompiler?> createCompiler() async {
final ResidentCompiler residentCompiler = ResidentCompiler(
globals.artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
artifacts: globals.artifacts,
globals.artifacts!.getArtifactPath(Artifact.flutterPatchedSdkPath),
artifacts: globals.artifacts!,
logger: globals.logger,
processManager: globals.processManager,
buildMode: buildInfo.mode,
@ -151,31 +151,30 @@ class TestCompiler {
final String mainUriString = buildInfo.packageConfig.toPackageUri(request.mainUri)?.toString()
?? request.mainUri.toString();
await generateMainDartWithPluginRegistrant(
flutterProject,
flutterProject!,
buildInfo.packageConfig,
mainUriString,
globals.fs.file(request.mainUri),
throwOnPluginPubspecError: false,
);
invalidatedRegistrantFiles.add(flutterProject.dartPluginRegistrant.absolute.uri);
invalidatedRegistrantFiles.add(flutterProject!.dartPluginRegistrant.absolute.uri);
}
final CompilerOutput compilerOutput = await compiler.recompile(
final CompilerOutput? compilerOutput = await compiler!.recompile(
request.mainUri,
<Uri>[request.mainUri, ...invalidatedRegistrantFiles],
outputPath: outputDill.path,
packageConfig: buildInfo.packageConfig,
projectRootPath: flutterProject?.directory?.absolute?.path,
projectRootPath: flutterProject?.directory.absolute.path,
checkDartPluginRegistry: true,
fs: globals.fs,
);
final String outputPath = compilerOutput?.outputFilename;
final String? outputPath = compilerOutput?.outputFilename;
// In case compiler didn't produce output or reported compilation
// errors, pass [null] upwards to the consumer and shutdown the
// compiler to avoid reusing compiler that might have gotten into
// a weird state.
if (outputPath == null || compilerOutput.errorCount > 0) {
if (outputPath == null || compilerOutput!.errorCount > 0) {
request.result.complete(null);
await _shutdown();
} else {
@ -197,8 +196,8 @@ class TestCompiler {
} else {
request.result.complete(outputPath);
}
compiler.accept();
compiler.reset();
compiler!.accept();
compiler!.reset();
}
globals.printTrace('Compiling ${request.mainUri} took ${compilerTime.elapsedMilliseconds}ms');
// Only remove now when we finished processing the element

View File

@ -99,7 +99,7 @@ typedef CompileExpression = Future<String> Function(
/// A method that pulls an SkSL shader from the device and writes it to a file.
///
/// The name of the file returned as a result.
typedef GetSkSLMethod = Future<String> Function();
typedef GetSkSLMethod = Future<String?> Function();
Future<io.WebSocket> _defaultOpenChannel(String url, {
io.CompressionOptions compression = io.CompressionOptions.compressionDefault,
@ -265,7 +265,14 @@ Future<vm_service.VmService> setUpVmService(
}
if (skSLMethod != null) {
vmService.registerServiceCallback('flutterGetSkSL', (Map<String, Object?> params) async {
final String filename = await skSLMethod();
final String? filename = await skSLMethod();
if (filename == null) {
return <String, Object>{
'result': <String, Object>{
'type': 'Success',
},
};
}
return <String, Object>{
'result': <String, Object>{
'type': 'Success',

View File

@ -2,10 +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:meta/meta.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
@ -16,7 +12,7 @@ import '../project.dart';
import '../reporting/reporting.dart';
import '../resident_runner.dart';
WebRunnerFactory get webRunnerFactory => context.get<WebRunnerFactory>();
WebRunnerFactory? get webRunnerFactory => context.get<WebRunnerFactory>();
// Hack to hide web imports for google3.
abstract class WebRunnerFactory {
@ -25,16 +21,16 @@ abstract class WebRunnerFactory {
/// Create a [ResidentRunner] for the web.
ResidentRunner createWebRunner(
FlutterDevice device, {
String target,
@required bool stayResident,
@required FlutterProject flutterProject,
@required bool ipv6,
@required DebuggingOptions debuggingOptions,
@required UrlTunneller urlTunneller,
@required Logger logger,
@required FileSystem fileSystem,
@required SystemClock systemClock,
@required Usage usage,
String? target,
required bool stayResident,
required FlutterProject flutterProject,
required bool? ipv6,
required DebuggingOptions debuggingOptions,
required UrlTunneller? urlTunneller,
required Logger? logger,
required FileSystem fileSystem,
required SystemClock systemClock,
required Usage usage,
bool machine = false,
});
}

View File

@ -173,14 +173,6 @@ void main() {
await device.start('example.dill');
expect(processManager.hasRemainingExpectations, isFalse);
});
testUsingContext('as null when set to null', () async {
platform.environment = <String, String>{'FLUTTER_TEST': null};
processManager.addCommand(flutterTestCommand(null));
await device.start('example.dill');
expect(processManager.hasRemainingExpectations, isFalse);
});
});
group('Dart Entrypoint Args', () {

View File

@ -52,7 +52,6 @@ void main() {
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
@ -80,7 +79,6 @@ void main() {
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
@ -103,7 +101,6 @@ void main() {
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
@ -125,7 +122,6 @@ void main() {
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),
@ -152,7 +148,6 @@ void main() {
flutterProject: project,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
systemClock: SystemClock.fixed(DateTime(0, 0, 0)),

View File

@ -159,7 +159,6 @@ void main() {
flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -188,7 +187,6 @@ void main() {
flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -207,7 +205,6 @@ void main() {
flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -220,7 +217,6 @@ void main() {
flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -322,7 +318,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
stayResident: false,
urlTunneller: null,
fileSystem: fileSystem,
logger: logger,
usage: globals.flutterUsage,
@ -346,7 +341,6 @@ void main() {
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
stayResident: false,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -463,7 +457,6 @@ void main() {
flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: BufferLogger.test(),
usage: globals.flutterUsage,
@ -789,6 +782,7 @@ void main() {
testUsingContext('cleanup of resources is safe to call multiple times', () async {
final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
mockDevice.dds = DartDevelopmentService();
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations,
]);
@ -882,7 +876,6 @@ void main() {
flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: logger,
usage: globals.flutterUsage,
@ -925,7 +918,6 @@ void main() {
flutterProject: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
urlTunneller: null,
fileSystem: fileSystem,
logger: logger,
usage: globals.flutterUsage,
@ -1075,7 +1067,6 @@ ResidentRunner setUpResidentRunner(FlutterDevice flutterDevice, {
flutterProject: FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
debuggingOptions: debuggingOptions ?? DebuggingOptions.enabled(BuildInfo.debug),
ipv6: true,
urlTunneller: null,
usage: globals.flutterUsage,
systemClock: systemClock ?? SystemClock.fixed(DateTime.now()),
fileSystem: globals.fs,

View File

@ -4,6 +4,8 @@
// @dart = 2.8
// ignore_for_file: avoid_redundant_argument_values
import 'dart:io' hide Directory, File;
import 'package:flutter_tools/src/artifacts.dart';

View File

@ -93,7 +93,7 @@ abstract class VmServiceExpectation {
class FakeVmServiceRequest implements VmServiceExpectation {
const FakeVmServiceRequest({
required this.method,
this.args = const <String, Object>{},
this.args = const <String, Object?>{},
this.jsonResponse,
this.errorCode,
this.close = false,
@ -107,7 +107,7 @@ class FakeVmServiceRequest implements VmServiceExpectation {
/// If non-null, the error code for a [vm_service.RPCError] in place of a
/// standard response.
final int? errorCode;
final Map<String, Object>? args;
final Map<String, Object?>? args;
final Map<String, Object?>? jsonResponse;
@override