Unverified Commit c86d090e authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] add --null-assertions flag for debugging with null safety (#63416)

parent cbe0999d
......@@ -626,9 +626,8 @@ class AndroidDevice extends Device {
);
}
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 @@ class AndroidDevice extends Device {
...<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)
......
......@@ -423,6 +423,7 @@ class RunCommand extends RunCommandBase {
fastStart: boolArg('fast-start')
&& !runningWithPrebuiltApplication
&& devices.every((Device device) => device.supportsFastStart),
nullAssertions: boolArg('null-assertions'),
);
}
}
......
......@@ -265,6 +265,7 @@ class TestCommand extends FlutterCommand {
web: stringArg('platform') == 'chrome',
randomSeed: stringArg('test-randomize-ordering-seed'),
extraFrontEndOptions: getBuildInfo(forcedBuildMode: BuildMode.debug).extraFrontEndOptions,
nullAssertions: boolArg(FlutterOptions.kNullAssertions),
);
if (collector != null) {
......
......@@ -790,6 +790,7 @@ class DebuggingOptions {
this.webEnableExpressionEvaluation = false,
this.vmserviceOutFile,
this.fastStart = false,
this.nullAssertions = false,
}) : debuggingEnabled = true;
DebuggingOptions.disabled(this.buildInfo, {
......@@ -821,7 +822,8 @@ class DebuggingOptions {
deviceVmServicePort = null,
vmserviceOutFile = null,
fastStart = false,
webEnableExpressionEvaluation = false;
webEnableExpressionEvaluation = false,
nullAssertions = false;
final bool debuggingEnabled;
......@@ -868,6 +870,8 @@ class DebuggingOptions {
final String vmserviceOutFile;
final bool fastStart;
final bool nullAssertions;
bool get hasObservatoryPort => hostVmServicePort != null;
}
......@@ -993,3 +997,14 @@ class NoOpDevicePortForwarder implements DevicePortForwarder {
@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(',');
}
......@@ -355,6 +355,7 @@ class IOSDevice extends Device {
?? 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 @@ class IOSDevice extends Device {
'--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
......
......@@ -411,6 +411,7 @@ class IOSSimulator extends Device {
}
// Prepare launch arguments.
final String dartVmFlags = computeDartVmFlags(debuggingOptions);
final List<String> args = <String>[
'--enable-dart-profiling',
if (debuggingOptions.debuggingEnabled) ...<String>[
......@@ -423,6 +424,7 @@ class IOSSimulator extends Device {
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}',
],
];
......
......@@ -113,6 +113,7 @@ class FlutterOptions {
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 @@ abstract class FlutterCommand extends Command<void> {
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() {
......
......@@ -92,6 +92,7 @@ FlutterPlatform installHook({
List<String> extraFrontEndOptions,
// Deprecated, use extraFrontEndOptions.
List<String> dartExperiments,
bool nullAssertions = false,
}) {
assert(testWrapper != null);
assert(enableObservatory || (!startPaused && observatoryPort == null));
......@@ -125,6 +126,7 @@ FlutterPlatform installHook({
flutterProject: flutterProject,
icudtlPath: icudtlPath,
extraFrontEndOptions: extraFrontEndOptions,
nullAssertions: nullAssertions,
);
platformPluginRegistration(platform);
return platform;
......@@ -268,6 +270,7 @@ class FlutterPlatform extends PlatformPlugin {
this.projectRootDirectory,
this.flutterProject,
this.icudtlPath,
this.nullAssertions = false,
@required this.extraFrontEndOptions,
}) : assert(shellPath != null);
......@@ -290,6 +293,7 @@ class FlutterPlatform extends PlatformPlugin {
final FlutterProject flutterProject;
final String icudtlPath;
final List<String> extraFrontEndOptions;
final bool nullAssertions;
Directory fontsDirectory;
......@@ -844,6 +848,8 @@ class FlutterPlatform extends PlatformPlugin {
'--non-interactive',
'--use-test-fonts',
'--packages=$packages',
if (nullAssertions)
'--dart-flags=--null_assertions',
testPath,
];
......
......@@ -52,6 +52,7 @@ abstract class FlutterTestRunner {
bool web = false,
String randomSeed,
@required List<String> extraFrontEndOptions,
bool nullAssertions = false,
});
}
......@@ -86,6 +87,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
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 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner {
flutterProject: flutterProject,
icudtlPath: icudtlPath,
extraFrontEndOptions: extraFrontEndOptions,
nullAssertions: nullAssertions,
);
// Make the global packages path absolute.
......
......@@ -185,6 +185,7 @@ class FakeFlutterTestRunner implements FlutterTestRunner {
bool web = false,
String randomSeed,
@override List<String> extraFrontEndOptions,
bool nullAssertions = false,
}) async {
lastEnableObservatoryValue = enableObservatory;
return exitCode;
......
......@@ -254,7 +254,7 @@ void main() {
'--ez', 'verify-entry-points', 'true',
'--ez', 'start-paused', 'true',
'--ez', 'disable-service-auth-codes', 'true',
'--es', 'dart-flags', 'foo',
'--es', 'dart-flags', 'foo,--null_assertions',
'--ez', 'use-test-fonts', 'true',
'--ez', 'verbose-logging', 'true',
'--user', '10',
......@@ -281,6 +281,7 @@ void main() {
purgePersistentCache: true,
useTestFonts: true,
verboseSystemLogs: true,
nullAssertions: true,
),
platformArgs: <String, dynamic>{},
userIdentifier: '10',
......
......@@ -416,6 +416,13 @@ void main() {
);
});
});
testWithoutContext('computeDartVmFlags handles various combinations of Dart VM flags and null_assertions', () {
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug, dartFlags: null)), '');
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug, dartFlags: '--foo')), '--foo');
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug, dartFlags: '', nullAssertions: true)), '--null_assertions');
expect(computeDartVmFlags(DebuggingOptions.enabled(BuildInfo.debug, dartFlags: '--foo', nullAssertions: true)), '--foo,--null_assertions');
});
}
class TestDeviceManager extends DeviceManager {
......
......@@ -319,7 +319,7 @@ void main() {
'--disable-service-auth-codes',
'--observatory-port=60700',
'--start-paused',
'--dart-flags="--foo"',
'--dart-flags="--foo,--null_assertions"',
'--enable-checked-mode',
'--verify-entry-points',
'--enable-software-rendering',
......@@ -385,6 +385,7 @@ void main() {
cacheSkSL: true,
purgePersistentCache: true,
verboseSystemLogs: true,
nullAssertions: true,
),
platformArgs: <String, dynamic>{},
fallbackPollingDelay: Duration.zero,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment