From 5be462f550b5519b664037eb1b8769381db1bddb Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 3 Nov 2021 17:36:32 -0700 Subject: [PATCH] Migrate doctor, format, and a few other commands to null safety (#92952) --- .../lib/src/commands/doctor.dart | 15 ++++---- .../lib/src/commands/format.dart | 14 ++++---- .../lib/src/commands/generate.dart | 2 -- .../src/commands/generate_localizations.dart | 28 +++++++-------- .../lib/src/commands/ide_config.dart | 25 ++++++------- .../lib/src/commands/screenshot.dart | 36 +++++++++---------- .../lib/src/commands/shell_completion.dart | 13 +++---- .../lib/src/commands/symbolize.dart | 30 ++++++++-------- packages/flutter_tools/lib/src/template.dart | 4 +-- 9 files changed, 72 insertions(+), 95 deletions(-) diff --git a/packages/flutter_tools/lib/src/commands/doctor.dart b/packages/flutter_tools/lib/src/commands/doctor.dart index c22595353f0..06de1b48784 100644 --- a/packages/flutter_tools/lib/src/commands/doctor.dart +++ b/packages/flutter_tools/lib/src/commands/doctor.dart @@ -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 '../android/android_workflow.dart'; import '../base/common.dart'; import '../globals.dart' as globals; @@ -12,7 +10,6 @@ import '../runner/flutter_command.dart'; class DoctorCommand extends FlutterCommand { DoctorCommand({this.verbose = false}) { argParser.addFlag('android-licenses', - defaultsTo: false, negatable: false, help: "Run the Android SDK manager tool to accept the SDK's licenses.", ); @@ -37,11 +34,11 @@ class DoctorCommand extends FlutterCommand { @override Future runCommand() async { globals.flutterVersion.fetchTagsAndUpdate(); - if (argResults.wasParsed('check-for-remote-artifacts')) { - final String engineRevision = stringArg('check-for-remote-artifacts'); + if (argResults?.wasParsed('check-for-remote-artifacts') == true) { + final String engineRevision = stringArg('check-for-remote-artifacts')!; if (engineRevision.startsWith(RegExp(r'[a-f0-9]{1,40}'))) { - final bool success = await globals.doctor.checkRemoteArtifacts(engineRevision); - if (!success) { + final bool success = await globals.doctor?.checkRemoteArtifacts(engineRevision) ?? false; + if (success) { throwToolExit('Artifacts for engine $engineRevision are missing or are ' 'not yet available.', exitCode: 1); } @@ -50,11 +47,11 @@ class DoctorCommand extends FlutterCommand { 'git hash.'); } } - final bool success = await globals.doctor.diagnose( + final bool success = await globals.doctor?.diagnose( androidLicenses: boolArg('android-licenses'), verbose: verbose, androidLicenseValidator: androidLicenseValidator, - ); + ) ?? false; return FlutterCommandResult(success ? ExitStatus.success : ExitStatus.warning); } } diff --git a/packages/flutter_tools/lib/src/commands/format.dart b/packages/flutter_tools/lib/src/commands/format.dart index 35d735f3c35..986dc7ba22b 100644 --- a/packages/flutter_tools/lib/src/commands/format.dart +++ b/packages/flutter_tools/lib/src/commands/format.dart @@ -2,10 +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:args/args.dart'; -import 'package:meta/meta.dart'; import '../artifacts.dart'; import '../base/common.dart'; @@ -13,7 +10,7 @@ import '../globals.dart' as globals; import '../runner/flutter_command.dart'; class FormatCommand extends FlutterCommand { - FormatCommand({@required this.verboseHelp}); + FormatCommand({required this.verboseHelp}); @override ArgParser argParser = ArgParser.allowAnything(); @@ -33,23 +30,24 @@ class FormatCommand extends FlutterCommand { String get category => FlutterCommandCategory.project; @override - String get invocation => '${runner.executableName} $name '; + String get invocation => '${runner?.executableName} $name '; @override Future runCommand() async { - final String dartBinary = globals.artifacts.getHostArtifact(HostArtifact.engineDartBinary).path; + final String dartBinary = globals.artifacts!.getHostArtifact(HostArtifact.engineDartBinary).path; final List command = [ dartBinary, 'format', ]; - if (argResults.rest.isEmpty) { + final List rest = argResults?.rest ?? []; + if (rest.isEmpty) { globals.printError( 'No files specified to be formatted.' ); command.add('-h'); } else { command.addAll([ - for (String arg in argResults.rest) + for (String arg in rest) if (arg == '--dry-run' || arg == '-n') '--output=none' else diff --git a/packages/flutter_tools/lib/src/commands/generate.dart b/packages/flutter_tools/lib/src/commands/generate.dart index a79aeef1045..d815d05d0e8 100644 --- a/packages/flutter_tools/lib/src/commands/generate.dart +++ b/packages/flutter_tools/lib/src/commands/generate.dart @@ -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 '../globals.dart' as globals; import '../runner/flutter_command.dart'; diff --git a/packages/flutter_tools/lib/src/commands/generate_localizations.dart b/packages/flutter_tools/lib/src/commands/generate_localizations.dart index 199825444d9..17bf0697129 100644 --- a/packages/flutter_tools/lib/src/commands/generate_localizations.dart +++ b/packages/flutter_tools/lib/src/commands/generate_localizations.dart @@ -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 '../base/common.dart'; import '../base/file_system.dart'; import '../base/logger.dart'; @@ -21,8 +19,8 @@ import '../runner/flutter_command.dart'; /// [internationalization user guide](flutter.dev/go/i18n-user-guide). class GenerateLocalizationsCommand extends FlutterCommand { GenerateLocalizationsCommand({ - FileSystem fileSystem, - Logger logger, + required FileSystem fileSystem, + required Logger logger, }) : _fileSystem = fileSystem, _logger = logger { @@ -108,7 +106,6 @@ class GenerateLocalizationsCommand extends FlutterCommand { ); argParser.addFlag( 'use-deferred-loading', - defaultsTo: false, help: 'Whether to generate the Dart localization file with locales imported ' 'as deferred, allowing for lazy loading of each locale in Flutter web.\n' '\n' @@ -214,25 +211,24 @@ class GenerateLocalizationsCommand extends FlutterCommand { logger: _logger, options: options, projectDir: _fileSystem.currentDirectory, - dependenciesDir: null, fileSystem: _fileSystem, ); return FlutterCommandResult.success(); } - final String inputPathString = stringArg('arb-dir'); - final String outputPathString = stringArg('output-dir'); - final String outputFileString = stringArg('output-localization-file'); - final String templateArbFileName = stringArg('template-arb-file'); - final String untranslatedMessagesFile = stringArg('untranslated-messages-file'); - final String classNameString = stringArg('output-class'); + final String inputPathString = stringArg('arb-dir')!; // Has default value, cannot be null. + final String? outputPathString = stringArg('output-dir'); + final String outputFileString = stringArg('output-localization-file')!; // Has default value, cannot be null. + final String templateArbFileName = stringArg('template-arb-file')!; // Has default value, cannot be null. + final String? untranslatedMessagesFile = stringArg('untranslated-messages-file'); + final String classNameString = stringArg('output-class')!; // Has default value, cannot be null. final List preferredSupportedLocales = stringsArg('preferred-supported-locales'); - final String headerString = stringArg('header'); - final String headerFile = stringArg('header-file'); + final String? headerString = stringArg('header'); + final String? headerFile = stringArg('header-file'); final bool useDeferredLoading = boolArg('use-deferred-loading'); - final String inputsAndOutputsListPath = stringArg('gen-inputs-and-outputs-list'); + final String? inputsAndOutputsListPath = stringArg('gen-inputs-and-outputs-list'); final bool useSyntheticPackage = boolArg('synthetic-package'); - final String projectPathString = stringArg('project-dir'); + final String? projectPathString = stringArg('project-dir'); final bool areResourceAttributesRequired = boolArg('required-resource-attributes'); final bool usesNullableGetter = boolArg('nullable-getter'); diff --git a/packages/flutter_tools/lib/src/commands/ide_config.dart b/packages/flutter_tools/lib/src/commands/ide_config.dart index 5f40c448aea..115a47a8684 100644 --- a/packages/flutter_tools/lib/src/commands/ide_config.dart +++ b/packages/flutter_tools/lib/src/commands/ide_config.dart @@ -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 '../base/common.dart'; import '../base/file_system.dart'; import '../cache.dart'; @@ -15,8 +13,6 @@ class IdeConfigCommand extends FlutterCommand { IdeConfigCommand() { argParser.addFlag( 'overwrite', - negatable: true, - defaultsTo: false, help: 'When performing operations, overwrite existing files.', ); argParser.addFlag( @@ -31,7 +27,6 @@ class IdeConfigCommand extends FlutterCommand { ); argParser.addFlag( 'with-root-module', - negatable: true, defaultsTo: true, help: 'Also create module that corresponds to the root of Flutter tree. ' 'This makes the entire Flutter tree browsable and searchable in IDE. ' @@ -60,12 +55,12 @@ class IdeConfigCommand extends FlutterCommand { final bool hidden = true; @override - String get invocation => '${runner.executableName} $name'; + String get invocation => '${runner?.executableName} $name'; static const String _ideName = 'intellij'; Directory get _templateDirectory { return globals.fs.directory(globals.fs.path.join( - Cache.flutterRoot, + Cache.flutterRoot!, 'packages', 'flutter_tools', 'ide_templates', @@ -75,14 +70,14 @@ class IdeConfigCommand extends FlutterCommand { Directory get _createTemplatesDirectory { return globals.fs.directory(globals.fs.path.join( - Cache.flutterRoot, + Cache.flutterRoot!, 'packages', 'flutter_tools', 'templates', )); } - Directory get _flutterRoot => globals.fs.directory(globals.fs.path.absolute(Cache.flutterRoot)); + Directory get _flutterRoot => globals.fs.directory(globals.fs.path.absolute(Cache.flutterRoot!)); // Returns true if any entire path element is equal to dir. bool _hasDirectoryInPath(FileSystemEntity entity, String dir) { @@ -213,7 +208,8 @@ class IdeConfigCommand extends FlutterCommand { @override Future runCommand() async { - if (argResults.rest.isNotEmpty) { + final List rest = argResults?.rest ?? []; + if (rest.isNotEmpty) { throwToolExit('Currently, the only supported IDE is IntelliJ\n$usage', exitCode: 2); } @@ -222,12 +218,12 @@ class IdeConfigCommand extends FlutterCommand { return FlutterCommandResult.success(); } - final String flutterRoot = globals.fs.path.absolute(Cache.flutterRoot); + final String flutterRoot = globals.fs.path.absolute(Cache.flutterRoot!); final String dirPath = globals.fs.path.normalize( - globals.fs.directory(globals.fs.path.absolute(Cache.flutterRoot)).absolute.path, + globals.fs.directory(globals.fs.path.absolute(Cache.flutterRoot!)).absolute.path, ); - final String error = _validateFlutterDir(dirPath, flutterRoot: flutterRoot); + final String? error = _validateFlutterDir(dirPath, flutterRoot: flutterRoot); if (error != null) { throwToolExit(error); } @@ -265,7 +261,7 @@ class IdeConfigCommand extends FlutterCommand { /// Return null if the flutter root directory is a valid destination. Return a /// validation message if we should disallow the directory. -String _validateFlutterDir(String dirPath, { String flutterRoot }) { +String? _validateFlutterDir(String dirPath, { String? flutterRoot }) { final FileSystemEntityType type = globals.fs.typeSync(dirPath); switch (type) { // ignore: exhaustive_cases, https://github.com/dart-lang/linter/issues/3017 @@ -277,5 +273,4 @@ String _validateFlutterDir(String dirPath, { String flutterRoot }) { case FileSystemEntityType.notFound: return null; } - return null; // dead code, remove after null safety migration } diff --git a/packages/flutter_tools/lib/src/commands/screenshot.dart b/packages/flutter_tools/lib/src/commands/screenshot.dart index 195829bb888..d8069ede5c1 100644 --- a/packages/flutter_tools/lib/src/commands/screenshot.dart +++ b/packages/flutter_tools/lib/src/commands/screenshot.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:vm_service/vm_service.dart' as vm_service; import '../base/common.dart'; @@ -67,9 +65,9 @@ class ScreenshotCommand extends FlutterCommand { @override final List aliases = ['pic']; - Device device; + Device? device; - Future _validateOptions(String screenshotType, String observatoryUrl) async { + Future _validateOptions(String? screenshotType, String? observatoryUrl) async { switch (screenshotType) { case _kDeviceType: if (observatoryUrl != null) { @@ -79,8 +77,8 @@ class ScreenshotCommand extends FlutterCommand { if (device == null) { throwToolExit('Must have a connected device for screenshot type $screenshotType'); } - if (!device.supportsScreenshot) { - throwToolExit('Screenshot not supported for ${device.name}.'); + if (!device!.supportsScreenshot) { + throwToolExit('Screenshot not supported for ${device!.name}.'); } break; default: @@ -94,15 +92,15 @@ class ScreenshotCommand extends FlutterCommand { } @override - Future verifyThenRunCommand(String commandPath) async { + Future verifyThenRunCommand(String? commandPath) async { await _validateOptions(stringArg(_kType), stringArg(_kObservatoryUrl)); return super.verifyThenRunCommand(commandPath); } @override Future runCommand() async { - File outputFile; - if (argResults.wasParsed(_kOut)) { + File? outputFile; + if (argResults?.wasParsed(_kOut) == true) { outputFile = globals.fs.file(stringArg(_kOut)); } @@ -123,24 +121,24 @@ class ScreenshotCommand extends FlutterCommand { : FlutterCommandResult.fail(); } - Future runScreenshot(File outputFile) async { + Future runScreenshot(File? outputFile) async { outputFile ??= globals.fsUtils.getUniqueFile( globals.fs.currentDirectory, 'flutter', 'png', ); try { - await device.takeScreenshot(outputFile); + await device!.takeScreenshot(outputFile); } on Exception catch (error) { throwToolExit('Error taking screenshot: $error'); } _showOutputFileInfo(outputFile); } - Future runSkia(File outputFile) async { - final Uri observatoryUrl = Uri.parse(stringArg(_kObservatoryUrl)); + Future runSkia(File? outputFile) async { + final Uri observatoryUrl = Uri.parse(stringArg(_kObservatoryUrl)!); final FlutterVmService vmService = await connectToVmService(observatoryUrl, logger: globals.logger); - final vm_service.Response skp = await vmService.screenshotSkp(); + final vm_service.Response? skp = await vmService.screenshotSkp(); if (skp == null) { globals.printError( 'The Skia picture request failed, probably because the device was ' @@ -154,17 +152,17 @@ class ScreenshotCommand extends FlutterCommand { 'skp', ); final IOSink sink = outputFile.openWrite(); - sink.add(base64.decode(skp.json['skp'] as String)); + sink.add(base64.decode(skp.json?['skp'] as String)); await sink.close(); _showOutputFileInfo(outputFile); _ensureOutputIsNotJsonRpcError(outputFile); return true; } - Future runRasterizer(File outputFile) async { - final Uri observatoryUrl = Uri.parse(stringArg(_kObservatoryUrl)); + Future runRasterizer(File? outputFile) async { + final Uri observatoryUrl = Uri.parse(stringArg(_kObservatoryUrl)!); final FlutterVmService vmService = await connectToVmService(observatoryUrl, logger: globals.logger); - final vm_service.Response response = await vmService.screenshot(); + final vm_service.Response? response = await vmService.screenshot(); if (response == null) { globals.printError( 'The screenshot request failed, probably because the device was ' @@ -178,7 +176,7 @@ class ScreenshotCommand extends FlutterCommand { 'png', ); final IOSink sink = outputFile.openWrite(); - sink.add(base64.decode(response.json['screenshot'] as String)); + sink.add(base64.decode(response.json?['screenshot'] as String)); await sink.close(); _showOutputFileInfo(outputFile); _ensureOutputIsNotJsonRpcError(outputFile); diff --git a/packages/flutter_tools/lib/src/commands/shell_completion.dart b/packages/flutter_tools/lib/src/commands/shell_completion.dart index f30cd6e092e..5fe8de30133 100644 --- a/packages/flutter_tools/lib/src/commands/shell_completion.dart +++ b/packages/flutter_tools/lib/src/commands/shell_completion.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:completion/completion.dart'; import '../base/common.dart'; @@ -15,8 +13,6 @@ class ShellCompletionCommand extends FlutterCommand { ShellCompletionCommand() { argParser.addFlag( 'overwrite', - defaultsTo: false, - negatable: true, help: 'Causes the given shell completion setup script to be overwritten if it already exists.', ); } @@ -42,21 +38,22 @@ class ShellCompletionCommand extends FlutterCommand { /// Return null to disable analytics recording of the `bash-completion` command. @override - Future get usagePath async => null; + Future get usagePath async => null; @override Future runCommand() async { - if (argResults.rest.length > 1) { + final List rest = argResults?.rest ?? []; + if (rest.length > 1) { throwToolExit('Too many arguments given to bash-completion command.', exitCode: 1); } - if (argResults.rest.isEmpty || argResults.rest.first == '-') { + if (rest.isEmpty || rest.first == '-') { final String script = generateCompletionScript(['flutter']); globals.stdio.stdoutWrite(script); return FlutterCommandResult.warning(); } - final File outputFile = globals.fs.file(argResults.rest.first); + final File outputFile = globals.fs.file(rest.first); if (outputFile.existsSync() && !boolArg('overwrite')) { throwToolExit( 'Output file ${outputFile.path} already exists, will not overwrite. ' diff --git a/packages/flutter_tools/lib/src/commands/symbolize.dart b/packages/flutter_tools/lib/src/commands/symbolize.dart index df915b50cad..f7ab2d20ded 100644 --- a/packages/flutter_tools/lib/src/commands/symbolize.dart +++ b/packages/flutter_tools/lib/src/commands/symbolize.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:typed_data'; @@ -24,8 +22,8 @@ import '../runner/flutter_command.dart'; /// over stdout. class SymbolizeCommand extends FlutterCommand { SymbolizeCommand({ - @required Stdio stdio, - @required FileSystem fileSystem, + required Stdio stdio, + required FileSystem fileSystem, DwarfSymbolizationService dwarfSymbolizationService = const DwarfSymbolizationService(), }) : _stdio = stdio, _fileSystem = fileSystem, @@ -67,13 +65,13 @@ class SymbolizeCommand extends FlutterCommand { @override Future validateCommand() { - if (!argResults.wasParsed('debug-info')) { + if (argResults?.wasParsed('debug-info') != true) { throwToolExit('"--debug-info" is required to symbolize stack traces.'); } - if (!_fileSystem.isFileSync(stringArg('debug-info'))) { + if (!_fileSystem.isFileSync(stringArg('debug-info')!)) { throwToolExit('${stringArg('debug-info')} does not exist.'); } - if (argResults.wasParsed('input') && !_fileSystem.isFileSync(stringArg('input'))) { + if (argResults?.wasParsed('input') == true && !_fileSystem.isFileSync(stringArg('input')!)) { throwToolExit('${stringArg('input')} does not exist.'); } return super.validateCommand(); @@ -85,7 +83,7 @@ class SymbolizeCommand extends FlutterCommand { IOSink output; // Configure output to either specified file or stdout. - if (argResults.wasParsed('output')) { + if (argResults?.wasParsed('output') == true) { final File outputFile = _fileSystem.file(stringArg('output')); if (!outputFile.parent.existsSync()) { outputFile.parent.createSync(recursive: true); @@ -101,7 +99,7 @@ class SymbolizeCommand extends FlutterCommand { } // Configure input from either specified file or stdin. - if (argResults.wasParsed('input')) { + if (argResults?.wasParsed('input') == true) { input = _fileSystem.file(stringArg('input')).openRead(); } else { input = _stdio.stdin; @@ -121,7 +119,7 @@ class SymbolizeCommand extends FlutterCommand { typedef SymbolsTransformer = StreamTransformer Function(Uint8List); StreamTransformer _defaultTransformer(Uint8List symbols) { - final Dwarf dwarf = Dwarf.fromBytes(symbols); + final Dwarf? dwarf = Dwarf.fromBytes(symbols); if (dwarf == null) { throwToolExit('Failed to decode symbols file'); } @@ -137,7 +135,7 @@ StreamTransformer _testTransformer(Uint8List buffer) { handleDone: (EventSink sink) { sink.close(); }, - handleError: (dynamic error, StackTrace stackTrace, EventSink sink) { + handleError: (Object error, StackTrace stackTrace, EventSink sink) { sink.addError(error, stackTrace); } ); @@ -167,12 +165,12 @@ class DwarfSymbolizationService { /// Throws a [ToolExit] if the symbols cannot be parsed or the stack trace /// cannot be decoded. Future decode({ - @required Stream> input, - @required IOSink output, - @required Uint8List symbols, + required Stream> input, + required IOSink output, + required Uint8List symbols, }) async { final Completer onDone = Completer(); - StreamSubscription subscription; + StreamSubscription? subscription; subscription = input .cast>() .transform(const Utf8Decoder()) @@ -182,7 +180,7 @@ class DwarfSymbolizationService { try { output.writeln(line); } on Exception catch(e, s) { - subscription.cancel().whenComplete(() { + subscription?.cancel().whenComplete(() { if (!onDone.isCompleted) { onDone.completeError(e, s); } diff --git a/packages/flutter_tools/lib/src/template.dart b/packages/flutter_tools/lib/src/template.dart index 851de59c170..da0fe4a54b0 100644 --- a/packages/flutter_tools/lib/src/template.dart +++ b/packages/flutter_tools/lib/src/template.dart @@ -38,7 +38,7 @@ const List kReservedKotlinKeywords = ['when', 'in']; /// Files in the destination will contain none of the '.tmpl', '.copy.tmpl', /// 'img.tmpl', or '-.tmpl' extensions. class Template { - factory Template(Directory templateSource, Directory imageSourceDir, { + factory Template(Directory templateSource, Directory? imageSourceDir, { required FileSystem fileSystem, required Logger logger, required TemplateRenderer templateRenderer, @@ -46,7 +46,7 @@ class Template { }) { return Template._( [templateSource], - [imageSourceDir], + imageSourceDir != null ? [imageSourceDir] : [], fileSystem: fileSystem, logger: logger, templateRenderer: templateRenderer,