Finish removing null-safety mode, checks, and reporting. (#163153)

Closes https://github.com/flutter/flutter/issues/162846.

At HEAD, including before this PR, it was impossible to use, or pass-in,
an unsound null-safety mode, but we still had code checking for it, and
reported analytics (I think? Some of these are `package:usage` specific
which is defunct).

This PR eradicates the otherwise unused code.
This commit is contained in:
Matan Lurey 2025-02-12 13:52:02 -08:00 committed by GitHub
parent d2a60f6c22
commit 063f80d40f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 14 additions and 380 deletions

View File

@ -39,7 +39,6 @@ class BuildInfo {
required this.treeShakeIcons,
this.performanceMeasurementFile,
required this.packageConfigPath,
this.nullSafetyMode = NullSafetyMode.sound,
this.codeSizeDirectory,
this.androidGradleDaemon = true,
this.androidSkipBuildDependencyValidation = false,
@ -56,11 +55,6 @@ class BuildInfo {
final BuildMode mode;
/// The null safety mode the application should be run in.
///
/// If not provided, defaults to [NullSafetyMode.autodetect].
final NullSafetyMode nullSafetyMode;
/// Whether the build should subset icon fonts.
final bool treeShakeIcons;
@ -1023,15 +1017,6 @@ List<String> decodeDartDefines(Map<String, String> environmentDefines, String ke
.toList();
}
/// The null safety runtime mode the app should be built in.
enum NullSafetyMode {
sound,
unsound,
/// The null safety mode was not detected. Only supported for 'flutter test'.
autodetect,
}
/// Indicates the module system DDC is targeting.
enum DdcModuleFormat { amd, ddc }

View File

@ -8,7 +8,6 @@ import '../android/android_sdk.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../build_info.dart';
import '../build_system/build_system.dart';
import '../commands/build_linux.dart';
import '../commands/build_macos.dart';
@ -95,24 +94,6 @@ abstract class BuildSubCommand extends FlutterCommand {
@protected
final Logger logger;
@override
bool get reportNullSafety => true;
/// Whether this command is supported and should be shown.
bool get supported => true;
/// Display a message describing the current null safety runtime mode
/// that was selected.
///
/// This is similar to the run message in run_hot.dart
@protected
void displayNullSafetyMode(BuildInfo buildInfo) {
if (buildInfo.nullSafetyMode != NullSafetyMode.sound) {
logger.printStatus('');
logger.printStatus('Building without sound null safety ⚠️', emphasis: true);
logger.printStatus(
'Dart 3 will only support sound null safety, see https://dart.dev/null-safety',
);
}
logger.printStatus('');
}
}

View File

@ -151,8 +151,6 @@ class BuildAarCommand extends BuildSubCommand {
throwToolExit('Please specify a build mode and try again.');
}
displayNullSafetyMode(androidBuildInfo.first.buildInfo);
await androidBuilder?.buildAar(
project: project,
target: targetFile.path,

View File

@ -137,7 +137,6 @@ class BuildApkCommand extends BuildSubCommand {
targetArchs: _targetArchs.map<AndroidArch>(getAndroidArchForName),
);
validateBuild(androidBuildInfo);
displayNullSafetyMode(androidBuildInfo.buildInfo);
globals.terminal.usesTerminalUi = true;
final FlutterProject project = FlutterProject.current();
await androidBuilder?.buildApk(

View File

@ -165,7 +165,6 @@ class BuildAppBundleCommand extends BuildSubCommand {
}
validateBuild(androidBuildInfo);
displayNullSafetyMode(androidBuildInfo.buildInfo);
globals.terminal.usesTerminalUi = true;
await androidBuilder?.buildAab(
project: project,

View File

@ -140,7 +140,6 @@ class BuildBundleCommand extends BuildSubCommand {
}
final BuildInfo buildInfo = await getBuildInfo();
displayNullSafetyMode(buildInfo);
await _bundleBuilder.build(
platform: platform,

View File

@ -468,7 +468,6 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
@override
Future<FlutterCommandResult> runCommand() async {
final BuildInfo buildInfo = await cachedBuildInfo;
displayNullSafetyMode(buildInfo);
final FlutterCommandResult xcarchiveResult = await super.runCommand();
final List<ValidationResult?> validationResults = <ValidationResult?>[];

View File

@ -259,7 +259,6 @@ class BuildIOSFrameworkCommand extends BuildFrameworkCommand {
globals.fs.path.absolute(globals.fs.path.normalize(outputArgument)),
);
final List<BuildInfo> buildInfos = await getBuildInfos();
displayNullSafetyMode(buildInfos.first);
for (final BuildInfo buildInfo in buildInfos) {
// Create the build-mode specific metadata.
//

View File

@ -86,7 +86,6 @@ class BuildLinuxCommand extends BuildSubCommand {
'Cross-build from Linux x64 host to Linux arm64 target is not currently supported.',
);
}
displayNullSafetyMode(buildInfo);
final Logger logger = globals.logger;
await buildLinux(
project.linux,

View File

@ -57,7 +57,6 @@ class BuildMacosCommand extends BuildSubCommand {
if (!supported) {
throwToolExit('"build macos" only supported on macOS hosts.');
}
displayNullSafetyMode(buildInfo);
await buildMacOS(
flutterProject: project,
buildInfo: buildInfo,

View File

@ -72,8 +72,6 @@ class BuildMacOSFrameworkCommand extends BuildFrameworkCommand {
);
final List<BuildInfo> buildInfos = await getBuildInfos();
displayNullSafetyMode(buildInfos.first);
for (final BuildInfo buildInfo in buildInfos) {
globals.printStatus('Building macOS frameworks in ${buildInfo.mode.cliName} mode...');
// Create the build-mode specific metadata.

View File

@ -240,7 +240,6 @@ class BuildWebCommand extends BuildSubCommand {
// valid approaches for setting output directory of build artifacts
final String? outputDirectoryPath = stringArg('output');
displayNullSafetyMode(buildInfo);
final WebBuilder webBuilder = WebBuilder(
logger: globals.logger,
processManager: globals.processManager,

View File

@ -64,7 +64,6 @@ class BuildWindowsCommand extends BuildSubCommand {
: 'windows-x64';
final TargetPlatform targetPlatform = getTargetPlatformForName(defaultTargetPlatform);
displayNullSafetyMode(buildInfo);
await buildWindows(
project.windows,
buildInfo,

View File

@ -778,13 +778,6 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
..writeAsStringSync(websocketUri.toString());
}
_logger.printStatus('Debug service listening on $websocketUri');
if (debuggingOptions.buildInfo.nullSafetyMode != NullSafetyMode.sound) {
_logger.printStatus('');
_logger.printStatus('Running without sound null safety ⚠️', emphasis: true);
_logger.printStatus(
'Dart 3 will only support sound null safety, see https://dart.dev/null-safety',
);
}
}
appStartedCompleter?.complete();
connectionInfoCompleter?.complete(DebugConnectionInfo(wsUri: websocketUri));

View File

@ -57,9 +57,6 @@ class CustomDimensions {
this.commandResultEventMaxRss,
this.commandRunAndroidEmbeddingVersion,
this.commandPackagesAndroidEmbeddingVersion,
this.nullSafety,
this.nullSafeMigratedLibraries,
this.nullSafeTotalLibraries,
this.hotEventCompileTimeInMs,
this.hotEventFindInvalidatedTimeInMs,
this.hotEventScannedSourcesCount,
@ -116,10 +113,7 @@ class CustomDimensions {
final int? commandResultEventMaxRss; // cd44
final String? commandRunAndroidEmbeddingVersion; // cd45
final String? commandPackagesAndroidEmbeddingVersion; // cd46
final bool? nullSafety; // cd47
// cd48 was fastReassemble but that feature was removed
final int? nullSafeMigratedLibraries; // cd49
final int? nullSafeTotalLibraries; // cd50
final int? hotEventCompileTimeInMs; // cd51
final int? hotEventFindInvalidatedTimeInMs; // cd52
final int? hotEventScannedSourcesCount; // cd53
@ -234,11 +228,6 @@ class CustomDimensions {
if (commandPackagesAndroidEmbeddingVersion != null)
CustomDimensionsEnum.commandPackagesAndroidEmbeddingVersion.cdKey:
commandPackagesAndroidEmbeddingVersion.toString(),
if (nullSafety != null) CustomDimensionsEnum.nullSafety.cdKey: nullSafety.toString(),
if (nullSafeMigratedLibraries != null)
CustomDimensionsEnum.nullSafeMigratedLibraries.cdKey: nullSafeMigratedLibraries.toString(),
if (nullSafeTotalLibraries != null)
CustomDimensionsEnum.nullSafeTotalLibraries.cdKey: nullSafeTotalLibraries.toString(),
if (hotEventCompileTimeInMs != null)
CustomDimensionsEnum.hotEventCompileTimeInMs.cdKey: hotEventCompileTimeInMs.toString(),
if (hotEventFindInvalidatedTimeInMs != null)
@ -326,9 +315,6 @@ class CustomDimensions {
other.commandRunAndroidEmbeddingVersion ?? commandRunAndroidEmbeddingVersion,
commandPackagesAndroidEmbeddingVersion:
other.commandPackagesAndroidEmbeddingVersion ?? commandPackagesAndroidEmbeddingVersion,
nullSafety: other.nullSafety ?? nullSafety,
nullSafeMigratedLibraries: other.nullSafeMigratedLibraries ?? nullSafeMigratedLibraries,
nullSafeTotalLibraries: other.nullSafeTotalLibraries ?? nullSafeTotalLibraries,
hotEventCompileTimeInMs: other.hotEventCompileTimeInMs ?? hotEventCompileTimeInMs,
hotEventFindInvalidatedTimeInMs:
other.hotEventFindInvalidatedTimeInMs ?? hotEventFindInvalidatedTimeInMs,
@ -430,9 +416,6 @@ class CustomDimensions {
map,
CustomDimensionsEnum.commandPackagesAndroidEmbeddingVersion,
),
nullSafety: _extractBool(map, CustomDimensionsEnum.nullSafety),
nullSafeMigratedLibraries: _extractInt(map, CustomDimensionsEnum.nullSafeMigratedLibraries),
nullSafeTotalLibraries: _extractInt(map, CustomDimensionsEnum.nullSafeTotalLibraries),
hotEventCompileTimeInMs: _extractInt(map, CustomDimensionsEnum.hotEventCompileTimeInMs),
hotEventFindInvalidatedTimeInMs: _extractInt(
map,
@ -522,10 +505,13 @@ enum CustomDimensionsEnum {
commandResultEventMaxRss, // cd44
commandRunAndroidEmbeddingVersion, // cd45
commandPackagesAndroidEmbeddingVersion, // cd46
nullSafety, // cd47
// ignore: unused_field
_nullSafetyDeprecatedDoNotUse, // cd47
obsolete1, // cd48 (was fastReassemble)
nullSafeMigratedLibraries, // cd49
nullSafeTotalLibraries, // cd50
// ignore: unused_field
_nullSafeMigratedLibrariesDoNotUse, // cd49
// ignore: unused_field
_nullSafeTotalLibrariesDoNotUse, // cd50
hotEventCompileTimeInMs, // cd51
hotEventFindInvalidatedTimeInMs, // cd52
hotEventScannedSourcesCount, // cd53

View File

@ -220,71 +220,3 @@ class ErrorHandlingEvent extends UsageEvent {
ErrorHandlingEvent(String parameter)
: super('error-handling', parameter, flutterUsage: globals.flutterUsage);
}
/// Emit various null safety analytic events.
///
/// 1. The current null safety runtime mode.
/// 2. The number of packages that are migrated, along with the total number of packages
/// 3. The main packages language version.
class NullSafetyAnalysisEvent implements UsageEvent {
NullSafetyAnalysisEvent(
this.packageConfig,
this.nullSafetyMode,
this.currentPackage,
this.flutterUsage,
);
/// The category for analytics events related to null safety.
static const String kNullSafetyCategory = 'null-safety';
final PackageConfig packageConfig;
final NullSafetyMode nullSafetyMode;
final String currentPackage;
@override
final Usage flutterUsage;
@override
void send() {
if (packageConfig.packages.isEmpty) {
return;
}
int migrated = 0;
LanguageVersion? languageVersion;
for (final Package package in packageConfig.packages) {
final LanguageVersion? packageLanguageVersion = package.languageVersion;
if (package.name == currentPackage) {
languageVersion = packageLanguageVersion;
}
if (packageLanguageVersion != null &&
packageLanguageVersion.major >= nullSafeVersion.major &&
packageLanguageVersion.minor >= nullSafeVersion.minor) {
migrated += 1;
}
}
flutterUsage.sendEvent(kNullSafetyCategory, 'runtime-mode', label: nullSafetyMode.toString());
flutterUsage.sendEvent(
kNullSafetyCategory,
'stats',
parameters: CustomDimensions(
nullSafeMigratedLibraries: migrated,
nullSafeTotalLibraries: packageConfig.packages.length,
),
);
if (languageVersion != null) {
final String formattedVersion = '${languageVersion.major}.${languageVersion.minor}';
flutterUsage.sendEvent(kNullSafetyCategory, 'language-version', label: formattedVersion);
}
}
@override
String get category => kNullSafetyCategory;
@override
String get label => throw UnsupportedError('');
@override
String get parameter => throw UnsupportedError('');
@override
int get value => throw UnsupportedError('');
}

View File

@ -8,14 +8,11 @@ import 'dart:async';
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:usage/usage_io.dart';
import '../base/error_handling_io.dart';
import '../base/file_system.dart';
import '../base/time.dart';
import '../build_info.dart';
import '../dart/language_version.dart';
import '../doctor_validator.dart';
import '../features.dart';
import '../globals.dart' as globals;

View File

@ -120,20 +120,7 @@ class FlutterDevice {
// used to file a bug, but the compiler will still start up correctly.
if (targetPlatform == TargetPlatform.web_javascript) {
// TODO(zanderso): consistently provide these flags across platforms.
final String platformDillName;
final List<String> extraFrontEndOptions = List<String>.of(buildInfo.extraFrontEndOptions);
switch (buildInfo.nullSafetyMode) {
case NullSafetyMode.unsound:
// TODO(matanlurey): Should be unreachable, remove as part of https://github.com/flutter/flutter/issues/162846.
throw UnsupportedError('Unsound null safety mode is not supported');
case NullSafetyMode.sound:
platformDillName = 'ddc_outline.dill';
case NullSafetyMode.autodetect:
throw StateError(
'Expected buildInfo.nullSafetyMode to be one of unsound or sound, '
'got NullSafetyMode.autodetect',
);
}
const String platformDillName = 'ddc_outline.dill';
final String platformDillPath = globals.fs.path.join(
globals.artifacts!.getHostArtifact(HostArtifact.webPlatformKernelFolder).path,
@ -153,12 +140,12 @@ class FlutterDevice {
getDefaultCachedKernelPath(
trackWidgetCreation: buildInfo.trackWidgetCreation,
dartDefines: buildInfo.dartDefines,
extraFrontEndOptions: extraFrontEndOptions,
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
),
assumeInitializeFromDillUpToDate: buildInfo.assumeInitializeFromDillUpToDate,
targetModel: TargetModel.dartdevc,
frontendServerStarterPath: buildInfo.frontendServerStarterPath,
extraFrontEndOptions: extraFrontEndOptions,
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
platformDill: globals.fs.file(platformDillPath).absolute.uri.toString(),
dartDefines: buildInfo.dartDefines,
librariesSpec:

View File

@ -1174,13 +1174,6 @@ class HotRunner extends ResidentRunner {
}
commandHelp.c.print();
commandHelp.q.print();
if (debuggingOptions.buildInfo.nullSafetyMode != NullSafetyMode.sound) {
globals.printStatus('');
globals.printStatus('Running without sound null safety ⚠️', emphasis: true);
globals.printStatus(
'Dart 3 will only support sound null safety, see https://dart.dev/null-safety',
);
}
globals.printStatus('');
printDebuggerList();
}

View File

@ -1355,23 +1355,6 @@ abstract class FlutterCommand extends Command<void> {
codeSizeDirectory = directory.path;
}
NullSafetyMode nullSafetyMode = NullSafetyMode.sound;
if (argParser.options.containsKey(FlutterOptions.kNullSafety)) {
final bool wasNullSafetyFlagParsed =
argResults?.wasParsed(FlutterOptions.kNullSafety) ?? false;
// Extra frontend options are only provided if explicitly
// requested.
if (wasNullSafetyFlagParsed) {
if (boolArg(FlutterOptions.kNullSafety)) {
nullSafetyMode = NullSafetyMode.sound;
extraFrontEndOptions.add('--sound-null-safety');
} else {
nullSafetyMode = NullSafetyMode.unsound;
extraFrontEndOptions.add('--no-sound-null-safety');
}
}
}
final bool dartObfuscation =
argParser.options.containsKey(FlutterOptions.kDartObfuscationOption) &&
boolArg(FlutterOptions.kDartObfuscationOption);
@ -1471,7 +1454,6 @@ abstract class FlutterCommand extends Command<void> {
dartExperiments: experiments,
performanceMeasurementFile: performanceMeasurementFile,
packageConfigPath: packagesPath ?? packageConfigFile.path,
nullSafetyMode: nullSafetyMode,
codeSizeDirectory: codeSizeDirectory,
androidGradleDaemon: androidGradleDaemon,
androidSkipBuildDependencyValidation: androidSkipBuildDependencyValidation,
@ -1880,9 +1862,6 @@ Run 'flutter -h' (or 'flutter <command> -h') for available flutter commands and
buildSystem: globals.buildSystem,
buildTargets: globals.buildTargets,
);
if (reportNullSafety) {
await _sendNullSafetyAnalyticsEvents(project);
}
}
if (regeneratePlatformSpecificToolingDuringVerify) {
@ -1946,16 +1925,6 @@ Run 'flutter -h' (or 'flutter <command> -h') for available flutter commands and
);
}
Future<void> _sendNullSafetyAnalyticsEvents(FlutterProject project) async {
final BuildInfo buildInfo = await getBuildInfo();
NullSafetyAnalysisEvent(
buildInfo.packageConfig,
buildInfo.nullSafetyMode,
project.manifest.appName,
globals.flutterUsage,
).send();
}
/// The set of development artifacts required for this command.
///
/// Defaults to an empty set. Including [DevelopmentArtifact.universal] is

View File

@ -148,7 +148,6 @@ String generateTestBootstrap({
Uri? packageConfigUri,
bool updateGoldens = false,
String languageVersionHeader = '',
bool nullSafety = false,
bool flutterTestDep = true,
bool integrationTest = false,
}) {

View File

@ -118,24 +118,10 @@ class WebTestCompiler {
required BuildInfo buildInfo,
required WebRendererMode webRenderer,
}) async {
LanguageVersion languageVersion = LanguageVersion(2, 8);
late final String platformDillName;
// TODO(zanderso): to support autodetect this would need to partition the source code into
// a sound and unsound set and perform separate compilations
final List<String> extraFrontEndOptions = List<String>.of(buildInfo.extraFrontEndOptions);
switch (buildInfo.nullSafetyMode) {
case NullSafetyMode.unsound || NullSafetyMode.autodetect:
// TODO(matanlurey): Should be unreachable, remove as part of https://github.com/flutter/flutter/issues/162846.
throw UnsupportedError('Unsound null safety mode is not supported');
case NullSafetyMode.sound:
languageVersion = currentLanguageVersion(_fileSystem, Cache.flutterRoot!);
platformDillName = 'ddc_outline.dill';
}
final LanguageVersion languageVersion = currentLanguageVersion(_fileSystem, Cache.flutterRoot!);
final String platformDillPath = _fileSystem.path.join(
_artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path,
platformDillName,
'ddc_outline.dill',
);
final Directory outputDirectory = _fileSystem.directory(testOutputDir)
@ -150,7 +136,7 @@ class WebTestCompiler {
final String cachedKernelPath = getDefaultCachedKernelPath(
trackWidgetCreation: buildInfo.trackWidgetCreation,
dartDefines: buildInfo.dartDefines,
extraFrontEndOptions: extraFrontEndOptions,
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
fileSystem: _fileSystem,
config: _config,
);
@ -165,7 +151,7 @@ class WebTestCompiler {
fileSystemScheme: 'org-dartlang-app',
initializeFromDill: cachedKernelPath,
targetModel: TargetModel.dartdevc,
extraFrontEndOptions: extraFrontEndOptions,
extraFrontEndOptions: buildInfo.extraFrontEndOptions,
platformDill: _fileSystem.file(platformDillPath).absolute.uri.toString(),
dartDefines: dartDefines,
librariesSpec:

View File

@ -103,35 +103,6 @@ void main() {
},
);
testUsingContext(
'supports --no-sound-null-safety with an overridden NonNullSafeBuilds',
() async {
fileSystem.file('lib/main.dart').createSync(recursive: true);
fileSystem.file('pubspec.yaml').createSync();
fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
final FakeDevice device = FakeDevice(
isLocalEmulator: true,
platformType: PlatformType.android,
);
testDeviceManager.devices = <Device>[device];
final TestRunCommandThatOnlyValidates command = TestRunCommandThatOnlyValidates();
await createTestCommandRunner(command).run(const <String>[
'run',
'--use-application-binary=app/bar/faz',
'--no-sound-null-safety',
]);
},
overrides: <Type, Generator>{
DeviceManager: () => testDeviceManager,
FileSystem: () => fileSystem,
Logger: () => logger,
NonNullSafeBuilds: () => NonNullSafeBuilds.allowed,
ProcessManager: () => FakeProcessManager.any(),
},
);
testUsingContext(
'does not support "--use-application-binary" and "--fast-start"',
() async {

View File

@ -287,7 +287,6 @@ void main() {
expect(buildInfo.splitDebugInfoPath, '/project-name/v1.2.3/');
expect(buildInfo.dartObfuscation, isTrue);
expect(buildInfo.dartDefines.contains('foo=bar'), isTrue);
expect(buildInfo.nullSafetyMode, NullSafetyMode.sound);
}, overrides: <Type, Generator>{AndroidBuilder: () => fakeAndroidBuilder});
});

View File

@ -11,7 +11,6 @@ import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/signals.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/commands/attach.dart';
import 'package:flutter_tools/src/commands/build.dart';
@ -97,20 +96,6 @@ void main() {
}
});
testUsingContext('BuildSubCommand displays current null safety mode', () async {
const BuildInfo unsound = BuildInfo(
BuildMode.debug,
'',
nullSafetyMode: NullSafetyMode.unsound,
treeShakeIcons: false,
packageConfigPath: '.dart_tool/package_config.json',
);
final BufferLogger logger = BufferLogger.test();
FakeBuildSubCommand(logger).test(unsound);
expect(logger.statusText, contains('Building without sound null safety ⚠️'));
});
testUsingContext('Include only supported sub commands', () {
final BufferLogger logger = BufferLogger.test();
final MemoryFileSystem fs = MemoryFileSystem.test();
@ -126,22 +111,3 @@ void main() {
}
});
}
class FakeBuildSubCommand extends BuildSubCommand {
FakeBuildSubCommand(Logger logger) : super(logger: logger, verboseHelp: false);
@override
String get description => throw UnimplementedError();
@override
String get name => throw UnimplementedError();
void test(BuildInfo buildInfo) {
displayNullSafetyMode(buildInfo);
}
@override
Future<FlutterCommandResult> runCommand() {
throw UnimplementedError();
}
}

View File

@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/doctor_validator.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:package_config/package_config.dart';
import '../../src/common.dart';
@ -58,100 +56,6 @@ void main() {
contains(const TestUsageEvent('doctor-result', 'FakeGroupedValidator', label: 'crash')),
);
});
testWithoutContext('Reports null safe analytics events', () {
final TestUsage usage = TestUsage();
final PackageConfig packageConfig = PackageConfig(<Package>[
Package('foo', Uri.parse('file:///foo/'), languageVersion: LanguageVersion(2, 12)),
Package('bar', Uri.parse('file:///fizz/'), languageVersion: LanguageVersion(2, 1)),
Package('baz', Uri.parse('file:///bar/'), languageVersion: LanguageVersion(2, 2)),
]);
NullSafetyAnalysisEvent(packageConfig, NullSafetyMode.sound, 'foo', usage).send();
expect(
usage.events,
unorderedEquals(<TestUsageEvent>[
const TestUsageEvent(
NullSafetyAnalysisEvent.kNullSafetyCategory,
'runtime-mode',
label: 'NullSafetyMode.sound',
),
TestUsageEvent(
NullSafetyAnalysisEvent.kNullSafetyCategory,
'stats',
parameters: CustomDimensions.fromMap(<String, String>{'cd49': '1', 'cd50': '3'}),
),
const TestUsageEvent(
NullSafetyAnalysisEvent.kNullSafetyCategory,
'language-version',
label: '2.12',
),
]),
);
});
testWithoutContext('Does not crash if main package is missing', () {
final TestUsage usage = TestUsage();
final PackageConfig packageConfig = PackageConfig(<Package>[
Package('foo', Uri.parse('file:///foo/lib/'), languageVersion: LanguageVersion(2, 12)),
Package('bar', Uri.parse('file:///fizz/lib/'), languageVersion: LanguageVersion(2, 1)),
Package('baz', Uri.parse('file:///bar/lib/'), languageVersion: LanguageVersion(2, 2)),
]);
NullSafetyAnalysisEvent(
packageConfig,
NullSafetyMode.sound,
'something-unrelated',
usage,
).send();
expect(
usage.events,
unorderedEquals(<TestUsageEvent>[
const TestUsageEvent(
NullSafetyAnalysisEvent.kNullSafetyCategory,
'runtime-mode',
label: 'NullSafetyMode.sound',
),
TestUsageEvent(
NullSafetyAnalysisEvent.kNullSafetyCategory,
'stats',
parameters: CustomDimensions.fromMap(<String, String>{'cd49': '1', 'cd50': '3'}),
),
]),
);
});
testWithoutContext('a null language version is treated as unmigrated', () {
final TestUsage usage = TestUsage();
final PackageConfig packageConfig = PackageConfig(<Package>[
Package('foo', Uri.parse('file:///foo/lib/')),
]);
NullSafetyAnalysisEvent(
packageConfig,
NullSafetyMode.sound,
'something-unrelated',
usage,
).send();
expect(
usage.events,
unorderedEquals(<TestUsageEvent>[
const TestUsageEvent(
NullSafetyAnalysisEvent.kNullSafetyCategory,
'runtime-mode',
label: 'NullSafetyMode.sound',
),
TestUsageEvent(
NullSafetyAnalysisEvent.kNullSafetyCategory,
'stats',
parameters: CustomDimensions.fromMap(<String, String>{'cd49': '0', 'cd50': '1'}),
),
]),
);
});
}
class FakeGroupedValidator extends GroupedValidator {

View File

@ -916,7 +916,6 @@ void main() {
BuildMode.debug,
'',
treeShakeIcons: false,
nullSafetyMode: NullSafetyMode.unsound,
packageConfigPath: '.dart_tool/package_config.json',
),
enableDwds: false,