Unverified Commit 5be462f5 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate doctor, format, and a few other commands to null safety (#92952)

parent cdbd0a92
......@@ -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<FlutterCommandResult> 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);
}
}
......@@ -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 <one or more paths>';
String get invocation => '${runner?.executableName} $name <one or more paths>';
@override
Future<FlutterCommandResult> runCommand() async {
final String dartBinary = globals.artifacts.getHostArtifact(HostArtifact.engineDartBinary).path;
final String dartBinary = globals.artifacts!.getHostArtifact(HostArtifact.engineDartBinary).path;
final List<String> command = <String>[
dartBinary,
'format',
];
if (argResults.rest.isEmpty) {
final List<String> rest = argResults?.rest ?? <String>[];
if (rest.isEmpty) {
globals.printError(
'No files specified to be formatted.'
);
command.add('-h');
} else {
command.addAll(<String>[
for (String arg in argResults.rest)
for (String arg in rest)
if (arg == '--dry-run' || arg == '-n')
'--output=none'
else
......
......@@ -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';
......
......@@ -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<String> 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');
......
......@@ -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<FlutterCommandResult> runCommand() async {
if (argResults.rest.isNotEmpty) {
final List<String> rest = argResults?.rest ?? <String>[];
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
}
......@@ -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<String> aliases = <String>['pic'];
Device device;
Device? device;
Future<void> _validateOptions(String screenshotType, String observatoryUrl) async {
Future<void> _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<FlutterCommandResult> verifyThenRunCommand(String commandPath) async {
Future<FlutterCommandResult> verifyThenRunCommand(String? commandPath) async {
await _validateOptions(stringArg(_kType), stringArg(_kObservatoryUrl));
return super.verifyThenRunCommand(commandPath);
}
@override
Future<FlutterCommandResult> 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<void> runScreenshot(File outputFile) async {
Future<void> 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<bool> runSkia(File outputFile) async {
final Uri observatoryUrl = Uri.parse(stringArg(_kObservatoryUrl));
Future<bool> 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<bool> runRasterizer(File outputFile) async {
final Uri observatoryUrl = Uri.parse(stringArg(_kObservatoryUrl));
Future<bool> 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);
......
......@@ -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<String> get usagePath async => null;
Future<String?> get usagePath async => null;
@override
Future<FlutterCommandResult> runCommand() async {
if (argResults.rest.length > 1) {
final List<String> rest = argResults?.rest ?? <String>[];
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(<String>['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. '
......
......@@ -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<void> 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<String, String> Function(Uint8List);
StreamTransformer<String, String> _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<String, String> _testTransformer(Uint8List buffer) {
handleDone: (EventSink<String> sink) {
sink.close();
},
handleError: (dynamic error, StackTrace stackTrace, EventSink<String> sink) {
handleError: (Object error, StackTrace stackTrace, EventSink<String> 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<void> decode({
@required Stream<List<int>> input,
@required IOSink output,
@required Uint8List symbols,
required Stream<List<int>> input,
required IOSink output,
required Uint8List symbols,
}) async {
final Completer<void> onDone = Completer<void>();
StreamSubscription<void> subscription;
StreamSubscription<void>? subscription;
subscription = input
.cast<List<int>>()
.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);
}
......
......@@ -38,7 +38,7 @@ const List<String> kReservedKotlinKeywords = <String>['when', 'in'];
/// Files in the destination will contain none of the '.tmpl', '.copy.tmpl',
/// 'img.tmpl', or '-<language>.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._(
<Directory>[templateSource],
<Directory>[imageSourceDir],
imageSourceDir != null ? <Directory>[imageSourceDir] : <Directory>[],
fileSystem: fileSystem,
logger: logger,
templateRenderer: templateRenderer,
......
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