Migrate flutter_command to null safety (#92871)
This commit is contained in:
parent
1980492997
commit
a4e7b5994c
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:args/args.dart';
|
import 'package:args/args.dart';
|
||||||
import 'package:args/command_runner.dart';
|
import 'package:args/command_runner.dart';
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
@ -70,7 +68,7 @@ class FlutterCommandResult {
|
|||||||
/// Optional data that can be appended to the timing event.
|
/// Optional data that can be appended to the timing event.
|
||||||
/// https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#timingLabel
|
/// https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#timingLabel
|
||||||
/// Do not add PII.
|
/// Do not add PII.
|
||||||
final List<String> timingLabelParts;
|
final List<String>? timingLabelParts;
|
||||||
|
|
||||||
/// Optional epoch time when the command's non-interactive wait time is
|
/// Optional epoch time when the command's non-interactive wait time is
|
||||||
/// complete during the command's execution. Use to measure user perceivable
|
/// complete during the command's execution. Use to measure user perceivable
|
||||||
@ -78,7 +76,7 @@ class FlutterCommandResult {
|
|||||||
///
|
///
|
||||||
/// [FlutterCommand] will automatically measure and report the command's
|
/// [FlutterCommand] will automatically measure and report the command's
|
||||||
/// complete time if not overridden.
|
/// complete time if not overridden.
|
||||||
final DateTime endTimeOverride;
|
final DateTime? endTimeOverride;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -92,7 +90,6 @@ class FlutterCommandResult {
|
|||||||
case ExitStatus.killed:
|
case ExitStatus.killed:
|
||||||
return 'killed';
|
return 'killed';
|
||||||
}
|
}
|
||||||
return null; // dead code, remove with null safety migration
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +128,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// The currently executing command (or sub-command).
|
/// The currently executing command (or sub-command).
|
||||||
///
|
///
|
||||||
/// Will be `null` until the top-most command has begun execution.
|
/// Will be `null` until the top-most command has begun execution.
|
||||||
static FlutterCommand get current => context.get<FlutterCommand>();
|
static FlutterCommand? get current => context.get<FlutterCommand>();
|
||||||
|
|
||||||
/// The option name for a custom observatory port.
|
/// The option name for a custom observatory port.
|
||||||
static const String observatoryPortOption = 'observatory-port';
|
static const String observatoryPortOption = 'observatory-port';
|
||||||
@ -168,7 +165,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FlutterCommandRunner get runner => super.runner as FlutterCommandRunner;
|
FlutterCommandRunner? get runner => super.runner as FlutterCommandRunner?;
|
||||||
|
|
||||||
bool _requiresPubspecYaml = false;
|
bool _requiresPubspecYaml = false;
|
||||||
|
|
||||||
@ -197,7 +194,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
_requiresPubspecYaml = true;
|
_requiresPubspecYaml = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usesWebOptions({ @required bool verboseHelp }) {
|
void usesWebOptions({ required bool verboseHelp }) {
|
||||||
argParser.addOption('web-hostname',
|
argParser.addOption('web-hostname',
|
||||||
defaultsTo: 'localhost',
|
defaultsTo: 'localhost',
|
||||||
help:
|
help:
|
||||||
@ -208,7 +205,6 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
);
|
);
|
||||||
argParser.addOption('web-port',
|
argParser.addOption('web-port',
|
||||||
defaultsTo: null,
|
|
||||||
help: 'The host port to serve the web application from. If not provided, the tool '
|
help: 'The host port to serve the web application from. If not provided, the tool '
|
||||||
'will select a random open port on the host.',
|
'will select a random open port on the host.',
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
@ -241,13 +237,11 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
);
|
);
|
||||||
argParser.addFlag('web-allow-expose-url',
|
argParser.addFlag('web-allow-expose-url',
|
||||||
defaultsTo: false,
|
|
||||||
help: 'Enables daemon-to-editor requests (app.exposeUrl) for exposing URLs '
|
help: 'Enables daemon-to-editor requests (app.exposeUrl) for exposing URLs '
|
||||||
'when running on remote machines.',
|
'when running on remote machines.',
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
);
|
);
|
||||||
argParser.addFlag('web-run-headless',
|
argParser.addFlag('web-run-headless',
|
||||||
defaultsTo: false,
|
|
||||||
help: 'Launches the browser in headless mode. Currently only Chrome '
|
help: 'Launches the browser in headless mode. Currently only Chrome '
|
||||||
'supports this option.',
|
'supports this option.',
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
@ -278,11 +272,12 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String get targetFile {
|
String get targetFile {
|
||||||
if (argResults.wasParsed('target')) {
|
if (argResults?.wasParsed('target') == true) {
|
||||||
return stringArg('target');
|
return stringArg('target')!;
|
||||||
}
|
}
|
||||||
if (argResults.rest.isNotEmpty) {
|
final List<String>? rest = argResults?.rest;
|
||||||
return argResults.rest.first;
|
if (rest != null && rest.isNotEmpty) {
|
||||||
|
return rest.first;
|
||||||
}
|
}
|
||||||
return bundle.defaultMainPath;
|
return bundle.defaultMainPath;
|
||||||
}
|
}
|
||||||
@ -290,12 +285,12 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// Path to the Dart's package config file.
|
/// Path to the Dart's package config file.
|
||||||
///
|
///
|
||||||
/// This can be overridden by some of its subclasses.
|
/// This can be overridden by some of its subclasses.
|
||||||
String get packagesPath => globalResults['packages'] as String;
|
String? get packagesPath => globalResults?['packages'] as String?;
|
||||||
|
|
||||||
/// The value of the `--filesystem-scheme` argument.
|
/// The value of the `--filesystem-scheme` argument.
|
||||||
///
|
///
|
||||||
/// This can be overridden by some of its subclasses.
|
/// This can be overridden by some of its subclasses.
|
||||||
String get fileSystemScheme =>
|
String? get fileSystemScheme =>
|
||||||
argParser.options.containsKey(FlutterOptions.kFileSystemScheme)
|
argParser.options.containsKey(FlutterOptions.kFileSystemScheme)
|
||||||
? stringArg(FlutterOptions.kFileSystemScheme)
|
? stringArg(FlutterOptions.kFileSystemScheme)
|
||||||
: null;
|
: null;
|
||||||
@ -303,7 +298,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// The values of the `--filesystem-root` argument.
|
/// The values of the `--filesystem-root` argument.
|
||||||
///
|
///
|
||||||
/// This can be overridden by some of its subclasses.
|
/// This can be overridden by some of its subclasses.
|
||||||
List<String> get fileSystemRoots =>
|
List<String>? get fileSystemRoots =>
|
||||||
argParser.options.containsKey(FlutterOptions.kFileSystemRoot)
|
argParser.options.containsKey(FlutterOptions.kFileSystemRoot)
|
||||||
? stringsArg(FlutterOptions.kFileSystemRoot)
|
? stringsArg(FlutterOptions.kFileSystemRoot)
|
||||||
: null;
|
: null;
|
||||||
@ -320,7 +315,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
///
|
///
|
||||||
/// The `hide` argument indicates whether or not to hide these options when
|
/// The `hide` argument indicates whether or not to hide these options when
|
||||||
/// the user asks for help.
|
/// the user asks for help.
|
||||||
void usesFilesystemOptions({ @required bool hide }) {
|
void usesFilesystemOptions({ required bool hide }) {
|
||||||
argParser
|
argParser
|
||||||
..addOption('output-dill',
|
..addOption('output-dill',
|
||||||
hide: hide,
|
hide: hide,
|
||||||
@ -342,7 +337,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds options for connecting to the Dart VM observatory port.
|
/// Adds options for connecting to the Dart VM observatory port.
|
||||||
void usesPortOptions({ @required bool verboseHelp }) {
|
void usesPortOptions({ required bool verboseHelp }) {
|
||||||
argParser.addOption(observatoryPortOption,
|
argParser.addOption(observatoryPortOption,
|
||||||
help: '(deprecated; use host-vmservice-port instead) '
|
help: '(deprecated; use host-vmservice-port instead) '
|
||||||
'Listen to the given port for an observatory debugger connection.\n'
|
'Listen to the given port for an observatory debugger connection.\n'
|
||||||
@ -364,7 +359,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
_usesPortOption = true;
|
_usesPortOption = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDevToolsOptions({@required bool verboseHelp}) {
|
void addDevToolsOptions({required bool verboseHelp}) {
|
||||||
argParser.addFlag(
|
argParser.addFlag(
|
||||||
kEnableDevTools,
|
kEnableDevTools,
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
@ -382,7 +377,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDdsOptions({@required bool verboseHelp}) {
|
void addDdsOptions({required bool verboseHelp}) {
|
||||||
argParser.addOption('dds-port',
|
argParser.addOption('dds-port',
|
||||||
help: 'When this value is provided, the Dart Development Service (DDS) will be '
|
help: 'When this value is provided, the Dart Development Service (DDS) will be '
|
||||||
'bound to the provided port.\n'
|
'bound to the provided port.\n'
|
||||||
@ -407,55 +402,61 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _ddsEnabled;
|
late final bool enableDds = () {
|
||||||
bool get enableDds {
|
bool ddsEnabled = false;
|
||||||
if (_ddsEnabled == null) {
|
if (argResults?.wasParsed('disable-dds') == true) {
|
||||||
if (argResults.wasParsed('disable-dds')) {
|
if (argResults?.wasParsed('dds') == true) {
|
||||||
if (argResults.wasParsed('dds')) {
|
throwToolExit(
|
||||||
throwToolExit('The "--[no-]dds" and "--[no-]disable-dds" arguments are mutually exclusive. Only specify "--[no-]dds".');
|
'The "--[no-]dds" and "--[no-]disable-dds" arguments are mutually exclusive. Only specify "--[no-]dds".');
|
||||||
}
|
|
||||||
_ddsEnabled = !boolArg('disable-dds');
|
|
||||||
// TODO(ianh): enable the following code once google3 is migrated away from --disable-dds (and add test to flutter_command_test.dart)
|
|
||||||
if (false) { // ignore: dead_code
|
|
||||||
if (_ddsEnabled) {
|
|
||||||
globals.printError('${globals.logger.terminal.warningMark} The "--no-disable-dds" argument is deprecated and redundant, and should be omitted.');
|
|
||||||
} else {
|
|
||||||
globals.printError('${globals.logger.terminal.warningMark} The "--disable-dds" argument is deprecated. Use "--no-dds" instead.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_ddsEnabled = boolArg('dds');
|
|
||||||
}
|
}
|
||||||
|
ddsEnabled = !boolArg('disable-dds');
|
||||||
|
// TODO(ianh): enable the following code once google3 is migrated away from --disable-dds (and add test to flutter_command_test.dart)
|
||||||
|
if (false) { // ignore: dead_code
|
||||||
|
if (ddsEnabled) {
|
||||||
|
globals.printError('${globals.logger.terminal
|
||||||
|
.warningMark} The "--no-disable-dds" argument is deprecated and redundant, and should be omitted.');
|
||||||
|
} else {
|
||||||
|
globals.printError('${globals.logger.terminal
|
||||||
|
.warningMark} The "--disable-dds" argument is deprecated. Use "--no-dds" instead.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ddsEnabled = boolArg('dds');
|
||||||
}
|
}
|
||||||
return _ddsEnabled;
|
return ddsEnabled;
|
||||||
}
|
}();
|
||||||
|
|
||||||
bool get _hostVmServicePortProvided => argResults.wasParsed('observatory-port') ||
|
bool get _hostVmServicePortProvided => argResults?.wasParsed('observatory-port') == true ||
|
||||||
argResults.wasParsed('host-vmservice-port');
|
argResults?.wasParsed('host-vmservice-port') == true;
|
||||||
|
|
||||||
int _tryParseHostVmservicePort() {
|
int _tryParseHostVmservicePort() {
|
||||||
|
final String? observatoryPort = stringArg('observatory-port');
|
||||||
|
final String? hostPort = stringArg('host-vmservice-port');
|
||||||
|
if (observatoryPort == null && hostPort == null) {
|
||||||
|
throwToolExit('Invalid port for `--observatory-port/--host-vmservice-port`');
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return int.parse(stringArg('observatory-port') ?? stringArg('host-vmservice-port'));
|
return int.parse((observatoryPort ?? hostPort)!);
|
||||||
} on FormatException catch (error) {
|
} on FormatException catch (error) {
|
||||||
throwToolExit('Invalid port for `--observatory-port/--host-vmservice-port`: $error');
|
throwToolExit('Invalid port for `--observatory-port/--host-vmservice-port`: $error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int get ddsPort {
|
int get ddsPort {
|
||||||
if (!argResults.wasParsed('dds-port') && _hostVmServicePortProvided) {
|
if (argResults?.wasParsed('dds-port') != true && _hostVmServicePortProvided) {
|
||||||
// If an explicit DDS port is _not_ provided, use the host-vmservice-port for DDS.
|
// If an explicit DDS port is _not_ provided, use the host-vmservice-port for DDS.
|
||||||
return _tryParseHostVmservicePort();
|
return _tryParseHostVmservicePort();
|
||||||
} else if (argResults.wasParsed('dds-port')) {
|
} else if (argResults?.wasParsed('dds-port') == true) {
|
||||||
// If an explicit DDS port is provided, use dds-port for DDS.
|
// If an explicit DDS port is provided, use dds-port for DDS.
|
||||||
return int.tryParse(stringArg('dds-port')) ?? 0;
|
return int.tryParse(stringArg('dds-port')!) ?? 0;
|
||||||
}
|
}
|
||||||
// Otherwise, DDS can bind to a random port.
|
// Otherwise, DDS can bind to a random port.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri get devToolsServerAddress {
|
Uri? get devToolsServerAddress {
|
||||||
if (argResults.wasParsed(kDevToolsServerAddress)) {
|
if (argResults?.wasParsed(kDevToolsServerAddress) == true) {
|
||||||
final Uri uri = Uri.tryParse(stringArg(kDevToolsServerAddress));
|
final Uri? uri = Uri.tryParse(stringArg(kDevToolsServerAddress)!);
|
||||||
if (uri != null && uri.host.isNotEmpty && uri.port != 0) {
|
if (uri != null && uri.host.isNotEmpty && uri.port != 0) {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
@ -470,19 +471,19 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// specified.
|
/// specified.
|
||||||
///
|
///
|
||||||
/// If no port is set, returns null.
|
/// If no port is set, returns null.
|
||||||
int get hostVmservicePort {
|
int? get hostVmservicePort {
|
||||||
if (!_usesPortOption || !_hostVmServicePortProvided) {
|
if (!_usesPortOption || !_hostVmServicePortProvided) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (argResults.wasParsed('observatory-port') &&
|
if (argResults?.wasParsed('observatory-port') == true &&
|
||||||
argResults.wasParsed('host-vmservice-port')) {
|
argResults?.wasParsed('host-vmservice-port') == true) {
|
||||||
throwToolExit('Only one of "--observatory-port" and '
|
throwToolExit('Only one of "--observatory-port" and '
|
||||||
'"--host-vmservice-port" may be specified.');
|
'"--host-vmservice-port" may be specified.');
|
||||||
}
|
}
|
||||||
// If DDS is enabled and no explicit DDS port is provided, use the
|
// If DDS is enabled and no explicit DDS port is provided, use the
|
||||||
// host-vmservice-port for DDS instead and bind the VM service to a random
|
// host-vmservice-port for DDS instead and bind the VM service to a random
|
||||||
// port.
|
// port.
|
||||||
if (enableDds && !argResults.wasParsed('dds-port')) {
|
if (enableDds && argResults?.wasParsed('dds-port') != true) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return _tryParseHostVmservicePort();
|
return _tryParseHostVmservicePort();
|
||||||
@ -491,12 +492,13 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// Gets the vmservice port provided to in the 'device-vmservice-port' option.
|
/// Gets the vmservice port provided to in the 'device-vmservice-port' option.
|
||||||
///
|
///
|
||||||
/// If no port is set, returns null.
|
/// If no port is set, returns null.
|
||||||
int get deviceVmservicePort {
|
int? get deviceVmservicePort {
|
||||||
if (!_usesPortOption || argResults['device-vmservice-port'] == null) {
|
final String? devicePort = stringArg('device-vmservice-port');
|
||||||
|
if (!_usesPortOption || devicePort == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return int.parse(stringArg('device-vmservice-port'));
|
return int.parse(devicePort);
|
||||||
} on FormatException catch (error) {
|
} on FormatException catch (error) {
|
||||||
throwToolExit('Invalid port for `--device-vmservice-port`: $error');
|
throwToolExit('Invalid port for `--device-vmservice-port`: $error');
|
||||||
}
|
}
|
||||||
@ -504,7 +506,6 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
|
|
||||||
void addPublishPort({ bool enabledByDefault = true, bool verboseHelp = false }) {
|
void addPublishPort({ bool enabledByDefault = true, bool verboseHelp = false }) {
|
||||||
argParser.addFlag('publish-port',
|
argParser.addFlag('publish-port',
|
||||||
negatable: true,
|
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
help: 'Publish the VM service port over mDNS. Disable to prevent the '
|
help: 'Publish the VM service port over mDNS. Disable to prevent the '
|
||||||
'local network permission app dialog in debug and profile build modes (iOS devices only).',
|
'local network permission app dialog in debug and profile build modes (iOS devices only).',
|
||||||
@ -514,7 +515,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
|
|
||||||
bool get disablePortPublication => !boolArg('publish-port');
|
bool get disablePortPublication => !boolArg('publish-port');
|
||||||
|
|
||||||
void usesIpv6Flag({@required bool verboseHelp}) {
|
void usesIpv6Flag({required bool verboseHelp}) {
|
||||||
argParser.addFlag(ipv6Flag,
|
argParser.addFlag(ipv6Flag,
|
||||||
negatable: false,
|
negatable: false,
|
||||||
help: 'Binds to IPv6 localhost instead of IPv4 when the flutter tool '
|
help: 'Binds to IPv6 localhost instead of IPv4 when the flutter tool '
|
||||||
@ -525,7 +526,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
_usesIpv6Flag = true;
|
_usesIpv6Flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get ipv6 => _usesIpv6Flag ? boolArg('ipv6') : null;
|
bool? get ipv6 => _usesIpv6Flag ? boolArg('ipv6') : null;
|
||||||
|
|
||||||
void usesBuildNumberOption() {
|
void usesBuildNumberOption() {
|
||||||
argParser.addOption('build-number',
|
argParser.addOption('build-number',
|
||||||
@ -592,22 +593,20 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// Whether this command should report null safety analytics.
|
/// Whether this command should report null safety analytics.
|
||||||
bool get reportNullSafety => false;
|
bool get reportNullSafety => false;
|
||||||
|
|
||||||
Duration get deviceDiscoveryTimeout {
|
late final Duration? deviceDiscoveryTimeout = () {
|
||||||
if (_deviceDiscoveryTimeout == null
|
if (argResults?.options.contains(FlutterOptions.kDeviceTimeout) == true
|
||||||
&& argResults.options.contains(FlutterOptions.kDeviceTimeout)
|
&& argResults?.wasParsed(FlutterOptions.kDeviceTimeout) == true) {
|
||||||
&& argResults.wasParsed(FlutterOptions.kDeviceTimeout)) {
|
final int? timeoutSeconds = int.tryParse(stringArg(FlutterOptions.kDeviceTimeout)!);
|
||||||
final int timeoutSeconds = int.tryParse(stringArg(FlutterOptions.kDeviceTimeout));
|
|
||||||
if (timeoutSeconds == null) {
|
if (timeoutSeconds == null) {
|
||||||
throwToolExit( 'Could not parse "--${FlutterOptions.kDeviceTimeout}" argument. It must be an integer.');
|
throwToolExit( 'Could not parse "--${FlutterOptions.kDeviceTimeout}" argument. It must be an integer.');
|
||||||
}
|
}
|
||||||
_deviceDiscoveryTimeout = Duration(seconds: timeoutSeconds);
|
return Duration(seconds: timeoutSeconds);
|
||||||
}
|
}
|
||||||
return _deviceDiscoveryTimeout;
|
return null;
|
||||||
}
|
}();
|
||||||
Duration _deviceDiscoveryTimeout;
|
|
||||||
|
|
||||||
void addBuildModeFlags({
|
void addBuildModeFlags({
|
||||||
@required bool verboseHelp,
|
required bool verboseHelp,
|
||||||
bool defaultToRelease = true,
|
bool defaultToRelease = true,
|
||||||
bool excludeDebug = false,
|
bool excludeDebug = false,
|
||||||
bool excludeRelease = false,
|
bool excludeRelease = false,
|
||||||
@ -669,7 +668,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addBundleSkSLPathOption({ @required bool hide }) {
|
void addBundleSkSLPathOption({ required bool hide }) {
|
||||||
argParser.addOption(FlutterOptions.kBundleSkSLPathOption,
|
argParser.addOption(FlutterOptions.kBundleSkSLPathOption,
|
||||||
help: 'A path to a file containing precompiled SkSL shaders generated '
|
help: 'A path to a file containing precompiled SkSL shaders generated '
|
||||||
'during "flutter run". These can be included in an application to '
|
'during "flutter run". These can be included in an application to '
|
||||||
@ -680,26 +679,24 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addTreeShakeIconsFlag({
|
void addTreeShakeIconsFlag({
|
||||||
bool enabledByDefault
|
bool? enabledByDefault
|
||||||
}) {
|
}) {
|
||||||
argParser.addFlag('tree-shake-icons',
|
argParser.addFlag('tree-shake-icons',
|
||||||
negatable: true,
|
|
||||||
defaultsTo: enabledByDefault
|
defaultsTo: enabledByDefault
|
||||||
?? kIconTreeShakerEnabledDefault,
|
?? kIconTreeShakerEnabledDefault,
|
||||||
help: 'Tree shake icon fonts so that only glyphs used by the application remain.',
|
help: 'Tree shake icon fonts so that only glyphs used by the application remain.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addShrinkingFlag({ @required bool verboseHelp }) {
|
void addShrinkingFlag({ required bool verboseHelp }) {
|
||||||
argParser.addFlag('shrink',
|
argParser.addFlag('shrink',
|
||||||
negatable: true,
|
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
help: 'This flag has no effect. Code shrinking is always enabled in release builds. '
|
help: 'This flag has no effect. Code shrinking is always enabled in release builds. '
|
||||||
'To learn more, see: https://developer.android.com/studio/build/shrink-code'
|
'To learn more, see: https://developer.android.com/studio/build/shrink-code'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addNullSafetyModeOptions({ @required bool hide }) {
|
void addNullSafetyModeOptions({ required bool hide }) {
|
||||||
argParser.addFlag(FlutterOptions.kNullSafety,
|
argParser.addFlag(FlutterOptions.kNullSafety,
|
||||||
help:
|
help:
|
||||||
'Whether to override the inferred null safety mode. This allows null-safe '
|
'Whether to override the inferred null safety mode. This allows null-safe '
|
||||||
@ -720,13 +717,12 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
|
|
||||||
/// Enables support for the hidden options --extra-front-end-options and
|
/// Enables support for the hidden options --extra-front-end-options and
|
||||||
/// --extra-gen-snapshot-options.
|
/// --extra-gen-snapshot-options.
|
||||||
void usesExtraDartFlagOptions({ @required bool verboseHelp }) {
|
void usesExtraDartFlagOptions({ required bool verboseHelp }) {
|
||||||
argParser.addMultiOption(FlutterOptions.kExtraFrontEndOptions,
|
argParser.addMultiOption(FlutterOptions.kExtraFrontEndOptions,
|
||||||
aliases: <String>[ kExtraFrontEndOptions ], // supported for historical reasons
|
aliases: <String>[ kExtraFrontEndOptions ], // supported for historical reasons
|
||||||
help: 'A comma-separated list of additional command line arguments that will be passed directly to the Dart front end. '
|
help: 'A comma-separated list of additional command line arguments that will be passed directly to the Dart front end. '
|
||||||
'For example, "--${FlutterOptions.kExtraFrontEndOptions}=--enable-experiment=nonfunction-type-aliases".',
|
'For example, "--${FlutterOptions.kExtraFrontEndOptions}=--enable-experiment=nonfunction-type-aliases".',
|
||||||
valueHelp: '--foo,--bar',
|
valueHelp: '--foo,--bar',
|
||||||
splitCommas: true,
|
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
);
|
);
|
||||||
argParser.addMultiOption(FlutterOptions.kExtraGenSnapshotOptions,
|
argParser.addMultiOption(FlutterOptions.kExtraGenSnapshotOptions,
|
||||||
@ -735,7 +731,6 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
'(Only used in "--profile" or "--release" builds.) '
|
'(Only used in "--profile" or "--release" builds.) '
|
||||||
'For example, "--${FlutterOptions.kExtraGenSnapshotOptions}=--no-strip".',
|
'For example, "--${FlutterOptions.kExtraGenSnapshotOptions}=--no-strip".',
|
||||||
valueHelp: '--foo,--bar',
|
valueHelp: '--foo,--bar',
|
||||||
splitCommas: true,
|
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -757,7 +752,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addEnableExperimentation({ @required bool hide }) {
|
void addEnableExperimentation({ required bool hide }) {
|
||||||
argParser.addMultiOption(
|
argParser.addMultiOption(
|
||||||
FlutterOptions.kEnableExperiment,
|
FlutterOptions.kEnableExperiment,
|
||||||
help:
|
help:
|
||||||
@ -810,7 +805,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usesInitializeFromDillOption({ @required bool hide }) {
|
void usesInitializeFromDillOption({ required bool hide }) {
|
||||||
argParser.addOption(FlutterOptions.kInitializeFromDill,
|
argParser.addOption(FlutterOptions.kInitializeFromDill,
|
||||||
help: 'Initializes the resident compiler with a specific kernel file instead of '
|
help: 'Initializes the resident compiler with a specific kernel file instead of '
|
||||||
'the default cached location.',
|
'the default cached location.',
|
||||||
@ -820,7 +815,6 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
|
|
||||||
void addMultidexOption({ bool hide = false }) {
|
void addMultidexOption({ bool hide = false }) {
|
||||||
argParser.addFlag('multidex',
|
argParser.addFlag('multidex',
|
||||||
negatable: true,
|
|
||||||
defaultsTo: true,
|
defaultsTo: true,
|
||||||
help: 'When enabled, indicates that the app should be built with multidex support. This '
|
help: 'When enabled, indicates that the app should be built with multidex support. This '
|
||||||
'flag adds the dependencies for multidex when the minimum android sdk is 20 or '
|
'flag adds the dependencies for multidex when the minimum android sdk is 20 or '
|
||||||
@ -829,7 +823,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds build options common to all of the desktop build commands.
|
/// Adds build options common to all of the desktop build commands.
|
||||||
void addCommonDesktopBuildOptions({ @required bool verboseHelp }) {
|
void addCommonDesktopBuildOptions({ required bool verboseHelp }) {
|
||||||
addBuildModeFlags(verboseHelp: verboseHelp);
|
addBuildModeFlags(verboseHelp: verboseHelp);
|
||||||
addBuildPerformanceFile(hide: !verboseHelp);
|
addBuildPerformanceFile(hide: !verboseHelp);
|
||||||
addBundleSkSLPathOption(hide: !verboseHelp);
|
addBundleSkSLPathOption(hide: !verboseHelp);
|
||||||
@ -850,7 +844,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// explicitly specified.
|
/// explicitly specified.
|
||||||
///
|
///
|
||||||
/// Use [getBuildMode] to obtain the actual effective build mode.
|
/// Use [getBuildMode] to obtain the actual effective build mode.
|
||||||
BuildMode defaultBuildMode;
|
BuildMode defaultBuildMode = BuildMode.debug;
|
||||||
|
|
||||||
BuildMode getBuildMode() {
|
BuildMode getBuildMode() {
|
||||||
// No debug when _excludeDebug is true.
|
// No debug when _excludeDebug is true.
|
||||||
@ -866,7 +860,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
];
|
];
|
||||||
if (modeFlags.where((bool flag) => flag).length > 1) {
|
if (modeFlags.where((bool flag) => flag).length > 1) {
|
||||||
throw UsageException('Only one of "--debug", "--profile", "--jit-release", '
|
throw UsageException('Only one of "--debug", "--profile", "--jit-release", '
|
||||||
'or "--release" can be specified.', null);
|
'or "--release" can be specified.', '');
|
||||||
}
|
}
|
||||||
if (debugResult) {
|
if (debugResult) {
|
||||||
return BuildMode.debug;
|
return BuildMode.debug;
|
||||||
@ -892,7 +886,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usesTrackWidgetCreation({ bool hasEffect = true, @required bool verboseHelp }) {
|
void usesTrackWidgetCreation({ bool hasEffect = true, required bool verboseHelp }) {
|
||||||
argParser.addFlag(
|
argParser.addFlag(
|
||||||
'track-widget-creation',
|
'track-widget-creation',
|
||||||
hide: !hasEffect && !verboseHelp,
|
hide: !hasEffect && !verboseHelp,
|
||||||
@ -905,7 +899,6 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
void usesAnalyzeSizeFlag() {
|
void usesAnalyzeSizeFlag() {
|
||||||
argParser.addFlag(
|
argParser.addFlag(
|
||||||
FlutterOptions.kAnalyzeSize,
|
FlutterOptions.kAnalyzeSize,
|
||||||
defaultsTo: false,
|
|
||||||
help: 'Whether to produce additional profile information for artifact output size. '
|
help: 'Whether to produce additional profile information for artifact output size. '
|
||||||
'This flag is only supported on "--release" builds. When building for Android, a single '
|
'This flag is only supported on "--release" builds. When building for Android, a single '
|
||||||
'ABI must be specified at a time with the "--target-platform" flag. When building for iOS, '
|
'ABI must be specified at a time with the "--target-platform" flag. When building for iOS, '
|
||||||
@ -928,11 +921,11 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
///
|
///
|
||||||
/// Throws a [ToolExit] if the current set of options is not compatible with
|
/// Throws a [ToolExit] if the current set of options is not compatible with
|
||||||
/// each other.
|
/// each other.
|
||||||
Future<BuildInfo> getBuildInfo({ BuildMode forcedBuildMode, File forcedTargetFile }) async {
|
Future<BuildInfo> getBuildInfo({ BuildMode? forcedBuildMode, File? forcedTargetFile }) async {
|
||||||
final bool trackWidgetCreation = argParser.options.containsKey('track-widget-creation') &&
|
final bool trackWidgetCreation = argParser.options.containsKey('track-widget-creation') &&
|
||||||
boolArg('track-widget-creation');
|
boolArg('track-widget-creation');
|
||||||
|
|
||||||
final String buildNumber = argParser.options.containsKey('build-number')
|
final String? buildNumber = argParser.options.containsKey('build-number')
|
||||||
? stringArg('build-number')
|
? stringArg('build-number')
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
@ -962,7 +955,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String codeSizeDirectory;
|
String? codeSizeDirectory;
|
||||||
if (argParser.options.containsKey(FlutterOptions.kAnalyzeSize) && boolArg(FlutterOptions.kAnalyzeSize)) {
|
if (argParser.options.containsKey(FlutterOptions.kAnalyzeSize) && boolArg(FlutterOptions.kAnalyzeSize)) {
|
||||||
Directory directory = globals.fsUtils.getUniqueDirectory(
|
Directory directory = globals.fsUtils.getUniqueDirectory(
|
||||||
globals.fs.directory(getBuildDirectory()),
|
globals.fs.directory(getBuildDirectory()),
|
||||||
@ -980,13 +973,13 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
// Explicitly check for `true` and `false` so that `null` results in not
|
// Explicitly check for `true` and `false` so that `null` results in not
|
||||||
// passing a flag. Examine the entrypoint file to determine if it
|
// passing a flag. Examine the entrypoint file to determine if it
|
||||||
// is opted in or out.
|
// is opted in or out.
|
||||||
final bool wasNullSafetyFlagParsed = argResults.wasParsed(FlutterOptions.kNullSafety);
|
final bool wasNullSafetyFlagParsed = argResults?.wasParsed(FlutterOptions.kNullSafety) == true;
|
||||||
if (!wasNullSafetyFlagParsed && (argParser.options.containsKey('target') || forcedTargetFile != null)) {
|
if (!wasNullSafetyFlagParsed && (argParser.options.containsKey('target') || forcedTargetFile != null)) {
|
||||||
final File entrypointFile = forcedTargetFile ?? globals.fs.file(targetFile);
|
final File entrypointFile = forcedTargetFile ?? globals.fs.file(targetFile);
|
||||||
final LanguageVersion languageVersion = determineLanguageVersion(
|
final LanguageVersion languageVersion = determineLanguageVersion(
|
||||||
entrypointFile,
|
entrypointFile,
|
||||||
packageConfig.packageOf(entrypointFile.absolute.uri),
|
packageConfig.packageOf(entrypointFile.absolute.uri),
|
||||||
Cache.flutterRoot,
|
Cache.flutterRoot!,
|
||||||
);
|
);
|
||||||
// Extra frontend options are only provided if explicitly
|
// Extra frontend options are only provided if explicitly
|
||||||
// requested.
|
// requested.
|
||||||
@ -1011,7 +1004,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
final bool dartObfuscation = argParser.options.containsKey(FlutterOptions.kDartObfuscationOption)
|
final bool dartObfuscation = argParser.options.containsKey(FlutterOptions.kDartObfuscationOption)
|
||||||
&& boolArg(FlutterOptions.kDartObfuscationOption);
|
&& boolArg(FlutterOptions.kDartObfuscationOption);
|
||||||
|
|
||||||
final String splitDebugInfoPath = argParser.options.containsKey(FlutterOptions.kSplitDebugInfoOption)
|
final String? splitDebugInfoPath = argParser.options.containsKey(FlutterOptions.kSplitDebugInfoOption)
|
||||||
? stringArg(FlutterOptions.kSplitDebugInfoOption)
|
? stringArg(FlutterOptions.kSplitDebugInfoOption)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
@ -1037,10 +1030,10 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final bool treeShakeIcons = argParser.options.containsKey('tree-shake-icons')
|
final bool treeShakeIcons = argParser.options.containsKey('tree-shake-icons')
|
||||||
&& buildMode.isPrecompiled
|
&& buildMode.isPrecompiled == true
|
||||||
&& boolArg('tree-shake-icons');
|
&& boolArg('tree-shake-icons');
|
||||||
|
|
||||||
final String bundleSkSLPath = argParser.options.containsKey(FlutterOptions.kBundleSkSLPathOption)
|
final String? bundleSkSLPath = argParser.options.containsKey(FlutterOptions.kBundleSkSLPathOption)
|
||||||
? stringArg(FlutterOptions.kBundleSkSLPathOption)
|
? stringArg(FlutterOptions.kBundleSkSLPathOption)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
@ -1048,7 +1041,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
throwToolExit('No SkSL shader bundle found at $bundleSkSLPath.');
|
throwToolExit('No SkSL shader bundle found at $bundleSkSLPath.');
|
||||||
}
|
}
|
||||||
|
|
||||||
final String performanceMeasurementFile = argParser.options.containsKey(FlutterOptions.kPerformanceMeasurementFile)
|
final String? performanceMeasurementFile = argParser.options.containsKey(FlutterOptions.kPerformanceMeasurementFile)
|
||||||
? stringArg(FlutterOptions.kPerformanceMeasurementFile)
|
? stringArg(FlutterOptions.kPerformanceMeasurementFile)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
@ -1057,7 +1050,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
: <String>[];
|
: <String>[];
|
||||||
|
|
||||||
if (argParser.options.containsKey('web-renderer')) {
|
if (argParser.options.containsKey('web-renderer')) {
|
||||||
dartDefines = updateDartDefines(dartDefines, stringArg('web-renderer'));
|
dartDefines = updateDartDefines(dartDefines, stringArg('web-renderer')!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BuildInfo(buildMode,
|
return BuildInfo(buildMode,
|
||||||
@ -1065,10 +1058,10 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
? stringArg('flavor')
|
? stringArg('flavor')
|
||||||
: null,
|
: null,
|
||||||
trackWidgetCreation: trackWidgetCreation,
|
trackWidgetCreation: trackWidgetCreation,
|
||||||
extraFrontEndOptions: extraFrontEndOptions?.isNotEmpty ?? false
|
extraFrontEndOptions: extraFrontEndOptions.isNotEmpty
|
||||||
? extraFrontEndOptions
|
? extraFrontEndOptions
|
||||||
: null,
|
: null,
|
||||||
extraGenSnapshotOptions: extraGenSnapshotOptions?.isNotEmpty ?? false
|
extraGenSnapshotOptions: extraGenSnapshotOptions.isNotEmpty
|
||||||
? extraGenSnapshotOptions
|
? extraGenSnapshotOptions
|
||||||
: null,
|
: null,
|
||||||
fileSystemRoots: fileSystemRoots,
|
fileSystemRoots: fileSystemRoots,
|
||||||
@ -1102,10 +1095,10 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
|
|
||||||
/// The path to send to Google Analytics. Return null here to disable
|
/// The path to send to Google Analytics. Return null here to disable
|
||||||
/// tracking of the command.
|
/// tracking of the command.
|
||||||
Future<String> get usagePath async {
|
Future<String?> get usagePath async {
|
||||||
if (parent is FlutterCommand) {
|
if (parent is FlutterCommand) {
|
||||||
final FlutterCommand commandParent = parent as FlutterCommand;
|
final FlutterCommand? commandParent = parent as FlutterCommand?;
|
||||||
final String path = await commandParent.usagePath;
|
final String? path = await commandParent?.usagePath;
|
||||||
// Don't report for parents that return null for usagePath.
|
// Don't report for parents that return null for usagePath.
|
||||||
return path == null ? null : '$path/$name';
|
return path == null ? null : '$path/$name';
|
||||||
} else {
|
} else {
|
||||||
@ -1133,15 +1126,19 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
// Prints the welcome message if needed.
|
// Prints the welcome message if needed.
|
||||||
globals.flutterUsage.printWelcome();
|
globals.flutterUsage.printWelcome();
|
||||||
_printDeprecationWarning();
|
_printDeprecationWarning();
|
||||||
final String commandPath = await usagePath;
|
final String? commandPath = await usagePath;
|
||||||
_registerSignalHandlers(commandPath, startTime);
|
if (commandPath != null) {
|
||||||
|
_registerSignalHandlers(commandPath, startTime);
|
||||||
|
}
|
||||||
FlutterCommandResult commandResult = FlutterCommandResult.fail();
|
FlutterCommandResult commandResult = FlutterCommandResult.fail();
|
||||||
try {
|
try {
|
||||||
commandResult = await verifyThenRunCommand(commandPath);
|
commandResult = await verifyThenRunCommand(commandPath);
|
||||||
} finally {
|
} finally {
|
||||||
final DateTime endTime = globals.systemClock.now();
|
final DateTime endTime = globals.systemClock.now();
|
||||||
globals.printTrace(userMessages.flutterElapsedTime(name, getElapsedAsMilliseconds(endTime.difference(startTime))));
|
globals.printTrace(userMessages.flutterElapsedTime(name, getElapsedAsMilliseconds(endTime.difference(startTime))));
|
||||||
_sendPostUsage(commandPath, commandResult, startTime, endTime);
|
if (commandPath != null) {
|
||||||
|
_sendPostUsage(commandPath, commandResult, startTime, endTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -1167,7 +1164,10 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
&& dartDefines.any((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA='))) {
|
&& dartDefines.any((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA='))) {
|
||||||
dartDefinesSet.removeWhere((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA='));
|
dartDefinesSet.removeWhere((String d) => d.startsWith('FLUTTER_WEB_USE_SKIA='));
|
||||||
}
|
}
|
||||||
dartDefinesSet.addAll(_webRendererDartDefines[webRenderer]);
|
final Iterable<String>? webRendererDefine = _webRendererDartDefines[webRenderer];
|
||||||
|
if (webRendererDefine != null) {
|
||||||
|
dartDefinesSet.addAll(webRendererDefine);
|
||||||
|
}
|
||||||
return dartDefinesSet.toList();
|
return dartDefinesSet.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1207,7 +1207,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
if (commandResult.exitStatus != null)
|
if (commandResult.exitStatus != null)
|
||||||
getEnumName(commandResult.exitStatus),
|
getEnumName(commandResult.exitStatus),
|
||||||
if (commandResult.timingLabelParts?.isNotEmpty ?? false)
|
if (commandResult.timingLabelParts?.isNotEmpty ?? false)
|
||||||
...commandResult.timingLabelParts,
|
...?commandResult.timingLabelParts,
|
||||||
];
|
];
|
||||||
|
|
||||||
final String label = labels
|
final String label = labels
|
||||||
@ -1233,7 +1233,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// then call this method to execute the command
|
/// then call this method to execute the command
|
||||||
/// rather than calling [runCommand] directly.
|
/// rather than calling [runCommand] directly.
|
||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) async {
|
Future<FlutterCommandResult> verifyThenRunCommand(String? commandPath) async {
|
||||||
// Populate the cache. We call this before pub get below so that the
|
// Populate the cache. We call this before pub get below so that the
|
||||||
// sky_engine package is available in the flutter cache for pub to find.
|
// sky_engine package is available in the flutter cache for pub to find.
|
||||||
if (shouldUpdateCache) {
|
if (shouldUpdateCache) {
|
||||||
@ -1249,7 +1249,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
if (shouldRunPub) {
|
if (shouldRunPub) {
|
||||||
final FlutterProject project = FlutterProject.current();
|
final FlutterProject project = FlutterProject.current();
|
||||||
final Environment environment = Environment(
|
final Environment environment = Environment(
|
||||||
artifacts: globals.artifacts,
|
artifacts: globals.artifacts!,
|
||||||
logger: globals.logger,
|
logger: globals.logger,
|
||||||
cacheDir: globals.cache.getRoot(),
|
cacheDir: globals.cache.getRoot(),
|
||||||
engineVersion: globals.flutterVersion.engineRevision,
|
engineVersion: globals.flutterVersion.engineRevision,
|
||||||
@ -1264,7 +1264,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
|
|
||||||
await generateLocalizationsSyntheticPackage(
|
await generateLocalizationsSyntheticPackage(
|
||||||
environment: environment,
|
environment: environment,
|
||||||
buildSystem: globals.buildSystem,
|
buildSystem: globals.buildSystem!,
|
||||||
);
|
);
|
||||||
|
|
||||||
await pub.get(
|
await pub.get(
|
||||||
@ -1314,21 +1314,21 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
/// devices and criteria entered by the user on the command line.
|
/// devices and criteria entered by the user on the command line.
|
||||||
/// If no device can be found that meets specified criteria,
|
/// If no device can be found that meets specified criteria,
|
||||||
/// then print an error message and return null.
|
/// then print an error message and return null.
|
||||||
Future<List<Device>> findAllTargetDevices({
|
Future<List<Device>?> findAllTargetDevices({
|
||||||
bool includeUnsupportedDevices = false,
|
bool includeUnsupportedDevices = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (!globals.doctor.canLaunchAnything) {
|
if (!globals.doctor!.canLaunchAnything) {
|
||||||
globals.printError(userMessages.flutterNoDevelopmentDevice);
|
globals.printError(userMessages.flutterNoDevelopmentDevice);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final DeviceManager deviceManager = globals.deviceManager;
|
final DeviceManager deviceManager = globals.deviceManager!;
|
||||||
List<Device> devices = await deviceManager.findTargetDevices(
|
List<Device> devices = await deviceManager.findTargetDevices(
|
||||||
includeUnsupportedDevices ? null : FlutterProject.current(),
|
includeUnsupportedDevices ? null : FlutterProject.current(),
|
||||||
timeout: deviceDiscoveryTimeout,
|
timeout: deviceDiscoveryTimeout,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
|
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
|
||||||
globals.printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId));
|
globals.printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId!));
|
||||||
return null;
|
return null;
|
||||||
} else if (devices.isEmpty) {
|
} else if (devices.isEmpty) {
|
||||||
if (deviceManager.hasSpecifiedAllDevices) {
|
if (deviceManager.hasSpecifiedAllDevices) {
|
||||||
@ -1346,7 +1346,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
.toList(),
|
.toList(),
|
||||||
'\n',
|
'\n',
|
||||||
);
|
);
|
||||||
result.writeln('');
|
result.writeln();
|
||||||
result.writeln(userMessages.flutterMissPlatformProjects(
|
result.writeln(userMessages.flutterMissPlatformProjects(
|
||||||
Device.devicesPlatformTypes(unsupportedDevices),
|
Device.devicesPlatformTypes(unsupportedDevices),
|
||||||
));
|
));
|
||||||
@ -1355,7 +1355,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
return null;
|
return null;
|
||||||
} else if (devices.length > 1 && !deviceManager.hasSpecifiedAllDevices) {
|
} else if (devices.length > 1 && !deviceManager.hasSpecifiedAllDevices) {
|
||||||
if (deviceManager.hasSpecifiedDeviceId) {
|
if (deviceManager.hasSpecifiedDeviceId) {
|
||||||
globals.printStatus(userMessages.flutterFoundSpecifiedDevices(devices.length, deviceManager.specifiedDeviceId));
|
globals.printStatus(userMessages.flutterFoundSpecifiedDevices(devices.length, deviceManager.specifiedDeviceId!));
|
||||||
} else {
|
} else {
|
||||||
globals.printStatus(userMessages.flutterSpecifyDeviceWithAllOption);
|
globals.printStatus(userMessages.flutterSpecifyDeviceWithAllOption);
|
||||||
devices = await deviceManager.getAllConnectedDevices();
|
devices = await deviceManager.getAllConnectedDevices();
|
||||||
@ -1374,16 +1374,16 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
///
|
///
|
||||||
/// If [includeUnsupportedDevices] is true, the tool does not filter
|
/// If [includeUnsupportedDevices] is true, the tool does not filter
|
||||||
/// the list by the current project support list.
|
/// the list by the current project support list.
|
||||||
Future<Device> findTargetDevice({
|
Future<Device?> findTargetDevice({
|
||||||
bool includeUnsupportedDevices = false,
|
bool includeUnsupportedDevices = false,
|
||||||
}) async {
|
}) async {
|
||||||
List<Device> deviceList = await findAllTargetDevices(includeUnsupportedDevices: includeUnsupportedDevices);
|
List<Device>? deviceList = await findAllTargetDevices(includeUnsupportedDevices: includeUnsupportedDevices);
|
||||||
if (deviceList == null) {
|
if (deviceList == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (deviceList.length > 1) {
|
if (deviceList.length > 1) {
|
||||||
globals.printStatus(userMessages.flutterSpecifyDevice);
|
globals.printStatus(userMessages.flutterSpecifyDevice);
|
||||||
deviceList = await globals.deviceManager.getAllConnectedDevices();
|
deviceList = await globals.deviceManager!.getAllConnectedDevices();
|
||||||
globals.printStatus('');
|
globals.printStatus('');
|
||||||
await Device.printDevices(deviceList, globals.logger);
|
await Device.printDevices(deviceList, globals.logger);
|
||||||
return null;
|
return null;
|
||||||
@ -1394,7 +1394,7 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
@protected
|
@protected
|
||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
Future<void> validateCommand() async {
|
Future<void> validateCommand() async {
|
||||||
if (_requiresPubspecYaml && !globalResults.wasParsed('packages')) {
|
if (_requiresPubspecYaml && globalResults?.wasParsed('packages') != true) {
|
||||||
// Don't expect a pubspec.yaml file if the user passed in an explicit .packages file path.
|
// Don't expect a pubspec.yaml file if the user passed in an explicit .packages file path.
|
||||||
|
|
||||||
// If there is no pubspec in the current directory, look in the parent
|
// If there is no pubspec in the current directory, look in the parent
|
||||||
@ -1433,23 +1433,23 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
description,
|
description,
|
||||||
'',
|
'',
|
||||||
'Global options:',
|
'Global options:',
|
||||||
runner.argParser.usage,
|
'${runner?.argParser.usage}',
|
||||||
'',
|
'',
|
||||||
usageWithoutDescription,
|
usageWithoutDescription,
|
||||||
].join('\n');
|
].join('\n');
|
||||||
return help;
|
return help;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationPackageFactory applicationPackages;
|
ApplicationPackageFactory? applicationPackages;
|
||||||
|
|
||||||
/// Gets the parsed command-line option named [name] as `bool`.
|
/// Gets the parsed command-line option named [name] as `bool`.
|
||||||
bool boolArg(String name) => argResults[name] as bool;
|
bool boolArg(String name) => argResults?[name] as bool? ?? false;
|
||||||
|
|
||||||
/// Gets the parsed command-line option named [name] as `String`.
|
/// Gets the parsed command-line option named [name] as `String`.
|
||||||
String stringArg(String name) => argResults[name] as String;
|
String? stringArg(String name) => argResults?[name] as String?;
|
||||||
|
|
||||||
/// Gets the parsed command-line option named [name] as `List<String>`.
|
/// Gets the parsed command-line option named [name] as `List<String>`.
|
||||||
List<String> stringsArg(String name) => argResults[name] as List<String>;
|
List<String> stringsArg(String name) => argResults?[name] as List<String>? ?? <String>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mixin which applies an implementation of [requiredArtifacts] that only
|
/// A mixin which applies an implementation of [requiredArtifacts] that only
|
||||||
@ -1460,7 +1460,7 @@ mixin DeviceBasedDevelopmentArtifacts on FlutterCommand {
|
|||||||
// If there are no attached devices, use the default configuration.
|
// If there are no attached devices, use the default configuration.
|
||||||
// Otherwise, only add development artifacts which correspond to a
|
// Otherwise, only add development artifacts which correspond to a
|
||||||
// connected device.
|
// connected device.
|
||||||
final List<Device> devices = await globals.deviceManager.getDevices();
|
final List<Device> devices = await globals.deviceManager!.getDevices();
|
||||||
if (devices.isEmpty) {
|
if (devices.isEmpty) {
|
||||||
return super.requiredArtifacts;
|
return super.requiredArtifacts;
|
||||||
}
|
}
|
||||||
@ -1469,7 +1469,7 @@ mixin DeviceBasedDevelopmentArtifacts on FlutterCommand {
|
|||||||
};
|
};
|
||||||
for (final Device device in devices) {
|
for (final Device device in devices) {
|
||||||
final TargetPlatform targetPlatform = await device.targetPlatform;
|
final TargetPlatform targetPlatform = await device.targetPlatform;
|
||||||
final DevelopmentArtifact developmentArtifact = artifactFromTargetPlatform(targetPlatform);
|
final DevelopmentArtifact? developmentArtifact = artifactFromTargetPlatform(targetPlatform);
|
||||||
if (developmentArtifact != null) {
|
if (developmentArtifact != null) {
|
||||||
artifacts.add(developmentArtifact);
|
artifacts.add(developmentArtifact);
|
||||||
}
|
}
|
||||||
@ -1481,7 +1481,7 @@ mixin DeviceBasedDevelopmentArtifacts on FlutterCommand {
|
|||||||
// Returns the development artifact for the target platform, or null
|
// Returns the development artifact for the target platform, or null
|
||||||
// if none is supported
|
// if none is supported
|
||||||
@protected
|
@protected
|
||||||
DevelopmentArtifact artifactFromTargetPlatform(TargetPlatform targetPlatform) {
|
DevelopmentArtifact? artifactFromTargetPlatform(TargetPlatform targetPlatform) {
|
||||||
switch (targetPlatform) {
|
switch (targetPlatform) {
|
||||||
case TargetPlatform.android:
|
case TargetPlatform.android:
|
||||||
case TargetPlatform.android_arm:
|
case TargetPlatform.android_arm:
|
||||||
@ -1518,7 +1518,6 @@ DevelopmentArtifact artifactFromTargetPlatform(TargetPlatform targetPlatform) {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if s is either null, empty or is solely made of whitespace characters (as defined by String.trim).
|
/// Returns true if s is either null, empty or is solely made of whitespace characters (as defined by String.trim).
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
// @dart = 2.8
|
|
||||||
|
|
||||||
import 'package:args/args.dart';
|
import 'package:args/args.dart';
|
||||||
import 'package:args/command_runner.dart';
|
import 'package:args/command_runner.dart';
|
||||||
import 'package:completion/completion.dart';
|
import 'package:completion/completion.dart';
|
||||||
@ -45,14 +43,12 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
argParser.addFlag('prefixed-errors',
|
argParser.addFlag('prefixed-errors',
|
||||||
negatable: false,
|
negatable: false,
|
||||||
help: 'Causes lines sent to stderr to be prefixed with "ERROR:".',
|
help: 'Causes lines sent to stderr to be prefixed with "ERROR:".',
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp);
|
||||||
defaultsTo: false);
|
|
||||||
argParser.addFlag('quiet',
|
argParser.addFlag('quiet',
|
||||||
negatable: false,
|
negatable: false,
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
help: 'Reduce the amount of output from some commands.');
|
help: 'Reduce the amount of output from some commands.');
|
||||||
argParser.addFlag('wrap',
|
argParser.addFlag('wrap',
|
||||||
negatable: true,
|
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
help: 'Toggles output word wrapping, regardless of whether or not the output is a terminal.',
|
help: 'Toggles output word wrapping, regardless of whether or not the output is a terminal.',
|
||||||
defaultsTo: true);
|
defaultsTo: true);
|
||||||
@ -60,8 +56,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
help: 'Sets the output wrap column. If not set, uses the width of the terminal. No '
|
help: 'Sets the output wrap column. If not set, uses the width of the terminal. No '
|
||||||
'wrapping occurs if not writing to a terminal. Use "--no-wrap" to turn off wrapping '
|
'wrapping occurs if not writing to a terminal. Use "--no-wrap" to turn off wrapping '
|
||||||
'when connected to a terminal.',
|
'when connected to a terminal.');
|
||||||
defaultsTo: null);
|
|
||||||
argParser.addOption('device-id',
|
argParser.addOption('device-id',
|
||||||
abbr: 'd',
|
abbr: 'd',
|
||||||
help: 'Target device id or name (prefixes allowed).');
|
help: 'Target device id or name (prefixes allowed).');
|
||||||
@ -73,12 +68,10 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
help: 'When used with the "--version" flag, outputs the information using JSON.');
|
help: 'When used with the "--version" flag, outputs the information using JSON.');
|
||||||
argParser.addFlag('color',
|
argParser.addFlag('color',
|
||||||
negatable: true,
|
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
help: 'Whether to use terminal colors (requires support for ANSI escape sequences).',
|
help: 'Whether to use terminal colors (requires support for ANSI escape sequences).',
|
||||||
defaultsTo: true);
|
defaultsTo: true);
|
||||||
argParser.addFlag('version-check',
|
argParser.addFlag('version-check',
|
||||||
negatable: true,
|
|
||||||
defaultsTo: true,
|
defaultsTo: true,
|
||||||
hide: !verboseHelp,
|
hide: !verboseHelp,
|
||||||
help: 'Allow Flutter to check for updates when this command runs.');
|
help: 'Allow Flutter to check for updates when this command runs.');
|
||||||
@ -158,12 +151,12 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
usageException(error.message);
|
usageException(error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Command<void> command = commands[error.commands.first];
|
Command<void>? command = commands[error.commands.first];
|
||||||
for (final String commandName in error.commands.skip(1)) {
|
for (final String commandName in error.commands.skip(1)) {
|
||||||
command = command.subcommands[commandName];
|
command = command?.subcommands[commandName];
|
||||||
}
|
}
|
||||||
|
|
||||||
command.usageException(error.message);
|
command!.usageException(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,12 +177,12 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> runCommand(ArgResults topLevelResults) async {
|
Future<void> runCommand(ArgResults topLevelResults) async {
|
||||||
final Map<Type, dynamic> contextOverrides = <Type, dynamic>{};
|
final Map<Type, Object?> contextOverrides = <Type, Object?>{};
|
||||||
|
|
||||||
// Don't set wrapColumns unless the user said to: if it's set, then all
|
// Don't set wrapColumns unless the user said to: if it's set, then all
|
||||||
// wrapping will occur at this width explicitly, and won't adapt if the
|
// wrapping will occur at this width explicitly, and won't adapt if the
|
||||||
// terminal size changes during a run.
|
// terminal size changes during a run.
|
||||||
int wrapColumn;
|
int? wrapColumn;
|
||||||
if (topLevelResults.wasParsed('wrap-column')) {
|
if (topLevelResults.wasParsed('wrap-column')) {
|
||||||
try {
|
try {
|
||||||
wrapColumn = int.parse(topLevelResults['wrap-column'] as String);
|
wrapColumn = int.parse(topLevelResults['wrap-column'] as String);
|
||||||
@ -208,53 +201,53 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
: globals.stdio.terminalColumns != null && topLevelResults['wrap'] as bool;
|
: globals.stdio.terminalColumns != null && topLevelResults['wrap'] as bool;
|
||||||
contextOverrides[OutputPreferences] = OutputPreferences(
|
contextOverrides[OutputPreferences] = OutputPreferences(
|
||||||
wrapText: useWrapping,
|
wrapText: useWrapping,
|
||||||
showColor: topLevelResults['color'] as bool,
|
showColor: topLevelResults['color'] as bool?,
|
||||||
wrapColumn: wrapColumn,
|
wrapColumn: wrapColumn,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (topLevelResults['show-test-device'] as bool ||
|
if ((topLevelResults['show-test-device'] as bool?) == true ||
|
||||||
topLevelResults['device-id'] == FlutterTesterDevices.kTesterDeviceId) {
|
topLevelResults['device-id'] == FlutterTesterDevices.kTesterDeviceId) {
|
||||||
FlutterTesterDevices.showFlutterTesterDevice = true;
|
FlutterTesterDevices.showFlutterTesterDevice = true;
|
||||||
}
|
}
|
||||||
if (topLevelResults['show-web-server-device'] as bool ||
|
if ((topLevelResults['show-web-server-device'] as bool?) == true ||
|
||||||
topLevelResults['device-id'] == WebServerDevice.kWebServerDeviceId) {
|
topLevelResults['device-id'] == WebServerDevice.kWebServerDeviceId) {
|
||||||
WebServerDevice.showWebServerDevice = true;
|
WebServerDevice.showWebServerDevice = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the tooling configuration.
|
// Set up the tooling configuration.
|
||||||
final EngineBuildPaths engineBuildPaths = await globals.localEngineLocator.findEnginePath(
|
final EngineBuildPaths? engineBuildPaths = await globals.localEngineLocator?.findEnginePath(
|
||||||
topLevelResults['local-engine-src-path'] as String,
|
topLevelResults['local-engine-src-path'] as String?,
|
||||||
topLevelResults['local-engine'] as String,
|
topLevelResults['local-engine'] as String?,
|
||||||
topLevelResults['packages'] as String,
|
topLevelResults['packages'] as String?,
|
||||||
);
|
);
|
||||||
if (engineBuildPaths != null) {
|
if (engineBuildPaths != null) {
|
||||||
contextOverrides.addAll(<Type, dynamic>{
|
contextOverrides.addAll(<Type, Object?>{
|
||||||
Artifacts: Artifacts.getLocalEngine(engineBuildPaths),
|
Artifacts: Artifacts.getLocalEngine(engineBuildPaths),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.run<void>(
|
await context.run<void>(
|
||||||
overrides: contextOverrides.map<Type, Generator>((Type type, dynamic value) {
|
overrides: contextOverrides.map<Type, Generator>((Type type, Object? value) {
|
||||||
return MapEntry<Type, Generator>(type, () => value);
|
return MapEntry<Type, Generator>(type, () => value);
|
||||||
}),
|
}),
|
||||||
body: () async {
|
body: () async {
|
||||||
globals.logger.quiet = topLevelResults['quiet'] as bool;
|
globals.logger.quiet = (topLevelResults['quiet'] as bool?) == true;
|
||||||
|
|
||||||
if (globals.platform.environment['FLUTTER_ALREADY_LOCKED'] != 'true') {
|
if (globals.platform.environment['FLUTTER_ALREADY_LOCKED'] != 'true') {
|
||||||
await globals.cache.lock();
|
await globals.cache.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topLevelResults['suppress-analytics'] as bool) {
|
if ((topLevelResults['suppress-analytics'] as bool?) == true) {
|
||||||
globals.flutterUsage.suppressAnalytics = true;
|
globals.flutterUsage.suppressAnalytics = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
globals.flutterVersion.ensureVersionFile();
|
globals.flutterVersion.ensureVersionFile();
|
||||||
final bool machineFlag = topLevelResults['machine'] as bool;
|
final bool machineFlag = topLevelResults['machine'] as bool? ?? false;
|
||||||
final bool ci = await globals.botDetector.isRunningOnBot;
|
final bool ci = await globals.botDetector.isRunningOnBot;
|
||||||
final bool redirectedCompletion = !globals.stdio.hasTerminal &&
|
final bool redirectedCompletion = !globals.stdio.hasTerminal &&
|
||||||
(topLevelResults.command?.name ?? '').endsWith('-completion');
|
(topLevelResults.command?.name ?? '').endsWith('-completion');
|
||||||
final bool isMachine = machineFlag || ci || redirectedCompletion;
|
final bool isMachine = machineFlag || ci || redirectedCompletion;
|
||||||
final bool versionCheckFlag = topLevelResults['version-check'] as bool;
|
final bool versionCheckFlag = topLevelResults['version-check'] as bool? ?? false;
|
||||||
final bool explicitVersionCheckPassed = topLevelResults.wasParsed('version-check') && versionCheckFlag;
|
final bool explicitVersionCheckPassed = topLevelResults.wasParsed('version-check') && versionCheckFlag;
|
||||||
|
|
||||||
if (topLevelResults.command?.name != 'upgrade' &&
|
if (topLevelResults.command?.name != 'upgrade' &&
|
||||||
@ -263,16 +256,16 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if the user specified a specific device.
|
// See if the user specified a specific device.
|
||||||
globals.deviceManager.specifiedDeviceId = topLevelResults['device-id'] as String;
|
globals.deviceManager?.specifiedDeviceId = topLevelResults['device-id'] as String?;
|
||||||
|
|
||||||
if (topLevelResults['version'] as bool) {
|
if ((topLevelResults['version'] as bool?) == true) {
|
||||||
globals.flutterUsage.sendCommand('version');
|
globals.flutterUsage.sendCommand('version');
|
||||||
globals.flutterVersion.fetchTagsAndUpdate();
|
globals.flutterVersion.fetchTagsAndUpdate();
|
||||||
String status;
|
String status;
|
||||||
if (machineFlag) {
|
if (machineFlag) {
|
||||||
final Map<String, Object> jsonOut = globals.flutterVersion.toJson();
|
final Map<String, Object> jsonOut = globals.flutterVersion.toJson();
|
||||||
if (jsonOut != null) {
|
if (jsonOut != null) {
|
||||||
jsonOut['flutterRoot'] = Cache.flutterRoot;
|
jsonOut['flutterRoot'] = Cache.flutterRoot!;
|
||||||
}
|
}
|
||||||
status = const JsonEncoder.withIndent(' ').convert(jsonOut);
|
status = const JsonEncoder.withIndent(' ').convert(jsonOut);
|
||||||
} else {
|
} else {
|
||||||
@ -292,7 +285,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
|
|
||||||
/// Get the root directories of the repo - the directories containing Dart packages.
|
/// Get the root directories of the repo - the directories containing Dart packages.
|
||||||
List<String> getRepoRoots() {
|
List<String> getRepoRoots() {
|
||||||
final String root = globals.fs.path.absolute(Cache.flutterRoot);
|
final String root = globals.fs.path.absolute(Cache.flutterRoot!);
|
||||||
// not bin, and not the root
|
// not bin, and not the root
|
||||||
return <String>['dev', 'examples', 'packages'].map<String>((String item) {
|
return <String>['dev', 'examples', 'packages'].map<String>((String item) {
|
||||||
return globals.fs.path.join(root, item);
|
return globals.fs.path.join(root, item);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user