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',
); );
} }
......
...@@ -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;
......
...@@ -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;
......
...@@ -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