Unverified Commit ce318b7b authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

All arguments must be documented. (#75888)

parent 696e4f70
...@@ -80,7 +80,7 @@ add_custom_command( ...@@ -80,7 +80,7 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E env COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT} ${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
linux-x64 ${CMAKE_BUILD_TYPE} ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
VERBATIM VERBATIM
) )
add_custom_target(flutter_assemble DEPENDS add_custom_target(flutter_assemble DEPENDS
......
...@@ -89,96 +89,108 @@ Future<void> main(List<String> args) async { ...@@ -89,96 +89,108 @@ Future<void> main(List<String> args) async {
userMessages: UserMessages(), userMessages: UserMessages(),
); );
await runner.run(args, () => <FlutterCommand>[ await runner.run(
AnalyzeCommand( args,
() => generateCommands(
verboseHelp: verboseHelp, verboseHelp: verboseHelp,
fileSystem: globals.fs, verbose: verbose,
platform: globals.platform,
processManager: globals.processManager,
logger: globals.logger,
terminal: globals.terminal,
artifacts: globals.artifacts,
), ),
AssembleCommand(), verbose: verbose,
AttachCommand(verboseHelp: verboseHelp), muteCommandLogging: muteCommandLogging,
BuildCommand(verboseHelp: verboseHelp), verboseHelp: verboseHelp,
ChannelCommand(verboseHelp: verboseHelp), overrides: <Type, Generator>{
CleanCommand(verbose: verbose), // The web runner is not supported in google3 because it depends
ConfigCommand(verboseHelp: verboseHelp), // on dwds.
CreateCommand(), WebRunnerFactory: () => DwdsWebRunnerFactory(),
DaemonCommand(hidden: !verboseHelp), // The mustache dependency is different in google3
DevicesCommand(), TemplateRenderer: () => const MustacheTemplateRenderer(),
DoctorCommand(verbose: verbose), // The devtools launcher is not supported in google3 because it depends on
DowngradeCommand(), // devtools source code.
DriveCommand(verboseHelp: verboseHelp, DevtoolsLauncher: () => DevtoolsServerLauncher(
fileSystem: globals.fs, processManager: globals.processManager,
logger: globals.logger, pubExecutable: globals.artifacts.getArtifactPath(Artifact.pubExecutable),
), logger: globals.logger,
EmulatorsCommand(), platform: globals.platform,
FormatCommand(), persistentToolState: globals.persistentToolState,
GenerateCommand(), ),
GenerateLocalizationsCommand( Logger: () {
fileSystem: globals.fs, final LoggerFactory loggerFactory = LoggerFactory(
logger: globals.logger, outputPreferences: globals.outputPreferences,
), terminal: globals.terminal,
InstallCommand(), stdio: globals.stdio,
LogsCommand(), );
MakeHostAppEditableCommand(), return loggerFactory.createLogger(
PackagesCommand(), daemon: daemon,
PrecacheCommand( machine: runMachine,
verboseHelp: verboseHelp, verbose: verbose && !muteCommandLogging,
cache: globals.cache, prefixedErrors: prefixedErrors,
logger: globals.logger, windows: globals.platform.isWindows,
platform: globals.platform, );
featureFlags: featureFlags, },
), },
RunCommand(verboseHelp: verboseHelp), );
ScreenshotCommand(),
ShellCompletionCommand(),
TestCommand(verboseHelp: verboseHelp),
UpgradeCommand(),
SymbolizeCommand(
stdio: globals.stdio,
fileSystem: globals.fs,
),
// Development-only commands. These are always hidden,
IdeConfigCommand(),
UpdatePackagesCommand(),
], verbose: verbose,
muteCommandLogging: muteCommandLogging,
verboseHelp: verboseHelp,
overrides: <Type, Generator>{
// The web runner is not supported in google3 because it depends
// on dwds.
WebRunnerFactory: () => DwdsWebRunnerFactory(),
// The mustache dependency is different in google3
TemplateRenderer: () => const MustacheTemplateRenderer(),
// The devtools launcher is not supported in google3 because it depends on
// devtools source code.
DevtoolsLauncher: () => DevtoolsServerLauncher(
processManager: globals.processManager,
pubExecutable: globals.artifacts.getArtifactPath(Artifact.pubExecutable),
logger: globals.logger,
platform: globals.platform,
persistentToolState: globals.persistentToolState,
),
Logger: () {
final LoggerFactory loggerFactory = LoggerFactory(
outputPreferences: globals.outputPreferences,
terminal: globals.terminal,
stdio: globals.stdio,
);
return loggerFactory.createLogger(
daemon: daemon,
machine: runMachine,
verbose: verbose && !muteCommandLogging,
prefixedErrors: prefixedErrors,
windows: globals.platform.isWindows,
);
}
});
} }
List<FlutterCommand> generateCommands({
@required bool verboseHelp,
@required bool verbose,
}) => <FlutterCommand>[
AnalyzeCommand(
verboseHelp: verboseHelp,
fileSystem: globals.fs,
platform: globals.platform,
processManager: globals.processManager,
logger: globals.logger,
terminal: globals.terminal,
artifacts: globals.artifacts,
),
AssembleCommand(verboseHelp: verboseHelp),
AttachCommand(verboseHelp: verboseHelp),
BuildCommand(verboseHelp: verboseHelp),
ChannelCommand(verboseHelp: verboseHelp),
CleanCommand(verbose: verbose),
ConfigCommand(verboseHelp: verboseHelp),
CreateCommand(verboseHelp: verboseHelp),
DaemonCommand(hidden: !verboseHelp),
DevicesCommand(verboseHelp: verboseHelp),
DoctorCommand(verbose: verbose),
DowngradeCommand(verboseHelp: verboseHelp),
DriveCommand(verboseHelp: verboseHelp,
fileSystem: globals.fs,
logger: globals.logger,
),
EmulatorsCommand(),
FormatCommand(),
GenerateCommand(),
GenerateLocalizationsCommand(
fileSystem: globals.fs,
logger: globals.logger,
),
InstallCommand(),
LogsCommand(),
MakeHostAppEditableCommand(),
PackagesCommand(),
PrecacheCommand(
verboseHelp: verboseHelp,
cache: globals.cache,
logger: globals.logger,
platform: globals.platform,
featureFlags: featureFlags,
),
RunCommand(verboseHelp: verboseHelp),
ScreenshotCommand(),
ShellCompletionCommand(),
TestCommand(verboseHelp: verboseHelp),
UpgradeCommand(verboseHelp: verboseHelp),
SymbolizeCommand(
stdio: globals.stdio,
fileSystem: globals.fs,
),
// Development-only commands. These are always hidden,
IdeConfigCommand(),
UpdatePackagesCommand(),
];
/// An abstraction for instantiation of the correct logger type. /// An abstraction for instantiation of the correct logger type.
/// ///
/// Our logger class hierarchy and runtime requirements are overly complicated. /// Our logger class hierarchy and runtime requirements are overly complicated.
......
...@@ -25,9 +25,6 @@ import 'src/runner/flutter_command.dart'; ...@@ -25,9 +25,6 @@ import 'src/runner/flutter_command.dart';
import 'src/runner/flutter_command_runner.dart'; import 'src/runner/flutter_command_runner.dart';
/// Runs the Flutter tool with support for the specified list of [commands]. /// Runs the Flutter tool with support for the specified list of [commands].
///
/// [commands] must be either `List<FlutterCommand>` or `List<FlutterCommand> Function()`.
// TODO(jonahwilliams): update command type once g3 has rolled.
Future<int> run( Future<int> run(
List<String> args, List<String> args,
List<FlutterCommand> Function() commands, { List<FlutterCommand> Function() commands, {
......
...@@ -42,14 +42,14 @@ class AnalyzeCommand extends FlutterCommand { ...@@ -42,14 +42,14 @@ class AnalyzeCommand extends FlutterCommand {
argParser.addFlag('dartdocs', argParser.addFlag('dartdocs',
negatable: false, negatable: false,
help: 'List every public member that is lacking documentation. ' help: 'List every public member that is lacking documentation. '
'(The public_member_api_docs lint must be enabled in analysis_options.yaml)', '(The "public_member_api_docs" lint must be enabled in "analysis_options.yaml".)',
hide: !verboseHelp); hide: !verboseHelp);
argParser.addFlag('watch', argParser.addFlag('watch',
help: 'Run analysis continuously, watching the filesystem for changes.', help: 'Run analysis continuously, watching the filesystem for changes.',
negatable: false); negatable: false);
argParser.addOption('write', argParser.addOption('write',
valueHelp: 'file', valueHelp: 'file',
help: 'Also output the results to a file. This is useful with --watch ' help: 'Also output the results to a file. This is useful with "--watch" '
'if you want a file to always contain the latest results.'); 'if you want a file to always contain the latest results.');
argParser.addOption('dart-sdk', argParser.addOption('dart-sdk',
valueHelp: 'path-to-sdk', valueHelp: 'path-to-sdk',
...@@ -67,13 +67,13 @@ class AnalyzeCommand extends FlutterCommand { ...@@ -67,13 +67,13 @@ class AnalyzeCommand extends FlutterCommand {
// Not used by analyze --watch // Not used by analyze --watch
argParser.addFlag('congratulate', argParser.addFlag('congratulate',
help: 'Show output even when there are no errors, warnings, hints, or lints. ' help: 'Show output even when there are no errors, warnings, hints, or lints. '
'Ignored if --watch is specified.', 'Ignored if "--watch" is specified.',
defaultsTo: true); defaultsTo: true);
argParser.addFlag('preamble', argParser.addFlag('preamble',
defaultsTo: true, defaultsTo: true,
help: 'When analyzing the flutter repository, display the number of ' help: 'When analyzing the flutter repository, display the number of '
'files that will be analyzed.\n' 'files that will be analyzed.\n'
'Ignored if --watch is specified.'); 'Ignored if "--watch" is specified.');
argParser.addFlag('fatal-infos', argParser.addFlag('fatal-infos',
negatable: true, negatable: true,
help: 'Treat info level issues as fatal.', help: 'Treat info level issues as fatal.',
......
...@@ -73,14 +73,20 @@ const List<Target> _kDefaultTargets = <Target>[ ...@@ -73,14 +73,20 @@ const List<Target> _kDefaultTargets = <Target>[
ReleaseBundleWindowsAssets(), ReleaseBundleWindowsAssets(),
]; ];
// TODO(ianh): https://github.com/dart-lang/args/issues/181 will allow us to remove useLegacyNames
// and just switch to arguments that use the regular style, which still supporting the old names.
// When fixing this, remove the hack in test/general.shard/args_test.dart that ignores these names.
const bool useLegacyNames = true;
/// Assemble provides a low level API to interact with the flutter tool build /// Assemble provides a low level API to interact with the flutter tool build
/// system. /// system.
class AssembleCommand extends FlutterCommand { class AssembleCommand extends FlutterCommand {
AssembleCommand() { AssembleCommand({ bool verboseHelp = false }) {
argParser.addMultiOption( argParser.addMultiOption(
'define', 'define',
abbr: 'd', abbr: 'd',
help: 'Allows passing configuration to a target with --define=target=key=value.', valueHelp: 'target=key=value',
help: 'Allows passing configuration to a target, as in "--define=target=key=value".',
); );
argParser.addOption( argParser.addOption(
'performance-measurement-file', 'performance-measurement-file',
...@@ -89,28 +95,28 @@ class AssembleCommand extends FlutterCommand { ...@@ -89,28 +95,28 @@ class AssembleCommand extends FlutterCommand {
argParser.addMultiOption( argParser.addMultiOption(
'input', 'input',
abbr: 'i', abbr: 'i',
help: 'Allows passing additional inputs with --input=key=value. Unlike ' help: 'Allows passing additional inputs with "--input=key=value". Unlike '
'defines, additional inputs do not generate a new configuration, instead ' 'defines, additional inputs do not generate a new configuration; instead '
'they are treated as dependencies of the targets that use them.' 'they are treated as dependencies of the targets that use them.'
); );
argParser.addOption('depfile', help: 'A file path where a depfile will be written. ' argParser.addOption('depfile',
'This contains all build inputs and outputs in a make style syntax' help: 'A file path where a depfile will be written. '
'This contains all build inputs and outputs in a Make-style syntax.'
); );
argParser.addOption('build-inputs', help: 'A file path where a newline ' argParser.addOption('build-inputs', help: 'A file path where a newline-separated '
'separated file containing all inputs used will be written after a build.' 'file containing all inputs used will be written after a build. '
' This file is not included as a build input or output. This file is not' 'This file is not included as a build input or output. This file is not '
' written if the build fails for any reason.'); 'written if the build fails for any reason.');
argParser.addOption('build-outputs', help: 'A file path where a newline ' argParser.addOption('build-outputs', help: 'A file path where a newline-separated '
'separated file containing all outputs used will be written after a build.' 'file containing all outputs created will be written after a build. '
' This file is not included as a build input or output. This file is not' 'This file is not included as a build input or output. This file is not '
' written if the build fails for any reason.'); 'written if the build fails for any reason.');
argParser.addOption('output', abbr: 'o', help: 'A directory where output ' argParser.addOption('output', abbr: 'o', help: 'A directory where output '
'files will be written. Must be either absolute or relative from the ' 'files will be written. Must be either absolute or relative from the '
'root of the current Flutter project.', 'root of the current Flutter project.',
); );
argParser.addOption(kExtraGenSnapshotOptions); usesExtraDartFlagOptions(verboseHelp: verboseHelp, useLegacyNames: useLegacyNames);
argParser.addOption(kExtraFrontEndOptions); usesDartDefineOption(useLegacyNames: useLegacyNames);
argParser.addOption(kDartDefines);
argParser.addOption( argParser.addOption(
'resource-pool-size', 'resource-pool-size',
help: 'The maximum number of concurrent tasks the build system will run.', help: 'The maximum number of concurrent tasks the build system will run.',
...@@ -205,15 +211,14 @@ class AssembleCommand extends FlutterCommand { ...@@ -205,15 +211,14 @@ class AssembleCommand extends FlutterCommand {
final String value = chunk.substring(indexEquals + 1); final String value = chunk.substring(indexEquals + 1);
results[key] = value; results[key] = value;
} }
// Workaround for extraGenSnapshot formatting. if (argResults.wasParsed(useLegacyNames ? kExtraGenSnapshotOptions : FlutterOptions.kExtraGenSnapshotOptions)) {
if (argResults.wasParsed(kExtraGenSnapshotOptions)) { results[kExtraGenSnapshotOptions] = (argResults[useLegacyNames ? kExtraGenSnapshotOptions : FlutterOptions.kExtraGenSnapshotOptions] as List<String>).join(',');
results[kExtraGenSnapshotOptions] = argResults[kExtraGenSnapshotOptions] as String;
} }
if (argResults.wasParsed(kDartDefines)) { if (argResults.wasParsed(useLegacyNames ? kDartDefines : FlutterOptions.kDartDefinesOption)) {
results[kDartDefines] = argResults[kDartDefines] as String; results[kDartDefines] = (argResults[useLegacyNames ? kDartDefines : FlutterOptions.kDartDefinesOption] as List<String>).join(',');
} }
if (argResults.wasParsed(kExtraFrontEndOptions)) { if (argResults.wasParsed(useLegacyNames ? kExtraFrontEndOptions : FlutterOptions.kExtraFrontEndOptions)) {
results[kExtraFrontEndOptions] = argResults[kExtraFrontEndOptions] as String; results[kExtraFrontEndOptions] = (argResults[useLegacyNames ? kExtraFrontEndOptions : FlutterOptions.kExtraFrontEndOptions] as List<String>).join(',');
} }
return results; return results;
} }
......
...@@ -59,10 +59,10 @@ import '../vmservice.dart'; ...@@ -59,10 +59,10 @@ import '../vmservice.dart';
/// also be provided. /// also be provided.
class AttachCommand extends FlutterCommand { class AttachCommand extends FlutterCommand {
AttachCommand({bool verboseHelp = false, this.hotRunnerFactory}) { AttachCommand({bool verboseHelp = false, this.hotRunnerFactory}) {
addBuildModeFlags(defaultToRelease: false, excludeRelease: true); addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false, excludeRelease: true);
usesTargetOption(); usesTargetOption();
usesPortOptions(); usesPortOptions(verboseHelp: verboseHelp);
usesIpv6Flag(); usesIpv6Flag(verboseHelp: verboseHelp);
usesFilesystemOptions(hide: !verboseHelp); usesFilesystemOptions(hide: !verboseHelp);
usesFuchsiaOptions(hide: !verboseHelp); usesFuchsiaOptions(hide: !verboseHelp);
usesDartDefineOption(); usesDartDefineOption();
...@@ -73,13 +73,13 @@ class AttachCommand extends FlutterCommand { ...@@ -73,13 +73,13 @@ class AttachCommand extends FlutterCommand {
..addOption( ..addOption(
'debug-port', 'debug-port',
hide: !verboseHelp, hide: !verboseHelp,
help: 'Device port where the observatory is listening. Requires ' help: '(deprecated) Device port where the observatory is listening. Requires '
'--disable-service-auth-codes to also be provided to the Flutter ' '"--disable-service-auth-codes" to also be provided to the Flutter '
'application at launch, otherwise this command will fail to connect to ' 'application at launch, otherwise this command will fail to connect to '
'the application. In general, --debug-uri should be used instead.', 'the application. In general, "--debug-uri" should be used instead.',
)..addOption( )..addOption(
'debug-uri', 'debug-uri', // TODO(ianh): we should support --debug-url as well (leaving this as an alias).
help: 'The URI at which the observatory is listening.', help: 'The URL at which the observatory is listening.',
)..addOption( )..addOption(
'app-id', 'app-id',
help: 'The package name (Android) or bundle identifier (iOS) for the app. ' help: 'The package name (Android) or bundle identifier (iOS) for the app. '
...@@ -99,7 +99,7 @@ class AttachCommand extends FlutterCommand { ...@@ -99,7 +99,7 @@ class AttachCommand extends FlutterCommand {
'report-ready', 'report-ready',
help: 'Print "ready" to the console after handling a keyboard command.\n' help: 'Print "ready" to the console after handling a keyboard command.\n'
'This is primarily useful for tests and other automation, but consider ' 'This is primarily useful for tests and other automation, but consider '
'using --machine instead.', 'using "--machine" instead.',
hide: !verboseHelp, hide: !verboseHelp,
)..addOption( )..addOption(
'project-root', 'project-root',
...@@ -417,8 +417,8 @@ known, it can be explicitly provided to attach via the command-line, e.g. ...@@ -417,8 +417,8 @@ known, it can be explicitly provided to attach via the command-line, e.g.
final FlutterDevice flutterDevice = await FlutterDevice.create( final FlutterDevice flutterDevice = await FlutterDevice.create(
device, device,
fileSystemRoots: stringsArg('filesystem-root'), fileSystemRoots: stringsArg(FlutterOptions.kFileSystemRoot),
fileSystemScheme: stringArg('filesystem-scheme'), fileSystemScheme: stringArg(FlutterOptions.kFileSystemScheme),
target: targetFile, target: targetFile,
targetModel: TargetModel(stringArg('target-model')), targetModel: TargetModel(stringArg('target-model')),
buildInfo: buildInfo, buildInfo: buildInfo,
......
...@@ -58,7 +58,7 @@ class BuildAarCommand extends BuildSubCommand { ...@@ -58,7 +58,7 @@ class BuildAarCommand extends BuildSubCommand {
..addOption( ..addOption(
'output-dir', 'output-dir',
help: 'The absolute path to the directory where the repository is generated. ' help: 'The absolute path to the directory where the repository is generated. '
"By default, this is '<current-directory>android/build'. ", 'By default, this is "<current-directory>android/build".',
); );
} }
......
...@@ -24,11 +24,11 @@ class BuildApkCommand extends BuildSubCommand { ...@@ -24,11 +24,11 @@ class BuildApkCommand extends BuildSubCommand {
usesPubOption(); usesPubOption();
usesBuildNumberOption(); usesBuildNumberOption();
usesBuildNameOption(); usesBuildNameOption();
addShrinkingFlag(); addShrinkingFlag(verboseHelp: verboseHelp);
addSplitDebugInfoOption(); addSplitDebugInfoOption();
addDartObfuscationOption(); addDartObfuscationOption();
usesDartDefineOption(); usesDartDefineOption();
usesExtraDartFlagOptions(); usesExtraDartFlagOptions(verboseHelp: verboseHelp);
addBundleSkSLPathOption(hide: !verboseHelp); addBundleSkSLPathOption(hide: !verboseHelp);
addEnableExperimentation(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp);
addBuildPerformanceFile(hide: !verboseHelp); addBuildPerformanceFile(hide: !verboseHelp);
......
...@@ -19,16 +19,16 @@ class BuildAppBundleCommand extends BuildSubCommand { ...@@ -19,16 +19,16 @@ class BuildAppBundleCommand extends BuildSubCommand {
BuildAppBundleCommand({bool verboseHelp = false}) { BuildAppBundleCommand({bool verboseHelp = false}) {
addTreeShakeIconsFlag(); addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
addBuildModeFlags(); addBuildModeFlags(verboseHelp: verboseHelp);
usesFlavorOption(); usesFlavorOption();
usesPubOption(); usesPubOption();
usesBuildNumberOption(); usesBuildNumberOption();
usesBuildNameOption(); usesBuildNameOption();
addShrinkingFlag(); addShrinkingFlag(verboseHelp: verboseHelp);
addSplitDebugInfoOption(); addSplitDebugInfoOption();
addDartObfuscationOption(); addDartObfuscationOption();
usesDartDefineOption(); usesDartDefineOption();
usesExtraDartFlagOptions(); usesExtraDartFlagOptions(verboseHelp: verboseHelp);
addBundleSkSLPathOption(hide: !verboseHelp); addBundleSkSLPathOption(hide: !verboseHelp);
addBuildPerformanceFile(hide: !verboseHelp); addBuildPerformanceFile(hide: !verboseHelp);
usesTrackWidgetCreation(verboseHelp: verboseHelp); usesTrackWidgetCreation(verboseHelp: verboseHelp);
......
...@@ -11,7 +11,7 @@ import '../features.dart'; ...@@ -11,7 +11,7 @@ import '../features.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
import '../project.dart'; import '../project.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
import '../runner/flutter_command.dart' show FlutterCommandResult; import '../runner/flutter_command.dart';
import 'build.dart'; import 'build.dart';
class BuildBundleCommand extends BuildSubCommand { class BuildBundleCommand extends BuildSubCommand {
...@@ -21,9 +21,13 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -21,9 +21,13 @@ class BuildBundleCommand extends BuildSubCommand {
usesFilesystemOptions(hide: !verboseHelp); usesFilesystemOptions(hide: !verboseHelp);
usesBuildNumberOption(); usesBuildNumberOption();
addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false); addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false);
usesExtraDartFlagOptions(); usesExtraDartFlagOptions(verboseHelp: verboseHelp);
argParser argParser
..addOption('depfile', defaultsTo: defaultDepfilePath) ..addOption('depfile',
defaultsTo: defaultDepfilePath,
help: 'A file path where a depfile will be written. '
'This contains all build inputs and outputs in a Make-style syntax.'
)
..addOption('target-platform', ..addOption('target-platform',
defaultsTo: 'android-arm', defaultsTo: 'android-arm',
allowed: const <String>[ allowed: const <String>[
...@@ -37,8 +41,13 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -37,8 +41,13 @@ class BuildBundleCommand extends BuildSubCommand {
'linux-arm64', 'linux-arm64',
'windows-x64', 'windows-x64',
], ],
help: 'The architecture for which to build the application.',
) )
..addOption('asset-dir', defaultsTo: getAssetBuildDirectory()); ..addOption('asset-dir',
defaultsTo: getAssetBuildDirectory(),
help: 'The output directory for the kernel_blob.bin file, the native snapshet, the assets, etc. '
'Can be used to redirect the output when driving the Flutter toolchain from another build system.',
);
usesPubOption(); usesPubOption();
usesTrackWidgetCreation(verboseHelp: verboseHelp); usesTrackWidgetCreation(verboseHelp: verboseHelp);
...@@ -112,8 +121,8 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -112,8 +121,8 @@ class BuildBundleCommand extends BuildSubCommand {
trackWidgetCreation: boolArg('track-widget-creation'), trackWidgetCreation: boolArg('track-widget-creation'),
extraFrontEndOptions: buildInfo.extraFrontEndOptions, extraFrontEndOptions: buildInfo.extraFrontEndOptions,
extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions, extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions,
fileSystemScheme: stringArg('filesystem-scheme'), fileSystemRoots: stringsArg(FlutterOptions.kFileSystemRoot),
fileSystemRoots: stringsArg('filesystem-root'), fileSystemScheme: stringArg(FlutterOptions.kFileSystemScheme),
treeShakeIcons: buildInfo.treeShakeIcons, treeShakeIcons: buildInfo.treeShakeIcons,
); );
return FlutterCommandResult.success(); return FlutterCommandResult.success();
......
...@@ -173,7 +173,7 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand { ...@@ -173,7 +173,7 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand {
_BuildIOSSubCommand({ @required bool verboseHelp }) { _BuildIOSSubCommand({ @required bool verboseHelp }) {
addTreeShakeIconsFlag(); addTreeShakeIconsFlag();
addSplitDebugInfoOption(); addSplitDebugInfoOption();
addBuildModeFlags(defaultToRelease: true); addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: true);
usesTargetOption(); usesTargetOption();
usesFlavorOption(); usesFlavorOption();
usesPubOption(); usesPubOption();
...@@ -181,7 +181,7 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand { ...@@ -181,7 +181,7 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand {
usesBuildNameOption(); usesBuildNameOption();
addDartObfuscationOption(); addDartObfuscationOption();
usesDartDefineOption(); usesDartDefineOption();
usesExtraDartFlagOptions(); usesExtraDartFlagOptions(verboseHelp: verboseHelp);
addEnableExperimentation(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp);
addBuildPerformanceFile(hide: !verboseHelp); addBuildPerformanceFile(hide: !verboseHelp);
addBundleSkSLPathOption(hide: !verboseHelp); addBundleSkSLPathOption(hide: !verboseHelp);
......
...@@ -50,7 +50,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -50,7 +50,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
usesDartDefineOption(); usesDartDefineOption();
addSplitDebugInfoOption(); addSplitDebugInfoOption();
addDartObfuscationOption(); addDartObfuscationOption();
usesExtraDartFlagOptions(); usesExtraDartFlagOptions(verboseHelp: verboseHelp);
addNullSafetyModeOptions(hide: !verboseHelp); addNullSafetyModeOptions(hide: !verboseHelp);
addEnableExperimentation(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp);
...@@ -74,15 +74,15 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -74,15 +74,15 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
'By default, all build configurations are built.' 'By default, all build configurations are built.'
) )
..addFlag('universal', ..addFlag('universal',
help: '(Deprecated) Produce universal frameworks that include all valid architectures.', help: '(deprecated) Produce universal frameworks that include all valid architectures.',
negatable: true, negatable: true,
hide: true, hide: !verboseHelp,
) )
..addFlag('xcframework', ..addFlag('xcframework',
help: 'Produce xcframeworks that include all valid architectures.', help: 'Produce xcframeworks that include all valid architectures.',
negatable: false, negatable: false,
defaultsTo: true, defaultsTo: true,
hide: true, hide: !verboseHelp,
) )
..addFlag('cocoapods', ..addFlag('cocoapods',
help: 'Produce a Flutter.podspec instead of an engine Flutter.xcframework (recommended if host app uses CocoaPods).', help: 'Produce a Flutter.podspec instead of an engine Flutter.xcframework (recommended if host app uses CocoaPods).',
...@@ -94,8 +94,8 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -94,8 +94,8 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
) )
..addFlag('force', ..addFlag('force',
abbr: 'f', abbr: 'f',
help: 'Force Flutter.podspec creation on the master channel. For testing only.', help: 'Force Flutter.podspec creation on the master channel. This is only intended for testing the tool itself.',
hide: true hide: !verboseHelp,
); );
} }
......
...@@ -23,7 +23,7 @@ class BuildWebCommand extends BuildSubCommand { ...@@ -23,7 +23,7 @@ class BuildWebCommand extends BuildSubCommand {
addTreeShakeIconsFlag(enabledByDefault: false); addTreeShakeIconsFlag(enabledByDefault: false);
usesTargetOption(); usesTargetOption();
usesPubOption(); usesPubOption();
addBuildModeFlags(excludeDebug: true); addBuildModeFlags(verboseHelp: verboseHelp, excludeDebug: true);
usesDartDefineOption(); usesDartDefineOption();
usesWebRendererOption(); usesWebRendererOption();
addEnableExperimentation(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp);
...@@ -33,30 +33,31 @@ class BuildWebCommand extends BuildSubCommand { ...@@ -33,30 +33,31 @@ class BuildWebCommand extends BuildSubCommand {
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
help: 'Disable dynamic generation of code in the generated output. ' help: 'Disable dynamic generation of code in the generated output. '
'This is necessary to satisfy CSP restrictions (see http://www.w3.org/TR/CSP/).' 'This is necessary to satisfy CSP restrictions (see http://www.w3.org/TR/CSP/).'
); );
argParser.addFlag( argParser.addFlag(
'source-maps', 'source-maps',
defaultsTo: false, defaultsTo: false,
help: 'Whether to generate a sourcemap file. These can be used by browsers ' help: 'Generate a sourcemap file. These can be used by browsers '
'To view and debug the original source code of a compiled and minified Dart ' 'to view and debug the original source code of a compiled and minified Dart '
'application. Defaults to false (i.e. no sourcemaps produced).' 'application.'
); );
argParser.addOption('pwa-strategy', argParser.addOption('pwa-strategy',
defaultsTo: kOfflineFirst, defaultsTo: kOfflineFirst,
help: help: 'The caching strategy to be used by the PWA service worker.',
'The caching strategy to be used by the PWA service worker.\n'
'offline-first will attempt to cache the app shell eagerly and '
'then lazily cache all subsequent assets as they are loaded. When '
'making a network request for an asset, the offline cache will be '
'preferred.\n'
'none will generate a service worker with no body. This is useful for '
'local testing or in cases where the service worker caching functionality '
'is not desirable',
allowed: <String>[ allowed: <String>[
kOfflineFirst, kOfflineFirst,
kNoneWorker, kNoneWorker,
] ],
allowedHelp: <String, String>{
kOfflineFirst: 'Attempt to cache the application shell eagerly and '
'then lazily cache all subsequent assets as they are loaded. When '
'making a network request for an asset, the offline cache will be '
'preferred.',
kNoneWorker: 'Generate a service worker with no body. This is useful for '
'local testing or in cases where the service worker caching functionality '
'is not desirable',
},
); );
} }
......
...@@ -22,7 +22,7 @@ class ConfigCommand extends FlutterCommand { ...@@ -22,7 +22,7 @@ class ConfigCommand extends FlutterCommand {
help: 'Clear the saved development certificate choice used to sign apps for iOS device deployment.'); help: 'Clear the saved development certificate choice used to sign apps for iOS device deployment.');
argParser.addOption('android-sdk', help: 'The Android SDK directory.'); argParser.addOption('android-sdk', help: 'The Android SDK directory.');
argParser.addOption('android-studio-dir', help: 'The Android Studio install directory.'); argParser.addOption('android-studio-dir', help: 'The Android Studio install directory.');
argParser.addOption('build-dir', help: 'The relative path to override a projects build directory', argParser.addOption('build-dir', help: 'The relative path to override a projects build directory.',
valueHelp: 'out/'); valueHelp: 'out/');
argParser.addFlag('machine', argParser.addFlag('machine',
negatable: false, negatable: false,
......
...@@ -23,10 +23,12 @@ import '../runner/flutter_command.dart'; ...@@ -23,10 +23,12 @@ import '../runner/flutter_command.dart';
import 'create_base.dart'; import 'create_base.dart';
class CreateCommand extends CreateBase { class CreateCommand extends CreateBase {
CreateCommand() { CreateCommand({
bool verboseHelp = false,
}) : super(verboseHelp: verboseHelp) {
addPlatformsOptions(customHelp: 'The platforms supported by this project. ' addPlatformsOptions(customHelp: 'The platforms supported by this project. '
'This argument only works when the --template is set to app or plugin. '
'Platform folders (e.g. android/) will be generated in the target project. ' 'Platform folders (e.g. android/) will be generated in the target project. '
'This argument only works when "--template" is set to app or plugin. '
'When adding platforms to a plugin project, the pubspec.yaml will be updated with the requested platform. ' 'When adding platforms to a plugin project, the pubspec.yaml will be updated with the requested platform. '
'Adding desktop platforms requires the corresponding desktop config setting to be enabled.'); 'Adding desktop platforms requires the corresponding desktop config setting to be enabled.');
argParser.addOption( argParser.addOption(
...@@ -50,17 +52,17 @@ class CreateCommand extends CreateBase { ...@@ -50,17 +52,17 @@ class CreateCommand extends CreateBase {
argParser.addOption( argParser.addOption(
'sample', 'sample',
abbr: 's', abbr: 's',
help: 'Specifies the Flutter code sample to use as the main.dart for an application. Implies ' help: 'Specifies the Flutter code sample to use as the "main.dart" for an application. Implies '
'--template=app. The value should be the sample ID of the desired sample from the API ' '"--template=app". The value should be the sample ID of the desired sample from the API '
'documentation website (http://docs.flutter.dev). An example can be found at ' 'documentation website (http://docs.flutter.dev/). An example can be found at: '
'https://master-api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html', 'https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html',
defaultsTo: null, defaultsTo: null,
valueHelp: 'id', valueHelp: 'id',
); );
argParser.addOption( argParser.addOption(
'list-samples', 'list-samples',
help: 'Specifies a JSON output file for a listing of Flutter code samples ' help: 'Specifies a JSON output file for a listing of Flutter code samples '
'that can be created with --sample.', 'that can be created with "--sample".',
valueHelp: 'path', valueHelp: 'path',
); );
} }
...@@ -218,7 +220,7 @@ class CreateCommand extends CreateBase { ...@@ -218,7 +220,7 @@ class CreateCommand extends CreateBase {
if (boolArg('with-driver-test')) { if (boolArg('with-driver-test')) {
globals.printError( globals.printError(
'--with-driver-test has been deprecated and will no longer add a flutter ' 'The "--with-driver-test" argument has been deprecated and will no longer add a flutter '
'driver template. Instead, learn how to use package:integration_test by ' 'driver template. Instead, learn how to use package:integration_test by '
'visiting https://pub.dev/packages/integration_test .' 'visiting https://pub.dev/packages/integration_test .'
); );
......
...@@ -32,13 +32,15 @@ const List<String> _kAvailablePlatforms = <String>[ ...@@ -32,13 +32,15 @@ const List<String> _kAvailablePlatforms = <String>[
]; ];
const String _kDefaultPlatformArgumentHelp = const String _kDefaultPlatformArgumentHelp =
'Required: The platforms supported by this project. ' '(required) The platforms supported by this project. '
'Platform folders (e.g. android/) will be generated in the target project. ' 'Platform folders (e.g. android/) will be generated in the target project. '
'Adding desktop platforms requires the corresponding desktop config setting to be enabled.'; 'Adding desktop platforms requires the corresponding desktop config setting to be enabled.';
/// Common behavior for `flutter create` commands. /// Common behavior for `flutter create` commands.
abstract class CreateBase extends FlutterCommand { abstract class CreateBase extends FlutterCommand {
CreateBase() { CreateBase({
@required bool verboseHelp,
}) {
argParser.addFlag( argParser.addFlag(
'pub', 'pub',
defaultsTo: true, defaultsTo: true,
...@@ -57,9 +59,10 @@ abstract class CreateBase extends FlutterCommand { ...@@ -57,9 +59,10 @@ abstract class CreateBase extends FlutterCommand {
'with-driver-test', 'with-driver-test',
negatable: true, negatable: true,
defaultsTo: false, defaultsTo: false,
help: '(Deprecated) Also add a flutter_driver dependency and generate a ' help: '(deprecated) Historically, this added a flutter_driver dependency and generated a '
"sample 'flutter drive' test. This flag has been deprecated, instead see " 'sample "flutter drive" test. Now it does nothing. Consider using the '
'package:integration_test at https://pub.dev/packages/integration_test .', '"integration_test" package: https://pub.dev/packages/integration_test',
hide: !verboseHelp,
); );
argParser.addFlag( argParser.addFlag(
'overwrite', 'overwrite',
...@@ -91,19 +94,21 @@ abstract class CreateBase extends FlutterCommand { ...@@ -91,19 +94,21 @@ abstract class CreateBase extends FlutterCommand {
abbr: 'i', abbr: 'i',
defaultsTo: 'swift', defaultsTo: 'swift',
allowed: <String>['objc', 'swift'], allowed: <String>['objc', 'swift'],
help: 'The language to use for iOS-specific code, either ObjectiveC (legacy) or Swift (recommended).'
); );
argParser.addOption( argParser.addOption(
'android-language', 'android-language',
abbr: 'a', abbr: 'a',
defaultsTo: 'kotlin', defaultsTo: 'kotlin',
allowed: <String>['java', 'kotlin'], allowed: <String>['java', 'kotlin'],
help: 'The language to use for Android-specific code, either Java (legacy) or Kotlin (recommended).',
); );
argParser.addFlag( argParser.addFlag(
'skip-name-checks', 'skip-name-checks',
help: help:
'integration test only parameter to allow creating applications/plugins with ' 'Allow the creation of applications and plugins with invalid names. '
'invalid names.', 'This is only intended to enable testing of the tool itself.',
hide: true, hide: !verboseHelp,
); );
} }
......
...@@ -12,17 +12,17 @@ import '../globals.dart' as globals; ...@@ -12,17 +12,17 @@ import '../globals.dart' as globals;
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
class DevicesCommand extends FlutterCommand { class DevicesCommand extends FlutterCommand {
DevicesCommand({ bool verboseHelp = false }) {
DevicesCommand() {
argParser.addFlag('machine', argParser.addFlag('machine',
negatable: false, negatable: false,
help: 'Output device information in machine readable structured JSON format', help: 'Output device information in machine readable structured JSON format.',
); );
argParser.addOption( argParser.addOption(
'timeout', 'timeout',
abbr: 't', abbr: 't',
defaultsTo: null, defaultsTo: null,
help: '(deprecated) Use --device-timeout instead', help: '(deprecated) This option has been replaced by "--${FlutterOptions.kDeviceTimeout}".',
hide: !verboseHelp,
); );
usesDeviceTimeoutOption(); usesDeviceTimeoutOption();
} }
...@@ -38,7 +38,7 @@ class DevicesCommand extends FlutterCommand { ...@@ -38,7 +38,7 @@ class DevicesCommand extends FlutterCommand {
if (argResults['timeout'] != null) { if (argResults['timeout'] != null) {
final int timeoutSeconds = int.tryParse(stringArg('timeout')); final int timeoutSeconds = int.tryParse(stringArg('timeout'));
if (timeoutSeconds == null) { if (timeoutSeconds == null) {
throwToolExit( 'Could not parse -t/--timeout argument. It must be an integer.'); throwToolExit('Could not parse -t/--timeout argument. It must be an integer.');
} }
return Duration(seconds: timeoutSeconds); return Duration(seconds: timeoutSeconds);
} }
...@@ -48,7 +48,7 @@ class DevicesCommand extends FlutterCommand { ...@@ -48,7 +48,7 @@ class DevicesCommand extends FlutterCommand {
@override @override
Future<void> validateCommand() { Future<void> validateCommand() {
if (argResults['timeout'] != null) { if (argResults['timeout'] != null) {
globals.printError('--timeout has been deprecated, use --${FlutterOptions.kDeviceTimeout} instead'); globals.printError('"--timeout" argument is deprecated, use "--${FlutterOptions.kDeviceTimeout}" instead');
} }
return super.validateCommand(); return super.validateCommand();
} }
......
...@@ -30,6 +30,7 @@ import '../version.dart'; ...@@ -30,6 +30,7 @@ import '../version.dart';
/// the command would fail since there was no previously recorded stable version. /// the command would fail since there was no previously recorded stable version.
class DowngradeCommand extends FlutterCommand { class DowngradeCommand extends FlutterCommand {
DowngradeCommand({ DowngradeCommand({
bool verboseHelp = false,
PersistentToolState persistentToolState, PersistentToolState persistentToolState,
Logger logger, Logger logger,
ProcessManager processManager, ProcessManager processManager,
...@@ -46,14 +47,17 @@ class DowngradeCommand extends FlutterCommand { ...@@ -46,14 +47,17 @@ class DowngradeCommand extends FlutterCommand {
_fileSystem = fileSystem { _fileSystem = fileSystem {
argParser.addOption( argParser.addOption(
'working-directory', 'working-directory',
hide: true, hide: !verboseHelp,
help: 'Override the downgrade working directory for integration testing.' help: 'Override the downgrade working directory. '
'This is only intended to enable integration testing of the tool itself.'
); );
argParser.addFlag( argParser.addFlag(
'prompt', 'prompt',
defaultsTo: true, defaultsTo: true,
hide: true, hide: !verboseHelp,
help: 'Disable the downgrade prompt for integration testing.' help: 'Show the downgrade prompt. '
'The ability to disable this using "--no-prompt" is only provided for '
'integration testing of the tool itself.'
); );
} }
...@@ -74,7 +78,7 @@ class DowngradeCommand extends FlutterCommand { ...@@ -74,7 +78,7 @@ class DowngradeCommand extends FlutterCommand {
@override @override
Future<FlutterCommandResult> runCommand() async { Future<FlutterCommandResult> runCommand() async {
// Note: commands do not necessarily have access to the correct zone injected // Commands do not necessarily have access to the correct zone injected
// values when being created. Fields must be lazily instantiated in runCommand, // values when being created. Fields must be lazily instantiated in runCommand,
// at least until the zone injection is refactored. // at least until the zone injection is refactored.
_terminal ??= globals.terminal; _terminal ??= globals.terminal;
......
...@@ -52,7 +52,8 @@ class DriveCommand extends RunCommandBase { ...@@ -52,7 +52,8 @@ class DriveCommand extends RunCommandBase {
@required Logger logger, @required Logger logger,
}) : _flutterDriverFactory = flutterDriverFactory, }) : _flutterDriverFactory = flutterDriverFactory,
_fileSystem = fileSystem, _fileSystem = fileSystem,
_logger = logger { _logger = logger,
super(verboseHelp: verboseHelp) {
requiresPubspecYaml(); requiresPubspecYaml();
addEnableExperimentation(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp);
...@@ -65,14 +66,14 @@ class DriveCommand extends RunCommandBase { ...@@ -65,14 +66,14 @@ class DriveCommand extends RunCommandBase {
defaultsTo: null, defaultsTo: null,
help: 'Will keep the Flutter application running when done testing.\n' help: 'Will keep the Flutter application running when done testing.\n'
'By default, "flutter drive" stops the application after tests are finished, ' 'By default, "flutter drive" stops the application after tests are finished, '
'and --keep-app-running overrides this. On the other hand, if --use-existing-app ' 'and "--keep-app-running" overrides this. On the other hand, if "--use-existing-app" '
'is specified, then "flutter drive" instead defaults to leaving the application ' 'is specified, then "flutter drive" instead defaults to leaving the application '
'running, and --no-keep-app-running overrides it.', 'running, and "--no-keep-app-running" overrides it.',
) )
..addOption('use-existing-app', ..addOption('use-existing-app',
help: 'Connect to an already running instance via the given observatory URL. ' help: 'Connect to an already running instance via the given observatory URL. '
'If this option is given, the application will not be automatically started, ' 'If this option is given, the application will not be automatically started, '
'and it will only be stopped if --no-keep-app-running is explicitly set.', 'and it will only be stopped if "--no-keep-app-running" is explicitly set.',
valueHelp: 'url', valueHelp: 'url',
) )
..addOption('driver', ..addOption('driver',
...@@ -86,23 +87,21 @@ class DriveCommand extends RunCommandBase { ...@@ -86,23 +87,21 @@ class DriveCommand extends RunCommandBase {
) )
..addFlag('build', ..addFlag('build',
defaultsTo: true, defaultsTo: true,
help: '(Deprecated) Build the app before running. To use an existing app, pass the --use-application-binary ' help: '(deprecated) Build the app before running. To use an existing app, pass the "--use-application-binary" '
'flag with an existing APK', 'flag with an existing APK.',
) )
..addOption('driver-port', ..addOption('driver-port',
defaultsTo: '4444', defaultsTo: '4444',
help: 'The port where Webdriver server is launched at. Defaults to 4444.', help: 'The port where Webdriver server is launched at.',
valueHelp: '4444' valueHelp: '4444'
) )
..addFlag('headless', ..addFlag('headless',
defaultsTo: true, defaultsTo: true,
help: 'Whether the driver browser is going to be launched in headless mode. Defaults to true.', help: 'Whether the driver browser is going to be launched in headless mode.',
) )
..addOption('browser-name', ..addOption('browser-name',
defaultsTo: 'chrome', defaultsTo: 'chrome',
help: 'Name of browser where tests will be executed. \n' help: 'Name of the browser where tests will be executed.',
'Following browsers are supported: \n'
'Chrome, Firefox, Safari (macOS and iOS) and Edge. Defaults to Chrome.',
allowed: <String>[ allowed: <String>[
'android-chrome', 'android-chrome',
'chrome', 'chrome',
...@@ -111,24 +110,31 @@ class DriveCommand extends RunCommandBase { ...@@ -111,24 +110,31 @@ class DriveCommand extends RunCommandBase {
'ios-safari', 'ios-safari',
'safari', 'safari',
], ],
allowedHelp: <String, String>{
'android-chrome': 'Chrome on Android (see also "--android-emulator").',
'chrome': 'Google Chrome on this computer (see also "--chrome-binary").',
'edge': 'Microsoft Edge on this computer (Windows only).',
'firefox': 'Mozilla Firefox on this computer.',
'ios-safari': 'Apple Safari on an iOS device.',
'safari': 'Apple Safari on this computer (macOS only).',
},
) )
..addOption('browser-dimension', ..addOption('browser-dimension',
defaultsTo: '1600,1024', defaultsTo: '1600,1024',
help: 'The dimension of browser when running Flutter Web test. \n' help: 'The dimension of the browser when running a Flutter Web test. '
'This will affect screenshot and all offset-related actions. \n' 'This will affect screenshot and all offset-related actions.',
'By default. it is set to 1600,1024 (1600 by 1024).', valueHelp: 'width,height',
) )
..addFlag('android-emulator', ..addFlag('android-emulator',
defaultsTo: true, defaultsTo: true,
help: 'Whether to perform Flutter Driver testing on Android Emulator.' help: 'Whether to perform Flutter Driver testing using an Android Emulator. '
'Works only if \'browser-name\' is set to \'android-chrome\'') 'Works only if "browser-name" is set to "android-chrome".')
..addOption('chrome-binary', ..addOption('chrome-binary',
help: 'Location of Chrome binary. ' help: 'Location of the Chrome binary. '
'Works only if \'browser-name\' is set to \'chrome\'') 'Works only if "browser-name" is set to "chrome".')
..addOption('write-sksl-on-exit', ..addOption('write-sksl-on-exit',
help: help: 'Attempts to write an SkSL file when the drive process is finished '
'Attempts to write an SkSL file when the drive process is finished ' 'to the provided file, overwriting it if necessary.')
'to the provided file, overwriting it if necessary.')
..addMultiOption('test-arguments', help: 'Additional arguments to pass to the ' ..addMultiOption('test-arguments', help: 'Additional arguments to pass to the '
'Dart VM running The test script.'); 'Dart VM running The test script.');
} }
......
...@@ -19,7 +19,7 @@ class EmulatorsCommand extends FlutterCommand { ...@@ -19,7 +19,7 @@ class EmulatorsCommand extends FlutterCommand {
help: 'Creates a new Android emulator based on a Pixel device.', help: 'Creates a new Android emulator based on a Pixel device.',
negatable: false); negatable: false);
argParser.addOption('name', argParser.addOption('name',
help: 'Used with flag --create. Specifies a name for the emulator being created.'); help: 'Used with the "--create" flag. Specifies a name for the emulator being created.');
} }
@override @override
......
...@@ -30,7 +30,8 @@ class FormatCommand extends FlutterCommand { ...@@ -30,7 +30,8 @@ class FormatCommand extends FlutterCommand {
); );
argParser.addOption('line-length', argParser.addOption('line-length',
abbr: 'l', abbr: 'l',
help: 'Wrap lines longer than this length. Defaults to 80 characters.', help: 'Wrap lines longer than this length.',
valueHelp: 'characters',
defaultsTo: '80', defaultsTo: '80',
); );
} }
......
...@@ -34,134 +34,143 @@ class GenerateLocalizationsCommand extends FlutterCommand { ...@@ -34,134 +34,143 @@ class GenerateLocalizationsCommand extends FlutterCommand {
argParser.addOption( argParser.addOption(
'output-dir', 'output-dir',
help: 'The directory where the generated localization classes will be written ' help: 'The directory where the generated localization classes will be written '
'if the synthetic-package flag is set to false.' 'if the synthetic-package flag is set to false.\n'
'\n\n' '\n'
'If output-dir is specified and the synthetic-package flag is enabled, ' 'If output-dir is specified and the synthetic-package flag is enabled, '
'this option will be ignored by the tool.' 'this option will be ignored by the tool.\n'
'\n\n' '\n'
'The app must import the file specified in the \'output-localization-file\' ' 'The app must import the file specified in the "--output-localization-file" '
'option from this directory. If unspecified, this defaults to the same ' 'option from this directory. If unspecified, this defaults to the same '
'directory as the input directory specified in \'arb-dir\'.', 'directory as the input directory specified in "--arb-dir".',
); );
argParser.addOption( argParser.addOption(
'template-arb-file', 'template-arb-file',
defaultsTo: 'app_en.arb', defaultsTo: 'app_en.arb',
help: 'The template arb file that will be used as the basis for ' help: 'The template arb file that will be used as the basis for '
'generating the Dart localization and messages files.', 'generating the Dart localization and messages files.',
); );
argParser.addOption( argParser.addOption(
'output-localization-file', 'output-localization-file',
defaultsTo: 'app_localizations.dart', defaultsTo: 'app_localizations.dart',
help: 'The filename for the output localization and localizations ' help: 'The filename for the output localization and localizations '
'delegate classes.', 'delegate classes.',
); );
argParser.addOption( argParser.addOption(
'untranslated-messages-file', 'untranslated-messages-file',
help: 'The location of a file that describes the localization\n' help: 'The location of a file that describes the localization '
'messages have not been translated yet. Using this option will create\n' 'messages have not been translated yet. Using this option will create '
'a JSON file at the target location, in the following format:\n\n' 'a JSON file at the target location, in the following format:\n'
'"locale": ["message_1", "message_2" ... "message_n"]\n\n' '\n'
'If this option is not specified, a summary of the messages that\n' ' "locale": ["message_1", "message_2" ... "message_n"]\n'
'have not been translated will be printed on the command line.' '\n'
'If this option is not specified, a summary of the messages that '
'have not been translated will be printed on the command line.',
); );
argParser.addOption( argParser.addOption(
'output-class', 'output-class',
defaultsTo: 'AppLocalizations', defaultsTo: 'AppLocalizations',
help: 'The Dart class name to use for the output localization and ' help: 'The Dart class name to use for the output localization and '
'localizations delegate classes.', 'localizations delegate classes.',
); );
argParser.addMultiOption( argParser.addMultiOption(
'preferred-supported-locales', 'preferred-supported-locales',
valueHelp: 'locale', valueHelp: 'locale',
help: 'The list of preferred supported locales for the application. ' help: 'The list of preferred supported locales for the application. '
'By default, the tool will generate the supported locales list in ' 'By default, the tool will generate the supported locales list in '
'alphabetical order. Use this flag if you would like to default to ' 'alphabetical order. Use this flag if you would like to default to '
'a different locale. \n\n' 'a different locale. '
'For example, pass in `en_US` if you would like your app to ' 'For example, pass in "en_US" if you would like your app to '
'default to American English if a device supports it.' 'default to American English on devices that support it. '
'(Pass this option multiple times for defining multiple items', 'Pass this option multiple times to define multiple items.',
); );
argParser.addOption( argParser.addOption(
'header', 'header',
help: 'The header to prepend to the generated Dart localizations ' help: 'The header to prepend to the generated Dart localizations '
'files. This option takes in a string. \n\n' 'files. This option takes in a string.\n'
'For example, pass in "/// All localized files." if you would ' '\n'
'like this string prepended to the generated Dart file. \n\n' 'For example, pass in "/// All localized files." if you would '
'Alternatively, see the `header-file` option to pass in a text ' 'like this string prepended to the generated Dart file.\n'
'file for longer headers.' '\n'
'Alternatively, see the "--header-file" option to pass in a text '
'file for longer headers.'
); );
argParser.addOption( argParser.addOption(
'header-file', 'header-file',
help: 'The header to prepend to the generated Dart localizations ' help: 'The header to prepend to the generated Dart localizations '
'files. The value of this option is the name of the file that ' 'files. The value of this option is the name of the file that '
'contains the header text which will be inserted at the top ' 'contains the header text which will be inserted at the top '
'of each generated Dart file. \n\n' 'of each generated Dart file.\n'
'Alternatively, see the `header` option to pass in a string ' '\n'
'for a simpler header. \n\n' 'Alternatively, see the "--header" option to pass in a string '
'This file should be placed in the directory specified in \'arb-dir\'.' 'for a simpler header.\n'
'\n'
'This file should be placed in the directory specified in "--arb-dir".'
); );
argParser.addFlag( argParser.addFlag(
'use-deferred-loading', 'use-deferred-loading',
defaultsTo: false, defaultsTo: false,
help: 'Whether to generate the Dart localization file with locales imported' help: 'Whether to generate the Dart localization file with locales imported '
' as deferred, allowing for lazy loading of each locale in Flutter web.\n' 'as deferred, allowing for lazy loading of each locale in Flutter web.\n'
'\n' '\n'
'This can reduce a web app’s initial startup time by decreasing the ' 'This can reduce a web app’s initial startup time by decreasing the '
'size of the JavaScript bundle. When this flag is set to true, the ' 'size of the JavaScript bundle. When this flag is set to true, the '
'messages for a particular locale are only downloaded and loaded by the ' 'messages for a particular locale are only downloaded and loaded by the '
'Flutter app as they are needed. For projects with a lot of different ' 'Flutter app as they are needed. For projects with a lot of different '
'locales and many localization strings, it can be an performance ' 'locales and many localization strings, it can be an performance '
'improvement to have deferred loading. For projects with a small number ' 'improvement to have deferred loading. For projects with a small number '
'of locales, the difference is negligible, and might slow down the start ' 'of locales, the difference is negligible, and might slow down the start '
'up compared to bundling the localizations with the rest of the ' 'up compared to bundling the localizations with the rest of the '
'application.\n\n' 'application.\n'
'Note that this flag does not affect other platforms such as mobile or ' '\n'
'desktop.', 'This flag does not affect other platforms such as mobile or desktop.',
); );
argParser.addOption( argParser.addOption(
'gen-inputs-and-outputs-list', 'gen-inputs-and-outputs-list',
valueHelp: 'path-to-output-directory', valueHelp: 'path-to-output-directory',
help: 'When specified, the tool generates a JSON file containing the ' help: 'When specified, the tool generates a JSON file containing the '
'tool\'s inputs and outputs named gen_l10n_inputs_and_outputs.json.' 'tool\'s inputs and outputs named gen_l10n_inputs_and_outputs.json.\n'
'\n\n' '\n'
'This can be useful for keeping track of which files of the Flutter ' 'This can be useful for keeping track of which files of the Flutter '
'project were used when generating the latest set of localizations. ' 'project were used when generating the latest set of localizations. '
'For example, the Flutter tool\'s build system uses this file to ' 'For example, the Flutter tool\'s build system uses this file to '
'keep track of when to call gen_l10n during hot reload.\n\n' 'keep track of when to call gen_l10n during hot reload.\n'
'The value of this option is the directory where the JSON file will be ' '\n'
'generated.' 'The value of this option is the directory where the JSON file will be '
'\n\n' 'generated.\n'
'When null, the JSON file will not be generated.' '\n'
'When null, the JSON file will not be generated.'
); );
argParser.addFlag( argParser.addFlag(
'synthetic-package', 'synthetic-package',
defaultsTo: true, defaultsTo: true,
help: 'Determines whether or not the generated output files will be ' help: 'Determines whether or not the generated output files will be '
'generated as a synthetic package or at a specified directory in ' 'generated as a synthetic package or at a specified directory in '
'the Flutter project.' 'the Flutter project.\n'
'\n\n' '\n'
'This flag is set to true by default.' 'This flag is set to true by default.\n'
'\n\n' '\n'
'When synthetic-package is set to false, it will generate the ' 'When synthetic-package is set to false, it will generate the '
'localizations files in the directory specified by arb-dir by default. ' 'localizations files in the directory specified by arb-dir by default.\n'
'\n\n' '\n'
'If output-dir is specified, files will be generated there.', 'If output-dir is specified, files will be generated there.',
); );
argParser.addOption( argParser.addOption(
'project-dir', 'project-dir',
valueHelp: 'absolute/path/to/flutter/project', valueHelp: 'absolute/path/to/flutter/project',
help: 'When specified, the tool uses the path passed into this option ' help: 'When specified, the tool uses the path passed into this option '
'as the directory of the root Flutter project.' 'as the directory of the root Flutter project.\n'
'\n\n' '\n'
'When null, the relative path to the present working directory will be used.' 'When null, the relative path to the present working directory will be used.'
); );
argParser.addFlag( argParser.addFlag(
'required-resource-attributes', 'required-resource-attributes',
help: 'Requires all resource ids to contain a corresponding resource attribute.\n\n' help: 'Requires all resource ids to contain a corresponding resource attribute.\n'
'By default, simple messages will not require metadata, but it is highly ' '\n'
'recommended as this provides context for the meaning of a message to ' 'By default, simple messages will not require metadata, but it is highly '
'readers.\n\n' 'recommended as this provides context for the meaning of a message to '
'Resource attributes are still required for plural messages.' 'readers.\n'
'\n'
'Resource attributes are still required for plural messages.'
); );
} }
......
...@@ -23,19 +23,19 @@ class IdeConfigCommand extends FlutterCommand { ...@@ -23,19 +23,19 @@ class IdeConfigCommand extends FlutterCommand {
'update-templates', 'update-templates',
negatable: false, negatable: false,
help: 'Update the templates in the template directory from the current ' help: 'Update the templates in the template directory from the current '
'configuration files. This is the opposite of what $name usually does. ' 'configuration files. This is the opposite of what $name usually does. '
'Will search the flutter tree for .iml files and copy any missing ones ' 'Will search the flutter tree for *.iml files and copy any missing ones '
'into the template directory. If --overwrite is also specified, it will ' 'into the template directory. If "--overwrite" is also specified, it will '
'update any out-of-date files, and remove any deleted files from the ' 'update any out-of-date files, and remove any deleted files from the '
'template directory.', 'template directory.',
); );
argParser.addFlag( argParser.addFlag(
'with-root-module', 'with-root-module',
negatable: true, negatable: true,
defaultsTo: true, defaultsTo: true,
help: 'Also create module that corresponds to the root of Flutter tree. ' help: 'Also create module that corresponds to the root of Flutter tree. '
'This makes the entire Flutter tree browsable and searchable in IDE. ' 'This makes the entire Flutter tree browsable and searchable in IDE. '
'Without this flag, only the child modules will be visible in IDE.', 'Without this flag, only the child modules will be visible in IDE.',
); );
} }
......
...@@ -32,7 +32,7 @@ class PrecacheCommand extends FlutterCommand { ...@@ -32,7 +32,7 @@ class PrecacheCommand extends FlutterCommand {
help: 'Force re-downloading of artifacts.'); help: 'Force re-downloading of artifacts.');
argParser.addFlag('android', negatable: true, defaultsTo: false, argParser.addFlag('android', negatable: true, defaultsTo: false,
help: 'Precache artifacts for Android development.', help: 'Precache artifacts for Android development.',
hide: verboseHelp); hide: !verboseHelp);
argParser.addFlag('android_gen_snapshot', negatable: true, defaultsTo: false, argParser.addFlag('android_gen_snapshot', negatable: true, defaultsTo: false,
help: 'Precache gen_snapshot for Android development.', help: 'Precache gen_snapshot for Android development.',
hide: !verboseHelp); hide: !verboseHelp);
...@@ -57,9 +57,9 @@ class PrecacheCommand extends FlutterCommand { ...@@ -57,9 +57,9 @@ class PrecacheCommand extends FlutterCommand {
argParser.addFlag('universal', negatable: true, defaultsTo: true, argParser.addFlag('universal', negatable: true, defaultsTo: true,
help: 'Precache artifacts required for any development platform.'); help: 'Precache artifacts required for any development platform.');
argParser.addFlag('flutter_runner', negatable: true, defaultsTo: false, argParser.addFlag('flutter_runner', negatable: true, defaultsTo: false,
help: 'Precache the flutter runner artifacts.', hide: true); help: 'Precache the flutter runner artifacts.', hide: !verboseHelp);
argParser.addFlag('use-unsigned-mac-binaries', negatable: true, defaultsTo: false, argParser.addFlag('use-unsigned-mac-binaries', negatable: true, defaultsTo: false,
help: 'Precache the unsigned mac binaries when available.', hide: true); help: 'Precache the unsigned macOS binaries when available.', hide: !verboseHelp);
} }
final Cache _cache; final Cache _cache;
......
...@@ -31,8 +31,8 @@ import 'daemon.dart'; ...@@ -31,8 +31,8 @@ import 'daemon.dart';
/// Shared logic between `flutter run` and `flutter drive` commands. /// Shared logic between `flutter run` and `flutter drive` commands.
abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopmentArtifacts { abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
RunCommandBase({ bool verboseHelp = false }) { RunCommandBase({ @required bool verboseHelp }) {
addBuildModeFlags(defaultToRelease: false, verboseHelp: verboseHelp); addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false);
usesDartDefineOption(); usesDartDefineOption();
usesFlavorOption(); usesFlavorOption();
usesWebRendererOption(); usesWebRendererOption();
...@@ -44,44 +44,45 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment ...@@ -44,44 +44,45 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
) )
..addFlag('verbose-system-logs', ..addFlag('verbose-system-logs',
negatable: false, negatable: false,
help: 'Include verbose logging from the flutter engine.', help: 'Include verbose logging from the Flutter engine.',
) )
..addFlag('cache-sksl', ..addFlag('cache-sksl',
negatable: false, negatable: false,
help: 'Only cache the shader in SkSL instead of binary or GLSL.', help: 'Cache the shader in the SkSL format instead of in binary or GLSL formats.',
) )
..addFlag('dump-skp-on-shader-compilation', ..addFlag('dump-skp-on-shader-compilation',
negatable: false, negatable: false,
help: 'Automatically dump the skp that triggers new shader compilations. ' help: 'Automatically dump the skp that triggers new shader compilations. '
'This is useful for writing custom ShaderWarmUp to reduce jank. ' 'This is useful for writing custom ShaderWarmUp to reduce jank. '
'By default, this is not enabled to reduce the overhead. ' 'By default, this is not enabled as it introduces significant overhead. '
'This is only available in profile or debug build. ', 'This is only available in profile or debug builds.',
) )
..addFlag('purge-persistent-cache', ..addFlag('purge-persistent-cache',
negatable: false, negatable: false,
help: 'Removes all existing persistent caches. This allows reproducing ' help: 'Removes all existing persistent caches. This allows reproducing '
'shader compilation jank that normally only happens the first time ' 'shader compilation jank that normally only happens the first time '
'an app is run, or for reliable testing of compilation jank fixes ' 'an app is run, or for reliable testing of compilation jank fixes '
'(e.g. shader warm-up).', '(e.g. shader warm-up).',
) )
..addOption('route', ..addOption('route',
help: 'Which route to load when running the app.', help: 'Which route to load when running the app.',
) )
..addOption('vmservice-out-file', ..addOption('vmservice-out-file',
help: 'A file to write the attached vmservice uri to after an' help: 'A file to write the attached vmservice URL to after an '
' application is started.', 'application is started.',
valueHelp: 'project/example/out.txt' valueHelp: 'project/example/out.txt',
hide: !verboseHelp,
) )
..addFlag('disable-service-auth-codes', ..addFlag('disable-service-auth-codes',
negatable: false, negatable: false,
hide: !verboseHelp, hide: !verboseHelp,
help: 'No longer require an authentication code to connect to the VM ' help: '(deprecated) Allow connections to the VM service without using authentication codes. '
'service (not recommended).' '(Not recommended! This can open your device to remote code execution attacks!)'
) )
..addOption('use-application-binary', ..addOption('use-application-binary',
help: 'Specify a pre-built application binary to use when running. For android applications, ' help: 'Specify a pre-built application binary to use when running. For Android applications, '
'this must be the path to an APK. For iOS applications, the path to an IPA. Other device types ' 'this must be the path to an APK. For iOS applications, the path to an IPA. Other device types '
'do not yet support prebuilt application binaries', 'do not yet support prebuilt application binaries.',
valueHelp: 'path/to/app.apk', valueHelp: 'path/to/app.apk',
) )
..addFlag('start-paused', ..addFlag('start-paused',
...@@ -101,10 +102,9 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment ...@@ -101,10 +102,9 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
) )
..addFlag('endless-trace-buffer', ..addFlag('endless-trace-buffer',
negatable: false, negatable: false,
help: 'Enable tracing to the endless tracer. This is useful when ' help: 'Enable tracing to an infinite buffer, instead of a ring buffer. '
'recording huge amounts of traces. If we need to use endless buffer to ' 'This is useful when recording large traces. To use an endless buffer to '
'record startup traces, we can combine the ("--trace-startup"). ' 'record startup traces, combine this with "--trace-startup".',
'For example, flutter run --trace-startup --endless-trace-buffer. ',
) )
..addFlag('trace-systrace', ..addFlag('trace-systrace',
negatable: false, negatable: false,
...@@ -115,12 +115,13 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment ...@@ -115,12 +115,13 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
negatable: false, negatable: false,
help: 'Enable tracing of Skia code. This is useful when debugging ' help: 'Enable tracing of Skia code. This is useful when debugging '
'the raster thread (formerly known as the GPU thread). ' 'the raster thread (formerly known as the GPU thread). '
'By default, Flutter will not log skia code.', 'By default, Flutter will not log Skia code, as it introduces significant '
'overhead that may affect recorded performance metrics in a misleading way.',
) )
..addOption('trace-allowlist', ..addOption('trace-allowlist',
hide: true, hide: !verboseHelp,
help: 'Filters out all trace events except those that are specified in ' help: 'Filters out all trace events except those that are specified in '
'this comma separated list of allowed prefixes.', 'this comma separated list of allowed prefixes.',
valueHelp: 'foo,bar', valueHelp: 'foo,bar',
) )
..addMultiOption('dart-entrypoint-args', ..addMultiOption('dart-entrypoint-args',
...@@ -129,11 +130,12 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment ...@@ -129,11 +130,12 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
'startup. By default this is main(List<String> args). Specify ' 'startup. By default this is main(List<String> args). Specify '
'this option multiple times each with one argument to pass ' 'this option multiple times each with one argument to pass '
'multiple arguments to the Dart entrypoint. Currently this is ' 'multiple arguments to the Dart entrypoint. Currently this is '
'only supported on desktop platforms.'); 'only supported on desktop platforms.'
usesWebOptions(hide: !verboseHelp); );
usesWebOptions(verboseHelp: verboseHelp);
usesTargetOption(); usesTargetOption();
usesPortOptions(); usesPortOptions(verboseHelp: verboseHelp);
usesIpv6Flag(); usesIpv6Flag(verboseHelp: verboseHelp);
usesPubOption(); usesPubOption();
usesTrackWidgetCreation(verboseHelp: verboseHelp); usesTrackWidgetCreation(verboseHelp: verboseHelp);
addNullSafetyModeOptions(hide: !verboseHelp); addNullSafetyModeOptions(hide: !verboseHelp);
...@@ -227,7 +229,7 @@ class RunCommand extends RunCommandBase { ...@@ -227,7 +229,7 @@ class RunCommand extends RunCommandBase {
RunCommand({ bool verboseHelp = false }) : super(verboseHelp: verboseHelp) { RunCommand({ bool verboseHelp = false }) : super(verboseHelp: verboseHelp) {
requiresPubspecYaml(); requiresPubspecYaml();
usesFilesystemOptions(hide: !verboseHelp); usesFilesystemOptions(hide: !verboseHelp);
usesExtraDartFlagOptions(); usesExtraDartFlagOptions(verboseHelp: verboseHelp);
addEnableExperimentation(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp);
// By default, the app should to publish the VM service port over mDNS. // By default, the app should to publish the VM service port over mDNS.
...@@ -244,8 +246,9 @@ class RunCommand extends RunCommandBase { ...@@ -244,8 +246,9 @@ class RunCommand extends RunCommandBase {
) )
..addFlag('skia-deterministic-rendering', ..addFlag('skia-deterministic-rendering',
negatable: false, negatable: false,
help: 'When combined with --enable-software-rendering, provides 100% ' help: 'When combined with "--enable-software-rendering", this should provide completely '
'deterministic Skia rendering.', 'deterministic (i.e. reproducible) Skia rendering. This is useful for testing purposes '
'(e.g. when comparing screenshots).',
) )
..addFlag('await-first-frame-when-tracing', ..addFlag('await-first-frame-when-tracing',
defaultsTo: true, defaultsTo: true,
...@@ -253,7 +256,7 @@ class RunCommand extends RunCommandBase { ...@@ -253,7 +256,7 @@ class RunCommand extends RunCommandBase {
'or just dump the trace as soon as the application is running. The first frame ' 'or just dump the trace as soon as the application is running. The first frame '
'is detected by looking for a Timeline event with the name ' 'is detected by looking for a Timeline event with the name '
'"${Tracing.firstUsefulFrameEventName}". ' '"${Tracing.firstUsefulFrameEventName}". '
"By default, the widgets library's binding takes care of sending this event. ", 'By default, the widgets library\'s binding takes care of sending this event.',
) )
..addFlag('use-test-fonts', ..addFlag('use-test-fonts',
negatable: true, negatable: true,
...@@ -298,7 +301,7 @@ class RunCommand extends RunCommandBase { ...@@ -298,7 +301,7 @@ class RunCommand extends RunCommandBase {
'report-ready', 'report-ready',
help: 'Print "ready" to the console after handling a keyboard command.\n' help: 'Print "ready" to the console after handling a keyboard command.\n'
'This is primarily useful for tests and other automation, but consider ' 'This is primarily useful for tests and other automation, but consider '
'using --machine instead.', 'using "--machine" instead.',
hide: !verboseHelp, hide: !verboseHelp,
)..addFlag('benchmark', )..addFlag('benchmark',
negatable: false, negatable: false,
...@@ -308,12 +311,6 @@ class RunCommand extends RunCommandBase { ...@@ -308,12 +311,6 @@ class RunCommand extends RunCommandBase {
'results out to "refresh_benchmark.json", and exit. This flag is ' 'results out to "refresh_benchmark.json", and exit. This flag is '
'intended for use in generating automated flutter benchmarks.', 'intended for use in generating automated flutter benchmarks.',
) )
..addFlag('web-initialize-platform',
negatable: true,
defaultsTo: true,
hide: true,
help: 'Whether to automatically invoke webOnlyInitializePlatform.',
)
// TODO(jonahwilliams): Off by default with investigating whether this // TODO(jonahwilliams): Off by default with investigating whether this
// is slower for certain use cases. // is slower for certain use cases.
// See: https://github.com/flutter/flutter/issues/49499 // See: https://github.com/flutter/flutter/issues/49499
...@@ -322,7 +319,8 @@ class RunCommand extends RunCommandBase { ...@@ -322,7 +319,8 @@ class RunCommand extends RunCommandBase {
defaultsTo: false, defaultsTo: false,
help: 'Whether to quickly bootstrap applications with a minimal app. ' help: 'Whether to quickly bootstrap applications with a minimal app. '
'Currently this is only supported on Android devices. This option ' 'Currently this is only supported on Android devices. This option '
'cannot be paired with --use-application-binary.' 'cannot be paired with "--use-application-binary".',
hide: !verboseHelp,
); );
} }
...@@ -451,7 +449,7 @@ class RunCommand extends RunCommandBase { ...@@ -451,7 +449,7 @@ class RunCommand extends RunCommandBase {
throwToolExit(null); throwToolExit(null);
} }
if (globals.deviceManager.hasSpecifiedAllDevices && runningWithPrebuiltApplication) { if (globals.deviceManager.hasSpecifiedAllDevices && runningWithPrebuiltApplication) {
throwToolExit('Using -d all with --use-application-binary is not supported'); throwToolExit('Using "-d all" with "--use-application-binary" is not supported');
} }
if (userIdentifier != null if (userIdentifier != null
...@@ -523,7 +521,7 @@ class RunCommand extends RunCommandBase { ...@@ -523,7 +521,7 @@ class RunCommand extends RunCommandBase {
if (boolArg('machine')) { if (boolArg('machine')) {
if (devices.length > 1) { if (devices.length > 1) {
throwToolExit('--machine does not support -d all.'); throwToolExit('"--machine" does not support "-d all".');
} }
final Daemon daemon = Daemon( final Daemon daemon = Daemon(
stdinCommandStream, stdinCommandStream,
...@@ -574,7 +572,7 @@ class RunCommand extends RunCommandBase { ...@@ -574,7 +572,7 @@ class RunCommand extends RunCommandBase {
} }
if (hotMode) { if (hotMode) {
if (!device.supportsHotReload) { if (!device.supportsHotReload) {
throwToolExit('Hot reload is not supported by ${device.name}. Run with --no-hot.'); throwToolExit('Hot reload is not supported by ${device.name}. Run with "--no-hot".');
} }
} }
if (await device.isLocalEmulator && await device.supportsHardwareRendering) { if (await device.isLocalEmulator && await device.supportsHardwareRendering) {
...@@ -602,8 +600,8 @@ class RunCommand extends RunCommandBase { ...@@ -602,8 +600,8 @@ class RunCommand extends RunCommandBase {
for (final Device device in devices) for (final Device device in devices)
await FlutterDevice.create( await FlutterDevice.create(
device, device,
fileSystemRoots: stringsArg('filesystem-root'), fileSystemRoots: stringsArg(FlutterOptions.kFileSystemRoot),
fileSystemScheme: stringArg('filesystem-scheme'), fileSystemScheme: stringArg(FlutterOptions.kFileSystemScheme),
experimentalFlags: expFlags, experimentalFlags: expFlags,
target: targetFile, target: targetFile,
buildInfo: buildInfo, buildInfo: buildInfo,
......
...@@ -16,7 +16,7 @@ import '../vmservice.dart'; ...@@ -16,7 +16,7 @@ import '../vmservice.dart';
const String _kOut = 'out'; const String _kOut = 'out';
const String _kType = 'type'; const String _kType = 'type';
const String _kObservatoryUri = 'observatory-uri'; const String _kObservatoryUri = 'observatory-uri'; // TODO(ianh): change this to "observatory-url" (but support -uri as an alias)
const String _kDeviceType = 'device'; const String _kDeviceType = 'device';
const String _kSkiaType = 'skia'; const String _kSkiaType = 'skia';
const String _kRasterizerType = 'rasterizer'; const String _kRasterizerType = 'rasterizer';
...@@ -32,9 +32,9 @@ class ScreenshotCommand extends FlutterCommand { ...@@ -32,9 +32,9 @@ class ScreenshotCommand extends FlutterCommand {
argParser.addOption( argParser.addOption(
_kObservatoryUri, _kObservatoryUri,
valueHelp: 'URI', valueHelp: 'URI',
help: 'The observatory URI to connect to.\n' help: 'The Observatory URL to which to connect.\n'
'This is required when --$_kType is "$_kSkiaType" or "$_kRasterizerType".\n' 'This is required when "--$_kType" is "$_kSkiaType" or "$_kRasterizerType".\n'
'To find the observatory URI, use "flutter run" and look for ' 'To find the Observatory URL, use "flutter run" and look for '
'"An Observatory ... is available at" in the output.', '"An Observatory ... is available at" in the output.',
); );
argParser.addOption( argParser.addOption(
...@@ -43,11 +43,11 @@ class ScreenshotCommand extends FlutterCommand { ...@@ -43,11 +43,11 @@ class ScreenshotCommand extends FlutterCommand {
help: 'The type of screenshot to retrieve.', help: 'The type of screenshot to retrieve.',
allowed: const <String>[_kDeviceType, _kSkiaType, _kRasterizerType], allowed: const <String>[_kDeviceType, _kSkiaType, _kRasterizerType],
allowedHelp: const <String, String>{ allowedHelp: const <String, String>{
_kDeviceType: "Delegate to the device's native screenshot capabilities. This " _kDeviceType: 'Delegate to the device\'s native screenshot capabilities. This '
'screenshots the entire screen currently being displayed (including content ' 'screenshots the entire screen currently being displayed (including content '
'not rendered by Flutter, like the device status bar).', 'not rendered by Flutter, like the device status bar).',
_kSkiaType: 'Render the Flutter app as a Skia picture. Requires --$_kObservatoryUri', _kSkiaType: 'Render the Flutter app as a Skia picture. Requires "--$_kObservatoryUri".',
_kRasterizerType: 'Render the Flutter app using the rasterizer. Requires --$_kObservatoryUri', _kRasterizerType: 'Render the Flutter app using the rasterizer. Requires "--$_kObservatoryUri."',
}, },
defaultsTo: _kDeviceType, defaultsTo: _kDeviceType,
); );
......
...@@ -45,7 +45,7 @@ class SymbolizeCommand extends FlutterCommand { ...@@ -45,7 +45,7 @@ class SymbolizeCommand extends FlutterCommand {
argParser.addOption( argParser.addOption(
'output', 'output',
abbr: 'o', abbr: 'o',
valueHelp: 'A file path for a symbolized stack trace to be written to.' help: 'A file path for a symbolized stack trace to be written to.'
); );
} }
......
...@@ -49,11 +49,11 @@ class TestCommand extends FlutterCommand { ...@@ -49,11 +49,11 @@ class TestCommand extends FlutterCommand {
) )
..addOption('tags', ..addOption('tags',
abbr: 't', abbr: 't',
help: 'Run only tests associated with tags', help: 'Run only tests associated with the specified tags. See: https://pub.dev/packages/test#tagging-tests',
) )
..addOption('exclude-tags', ..addOption('exclude-tags',
abbr: 'x', abbr: 'x',
help: 'Run only tests WITHOUT given tags', help: 'Run only tests that do not have the specified tags. See: https://pub.dev/packages/test#tagging-tests',
) )
..addFlag('start-paused', ..addFlag('start-paused',
defaultsTo: false, defaultsTo: false,
...@@ -64,11 +64,11 @@ class TestCommand extends FlutterCommand { ...@@ -64,11 +64,11 @@ class TestCommand extends FlutterCommand {
'console once the test has started.', 'console once the test has started.',
) )
..addFlag('disable-service-auth-codes', ..addFlag('disable-service-auth-codes',
hide: !verboseHelp,
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
help: 'No longer require an authentication code to connect to the VM ' hide: !verboseHelp,
'service (not recommended).', help: '(deprecated) Allow connections to the VM service without using authentication codes. '
'(Not recommended! This can open your device to remote code execution attacks!)'
) )
..addFlag('coverage', ..addFlag('coverage',
defaultsTo: false, defaultsTo: false,
...@@ -79,11 +79,11 @@ class TestCommand extends FlutterCommand { ...@@ -79,11 +79,11 @@ class TestCommand extends FlutterCommand {
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
help: 'Whether to merge coverage data with "coverage/lcov.base.info".\n' help: 'Whether to merge coverage data with "coverage/lcov.base.info".\n'
'Implies collecting coverage data. (Requires lcov)', 'Implies collecting coverage data. (Requires lcov.)',
) )
..addFlag('ipv6', ..addFlag('ipv6',
negatable: false, negatable: false,
hide: true, hide: !verboseHelp,
help: 'Whether to use IPv6 for the test harness server socket.', help: 'Whether to use IPv6 for the test harness server socket.',
) )
..addOption('coverage-path', ..addOption('coverage-path',
...@@ -93,12 +93,12 @@ class TestCommand extends FlutterCommand { ...@@ -93,12 +93,12 @@ class TestCommand extends FlutterCommand {
..addFlag('machine', ..addFlag('machine',
hide: !verboseHelp, hide: !verboseHelp,
negatable: false, negatable: false,
help: 'Handle machine structured JSON command input\n' help: 'Handle machine structured JSON command input '
'and provide output and progress in machine friendly format.', 'and provide output and progress in machine friendly format.',
) )
..addFlag('update-goldens', ..addFlag('update-goldens',
negatable: false, negatable: false,
help: 'Whether matchesGoldenFile() calls within your test methods should ' help: 'Whether "matchesGoldenFile()" calls within your test methods should '
'update the golden files rather than test for an existing match.', 'update the golden files rather than test for an existing match.',
) )
..addOption('concurrency', ..addOption('concurrency',
...@@ -110,8 +110,9 @@ class TestCommand extends FlutterCommand { ...@@ -110,8 +110,9 @@ class TestCommand extends FlutterCommand {
..addFlag('test-assets', ..addFlag('test-assets',
defaultsTo: true, defaultsTo: true,
negatable: true, negatable: true,
help: 'Whether to build the assets bundle for testing.\n' help: 'Whether to build the assets bundle for testing. '
'Consider using --no-test-assets if assets are not required.', 'This takes additional time before running the tests. '
'Consider using "--no-test-assets" if assets are not required.',
) )
// --platform is not supported to be used by Flutter developers. It only // --platform is not supported to be used by Flutter developers. It only
// exists to test the Flutter framework itself and may be removed entirely // exists to test the Flutter framework itself and may be removed entirely
...@@ -119,33 +120,47 @@ class TestCommand extends FlutterCommand { ...@@ -119,33 +120,47 @@ class TestCommand extends FlutterCommand {
// `package:integration_test` instead. // `package:integration_test` instead.
..addOption('platform', ..addOption('platform',
allowed: const <String>['tester', 'chrome'], allowed: const <String>['tester', 'chrome'],
hide: true, hide: !verboseHelp,
defaultsTo: 'tester', defaultsTo: 'tester',
help: 'Selects the test backend.',
allowedHelp: <String, String>{
'tester': 'Run tests using the default VM-based test environment.',
'chrome': '(deprecated) Run tests using the Google Chrome web browser. '
'This value is intended for testing the Flutter framework '
'itself and may be removed at any time.',
},
) )
..addOption('test-randomize-ordering-seed', ..addOption('test-randomize-ordering-seed',
help: 'The seed to randomize the execution order of test cases.\n' help: 'The seed to randomize the execution order of test cases within test files. '
'Must be a 32bit unsigned integer or "random".\n' 'Must be a 32bit unsigned integer or the string "random", '
'If "random", pick a random seed to use.\n' 'which indicates that a seed should be selected randomly. '
'If not passed, do not randomize test case execution order.', 'By default, tests run in the order they are declared.',
) )
..addFlag('enable-vmservice', ..addFlag('enable-vmservice',
defaultsTo: false, defaultsTo: false,
hide: !verboseHelp, hide: !verboseHelp,
help: 'Enables the vmservice without --start-paused. This flag is ' help: 'Enables the VM service without "--start-paused". This flag is '
'intended for use with tests that will use dart:developer to ' 'intended for use with tests that will use "dart:developer" to '
'interact with the vmservice at runtime.\n' 'interact with the VM service at runtime.\n'
'This flag is ignored if --start-paused or coverage are requested. ' 'This flag is ignored if "--start-paused" or coverage are requested, as '
'The vmservice will be enabled no matter what in those cases.' 'the VM service will be enabled in those cases regardless.'
) )
..addOption('reporter', ..addOption('reporter',
abbr: 'r', abbr: 'r',
defaultsTo: 'compact', defaultsTo: 'compact',
help: 'Set how to print test results.\n' help: 'Set how to print test results.',
'[compact] (default) A single line, updated continuously.\n' allowed: <String>['compact', 'expanded', 'json'],
'[expanded] A separate line for each update.\n' allowedHelp: <String, String>{
'[json] A machine-readable format (see https://dart.dev/go/test-docs/json_reporter.md).\n') 'compact': 'A single line that updates dynamically.',
'expanded': 'A separate line for each update. May be preferred when logging to a file or in continuous integration.',
'json': 'A machine-readable format. See: https://dart.dev/go/test-docs/json_reporter.md',
},
)
..addOption('timeout', ..addOption('timeout',
help: 'The default test timeout. For example: 15s, 2x, none. Defaults to "30s"', help: 'The default test timeout, specified either '
'in seconds (e.g. "60s"), '
'as a multiplier of the default timeout (e.g. "2x"), '
'or as the string "none" to disable the timeout entirely.',
defaultsTo: '30s', defaultsTo: '30s',
); );
addDdsOptions(verboseHelp: verboseHelp); addDdsOptions(verboseHelp: verboseHelp);
......
...@@ -86,19 +86,19 @@ class UpdatePackagesCommand extends FlutterCommand { ...@@ -86,19 +86,19 @@ class UpdatePackagesCommand extends FlutterCommand {
..addFlag( ..addFlag(
'paths', 'paths',
help: 'Finds paths in the dependency chain leading from package specified ' help: 'Finds paths in the dependency chain leading from package specified '
'in --from to package specified in --to.', 'in "--from" to package specified in "--to".',
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
) )
..addOption( ..addOption(
'from', 'from',
help: 'Used with flag --dependency-path. Specifies the package to begin ' help: 'Used with "--dependency-path". Specifies the package to begin '
'searching dependency path from.', 'searching dependency path from.',
) )
..addOption( ..addOption(
'to', 'to',
help: 'Used with flag --dependency-path. Specifies the package that the ' help: 'Used with "--dependency-path". Specifies the package that the '
'sought after dependency path leads to.', 'sought-after dependency path leads to.',
) )
..addFlag( ..addFlag(
'transitive-closure', 'transitive-closure',
...@@ -110,20 +110,20 @@ class UpdatePackagesCommand extends FlutterCommand { ...@@ -110,20 +110,20 @@ class UpdatePackagesCommand extends FlutterCommand {
..addFlag( ..addFlag(
'consumer-only', 'consumer-only',
help: 'Only prints the dependency graph that is the transitive closure ' help: 'Only prints the dependency graph that is the transitive closure '
'that a consumer of the Flutter SDK will observe (When combined ' 'that a consumer of the Flutter SDK will observe (when combined '
'with transitive-closure)', 'with transitive-closure).',
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
) )
..addFlag( ..addFlag(
'verify-only', 'verify-only',
help: 'verifies the package checksum without changing or updating deps', help: 'Verifies the package checksum without changing or updating deps.',
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
) )
..addFlag( ..addFlag(
'offline', 'offline',
help: 'Use cached packages instead of accessing the network', help: 'Use cached packages instead of accessing the network.',
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
); );
......
...@@ -18,7 +18,10 @@ import '../runner/flutter_command.dart'; ...@@ -18,7 +18,10 @@ import '../runner/flutter_command.dart';
import '../version.dart'; import '../version.dart';
class UpgradeCommand extends FlutterCommand { class UpgradeCommand extends FlutterCommand {
UpgradeCommand([UpgradeCommandRunner commandRunner]) UpgradeCommand({
@required bool verboseHelp,
UpgradeCommandRunner commandRunner,
})
: _commandRunner = commandRunner ?? UpgradeCommandRunner() { : _commandRunner = commandRunner ?? UpgradeCommandRunner() {
argParser argParser
..addFlag( ..addFlag(
...@@ -29,20 +32,22 @@ class UpgradeCommand extends FlutterCommand { ...@@ -29,20 +32,22 @@ class UpgradeCommand extends FlutterCommand {
) )
..addFlag( ..addFlag(
'continue', 'continue',
hide: true, hide: !verboseHelp,
negatable: false, negatable: false,
help: 'For the second half of the upgrade flow requiring the new ' help: 'Trigger the second half of the upgrade flow. This should not be invoked '
'version of Flutter. Should not be invoked manually, but ' 'manually. It is used re-entrantly by the standard upgrade command after '
're-entrantly by the standard upgrade command.', 'the new version of Flutter is available, to hand off the upgrade process '
'from the old version to the new version.',
) )
..addOption( ..addOption(
'working-directory', 'working-directory',
hide: true, hide: !verboseHelp,
help: 'Override the upgrade working directory for integration testing.' help: 'Override the upgrade working directory. '
'This is only intended to enable integration testing of the tool itself.'
) )
..addFlag( ..addFlag(
'verify-only', 'verify-only',
help: 'Verifies for any new flutter update, without fetching the update.', help: 'Checks for any new flutter updates, without actually fetching them.',
negatable: false, negatable: false,
); );
} }
...@@ -138,7 +143,7 @@ class UpgradeCommandRunner { ...@@ -138,7 +143,7 @@ class UpgradeCommandRunner {
throwToolExit( throwToolExit(
'Unknown flutter tag. Abandoning upgrade to avoid destroying local ' 'Unknown flutter tag. Abandoning upgrade to avoid destroying local '
'changes. If it is okay to remove local changes, then re-run this ' 'changes. If it is okay to remove local changes, then re-run this '
'command with --force.' 'command with "--force".'
); );
} }
} }
...@@ -150,7 +155,7 @@ class UpgradeCommandRunner { ...@@ -150,7 +155,7 @@ class UpgradeCommandRunner {
'upgrading. If you want to keep these changes, it is recommended that ' 'upgrading. If you want to keep these changes, it is recommended that '
'you stash them via "git stash" or else commit the changes to a local ' 'you stash them via "git stash" or else commit the changes to a local '
'branch. If it is okay to remove local changes, then re-run this ' 'branch. If it is okay to remove local changes, then re-run this '
'command with --force.' 'command with "--force".'
); );
} }
recordState(flutterVersion); recordState(flutterVersion);
...@@ -211,8 +216,8 @@ class UpgradeCommandRunner { ...@@ -211,8 +216,8 @@ class UpgradeCommandRunner {
'The tool could not verify the status of the current flutter checkout. ' 'The tool could not verify the status of the current flutter checkout. '
'This might be due to git not being installed or an internal error. ' 'This might be due to git not being installed or an internal error. '
'If it is okay to ignore potential local changes, then re-run this ' 'If it is okay to ignore potential local changes, then re-run this '
'command with --force.' 'command with "--force".\n'
'\nError: $error.' 'Error: $error.'
); );
} }
return false; return false;
......
...@@ -20,6 +20,7 @@ import '../base/user_messages.dart'; ...@@ -20,6 +20,7 @@ import '../base/user_messages.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../build_system/build_system.dart'; import '../build_system/build_system.dart';
import '../build_system/targets/common.dart' show kExtraFrontEndOptions, kExtraGenSnapshotOptions; // for "useLegacyNames" only
import '../build_system/targets/icon_tree_shaker.dart' show kIconTreeShakerEnabledDefault; import '../build_system/targets/icon_tree_shaker.dart' show kIconTreeShakerEnabledDefault;
import '../bundle.dart' as bundle; import '../bundle.dart' as bundle;
import '../cache.dart'; import '../cache.dart';
...@@ -194,7 +195,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -194,7 +195,7 @@ abstract class FlutterCommand extends Command<void> {
_requiresPubspecYaml = true; _requiresPubspecYaml = true;
} }
void usesWebOptions({ bool hide = true }) { void usesWebOptions({ @required bool verboseHelp }) {
argParser.addOption('web-hostname', argParser.addOption('web-hostname',
defaultsTo: 'localhost', defaultsTo: 'localhost',
help: help:
...@@ -202,13 +203,13 @@ abstract class FlutterCommand extends Command<void> { ...@@ -202,13 +203,13 @@ abstract class FlutterCommand extends Command<void> {
'from. The unresolved hostname is used to launch Chrome when using ' 'from. The unresolved hostname is used to launch Chrome when using '
'the chrome Device. The name "any" may also be used to serve on any ' 'the chrome Device. The name "any" may also be used to serve on any '
'IPV4 for either the Chrome or web-server device.', 'IPV4 for either the Chrome or web-server device.',
hide: hide, hide: !verboseHelp,
); );
argParser.addOption('web-port', argParser.addOption('web-port',
defaultsTo: null, 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: hide, hide: !verboseHelp,
); );
argParser.addOption('web-server-debug-protocol', argParser.addOption('web-server-debug-protocol',
allowed: <String>['sse', 'ws'], allowed: <String>['sse', 'ws'],
...@@ -217,7 +218,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -217,7 +218,7 @@ abstract class FlutterCommand extends Command<void> {
'when using the Web Server device and Dart Debug extension. ' 'when using the Web Server device and Dart Debug extension. '
'This is useful for editors/debug adapters that do not support debugging ' 'This is useful for editors/debug adapters that do not support debugging '
'over SSE (the default protocol for Web Server/Dart Debugger extension).', 'over SSE (the default protocol for Web Server/Dart Debugger extension).',
hide: hide, hide: !verboseHelp,
); );
argParser.addOption('web-server-debug-backend-protocol', argParser.addOption('web-server-debug-backend-protocol',
allowed: <String>['sse', 'ws'], allowed: <String>['sse', 'ws'],
...@@ -226,31 +227,31 @@ abstract class FlutterCommand extends Command<void> { ...@@ -226,31 +227,31 @@ abstract class FlutterCommand extends Command<void> {
'backend service when using the Web Server device. ' 'backend service when using the Web Server device. '
'Using WebSockets can improve performance but may fail when connecting through ' 'Using WebSockets can improve performance but may fail when connecting through '
'some proxy servers.', 'some proxy servers.',
hide: hide, hide: !verboseHelp,
); );
argParser.addFlag('web-allow-expose-url', argParser.addFlag('web-allow-expose-url',
defaultsTo: false, 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: hide, hide: !verboseHelp,
); );
argParser.addFlag('web-run-headless', argParser.addFlag('web-run-headless',
defaultsTo: false, 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: true, hide: !verboseHelp,
); );
argParser.addOption('web-browser-debug-port', argParser.addOption('web-browser-debug-port',
help: 'The debug port the browser should use. If not specified, a ' help: 'The debug port the browser should use. If not specified, a '
'random port is selected. Currently only Chrome supports this option. ' 'random port is selected. Currently only Chrome supports this option. '
'It serves the Chrome DevTools Protocol ' 'It serves the Chrome DevTools Protocol '
'(https://chromedevtools.github.io/devtools-protocol/).', '(https://chromedevtools.github.io/devtools-protocol/).',
hide: true, hide: !verboseHelp,
); );
argParser.addFlag('web-enable-expression-evaluation', argParser.addFlag('web-enable-expression-evaluation',
defaultsTo: true, defaultsTo: true,
help: 'Enables expression evaluation in the debugger.', help: 'Enables expression evaluation in the debugger.',
hide: hide, hide: !verboseHelp,
); );
} }
...@@ -259,7 +260,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -259,7 +260,7 @@ abstract class FlutterCommand extends Command<void> {
abbr: 't', abbr: 't',
defaultsTo: bundle.defaultMainPath, defaultsTo: bundle.defaultMainPath,
help: 'The main entry-point file of the application, as run on the device.\n' help: 'The main entry-point file of the application, as run on the device.\n'
'If the --target option is omitted, but a file name is provided on ' 'If the "--target" option is omitted, but a file name is provided on '
'the command line, then that is used instead.', 'the command line, then that is used instead.',
valueHelp: 'path'); valueHelp: 'path');
_usesTargetOption = true; _usesTargetOption = true;
...@@ -285,8 +286,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -285,8 +286,8 @@ abstract class FlutterCommand extends Command<void> {
/// Adds flags for using a specific filesystem root and scheme. /// Adds flags for using a specific filesystem root and scheme.
/// ///
/// [hide] indicates whether or not to hide these options when the user asks /// The `hide` argument indicates whether or not to hide these options when
/// 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',
...@@ -295,27 +296,28 @@ abstract class FlutterCommand extends Command<void> { ...@@ -295,27 +296,28 @@ abstract class FlutterCommand extends Command<void> {
) )
..addMultiOption(FlutterOptions.kFileSystemRoot, ..addMultiOption(FlutterOptions.kFileSystemRoot,
hide: hide, hide: hide,
help: 'Specify the path, that is used as root in a virtual file system\n' help: 'Specify the path that is used as the root of a virtual file system '
'for compilation. Input file name should be specified as Uri in\n' 'during compilation. The input file name should be specified as a URL '
'filesystem-scheme scheme. Use only in Dart 2 mode.\n' 'using the scheme given in "--${FlutterOptions.kFileSystemScheme}".\n'
'Requires --output-dill option to be explicitly specified.\n', 'Requires the "--output-dill" option to be explicitly specified.',
) )
..addOption(FlutterOptions.kFileSystemScheme, ..addOption(FlutterOptions.kFileSystemScheme,
defaultsTo: 'org-dartlang-root', defaultsTo: 'org-dartlang-root',
hide: hide, hide: hide,
help: 'Specify the scheme that is used for virtual file system used in\n' help: 'Specify the scheme that is used for virtual file system used in '
'compilation. See more details on filesystem-root option.\n', 'compilation. See also the "--${FlutterOptions.kFileSystemRoot}" option.',
); );
} }
/// Adds options for connecting to the Dart VM observatory port. /// Adds options for connecting to the Dart VM observatory port.
void usesPortOptions() { 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'
'Specifying port 0 (the default) will find a random free port.\nNote: ' 'Specifying port 0 (the default) will find a random free port.\n '
'if the Dart Development Service (DDS) is enabled, this will not be the port ' 'if the Dart Development Service (DDS) is enabled, this will not be the port '
'of the Observatory instance advertised on the command line.', 'of the Observatory instance advertised on the command line.',
hide: !verboseHelp,
); );
argParser.addOption('device-vmservice-port', argParser.addOption('device-vmservice-port',
help: 'Look for vmservice connections only from the specified port.\n' help: 'Look for vmservice connections only from the specified port.\n'
...@@ -335,16 +337,16 @@ abstract class FlutterCommand extends Command<void> { ...@@ -335,16 +337,16 @@ abstract class FlutterCommand extends Command<void> {
kEnableDevTools, kEnableDevTools,
hide: !verboseHelp, hide: !verboseHelp,
defaultsTo: true, defaultsTo: true,
help: 'Enable (or disable, with --no-$kEnableDevTools) the launching of the ' help: 'Enable (or disable, with "--no-$kEnableDevTools") the launching of the '
'Flutter DevTools debugger and profiler. ' 'Flutter DevTools debugger and profiler. '
'If specified, --$kDevToolsServerAddress is ignored.' 'If specified, "--$kDevToolsServerAddress" is ignored.'
); );
argParser.addOption( argParser.addOption(
kDevToolsServerAddress, kDevToolsServerAddress,
hide: !verboseHelp, hide: !verboseHelp,
help: 'When this value is provided, the Flutter tool will not spin up a ' help: 'When this value is provided, the Flutter tool will not spin up a '
'new DevTools server instance, and will instead use the one provided ' 'new DevTools server instance, and will instead use the one provided '
'at the given address. Ignored if --no-$kEnableDevTools is specified.' 'at the given address. Ignored if "--no-$kEnableDevTools" is specified.'
); );
} }
...@@ -453,13 +455,13 @@ abstract class FlutterCommand extends Command<void> { ...@@ -453,13 +455,13 @@ abstract class FlutterCommand extends Command<void> {
bool get disablePortPublication => !boolArg('publish-port'); bool get disablePortPublication => !boolArg('publish-port');
void usesIpv6Flag() { void usesIpv6Flag({@required bool verboseHelp}) {
argParser.addFlag(ipv6Flag, argParser.addFlag(ipv6Flag,
hide: true,
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 '
'forwards the host port to a device port. Not used when the ' 'forwards the host port to a device port. Not used when the '
'--debug-port flag is not set.', '"--debug-port" flag is not set.',
hide: !verboseHelp,
); );
_usesIpv6Flag = true; _usesIpv6Flag = true;
} }
...@@ -471,8 +473,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -471,8 +473,8 @@ abstract class FlutterCommand extends Command<void> {
help: 'An identifier used as an internal version number.\n' help: 'An identifier used as an internal version number.\n'
'Each build must have a unique identifier to differentiate it from previous builds.\n' 'Each build must have a unique identifier to differentiate it from previous builds.\n'
'It is used to determine whether one build is more recent than another, with higher numbers indicating more recent build.\n' 'It is used to determine whether one build is more recent than another, with higher numbers indicating more recent build.\n'
"On Android it is used as 'versionCode'.\n" 'On Android it is used as "versionCode".\n'
"On Xcode builds it is used as 'CFBundleVersion'", 'On Xcode builds it is used as "CFBundleVersion".',
); );
} }
...@@ -480,18 +482,18 @@ abstract class FlutterCommand extends Command<void> { ...@@ -480,18 +482,18 @@ abstract class FlutterCommand extends Command<void> {
argParser.addOption('build-name', argParser.addOption('build-name',
help: 'A "x.y.z" string used as the version number shown to users.\n' help: 'A "x.y.z" string used as the version number shown to users.\n'
'For each new version of your app, you will provide a version number to differentiate it from previous versions.\n' 'For each new version of your app, you will provide a version number to differentiate it from previous versions.\n'
"On Android it is used as 'versionName'.\n" 'On Android it is used as "versionName".\n'
"On Xcode builds it is used as 'CFBundleShortVersionString'", 'On Xcode builds it is used as "CFBundleShortVersionString".',
valueHelp: 'x.y.z'); valueHelp: 'x.y.z');
} }
void usesDartDefineOption() { void usesDartDefineOption({ bool useLegacyNames = false }) {
argParser.addMultiOption( argParser.addMultiOption(
FlutterOptions.kDartDefinesOption, useLegacyNames ? kDartDefines : FlutterOptions.kDartDefinesOption,
help: 'Additional key-value pairs that will be available as constants ' help: 'Additional key-value pairs that will be available as constants '
'from the String.fromEnvironment, bool.fromEnvironment, int.fromEnvironment, ' 'from the String.fromEnvironment, bool.fromEnvironment, int.fromEnvironment, '
'and double.fromEnvironment constructors.\n' 'and double.fromEnvironment constructors.\n'
'Multiple defines can be passed by repeating --dart-define multiple times.', 'Multiple defines can be passed by repeating "--${FlutterOptions.kDartDefinesOption}" multiple times.',
valueHelp: 'foo=bar', valueHelp: 'foo=bar',
splitCommas: false, splitCommas: false,
); );
...@@ -501,10 +503,12 @@ abstract class FlutterCommand extends Command<void> { ...@@ -501,10 +503,12 @@ abstract class FlutterCommand extends Command<void> {
argParser.addOption('web-renderer', argParser.addOption('web-renderer',
defaultsTo: 'auto', defaultsTo: 'auto',
allowed: <String>['auto', 'canvaskit', 'html'], allowed: <String>['auto', 'canvaskit', 'html'],
help: 'The renderer implementation to use when building for the web. Possible values are:\n' help: 'The renderer implementation to use when building for the web.',
'html - always use the HTML renderer. This renderer uses a combination of HTML, CSS, SVG, 2D Canvas, and WebGL. This is the default.\n' allowedHelp: <String, String>{
'canvaskit - always use the CanvasKit renderer. This renderer uses WebGL and WebAssembly to render graphics.\n' 'html': 'Always use the HTML renderer. This renderer uses a combination of HTML, CSS, SVG, 2D Canvas, and WebGL. This is the default.',
'auto - use the HTML renderer on mobile devices, and CanvasKit on desktop devices.', 'canvaskit': 'Always use the CanvasKit renderer. This renderer uses WebGL and WebAssembly to render graphics.',
'auto': 'Use the HTML renderer on mobile devices, and CanvasKit on desktop devices.',
}
); );
} }
...@@ -534,7 +538,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -534,7 +538,7 @@ abstract class FlutterCommand extends Command<void> {
&& argResults.wasParsed(FlutterOptions.kDeviceTimeout)) { && 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); _deviceDiscoveryTimeout = Duration(seconds: timeoutSeconds);
} }
...@@ -543,8 +547,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -543,8 +547,8 @@ abstract class FlutterCommand extends Command<void> {
Duration _deviceDiscoveryTimeout; Duration _deviceDiscoveryTimeout;
void addBuildModeFlags({ void addBuildModeFlags({
@required bool verboseHelp,
bool defaultToRelease = true, bool defaultToRelease = true,
bool verboseHelp = false,
bool excludeDebug = false, bool excludeDebug = false,
bool excludeRelease = false, bool excludeRelease = false,
}) { }) {
...@@ -576,13 +580,13 @@ abstract class FlutterCommand extends Command<void> { ...@@ -576,13 +580,13 @@ abstract class FlutterCommand extends Command<void> {
void addSplitDebugInfoOption() { void addSplitDebugInfoOption() {
argParser.addOption(FlutterOptions.kSplitDebugInfoOption, argParser.addOption(FlutterOptions.kSplitDebugInfoOption,
help: 'In a release build, this flag reduces application size by storing ' help: 'In a release build, this flag reduces application size by storing '
'Dart program symbols in a separate file on the host rather than in the ' 'Dart program symbols in a separate file on the host rather than in the '
'application. The value of the flag should be a directory where program ' 'application. The value of the flag should be a directory where program '
'symbol files can be stored for later use. These symbol files contain ' 'symbol files can be stored for later use. These symbol files contain '
'the information needed to symbolize Dart stack traces. For an app built ' 'the information needed to symbolize Dart stack traces. For an app built '
"with this flag, the 'flutter symbolize' command with the right program " 'with this flag, the "flutter symbolize" command with the right program '
'symbol file is required to obtain a human readable stack trace.\n' 'symbol file is required to obtain a human readable stack trace.\n'
'This flag cannot be combined with --analyze-size', 'This flag cannot be combined with "--${FlutterOptions.kAnalyzeSize}".',
valueHelp: 'v1.2.3/', valueHelp: 'v1.2.3/',
); );
} }
...@@ -590,17 +594,18 @@ abstract class FlutterCommand extends Command<void> { ...@@ -590,17 +594,18 @@ abstract class FlutterCommand extends Command<void> {
void addDartObfuscationOption() { void addDartObfuscationOption() {
argParser.addFlag(FlutterOptions.kDartObfuscationOption, argParser.addFlag(FlutterOptions.kDartObfuscationOption,
help: 'In a release build, this flag removes identifiers and replaces them ' help: 'In a release build, this flag removes identifiers and replaces them '
'with randomized values for the purposes of source code obfuscation. This ' 'with randomized values for the purposes of source code obfuscation. This '
'flag must always be combined with "--split-debug-info" option, the ' 'flag must always be combined with "--${FlutterOptions.kSplitDebugInfoOption}" option, the '
'mapping between the values and the original identifiers is stored in the ' 'mapping between the values and the original identifiers is stored in the '
'symbol map created in the specified directory. For an app built with this ' 'symbol map created in the specified directory. For an app built with this '
'flag, the \'flutter symbolize\' command with the right program ' 'flag, the "flutter symbolize" command with the right program '
'symbol file is required to obtain a human readable stack trace.\n\n' 'symbol file is required to obtain a human readable stack trace.\n'
'Because all identifiers are renamed, methods like Object.runtimeType, ' '\n'
'Type.toString, Enum.toString, Stacktrace.toString, Symbol.toString ' 'Because all identifiers are renamed, methods like Object.runtimeType, '
'(for constant symbols or those generated by runtime system) will ' 'Type.toString, Enum.toString, Stacktrace.toString, Symbol.toString '
'return obfuscated results. Any code or tests that rely on exact names ' '(for constant symbols or those generated by runtime system) will '
'will break.' 'return obfuscated results. Any code or tests that rely on exact names '
'will break.'
); );
} }
...@@ -625,11 +630,11 @@ abstract class FlutterCommand extends Command<void> { ...@@ -625,11 +630,11 @@ abstract class FlutterCommand extends Command<void> {
); );
} }
void addShrinkingFlag() { void addShrinkingFlag({ @required bool verboseHelp }) {
argParser.addFlag('shrink', argParser.addFlag('shrink',
negatable: true, negatable: true,
hide: true, hide: !verboseHelp,
help: 'This flag is deprecated. 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'
); );
} }
...@@ -655,21 +660,28 @@ abstract class FlutterCommand extends Command<void> { ...@@ -655,21 +660,28 @@ 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() { void usesExtraDartFlagOptions({ @required bool verboseHelp, bool useLegacyNames = false }) {
argParser.addMultiOption(FlutterOptions.kExtraFrontEndOptions, argParser.addMultiOption(useLegacyNames ? kExtraFrontEndOptions : FlutterOptions.kExtraFrontEndOptions,
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".',
valueHelp: '--foo,--bar',
splitCommas: true, splitCommas: true,
hide: true, hide: !verboseHelp,
); );
argParser.addMultiOption(FlutterOptions.kExtraGenSnapshotOptions, argParser.addMultiOption(useLegacyNames ? kExtraGenSnapshotOptions : FlutterOptions.kExtraGenSnapshotOptions,
help: 'A comma-separated list of additional command line arguments that will be passed directly to the Dart native compiler. '
'(Only used in "--profile" or "--release" builds.)'
'For example, "--${FlutterOptions.kExtraGenSnapshotOptions}=--no-strip".',
valueHelp: '--foo,--bar',
splitCommas: true, splitCommas: true,
hide: true, hide: !verboseHelp,
); );
} }
void usesFuchsiaOptions({ bool hide = false }) { void usesFuchsiaOptions({ bool hide = false }) {
argParser.addOption( argParser.addOption(
'target-model', 'target-model',
help: 'Target model that determines what core libraries are available', help: 'Target model that determines what core libraries are available.',
defaultsTo: 'flutter', defaultsTo: 'flutter',
hide: hide, hide: hide,
allowed: const <String>['flutter', 'flutter_runner'], allowed: const <String>['flutter', 'flutter_runner'],
...@@ -678,7 +690,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -678,7 +690,7 @@ abstract class FlutterCommand extends Command<void> {
'module', 'module',
abbr: 'm', abbr: 'm',
hide: hide, hide: hide,
help: 'The name of the module (required if attaching to a fuchsia device)', help: 'The name of the module (required if attaching to a fuchsia device).',
valueHelp: 'module-name', valueHelp: 'module-name',
); );
} }
...@@ -687,9 +699,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -687,9 +699,8 @@ abstract class FlutterCommand extends Command<void> {
argParser.addMultiOption( argParser.addMultiOption(
FlutterOptions.kEnableExperiment, FlutterOptions.kEnableExperiment,
help: help:
'The name of an experimental Dart feature to enable. For more info ' 'The name of an experimental Dart feature to enable. For more information see: '
'see: https://github.com/dart-lang/sdk/blob/master/docs/process/' 'https://github.com/dart-lang/sdk/blob/master/docs/process/experimental-flags.md',
'experimental-flags.md',
hide: hide, hide: hide,
); );
} }
...@@ -708,10 +719,10 @@ abstract class FlutterCommand extends Command<void> { ...@@ -708,10 +719,10 @@ abstract class FlutterCommand extends Command<void> {
argParser.addFlag( argParser.addFlag(
FlutterOptions.kAndroidGradleDaemon, FlutterOptions.kAndroidGradleDaemon,
help: 'Whether to enable the Gradle daemon when performing an Android build. ' help: 'Whether to enable the Gradle daemon when performing an Android build. '
'Starting the daemon is the default behavior of the gradle wrapper script created ' 'Starting the daemon is the default behavior of the gradle wrapper script created '
' in a Flutter project. Setting this flag to false corresponds to passing ' 'in a Flutter project. Setting this flag to false corresponds to passing '
"'--no-daemon' to the gradle wrapper script. This flag will cause the daemon " '"--no-daemon" to the gradle wrapper script. This flag will cause the daemon '
'process to terminate after the build is completed', 'process to terminate after the build is completed.',
defaultsTo: true, defaultsTo: true,
hide: hide, hide: hide,
); );
...@@ -725,13 +736,13 @@ abstract class FlutterCommand extends Command<void> { ...@@ -725,13 +736,13 @@ abstract class FlutterCommand extends Command<void> {
'the correct nullability of native (such as in dart:html) and external ' 'the correct nullability of native (such as in dart:html) and external '
'(such as with JS interop) types. This is enabled by default but only takes ' '(such as with JS interop) types. This is enabled by default but only takes '
'effect in sound mode. To report an issue with a null assertion failure in ' 'effect in sound mode. To report an issue with a null assertion failure in '
'dart:html or the other dart web libraries, please file a bug at ' 'dart:html or the other dart web libraries, please file a bug at: '
'https://github.com/dart-lang/sdk/issues/labels/web-libraries .' 'https://github.com/dart-lang/sdk/issues/labels/web-libraries'
); );
} }
/// Adds build options common to all of the desktop build commands. /// Adds build options common to all of the desktop build commands.
void addCommonDesktopBuildOptions({ bool verboseHelp = false }) { void addCommonDesktopBuildOptions({ @required bool verboseHelp }) {
addBuildModeFlags(verboseHelp: verboseHelp); addBuildModeFlags(verboseHelp: verboseHelp);
addBuildPerformanceFile(hide: !verboseHelp); addBuildPerformanceFile(hide: !verboseHelp);
addBundleSkSLPathOption(hide: !verboseHelp); addBundleSkSLPathOption(hide: !verboseHelp);
...@@ -742,7 +753,7 @@ abstract class FlutterCommand extends Command<void> { ...@@ -742,7 +753,7 @@ abstract class FlutterCommand extends Command<void> {
addTreeShakeIconsFlag(); addTreeShakeIconsFlag();
usesAnalyzeSizeFlag(); usesAnalyzeSizeFlag();
usesDartDefineOption(); usesDartDefineOption();
usesExtraDartFlagOptions(); usesExtraDartFlagOptions(verboseHelp: verboseHelp);
usesPubOption(); usesPubOption();
usesTargetOption(); usesTargetOption();
usesTrackWidgetCreation(verboseHelp: verboseHelp); usesTrackWidgetCreation(verboseHelp: verboseHelp);
...@@ -765,8 +776,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -765,8 +776,8 @@ abstract class FlutterCommand extends Command<void> {
releaseResult, releaseResult,
]; ];
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.', null);
} }
if (debugResult) { if (debugResult) {
return BuildMode.debug; return BuildMode.debug;
...@@ -807,10 +818,10 @@ abstract class FlutterCommand extends Command<void> { ...@@ -807,10 +818,10 @@ abstract class FlutterCommand extends Command<void> {
FlutterOptions.kAnalyzeSize, FlutterOptions.kAnalyzeSize,
defaultsTo: false, 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, '
'only the symbols from the arm64 architecture are used to analyze code size.\n' 'only the symbols from the arm64 architecture are used to analyze code size.\n'
'This flag cannot be combined with --split-debug-info.' 'This flag cannot be combined with "--${FlutterOptions.kSplitDebugInfoOption}".'
); );
} }
...@@ -914,10 +925,10 @@ abstract class FlutterCommand extends Command<void> { ...@@ -914,10 +925,10 @@ abstract class FlutterCommand extends Command<void> {
} }
final BuildMode buildMode = forcedBuildMode ?? getBuildMode(); final BuildMode buildMode = forcedBuildMode ?? getBuildMode();
if (buildMode != BuildMode.release && codeSizeDirectory != null) { if (buildMode != BuildMode.release && codeSizeDirectory != null) {
throwToolExit('--analyze-size can only be used on release builds.'); throwToolExit('"--${FlutterOptions.kAnalyzeSize}" can only be used on release builds.');
} }
if (codeSizeDirectory != null && splitDebugInfoPath != null) { if (codeSizeDirectory != null && splitDebugInfoPath != null) {
throwToolExit('--analyze-size cannot be combined with --split-debug-info.'); throwToolExit('"--${FlutterOptions.kAnalyzeSize}" cannot be combined with "--${FlutterOptions.kSplitDebugInfoOption}".');
} }
final bool treeShakeIcons = argParser.options.containsKey('tree-shake-icons') final bool treeShakeIcons = argParser.options.containsKey('tree-shake-icons')
......
...@@ -45,10 +45,13 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -45,10 +45,13 @@ class FlutterCommandRunner extends CommandRunner<void> {
abbr: 'v', abbr: 'v',
negatable: false, negatable: false,
help: 'Noisy logging, including all shell commands executed.\n' help: 'Noisy logging, including all shell commands executed.\n'
'If used with --help, shows hidden options.'); 'If used with "--help", shows hidden options. '
'If used with "flutter doctor", shows additional diagnostic information. '
'(Use "-vv" to force verbose logging in those cases.)');
argParser.addFlag('prefixed-errors', argParser.addFlag('prefixed-errors',
negatable: false, negatable: false,
hide: true, help: 'Causes lines sent to stderr to be prefixed with "ERROR:".',
hide: !verboseHelp,
defaultsTo: false); defaultsTo: false);
argParser.addFlag('quiet', argParser.addFlag('quiet',
negatable: false, negatable: false,
...@@ -62,8 +65,8 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -62,8 +65,8 @@ class FlutterCommandRunner extends CommandRunner<void> {
argParser.addOption('wrap-column', argParser.addOption('wrap-column',
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); defaultsTo: null);
argParser.addOption('device-id', argParser.addOption('device-id',
abbr: 'd', abbr: 'd',
...@@ -74,7 +77,7 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -74,7 +77,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
argParser.addFlag('machine', argParser.addFlag('machine',
negatable: false, negatable: false,
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, negatable: true,
hide: !verboseHelp, hide: !verboseHelp,
...@@ -106,7 +109,7 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -106,7 +109,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
hide: !verboseHelp, hide: !verboseHelp,
help: 'Name of a build output within the engine out directory, if you are building Flutter locally.\n' help: 'Name of a build output within the engine out directory, if you are building Flutter locally.\n'
'Use this to select a specific version of the engine if you have built multiple engine targets.\n' 'Use this to select a specific version of the engine if you have built multiple engine targets.\n'
'This path is relative to --local-engine-src-path/out.'); 'This path is relative to "--local-engine-src-path" or "--local-engine-src-out" (q.v.).');
if (verboseHelp) { if (verboseHelp) {
argParser.addSeparator('Options for testing the "flutter" tool itself:'); argParser.addSeparator('Options for testing the "flutter" tool itself:');
...@@ -114,12 +117,12 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -114,12 +117,12 @@ class FlutterCommandRunner extends CommandRunner<void> {
argParser.addFlag('show-test-device', argParser.addFlag('show-test-device',
negatable: false, negatable: false,
hide: !verboseHelp, hide: !verboseHelp,
help: "List the special 'flutter-tester' device in device listings. " help: 'List the special "flutter-tester" device in device listings. '
'This headless device is used to\ntest Flutter tooling.'); 'This headless device is used to test Flutter tooling.');
argParser.addFlag('show-web-server-device', argParser.addFlag('show-web-server-device',
negatable: false, negatable: false,
hide: !verboseHelp, hide: !verboseHelp,
help: "List the special 'web-server' device in device listings. " help: 'List the special "web-server" device in device listings.',
); );
} }
...@@ -275,7 +278,7 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -275,7 +278,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
} }
if (machineFlag) { if (machineFlag) {
throwToolExit('The --machine flag is only valid with the --version flag.', exitCode: 2); throwToolExit('The "--machine" flag is only valid with the "--version" flag.', exitCode: 2);
} }
await super.runCommand(topLevelResults); await super.runCommand(topLevelResults);
}, },
......
...@@ -434,7 +434,10 @@ void main() { ...@@ -434,7 +434,10 @@ void main() {
}); });
testUsingContext('upgrade continue prints welcome message', () async { testUsingContext('upgrade continue prints welcome message', () async {
final UpgradeCommand upgradeCommand = UpgradeCommand(fakeCommandRunner); final UpgradeCommand upgradeCommand = UpgradeCommand(
verboseHelp: false,
commandRunner: fakeCommandRunner,
);
await createTestCommandRunner(upgradeCommand).run( await createTestCommandRunner(upgradeCommand).run(
<String>[ <String>[
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// 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:args/command_runner.dart';
import 'package:flutter_tools/executable.dart' as executable;
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
import '../src/common.dart';
import '../src/testbed.dart';
void main() {
test('Help for command line arguments is consistently styled and complete', () => Testbed().run(() {
final FlutterCommandRunner runner = FlutterCommandRunner(verboseHelp: true);
executable.generateCommands(
verboseHelp: true,
verbose: true,
).forEach(runner.addCommand);
verifyCommandRunner(runner);
}));
}
void verifyCommandRunner(CommandRunner<Object> runner) {
expect(runner.argParser, isNotNull, reason: '${runner.runtimeType} has no argParser');
expect(runner.argParser.allowsAnything, isFalse, reason: '${runner.runtimeType} allows anything');
expect(runner.argParser.allowTrailingOptions, isFalse, reason: '${runner.runtimeType} allows trailing options');
verifyOptions('the global argument "', runner.argParser.options.values);
runner.commands.values.forEach(verifyCommand);
}
void verifyCommand(Command<Object> runner) {
expect(runner.argParser, isNotNull, reason: 'command ${runner.name} has no argParser');
verifyOptions('"flutter ${runner.name} ', runner.argParser.options.values);
runner.subcommands.values.forEach(verifyCommand);
}
// Patterns for arguments names.
// The "ExtraFrontEndOptions", "ExtraGenSnapshotOptions", and "DartDefines" cases are special cases
// that we should remove; search for "useLegacyNames" in commands/assemble.dart and other files.
// TODO(ianh): consider changing all underscores to hyphens in argument names when we can do aliases.
// That depends on being able to have argument aliases: https://github.com/dart-lang/args/issues/181
final RegExp _allowedArgumentNamePattern = RegExp(r'^([-a-z0-9_]+|ExtraFrontEndOptions|ExtraGenSnapshotOptions|DartDefines)$');
// Patterns for help messages.
final RegExp _bannedLeadingPatterns = RegExp(r'^[-a-z]', multiLine: true);
final RegExp _allowedTrailingPatterns = RegExp(r'([^ ][.!:]\)?|: https?://[^ ]+[^.]|^)$');
final RegExp _bannedQuotePatterns = RegExp(r" '|' |'\.|\('|'\)|`");
final RegExp _bannedArgumentReferencePatterns = RegExp(r'[^"=]--[^ ]');
final RegExp _questionablePatterns = RegExp(r'[a-z]\.[A-Z]');
const String _needHelp = 'Every option must have help explaining what it does, even if it\'s '
'for testing purposes, because this is the bare minimum of '
'documentation we can add just for ourselves. If it is not intended '
'for developers, then use "hide: !verboseHelp" to only show the '
'help when people run with "--help --verbose".';
const String _header = ' Comment: ';
void verifyOptions(String command, Iterable<Option> options) {
assert(command.contains('"'));
for (final Option option in options) {
// If you think you need to add an exception here, please ask Hixie (but he'll say no).
expect(option.name, matches(_allowedArgumentNamePattern), reason: '$_header$command--${option.name}" is not a valid name for a command line argument. (Is it all lowercase?)');
expect(option.hide, isFalse, reason: '${_header}Help for $command--${option.name}" is always hidden. $_needHelp');
expect(option.help, isNotNull, reason: '${_header}Help for $command--${option.name}" has null help. $_needHelp');
expect(option.help, isNotEmpty, reason: '${_header}Help for $command--${option.name}" has empty help. $_needHelp');
expect(option.help, isNot(matches(_bannedLeadingPatterns)), reason: '${_header}A line in the help for $command--${option.name}" starts with a lowercase letter. For stylistic consistency, all help messages must start with a capital letter.');
expect(option.help, isNot(startsWith('(Deprecated')), reason: '${_header}Help for $command--${option.name}" should start with lowercase "(deprecated)" for consistency with other deprecated commands.');
expect(option.help, isNot(startsWith('(Required')), reason: '${_header}Help for $command--${option.name}" should start with lowercase "(required)" for consistency with other deprecated commands.');
expect(option.help, isNot(contains('?')), reason: '${_header}Help for $command--${option.name}" has a question mark. Generally we prefer the passive voice for help messages.');
expect(option.help, isNot(contains('Note:')), reason: '${_header}Help for $command--${option.name}" uses "Note:". See our style guide entry about "empty prose".');
expect(option.help, isNot(contains('Note that')), reason: '${_header}Help for $command--${option.name}" uses "Note that". See our style guide entry about "empty prose".');
expect(option.help, isNot(matches(_bannedQuotePatterns)), reason: '${_header}Help for $command--${option.name}" uses single quotes or backticks instead of double quotes in the help message. For consistency we use double quotes throughout.');
expect(option.help, isNot(matches(_questionablePatterns)), reason: '${_header}Help for $command--${option.name}" may have a typo. (If it does not you may have to update args_test.dart, sorry. Search for "_questionablePatterns")');
if (option.defaultsTo != null) {
expect(option.help, isNot(contains('Default')), reason: '${_header}Help for $command--${option.name}" mentions the default value but that is redundant with the defaultsTo option which is also specified (and preferred).');
}
expect(option.help, isNot(matches(_bannedArgumentReferencePatterns)), reason: '${_header}Help for $command--${option.name}" contains the string "--" in an unexpected way. If it\'s trying to mention another argument, it should be quoted, as in "--foo".');
for (final String line in option.help.split('\n')) {
if (!line.startsWith(' ')) {
expect(line, isNot(contains(' ')), reason: '${_header}Help for $command--${option.name}" has excessive whitespace (check e.g. for double spaces after periods or round line breaks in the source).');
expect(line, matches(_allowedTrailingPatterns), reason: '${_header}A line in the help for $command--${option.name}" does not end with the expected period that a full sentence should end with. (If the help ends with a URL, place it after a colon, don\'t leave a trailing period; if it\'s sample code, prefix the line with four spaces.)');
}
}
expect(option.help, isNot(endsWith(':')), reason: '${_header}Help for $command--${option.name}" ends with a colon, which seems unlikely to be correct.');
// TODO(ianh): add some checking for embedded URLs to make sure we're consistent on how we format those.
// TODO(ianh): arguably we should ban help text that starts with "Whether to..." since by definition a flag is to enable a feature, so the "whether to" is redundant.
// TODO(ianh): consider looking for strings that use the term "URI" instead of "URL".
}
}
...@@ -96,7 +96,7 @@ void main() { ...@@ -96,7 +96,7 @@ void main() {
print(result.stdout); print(result.stdout);
print(result.stderr); print(result.stderr);
expect(result.stderr.toString(), contains('--analyze-size can only be used on release builds')); expect(result.stderr.toString(), contains('"--analyze-size" can only be used on release builds'));
expect(result.exitCode, 1); expect(result.exitCode, 1);
}); });
...@@ -113,7 +113,7 @@ void main() { ...@@ -113,7 +113,7 @@ void main() {
'--split-debug-info=infos' '--split-debug-info=infos'
], workingDirectory: fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world')); ], workingDirectory: fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world'));
expect(result.stderr.toString(), contains('--analyze-size cannot be combined with --split-debug-info')); expect(result.stderr.toString(), contains('"--analyze-size" cannot be combined with "--split-debug-info"'));
expect(result.exitCode, 1); expect(result.exitCode, 1);
}); });
......
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