[flutter_tools] add --null-assertions flag for debugging with null safety (#63416)
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index 652ba17..262636c 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -626,9 +626,8 @@ ); } - List<String> cmd; - - cmd = <String>[ + final String dartVmFlags = computeDartVmFlags(debuggingOptions); + final List<String> cmd = <String>[ 'shell', 'am', 'start', '-a', 'android.intent.action.RUN', '-f', '0x20000000', // FLAG_ACTIVITY_SINGLE_TOP @@ -665,8 +664,8 @@ ...<String>['--ez', 'start-paused', 'true'], if (debuggingOptions.disableServiceAuthCodes) ...<String>['--ez', 'disable-service-auth-codes', 'true'], - if (debuggingOptions.dartFlags.isNotEmpty) - ...<String>['--es', 'dart-flags', debuggingOptions.dartFlags], + if (dartVmFlags.isNotEmpty) + ...<String>['--es', 'dart-flags', dartVmFlags], if (debuggingOptions.useTestFonts) ...<String>['--ez', 'use-test-fonts', 'true'], if (debuggingOptions.verboseSystemLogs)
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index 403205e..fd5b739 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -423,6 +423,7 @@ fastStart: boolArg('fast-start') && !runningWithPrebuiltApplication && devices.every((Device device) => device.supportsFastStart), + nullAssertions: boolArg('null-assertions'), ); } }
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index 077cae8..a990b39 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -265,6 +265,7 @@ web: stringArg('platform') == 'chrome', randomSeed: stringArg('test-randomize-ordering-seed'), extraFrontEndOptions: getBuildInfo(forcedBuildMode: BuildMode.debug).extraFrontEndOptions, + nullAssertions: boolArg(FlutterOptions.kNullAssertions), ); if (collector != null) {
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index c691610..2a16f8e 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -790,6 +790,7 @@ this.webEnableExpressionEvaluation = false, this.vmserviceOutFile, this.fastStart = false, + this.nullAssertions = false, }) : debuggingEnabled = true; DebuggingOptions.disabled(this.buildInfo, { @@ -821,7 +822,8 @@ deviceVmServicePort = null, vmserviceOutFile = null, fastStart = false, - webEnableExpressionEvaluation = false; + webEnableExpressionEvaluation = false, + nullAssertions = false; final bool debuggingEnabled; @@ -868,6 +870,8 @@ final String vmserviceOutFile; final bool fastStart; + final bool nullAssertions; + bool get hasObservatoryPort => hostVmServicePort != null; } @@ -993,3 +997,14 @@ @override Future<void> dispose() async { } } + +/// Append --null_assertions to any existing Dart VM flags if +/// [debuggingOptions.nullAssertions] is true. +String computeDartVmFlags(DebuggingOptions debuggingOptions) { + return <String>[ + if (debuggingOptions.dartFlags?.isNotEmpty ?? false) + debuggingOptions.dartFlags, + if (debuggingOptions.nullAssertions) + '--null_assertions', + ].join(','); +}
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index 056c857..d8e7c74 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -355,6 +355,7 @@ ?? math.Random(packageId.hashCode).nextInt(16383) + 49152; // Step 3: Attempt to install the application on the device. + final String dartVmFlags = computeDartVmFlags(debuggingOptions); final List<String> launchArguments = <String>[ '--enable-dart-profiling', // These arguments are required to support the fallback connection strategy @@ -363,7 +364,7 @@ '--disable-service-auth-codes', '--observatory-port=$assumedObservatoryPort', if (debuggingOptions.startPaused) '--start-paused', - if (debuggingOptions.dartFlags.isNotEmpty) '--dart-flags="${debuggingOptions.dartFlags}"', + if (dartVmFlags.isNotEmpty) '--dart-flags="$dartVmFlags"', if (debuggingOptions.useTestFonts) '--use-test-fonts', // "--enable-checked-mode" and "--verify-entry-points" should always be // passed when we launch debug build via "ios-deploy". However, we don't
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart index 43aa7a7..dcba2bb 100644 --- a/packages/flutter_tools/lib/src/ios/simulators.dart +++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -411,6 +411,7 @@ } // Prepare launch arguments. + final String dartVmFlags = computeDartVmFlags(debuggingOptions); final List<String> args = <String>[ '--enable-dart-profiling', if (debuggingOptions.debuggingEnabled) ...<String>[ @@ -423,6 +424,7 @@ if (debuggingOptions.skiaDeterministicRendering) '--skia-deterministic-rendering', if (debuggingOptions.useTestFonts) '--use-test-fonts', if (debuggingOptions.traceAllowlist != null) '--trace-allowlist="${debuggingOptions.traceAllowlist}"', + if (dartVmFlags.isNotEmpty) '--dart-flags=$dartVmFlags' '--observatory-port=${debuggingOptions.hostVmServicePort ?? 0}', ], ];
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 404b74e..6791a8c 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -113,6 +113,7 @@ static const String kNullSafety = 'sound-null-safety'; static const String kDeviceUser = 'device-user'; static const String kAnalyzeSize = 'analyze-size'; + static const String kNullAssertions = 'null-assertions'; } abstract class FlutterCommand extends Command<void> { @@ -500,6 +501,12 @@ defaultsTo: null, hide: hide, ); + argParser.addFlag(FlutterOptions.kNullAssertions, + help: + 'Perform additional null assertions on the boundaries of migrated and ' + 'unmigrated code. This setting is not currently supported on desktop ' + 'devices.' + ); } void usesExtraFrontendOptions() {
diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart index a6127c4..686ccaa 100644 --- a/packages/flutter_tools/lib/src/test/flutter_platform.dart +++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart
@@ -92,6 +92,7 @@ List<String> extraFrontEndOptions, // Deprecated, use extraFrontEndOptions. List<String> dartExperiments, + bool nullAssertions = false, }) { assert(testWrapper != null); assert(enableObservatory || (!startPaused && observatoryPort == null)); @@ -125,6 +126,7 @@ flutterProject: flutterProject, icudtlPath: icudtlPath, extraFrontEndOptions: extraFrontEndOptions, + nullAssertions: nullAssertions, ); platformPluginRegistration(platform); return platform; @@ -268,6 +270,7 @@ this.projectRootDirectory, this.flutterProject, this.icudtlPath, + this.nullAssertions = false, @required this.extraFrontEndOptions, }) : assert(shellPath != null); @@ -290,6 +293,7 @@ final FlutterProject flutterProject; final String icudtlPath; final List<String> extraFrontEndOptions; + final bool nullAssertions; Directory fontsDirectory; @@ -844,6 +848,8 @@ '--non-interactive', '--use-test-fonts', '--packages=$packages', + if (nullAssertions) + '--dart-flags=--null_assertions', testPath, ];
diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart index 3f3c951..daa1cff 100644 --- a/packages/flutter_tools/lib/src/test/runner.dart +++ b/packages/flutter_tools/lib/src/test/runner.dart
@@ -52,6 +52,7 @@ bool web = false, String randomSeed, @required List<String> extraFrontEndOptions, + bool nullAssertions = false, }); } @@ -86,6 +87,7 @@ bool web = false, String randomSeed, @required List<String> extraFrontEndOptions, + bool nullAssertions = false, }) async { // Configure package:test to use the Flutter engine for child processes. final String shellPath = globals.artifacts.getArtifactPath(Artifact.flutterTester); @@ -178,6 +180,7 @@ flutterProject: flutterProject, icudtlPath: icudtlPath, extraFrontEndOptions: extraFrontEndOptions, + nullAssertions: nullAssertions, ); // Make the global packages path absolute.