diff --git a/dev/integration_tests/flutter_gallery/linux/flutter/CMakeLists.txt b/dev/integration_tests/flutter_gallery/linux/flutter/CMakeLists.txt index 9f236b5a57..5b465c7ecf 100644 --- a/dev/integration_tests/flutter_gallery/linux/flutter/CMakeLists.txt +++ b/dev/integration_tests/flutter_gallery/linux/flutter/CMakeLists.txt @@ -80,7 +80,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - linux-x64 ${CMAKE_BUILD_TYPE} + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 70499824e6..5961e876b9 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart @@ -89,96 +89,108 @@ Future main(List args) async { userMessages: UserMessages(), ); - await runner.run(args, () => [ - AnalyzeCommand( + await runner.run( + args, + () => generateCommands( verboseHelp: verboseHelp, - fileSystem: globals.fs, - platform: globals.platform, - processManager: globals.processManager, - logger: globals.logger, - terminal: globals.terminal, - artifacts: globals.artifacts, + verbose: verbose, ), - AssembleCommand(), - AttachCommand(verboseHelp: verboseHelp), - BuildCommand(verboseHelp: verboseHelp), - ChannelCommand(verboseHelp: verboseHelp), - CleanCommand(verbose: verbose), - ConfigCommand(verboseHelp: verboseHelp), - CreateCommand(), - DaemonCommand(hidden: !verboseHelp), - DevicesCommand(), - DoctorCommand(verbose: verbose), - DowngradeCommand(), - 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(), - SymbolizeCommand( - stdio: globals.stdio, - fileSystem: globals.fs, - ), - // Development-only commands. These are always hidden, - IdeConfigCommand(), - UpdatePackagesCommand(), - ], verbose: verbose, - muteCommandLogging: muteCommandLogging, - verboseHelp: verboseHelp, - overrides: { - // 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, - ); - } - }); + verbose: verbose, + muteCommandLogging: muteCommandLogging, + verboseHelp: verboseHelp, + overrides: { + // 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 generateCommands({ + @required bool verboseHelp, + @required bool verbose, +}) => [ + 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. /// /// Our logger class hierarchy and runtime requirements are overly complicated. diff --git a/packages/flutter_tools/lib/runner.dart b/packages/flutter_tools/lib/runner.dart index 7eb1be4b02..b9c84cf42d 100644 --- a/packages/flutter_tools/lib/runner.dart +++ b/packages/flutter_tools/lib/runner.dart @@ -25,9 +25,6 @@ import 'src/runner/flutter_command.dart'; import 'src/runner/flutter_command_runner.dart'; /// Runs the Flutter tool with support for the specified list of [commands]. -/// -/// [commands] must be either `List` or `List Function()`. -// TODO(jonahwilliams): update command type once g3 has rolled. Future run( List args, List Function() commands, { diff --git a/packages/flutter_tools/lib/src/commands/analyze.dart b/packages/flutter_tools/lib/src/commands/analyze.dart index 8b014f5e65..de98d99799 100644 --- a/packages/flutter_tools/lib/src/commands/analyze.dart +++ b/packages/flutter_tools/lib/src/commands/analyze.dart @@ -42,14 +42,14 @@ class AnalyzeCommand extends FlutterCommand { argParser.addFlag('dartdocs', negatable: false, 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); argParser.addFlag('watch', help: 'Run analysis continuously, watching the filesystem for changes.', negatable: false); argParser.addOption('write', 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.'); argParser.addOption('dart-sdk', valueHelp: 'path-to-sdk', @@ -67,13 +67,13 @@ class AnalyzeCommand extends FlutterCommand { // Not used by analyze --watch argParser.addFlag('congratulate', 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); argParser.addFlag('preamble', defaultsTo: true, help: 'When analyzing the flutter repository, display the number of ' 'files that will be analyzed.\n' - 'Ignored if --watch is specified.'); + 'Ignored if "--watch" is specified.'); argParser.addFlag('fatal-infos', negatable: true, help: 'Treat info level issues as fatal.', diff --git a/packages/flutter_tools/lib/src/commands/assemble.dart b/packages/flutter_tools/lib/src/commands/assemble.dart index 26412bf6f4..d7e72d74be 100644 --- a/packages/flutter_tools/lib/src/commands/assemble.dart +++ b/packages/flutter_tools/lib/src/commands/assemble.dart @@ -73,14 +73,20 @@ const List _kDefaultTargets = [ 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 /// system. class AssembleCommand extends FlutterCommand { - AssembleCommand() { + AssembleCommand({ bool verboseHelp = false }) { argParser.addMultiOption( 'define', 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( 'performance-measurement-file', @@ -89,28 +95,28 @@ class AssembleCommand extends FlutterCommand { argParser.addMultiOption( 'input', abbr: 'i', - help: 'Allows passing additional inputs with --input=key=value. Unlike ' - 'defines, additional inputs do not generate a new configuration, instead ' + help: 'Allows passing additional inputs with "--input=key=value". Unlike ' + 'defines, additional inputs do not generate a new configuration; instead ' 'they are treated as dependencies of the targets that use them.' ); - argParser.addOption('depfile', help: 'A file path where a depfile will be written. ' - 'This contains all build inputs and outputs in a make style syntax' + argParser.addOption('depfile', + 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 ' - 'separated 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' - ' written if the build fails for any reason.'); - argParser.addOption('build-outputs', help: 'A file path where a newline ' - 'separated file containing all outputs used will be written after a build.' - ' This file is not included as a build input or output. This file is not' - ' written if the build fails for any reason.'); + argParser.addOption('build-inputs', help: 'A file path where a newline-separated ' + '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 ' + 'written if the build fails for any reason.'); + argParser.addOption('build-outputs', help: 'A file path where a newline-separated ' + '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 ' + 'written if the build fails for any reason.'); argParser.addOption('output', abbr: 'o', help: 'A directory where output ' 'files will be written. Must be either absolute or relative from the ' 'root of the current Flutter project.', ); - argParser.addOption(kExtraGenSnapshotOptions); - argParser.addOption(kExtraFrontEndOptions); - argParser.addOption(kDartDefines); + usesExtraDartFlagOptions(verboseHelp: verboseHelp, useLegacyNames: useLegacyNames); + usesDartDefineOption(useLegacyNames: useLegacyNames); argParser.addOption( 'resource-pool-size', help: 'The maximum number of concurrent tasks the build system will run.', @@ -205,15 +211,14 @@ class AssembleCommand extends FlutterCommand { final String value = chunk.substring(indexEquals + 1); results[key] = value; } - // Workaround for extraGenSnapshot formatting. - if (argResults.wasParsed(kExtraGenSnapshotOptions)) { - results[kExtraGenSnapshotOptions] = argResults[kExtraGenSnapshotOptions] as String; + if (argResults.wasParsed(useLegacyNames ? kExtraGenSnapshotOptions : FlutterOptions.kExtraGenSnapshotOptions)) { + results[kExtraGenSnapshotOptions] = (argResults[useLegacyNames ? kExtraGenSnapshotOptions : FlutterOptions.kExtraGenSnapshotOptions] as List).join(','); } - if (argResults.wasParsed(kDartDefines)) { - results[kDartDefines] = argResults[kDartDefines] as String; + if (argResults.wasParsed(useLegacyNames ? kDartDefines : FlutterOptions.kDartDefinesOption)) { + results[kDartDefines] = (argResults[useLegacyNames ? kDartDefines : FlutterOptions.kDartDefinesOption] as List).join(','); } - if (argResults.wasParsed(kExtraFrontEndOptions)) { - results[kExtraFrontEndOptions] = argResults[kExtraFrontEndOptions] as String; + if (argResults.wasParsed(useLegacyNames ? kExtraFrontEndOptions : FlutterOptions.kExtraFrontEndOptions)) { + results[kExtraFrontEndOptions] = (argResults[useLegacyNames ? kExtraFrontEndOptions : FlutterOptions.kExtraFrontEndOptions] as List).join(','); } return results; } diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart index 3e9c25bdd3..6658c4a9c0 100644 --- a/packages/flutter_tools/lib/src/commands/attach.dart +++ b/packages/flutter_tools/lib/src/commands/attach.dart @@ -59,10 +59,10 @@ import '../vmservice.dart'; /// also be provided. class AttachCommand extends FlutterCommand { AttachCommand({bool verboseHelp = false, this.hotRunnerFactory}) { - addBuildModeFlags(defaultToRelease: false, excludeRelease: true); + addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false, excludeRelease: true); usesTargetOption(); - usesPortOptions(); - usesIpv6Flag(); + usesPortOptions(verboseHelp: verboseHelp); + usesIpv6Flag(verboseHelp: verboseHelp); usesFilesystemOptions(hide: !verboseHelp); usesFuchsiaOptions(hide: !verboseHelp); usesDartDefineOption(); @@ -73,13 +73,13 @@ class AttachCommand extends FlutterCommand { ..addOption( 'debug-port', hide: !verboseHelp, - help: 'Device port where the observatory is listening. Requires ' - '--disable-service-auth-codes to also be provided to the Flutter ' - 'application at launch, otherwise this command will fail to connect to ' - 'the application. In general, --debug-uri should be used instead.', + help: '(deprecated) Device port where the observatory is listening. Requires ' + '"--disable-service-auth-codes" to also be provided to the Flutter ' + 'application at launch, otherwise this command will fail to connect to ' + 'the application. In general, "--debug-uri" should be used instead.', )..addOption( - 'debug-uri', - help: 'The URI at which the observatory is listening.', + 'debug-uri', // TODO(ianh): we should support --debug-url as well (leaving this as an alias). + help: 'The URL at which the observatory is listening.', )..addOption( 'app-id', help: 'The package name (Android) or bundle identifier (iOS) for the app. ' @@ -99,7 +99,7 @@ class AttachCommand extends FlutterCommand { 'report-ready', help: 'Print "ready" to the console after handling a keyboard command.\n' 'This is primarily useful for tests and other automation, but consider ' - 'using --machine instead.', + 'using "--machine" instead.', hide: !verboseHelp, )..addOption( 'project-root', @@ -417,8 +417,8 @@ known, it can be explicitly provided to attach via the command-line, e.g. final FlutterDevice flutterDevice = await FlutterDevice.create( device, - fileSystemRoots: stringsArg('filesystem-root'), - fileSystemScheme: stringArg('filesystem-scheme'), + fileSystemRoots: stringsArg(FlutterOptions.kFileSystemRoot), + fileSystemScheme: stringArg(FlutterOptions.kFileSystemScheme), target: targetFile, targetModel: TargetModel(stringArg('target-model')), buildInfo: buildInfo, diff --git a/packages/flutter_tools/lib/src/commands/build_aar.dart b/packages/flutter_tools/lib/src/commands/build_aar.dart index 8f7d125d47..69884ad7d8 100644 --- a/packages/flutter_tools/lib/src/commands/build_aar.dart +++ b/packages/flutter_tools/lib/src/commands/build_aar.dart @@ -58,7 +58,7 @@ class BuildAarCommand extends BuildSubCommand { ..addOption( 'output-dir', help: 'The absolute path to the directory where the repository is generated. ' - "By default, this is 'android/build'. ", + 'By default, this is "android/build".', ); } diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart index ef2c22b208..0517911960 100644 --- a/packages/flutter_tools/lib/src/commands/build_apk.dart +++ b/packages/flutter_tools/lib/src/commands/build_apk.dart @@ -24,11 +24,11 @@ class BuildApkCommand extends BuildSubCommand { usesPubOption(); usesBuildNumberOption(); usesBuildNameOption(); - addShrinkingFlag(); + addShrinkingFlag(verboseHelp: verboseHelp); addSplitDebugInfoOption(); addDartObfuscationOption(); usesDartDefineOption(); - usesExtraDartFlagOptions(); + usesExtraDartFlagOptions(verboseHelp: verboseHelp); addBundleSkSLPathOption(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp); addBuildPerformanceFile(hide: !verboseHelp); diff --git a/packages/flutter_tools/lib/src/commands/build_appbundle.dart b/packages/flutter_tools/lib/src/commands/build_appbundle.dart index 157a9f665c..aa8c45f339 100644 --- a/packages/flutter_tools/lib/src/commands/build_appbundle.dart +++ b/packages/flutter_tools/lib/src/commands/build_appbundle.dart @@ -19,16 +19,16 @@ class BuildAppBundleCommand extends BuildSubCommand { BuildAppBundleCommand({bool verboseHelp = false}) { addTreeShakeIconsFlag(); usesTargetOption(); - addBuildModeFlags(); + addBuildModeFlags(verboseHelp: verboseHelp); usesFlavorOption(); usesPubOption(); usesBuildNumberOption(); usesBuildNameOption(); - addShrinkingFlag(); + addShrinkingFlag(verboseHelp: verboseHelp); addSplitDebugInfoOption(); addDartObfuscationOption(); usesDartDefineOption(); - usesExtraDartFlagOptions(); + usesExtraDartFlagOptions(verboseHelp: verboseHelp); addBundleSkSLPathOption(hide: !verboseHelp); addBuildPerformanceFile(hide: !verboseHelp); usesTrackWidgetCreation(verboseHelp: verboseHelp); diff --git a/packages/flutter_tools/lib/src/commands/build_bundle.dart b/packages/flutter_tools/lib/src/commands/build_bundle.dart index 347477ca06..3e797f414b 100644 --- a/packages/flutter_tools/lib/src/commands/build_bundle.dart +++ b/packages/flutter_tools/lib/src/commands/build_bundle.dart @@ -11,7 +11,7 @@ import '../features.dart'; import '../globals.dart' as globals; import '../project.dart'; import '../reporting/reporting.dart'; -import '../runner/flutter_command.dart' show FlutterCommandResult; +import '../runner/flutter_command.dart'; import 'build.dart'; class BuildBundleCommand extends BuildSubCommand { @@ -21,9 +21,13 @@ class BuildBundleCommand extends BuildSubCommand { usesFilesystemOptions(hide: !verboseHelp); usesBuildNumberOption(); addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false); - usesExtraDartFlagOptions(); + usesExtraDartFlagOptions(verboseHelp: verboseHelp); 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', defaultsTo: 'android-arm', allowed: const [ @@ -37,8 +41,13 @@ class BuildBundleCommand extends BuildSubCommand { 'linux-arm64', '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(); usesTrackWidgetCreation(verboseHelp: verboseHelp); @@ -112,8 +121,8 @@ class BuildBundleCommand extends BuildSubCommand { trackWidgetCreation: boolArg('track-widget-creation'), extraFrontEndOptions: buildInfo.extraFrontEndOptions, extraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions, - fileSystemScheme: stringArg('filesystem-scheme'), - fileSystemRoots: stringsArg('filesystem-root'), + fileSystemRoots: stringsArg(FlutterOptions.kFileSystemRoot), + fileSystemScheme: stringArg(FlutterOptions.kFileSystemScheme), treeShakeIcons: buildInfo.treeShakeIcons, ); return FlutterCommandResult.success(); diff --git a/packages/flutter_tools/lib/src/commands/build_ios.dart b/packages/flutter_tools/lib/src/commands/build_ios.dart index ec03765e7c..24f0ce627c 100644 --- a/packages/flutter_tools/lib/src/commands/build_ios.dart +++ b/packages/flutter_tools/lib/src/commands/build_ios.dart @@ -173,7 +173,7 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand { _BuildIOSSubCommand({ @required bool verboseHelp }) { addTreeShakeIconsFlag(); addSplitDebugInfoOption(); - addBuildModeFlags(defaultToRelease: true); + addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: true); usesTargetOption(); usesFlavorOption(); usesPubOption(); @@ -181,7 +181,7 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand { usesBuildNameOption(); addDartObfuscationOption(); usesDartDefineOption(); - usesExtraDartFlagOptions(); + usesExtraDartFlagOptions(verboseHelp: verboseHelp); addEnableExperimentation(hide: !verboseHelp); addBuildPerformanceFile(hide: !verboseHelp); addBundleSkSLPathOption(hide: !verboseHelp); diff --git a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart index 46211b5263..9854989e1c 100644 --- a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart +++ b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart @@ -50,7 +50,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { usesDartDefineOption(); addSplitDebugInfoOption(); addDartObfuscationOption(); - usesExtraDartFlagOptions(); + usesExtraDartFlagOptions(verboseHelp: verboseHelp); addNullSafetyModeOptions(hide: !verboseHelp); addEnableExperimentation(hide: !verboseHelp); @@ -74,15 +74,15 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { 'By default, all build configurations are built.' ) ..addFlag('universal', - help: '(Deprecated) Produce universal frameworks that include all valid architectures.', + help: '(deprecated) Produce universal frameworks that include all valid architectures.', negatable: true, - hide: true, + hide: !verboseHelp, ) ..addFlag('xcframework', help: 'Produce xcframeworks that include all valid architectures.', negatable: false, defaultsTo: true, - hide: true, + hide: !verboseHelp, ) ..addFlag('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 { ) ..addFlag('force', abbr: 'f', - help: 'Force Flutter.podspec creation on the master channel. For testing only.', - hide: true + help: 'Force Flutter.podspec creation on the master channel. This is only intended for testing the tool itself.', + hide: !verboseHelp, ); } diff --git a/packages/flutter_tools/lib/src/commands/build_web.dart b/packages/flutter_tools/lib/src/commands/build_web.dart index 5756232961..d6b367e25d 100644 --- a/packages/flutter_tools/lib/src/commands/build_web.dart +++ b/packages/flutter_tools/lib/src/commands/build_web.dart @@ -23,7 +23,7 @@ class BuildWebCommand extends BuildSubCommand { addTreeShakeIconsFlag(enabledByDefault: false); usesTargetOption(); usesPubOption(); - addBuildModeFlags(excludeDebug: true); + addBuildModeFlags(verboseHelp: verboseHelp, excludeDebug: true); usesDartDefineOption(); usesWebRendererOption(); addEnableExperimentation(hide: !verboseHelp); @@ -33,30 +33,31 @@ class BuildWebCommand extends BuildSubCommand { defaultsTo: false, negatable: false, 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( 'source-maps', defaultsTo: false, - help: 'Whether to generate a sourcemap file. These can be used by browsers ' - 'To view and debug the original source code of a compiled and minified Dart ' - 'application. Defaults to false (i.e. no sourcemaps produced).' + 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 ' + 'application.' ); argParser.addOption('pwa-strategy', defaultsTo: kOfflineFirst, - help: - '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', + help: 'The caching strategy to be used by the PWA service worker.', allowed: [ kOfflineFirst, kNoneWorker, - ] + ], + allowedHelp: { + 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', + }, ); } diff --git a/packages/flutter_tools/lib/src/commands/config.dart b/packages/flutter_tools/lib/src/commands/config.dart index d9f44b9355..9e635586e2 100644 --- a/packages/flutter_tools/lib/src/commands/config.dart +++ b/packages/flutter_tools/lib/src/commands/config.dart @@ -22,7 +22,7 @@ class ConfigCommand extends FlutterCommand { 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-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/'); argParser.addFlag('machine', negatable: false, diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart index bbbac69f28..5f1e551470 100644 --- a/packages/flutter_tools/lib/src/commands/create.dart +++ b/packages/flutter_tools/lib/src/commands/create.dart @@ -23,10 +23,12 @@ import '../runner/flutter_command.dart'; import 'create_base.dart'; class CreateCommand extends CreateBase { - CreateCommand() { + CreateCommand({ + bool verboseHelp = false, + }) : super(verboseHelp: verboseHelp) { 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. ' + '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. ' 'Adding desktop platforms requires the corresponding desktop config setting to be enabled.'); argParser.addOption( @@ -50,17 +52,17 @@ class CreateCommand extends CreateBase { argParser.addOption( 'sample', abbr: 's', - 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 ' - 'documentation website (http://docs.flutter.dev). An example can be found at ' - 'https://master-api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html', + 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 ' + 'documentation website (http://docs.flutter.dev/). An example can be found at: ' + 'https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html', defaultsTo: null, valueHelp: 'id', ); argParser.addOption( 'list-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', ); } @@ -218,7 +220,7 @@ class CreateCommand extends CreateBase { if (boolArg('with-driver-test')) { 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 ' 'visiting https://pub.dev/packages/integration_test .' ); diff --git a/packages/flutter_tools/lib/src/commands/create_base.dart b/packages/flutter_tools/lib/src/commands/create_base.dart index 63b66e6941..2ebc0d5c2a 100644 --- a/packages/flutter_tools/lib/src/commands/create_base.dart +++ b/packages/flutter_tools/lib/src/commands/create_base.dart @@ -32,13 +32,15 @@ const List _kAvailablePlatforms = [ ]; 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. ' 'Adding desktop platforms requires the corresponding desktop config setting to be enabled.'; /// Common behavior for `flutter create` commands. abstract class CreateBase extends FlutterCommand { - CreateBase() { + CreateBase({ + @required bool verboseHelp, + }) { argParser.addFlag( 'pub', defaultsTo: true, @@ -57,9 +59,10 @@ abstract class CreateBase extends FlutterCommand { 'with-driver-test', negatable: true, defaultsTo: false, - help: '(Deprecated) Also add a flutter_driver dependency and generate a ' - "sample 'flutter drive' test. This flag has been deprecated, instead see " - 'package:integration_test at https://pub.dev/packages/integration_test .', + help: '(deprecated) Historically, this added a flutter_driver dependency and generated a ' + 'sample "flutter drive" test. Now it does nothing. Consider using the ' + '"integration_test" package: https://pub.dev/packages/integration_test', + hide: !verboseHelp, ); argParser.addFlag( 'overwrite', @@ -91,19 +94,21 @@ abstract class CreateBase extends FlutterCommand { abbr: 'i', defaultsTo: 'swift', allowed: ['objc', 'swift'], + help: 'The language to use for iOS-specific code, either ObjectiveC (legacy) or Swift (recommended).' ); argParser.addOption( 'android-language', abbr: 'a', defaultsTo: 'kotlin', allowed: ['java', 'kotlin'], + help: 'The language to use for Android-specific code, either Java (legacy) or Kotlin (recommended).', ); argParser.addFlag( 'skip-name-checks', help: - 'integration test only parameter to allow creating applications/plugins with ' - 'invalid names.', - hide: true, + 'Allow the creation of applications and plugins with invalid names. ' + 'This is only intended to enable testing of the tool itself.', + hide: !verboseHelp, ); } diff --git a/packages/flutter_tools/lib/src/commands/devices.dart b/packages/flutter_tools/lib/src/commands/devices.dart index 73d4267daa..afe635bcca 100644 --- a/packages/flutter_tools/lib/src/commands/devices.dart +++ b/packages/flutter_tools/lib/src/commands/devices.dart @@ -12,17 +12,17 @@ import '../globals.dart' as globals; import '../runner/flutter_command.dart'; class DevicesCommand extends FlutterCommand { - - DevicesCommand() { + DevicesCommand({ bool verboseHelp = false }) { argParser.addFlag('machine', negatable: false, - help: 'Output device information in machine readable structured JSON format', + help: 'Output device information in machine readable structured JSON format.', ); argParser.addOption( 'timeout', abbr: 't', defaultsTo: null, - help: '(deprecated) Use --device-timeout instead', + help: '(deprecated) This option has been replaced by "--${FlutterOptions.kDeviceTimeout}".', + hide: !verboseHelp, ); usesDeviceTimeoutOption(); } @@ -38,7 +38,7 @@ class DevicesCommand extends FlutterCommand { if (argResults['timeout'] != null) { final int timeoutSeconds = int.tryParse(stringArg('timeout')); 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); } @@ -48,7 +48,7 @@ class DevicesCommand extends FlutterCommand { @override Future validateCommand() { 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(); } diff --git a/packages/flutter_tools/lib/src/commands/downgrade.dart b/packages/flutter_tools/lib/src/commands/downgrade.dart index 71dfec2bd0..e6dee4142a 100644 --- a/packages/flutter_tools/lib/src/commands/downgrade.dart +++ b/packages/flutter_tools/lib/src/commands/downgrade.dart @@ -30,6 +30,7 @@ import '../version.dart'; /// the command would fail since there was no previously recorded stable version. class DowngradeCommand extends FlutterCommand { DowngradeCommand({ + bool verboseHelp = false, PersistentToolState persistentToolState, Logger logger, ProcessManager processManager, @@ -46,14 +47,17 @@ class DowngradeCommand extends FlutterCommand { _fileSystem = fileSystem { argParser.addOption( 'working-directory', - hide: true, - help: 'Override the downgrade working directory for integration testing.' + hide: !verboseHelp, + help: 'Override the downgrade working directory. ' + 'This is only intended to enable integration testing of the tool itself.' ); argParser.addFlag( 'prompt', defaultsTo: true, - hide: true, - help: 'Disable the downgrade prompt for integration testing.' + hide: !verboseHelp, + 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 { @override Future 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, // at least until the zone injection is refactored. _terminal ??= globals.terminal; diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart index 6689b80b77..be6e318e2f 100644 --- a/packages/flutter_tools/lib/src/commands/drive.dart +++ b/packages/flutter_tools/lib/src/commands/drive.dart @@ -52,7 +52,8 @@ class DriveCommand extends RunCommandBase { @required Logger logger, }) : _flutterDriverFactory = flutterDriverFactory, _fileSystem = fileSystem, - _logger = logger { + _logger = logger, + super(verboseHelp: verboseHelp) { requiresPubspecYaml(); addEnableExperimentation(hide: !verboseHelp); @@ -65,14 +66,14 @@ class DriveCommand extends RunCommandBase { defaultsTo: null, help: 'Will keep the Flutter application running when done testing.\n' '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 ' - 'running, and --no-keep-app-running overrides it.', + 'running, and "--no-keep-app-running" overrides it.', ) ..addOption('use-existing-app', help: 'Connect to an already running instance via the given observatory URL. ' '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', ) ..addOption('driver', @@ -86,23 +87,21 @@ class DriveCommand extends RunCommandBase { ) ..addFlag('build', defaultsTo: true, - help: '(Deprecated) Build the app before running. To use an existing app, pass the --use-application-binary ' - 'flag with an existing APK', + help: '(deprecated) Build the app before running. To use an existing app, pass the "--use-application-binary" ' + 'flag with an existing APK.', ) ..addOption('driver-port', 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' ) ..addFlag('headless', 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', defaultsTo: 'chrome', - help: 'Name of browser where tests will be executed. \n' - 'Following browsers are supported: \n' - 'Chrome, Firefox, Safari (macOS and iOS) and Edge. Defaults to Chrome.', + help: 'Name of the browser where tests will be executed.', allowed: [ 'android-chrome', 'chrome', @@ -111,24 +110,31 @@ class DriveCommand extends RunCommandBase { 'ios-safari', 'safari', ], + allowedHelp: { + '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', defaultsTo: '1600,1024', - help: 'The dimension of browser when running Flutter Web test. \n' - 'This will affect screenshot and all offset-related actions. \n' - 'By default. it is set to 1600,1024 (1600 by 1024).', + help: 'The dimension of the browser when running a Flutter Web test. ' + 'This will affect screenshot and all offset-related actions.', + valueHelp: 'width,height', ) ..addFlag('android-emulator', defaultsTo: true, - help: 'Whether to perform Flutter Driver testing on Android Emulator.' - 'Works only if \'browser-name\' is set to \'android-chrome\'') + help: 'Whether to perform Flutter Driver testing using an Android Emulator. ' + 'Works only if "browser-name" is set to "android-chrome".') ..addOption('chrome-binary', - help: 'Location of Chrome binary. ' - 'Works only if \'browser-name\' is set to \'chrome\'') + help: 'Location of the Chrome binary. ' + 'Works only if "browser-name" is set to "chrome".') ..addOption('write-sksl-on-exit', - help: - 'Attempts to write an SkSL file when the drive process is finished ' - 'to the provided file, overwriting it if necessary.') + help: 'Attempts to write an SkSL file when the drive process is finished ' + 'to the provided file, overwriting it if necessary.') ..addMultiOption('test-arguments', help: 'Additional arguments to pass to the ' 'Dart VM running The test script.'); } diff --git a/packages/flutter_tools/lib/src/commands/emulators.dart b/packages/flutter_tools/lib/src/commands/emulators.dart index 44827210f1..caafe6313a 100644 --- a/packages/flutter_tools/lib/src/commands/emulators.dart +++ b/packages/flutter_tools/lib/src/commands/emulators.dart @@ -19,7 +19,7 @@ class EmulatorsCommand extends FlutterCommand { help: 'Creates a new Android emulator based on a Pixel device.', negatable: false); 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 diff --git a/packages/flutter_tools/lib/src/commands/format.dart b/packages/flutter_tools/lib/src/commands/format.dart index cd2f32ebb7..cf6d292cd1 100644 --- a/packages/flutter_tools/lib/src/commands/format.dart +++ b/packages/flutter_tools/lib/src/commands/format.dart @@ -30,7 +30,8 @@ class FormatCommand extends FlutterCommand { ); argParser.addOption('line-length', abbr: 'l', - help: 'Wrap lines longer than this length. Defaults to 80 characters.', + help: 'Wrap lines longer than this length.', + valueHelp: 'characters', defaultsTo: '80', ); } diff --git a/packages/flutter_tools/lib/src/commands/generate_localizations.dart b/packages/flutter_tools/lib/src/commands/generate_localizations.dart index 9a9c23d922..47775b5d0f 100644 --- a/packages/flutter_tools/lib/src/commands/generate_localizations.dart +++ b/packages/flutter_tools/lib/src/commands/generate_localizations.dart @@ -34,134 +34,143 @@ class GenerateLocalizationsCommand extends FlutterCommand { argParser.addOption( 'output-dir', help: 'The directory where the generated localization classes will be written ' - 'if the synthetic-package flag is set to false.' - '\n\n' - 'If output-dir is specified and the synthetic-package flag is enabled, ' - 'this option will be ignored by the tool.' - '\n\n' - 'The app must import the file specified in the \'output-localization-file\' ' - 'option from this directory. If unspecified, this defaults to the same ' - 'directory as the input directory specified in \'arb-dir\'.', + 'if the synthetic-package flag is set to false.\n' + '\n' + 'If output-dir is specified and the synthetic-package flag is enabled, ' + 'this option will be ignored by the tool.\n' + '\n' + 'The app must import the file specified in the "--output-localization-file" ' + 'option from this directory. If unspecified, this defaults to the same ' + 'directory as the input directory specified in "--arb-dir".', ); argParser.addOption( 'template-arb-file', defaultsTo: 'app_en.arb', 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( 'output-localization-file', defaultsTo: 'app_localizations.dart', help: 'The filename for the output localization and localizations ' - 'delegate classes.', + 'delegate classes.', ); argParser.addOption( 'untranslated-messages-file', - help: 'The location of a file that describes the localization\n' - 'messages have not been translated yet. Using this option will create\n' - 'a JSON file at the target location, in the following format:\n\n' - '"locale": ["message_1", "message_2" ... "message_n"]\n\n' - 'If this option is not specified, a summary of the messages that\n' - 'have not been translated will be printed on the command line.' + help: 'The location of a file that describes the localization ' + 'messages have not been translated yet. Using this option will create ' + 'a JSON file at the target location, in the following format:\n' + '\n' + ' "locale": ["message_1", "message_2" ... "message_n"]\n' + '\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( 'output-class', defaultsTo: 'AppLocalizations', help: 'The Dart class name to use for the output localization and ' - 'localizations delegate classes.', + 'localizations delegate classes.', ); argParser.addMultiOption( 'preferred-supported-locales', valueHelp: 'locale', help: 'The list of preferred supported locales for the application. ' - 'By default, the tool will generate the supported locales list in ' - 'alphabetical order. Use this flag if you would like to default to ' - 'a different locale. \n\n' - 'For example, pass in `en_US` if you would like your app to ' - 'default to American English if a device supports it.' - '(Pass this option multiple times for defining multiple items', + 'By default, the tool will generate the supported locales list in ' + 'alphabetical order. Use this flag if you would like to default to ' + 'a different locale. ' + 'For example, pass in "en_US" if you would like your app to ' + 'default to American English on devices that support it. ' + 'Pass this option multiple times to define multiple items.', ); argParser.addOption( 'header', help: 'The header to prepend to the generated Dart localizations ' - 'files. This option takes in a string. \n\n' - 'For example, pass in "/// All localized files." if you would ' - 'like this string prepended to the generated Dart file. \n\n' - 'Alternatively, see the `header-file` option to pass in a text ' - 'file for longer headers.' + 'files. This option takes in a string.\n' + '\n' + 'For example, pass in "/// All localized files." if you would ' + 'like this string prepended to the generated Dart file.\n' + '\n' + 'Alternatively, see the "--header-file" option to pass in a text ' + 'file for longer headers.' ); argParser.addOption( 'header-file', help: 'The header to prepend to the generated Dart localizations ' - 'files. The value of this option is the name of the file that ' - 'contains the header text which will be inserted at the top ' - 'of each generated Dart file. \n\n' - 'Alternatively, see the `header` option to pass in a string ' - 'for a simpler header. \n\n' - 'This file should be placed in the directory specified in \'arb-dir\'.' + 'files. The value of this option is the name of the file that ' + 'contains the header text which will be inserted at the top ' + 'of each generated Dart file.\n' + '\n' + 'Alternatively, see the "--header" option to pass in a string ' + 'for a simpler header.\n' + '\n' + 'This file should be placed in the directory specified in "--arb-dir".' ); argParser.addFlag( 'use-deferred-loading', defaultsTo: false, - help: 'Whether to generate the Dart localization file with locales imported' - ' as deferred, allowing for lazy loading of each locale in Flutter web.\n' - '\n' - '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 ' - '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 ' - 'locales and many localization strings, it can be an performance ' - 'improvement to have deferred loading. For projects with a small number ' - 'of locales, the difference is negligible, and might slow down the start ' - 'up compared to bundling the localizations with the rest of the ' - 'application.\n\n' - 'Note that this flag does not affect other platforms such as mobile or ' - 'desktop.', + help: 'Whether to generate the Dart localization file with locales imported ' + 'as deferred, allowing for lazy loading of each locale in Flutter web.\n' + '\n' + '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 ' + '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 ' + 'locales and many localization strings, it can be an performance ' + 'improvement to have deferred loading. For projects with a small number ' + 'of locales, the difference is negligible, and might slow down the start ' + 'up compared to bundling the localizations with the rest of the ' + 'application.\n' + '\n' + 'This flag does not affect other platforms such as mobile or desktop.', ); argParser.addOption( 'gen-inputs-and-outputs-list', valueHelp: 'path-to-output-directory', help: 'When specified, the tool generates a JSON file containing the ' - 'tool\'s inputs and outputs named gen_l10n_inputs_and_outputs.json.' - '\n\n' - 'This can be useful for keeping track of which files of the Flutter ' - 'project were used when generating the latest set of localizations. ' - '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' - 'The value of this option is the directory where the JSON file will be ' - 'generated.' - '\n\n' - 'When null, the JSON file will not be generated.' + 'tool\'s inputs and outputs named gen_l10n_inputs_and_outputs.json.\n' + '\n' + 'This can be useful for keeping track of which files of the Flutter ' + 'project were used when generating the latest set of localizations. ' + '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' + 'The value of this option is the directory where the JSON file will be ' + 'generated.\n' + '\n' + 'When null, the JSON file will not be generated.' ); argParser.addFlag( 'synthetic-package', defaultsTo: true, help: 'Determines whether or not the generated output files will be ' - 'generated as a synthetic package or at a specified directory in ' - 'the Flutter project.' - '\n\n' - 'This flag is set to true by default.' - '\n\n' - 'When synthetic-package is set to false, it will generate the ' - 'localizations files in the directory specified by arb-dir by default. ' - '\n\n' - 'If output-dir is specified, files will be generated there.', + 'generated as a synthetic package or at a specified directory in ' + 'the Flutter project.\n' + '\n' + 'This flag is set to true by default.\n' + '\n' + 'When synthetic-package is set to false, it will generate the ' + 'localizations files in the directory specified by arb-dir by default.\n' + '\n' + 'If output-dir is specified, files will be generated there.', ); argParser.addOption( 'project-dir', valueHelp: 'absolute/path/to/flutter/project', help: 'When specified, the tool uses the path passed into this option ' - 'as the directory of the root Flutter project.' - '\n\n' - 'When null, the relative path to the present working directory will be used.' + 'as the directory of the root Flutter project.\n' + '\n' + 'When null, the relative path to the present working directory will be used.' ); argParser.addFlag( 'required-resource-attributes', - help: 'Requires all resource ids to contain a corresponding resource attribute.\n\n' - 'By default, simple messages will not require metadata, but it is highly ' - 'recommended as this provides context for the meaning of a message to ' - 'readers.\n\n' - 'Resource attributes are still required for plural messages.' + help: 'Requires all resource ids to contain a corresponding resource attribute.\n' + '\n' + 'By default, simple messages will not require metadata, but it is highly ' + 'recommended as this provides context for the meaning of a message to ' + 'readers.\n' + '\n' + 'Resource attributes are still required for plural messages.' ); } diff --git a/packages/flutter_tools/lib/src/commands/ide_config.dart b/packages/flutter_tools/lib/src/commands/ide_config.dart index 723bac0b8e..d6fa7b185c 100644 --- a/packages/flutter_tools/lib/src/commands/ide_config.dart +++ b/packages/flutter_tools/lib/src/commands/ide_config.dart @@ -23,19 +23,19 @@ class IdeConfigCommand extends FlutterCommand { 'update-templates', negatable: false, help: 'Update the templates in the template directory from the current ' - 'configuration files. This is the opposite of what $name usually does. ' - 'Will search the flutter tree for .iml files and copy any missing ones ' - 'into the template directory. If --overwrite is also specified, it will ' - 'update any out-of-date files, and remove any deleted files from the ' - 'template directory.', + 'configuration files. This is the opposite of what $name usually does. ' + 'Will search the flutter tree for *.iml files and copy any missing ones ' + 'into the template directory. If "--overwrite" is also specified, it will ' + 'update any out-of-date files, and remove any deleted files from the ' + 'template directory.', ); argParser.addFlag( 'with-root-module', negatable: true, defaultsTo: true, help: 'Also create module that corresponds to the root of Flutter tree. ' - 'This makes the entire Flutter tree browsable and searchable in IDE. ' - 'Without this flag, only the child modules will be visible 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.', ); } diff --git a/packages/flutter_tools/lib/src/commands/precache.dart b/packages/flutter_tools/lib/src/commands/precache.dart index d631ade1b4..5d15a0a0ea 100644 --- a/packages/flutter_tools/lib/src/commands/precache.dart +++ b/packages/flutter_tools/lib/src/commands/precache.dart @@ -32,7 +32,7 @@ class PrecacheCommand extends FlutterCommand { help: 'Force re-downloading of artifacts.'); argParser.addFlag('android', negatable: true, defaultsTo: false, help: 'Precache artifacts for Android development.', - hide: verboseHelp); + hide: !verboseHelp); argParser.addFlag('android_gen_snapshot', negatable: true, defaultsTo: false, help: 'Precache gen_snapshot for Android development.', hide: !verboseHelp); @@ -57,9 +57,9 @@ class PrecacheCommand extends FlutterCommand { argParser.addFlag('universal', negatable: true, defaultsTo: true, help: 'Precache artifacts required for any development platform.'); 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, - help: 'Precache the unsigned mac binaries when available.', hide: true); + help: 'Precache the unsigned macOS binaries when available.', hide: !verboseHelp); } final Cache _cache; diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index 982e67cd2a..6d068fd647 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -31,8 +31,8 @@ import 'daemon.dart'; /// Shared logic between `flutter run` and `flutter drive` commands. abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopmentArtifacts { - RunCommandBase({ bool verboseHelp = false }) { - addBuildModeFlags(defaultToRelease: false, verboseHelp: verboseHelp); + RunCommandBase({ @required bool verboseHelp }) { + addBuildModeFlags(verboseHelp: verboseHelp, defaultToRelease: false); usesDartDefineOption(); usesFlavorOption(); usesWebRendererOption(); @@ -44,44 +44,45 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment ) ..addFlag('verbose-system-logs', negatable: false, - help: 'Include verbose logging from the flutter engine.', + help: 'Include verbose logging from the Flutter engine.', ) ..addFlag('cache-sksl', 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', negatable: false, help: 'Automatically dump the skp that triggers new shader compilations. ' - 'This is useful for writing custom ShaderWarmUp to reduce jank. ' - 'By default, this is not enabled to reduce the overhead. ' - 'This is only available in profile or debug build. ', + 'This is useful for writing custom ShaderWarmUp to reduce jank. ' + 'By default, this is not enabled as it introduces significant overhead. ' + 'This is only available in profile or debug builds.', ) ..addFlag('purge-persistent-cache', negatable: false, help: 'Removes all existing persistent caches. This allows reproducing ' - 'shader compilation jank that normally only happens the first time ' - 'an app is run, or for reliable testing of compilation jank fixes ' - '(e.g. shader warm-up).', + 'shader compilation jank that normally only happens the first time ' + 'an app is run, or for reliable testing of compilation jank fixes ' + '(e.g. shader warm-up).', ) ..addOption('route', help: 'Which route to load when running the app.', ) ..addOption('vmservice-out-file', - help: 'A file to write the attached vmservice uri to after an' - ' application is started.', - valueHelp: 'project/example/out.txt' + help: 'A file to write the attached vmservice URL to after an ' + 'application is started.', + valueHelp: 'project/example/out.txt', + hide: !verboseHelp, ) ..addFlag('disable-service-auth-codes', negatable: false, hide: !verboseHelp, - help: 'No longer require an authentication code to connect to the VM ' - '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!)' ) ..addOption('use-application-binary', - 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 ' - 'do not yet support prebuilt application binaries', + 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 ' + 'do not yet support prebuilt application binaries.', valueHelp: 'path/to/app.apk', ) ..addFlag('start-paused', @@ -101,10 +102,9 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment ) ..addFlag('endless-trace-buffer', negatable: false, - help: 'Enable tracing to the endless tracer. This is useful when ' - 'recording huge amounts of traces. If we need to use endless buffer to ' - 'record startup traces, we can combine the ("--trace-startup"). ' - 'For example, flutter run --trace-startup --endless-trace-buffer. ', + help: 'Enable tracing to an infinite buffer, instead of a ring buffer. ' + 'This is useful when recording large traces. To use an endless buffer to ' + 'record startup traces, combine this with "--trace-startup".', ) ..addFlag('trace-systrace', negatable: false, @@ -115,12 +115,13 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment negatable: false, help: 'Enable tracing of Skia code. This is useful when debugging ' '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', - hide: true, + hide: !verboseHelp, 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', ) ..addMultiOption('dart-entrypoint-args', @@ -129,11 +130,12 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment 'startup. By default this is main(List args). Specify ' 'this option multiple times each with one argument to pass ' 'multiple arguments to the Dart entrypoint. Currently this is ' - 'only supported on desktop platforms.'); - usesWebOptions(hide: !verboseHelp); + 'only supported on desktop platforms.' + ); + usesWebOptions(verboseHelp: verboseHelp); usesTargetOption(); - usesPortOptions(); - usesIpv6Flag(); + usesPortOptions(verboseHelp: verboseHelp); + usesIpv6Flag(verboseHelp: verboseHelp); usesPubOption(); usesTrackWidgetCreation(verboseHelp: verboseHelp); addNullSafetyModeOptions(hide: !verboseHelp); @@ -227,7 +229,7 @@ class RunCommand extends RunCommandBase { RunCommand({ bool verboseHelp = false }) : super(verboseHelp: verboseHelp) { requiresPubspecYaml(); usesFilesystemOptions(hide: !verboseHelp); - usesExtraDartFlagOptions(); + usesExtraDartFlagOptions(verboseHelp: verboseHelp); addEnableExperimentation(hide: !verboseHelp); // By default, the app should to publish the VM service port over mDNS. @@ -244,8 +246,9 @@ class RunCommand extends RunCommandBase { ) ..addFlag('skia-deterministic-rendering', negatable: false, - help: 'When combined with --enable-software-rendering, provides 100% ' - 'deterministic Skia rendering.', + help: 'When combined with "--enable-software-rendering", this should provide completely ' + 'deterministic (i.e. reproducible) Skia rendering. This is useful for testing purposes ' + '(e.g. when comparing screenshots).', ) ..addFlag('await-first-frame-when-tracing', defaultsTo: true, @@ -253,7 +256,7 @@ class RunCommand extends RunCommandBase { '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 ' '"${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', negatable: true, @@ -298,7 +301,7 @@ class RunCommand extends RunCommandBase { 'report-ready', help: 'Print "ready" to the console after handling a keyboard command.\n' 'This is primarily useful for tests and other automation, but consider ' - 'using --machine instead.', + 'using "--machine" instead.', hide: !verboseHelp, )..addFlag('benchmark', negatable: false, @@ -308,12 +311,6 @@ class RunCommand extends RunCommandBase { 'results out to "refresh_benchmark.json", and exit. This flag is ' '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 // is slower for certain use cases. // See: https://github.com/flutter/flutter/issues/49499 @@ -322,7 +319,8 @@ class RunCommand extends RunCommandBase { defaultsTo: false, help: 'Whether to quickly bootstrap applications with a minimal app. ' '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 { throwToolExit(null); } 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 @@ -523,7 +521,7 @@ class RunCommand extends RunCommandBase { if (boolArg('machine')) { if (devices.length > 1) { - throwToolExit('--machine does not support -d all.'); + throwToolExit('"--machine" does not support "-d all".'); } final Daemon daemon = Daemon( stdinCommandStream, @@ -574,7 +572,7 @@ class RunCommand extends RunCommandBase { } if (hotMode) { 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) { @@ -602,8 +600,8 @@ class RunCommand extends RunCommandBase { for (final Device device in devices) await FlutterDevice.create( device, - fileSystemRoots: stringsArg('filesystem-root'), - fileSystemScheme: stringArg('filesystem-scheme'), + fileSystemRoots: stringsArg(FlutterOptions.kFileSystemRoot), + fileSystemScheme: stringArg(FlutterOptions.kFileSystemScheme), experimentalFlags: expFlags, target: targetFile, buildInfo: buildInfo, diff --git a/packages/flutter_tools/lib/src/commands/screenshot.dart b/packages/flutter_tools/lib/src/commands/screenshot.dart index d9aaeb37ab..d88758a306 100644 --- a/packages/flutter_tools/lib/src/commands/screenshot.dart +++ b/packages/flutter_tools/lib/src/commands/screenshot.dart @@ -16,7 +16,7 @@ import '../vmservice.dart'; const String _kOut = 'out'; 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 _kSkiaType = 'skia'; const String _kRasterizerType = 'rasterizer'; @@ -32,9 +32,9 @@ class ScreenshotCommand extends FlutterCommand { argParser.addOption( _kObservatoryUri, valueHelp: 'URI', - help: 'The observatory URI to connect to.\n' - 'This is required when --$_kType is "$_kSkiaType" or "$_kRasterizerType".\n' - 'To find the observatory URI, use "flutter run" and look for ' + help: 'The Observatory URL to which to connect.\n' + 'This is required when "--$_kType" is "$_kSkiaType" or "$_kRasterizerType".\n' + 'To find the Observatory URL, use "flutter run" and look for ' '"An Observatory ... is available at" in the output.', ); argParser.addOption( @@ -43,11 +43,11 @@ class ScreenshotCommand extends FlutterCommand { help: 'The type of screenshot to retrieve.', allowed: const [_kDeviceType, _kSkiaType, _kRasterizerType], allowedHelp: const { - _kDeviceType: "Delegate to the device's native screenshot capabilities. This " - 'screenshots the entire screen currently being displayed (including content ' - 'not rendered by Flutter, like the device status bar).', - _kSkiaType: 'Render the Flutter app as a Skia picture. Requires --$_kObservatoryUri', - _kRasterizerType: 'Render the Flutter app using the rasterizer. Requires --$_kObservatoryUri', + _kDeviceType: 'Delegate to the device\'s native screenshot capabilities. This ' + 'screenshots the entire screen currently being displayed (including content ' + 'not rendered by Flutter, like the device status bar).', + _kSkiaType: 'Render the Flutter app as a Skia picture. Requires "--$_kObservatoryUri".', + _kRasterizerType: 'Render the Flutter app using the rasterizer. Requires "--$_kObservatoryUri."', }, defaultsTo: _kDeviceType, ); diff --git a/packages/flutter_tools/lib/src/commands/symbolize.dart b/packages/flutter_tools/lib/src/commands/symbolize.dart index 49982a9320..3d86e66964 100644 --- a/packages/flutter_tools/lib/src/commands/symbolize.dart +++ b/packages/flutter_tools/lib/src/commands/symbolize.dart @@ -45,7 +45,7 @@ class SymbolizeCommand extends FlutterCommand { argParser.addOption( 'output', 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.' ); } diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index 65f30223b4..1fd8917575 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart @@ -49,11 +49,11 @@ class TestCommand extends FlutterCommand { ) ..addOption('tags', 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', 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', defaultsTo: false, @@ -64,11 +64,11 @@ class TestCommand extends FlutterCommand { 'console once the test has started.', ) ..addFlag('disable-service-auth-codes', - hide: !verboseHelp, defaultsTo: false, negatable: false, - help: 'No longer require an authentication code to connect to the VM ' - 'service (not recommended).', + hide: !verboseHelp, + 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', defaultsTo: false, @@ -79,11 +79,11 @@ class TestCommand extends FlutterCommand { defaultsTo: false, negatable: false, 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', negatable: false, - hide: true, + hide: !verboseHelp, help: 'Whether to use IPv6 for the test harness server socket.', ) ..addOption('coverage-path', @@ -93,12 +93,12 @@ class TestCommand extends FlutterCommand { ..addFlag('machine', hide: !verboseHelp, 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.', ) ..addFlag('update-goldens', 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.', ) ..addOption('concurrency', @@ -110,8 +110,9 @@ class TestCommand extends FlutterCommand { ..addFlag('test-assets', defaultsTo: true, negatable: true, - help: 'Whether to build the assets bundle for testing.\n' - 'Consider using --no-test-assets if assets are not required.', + help: 'Whether to build the assets bundle for testing. ' + '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 // exists to test the Flutter framework itself and may be removed entirely @@ -119,33 +120,47 @@ class TestCommand extends FlutterCommand { // `package:integration_test` instead. ..addOption('platform', allowed: const ['tester', 'chrome'], - hide: true, + hide: !verboseHelp, defaultsTo: 'tester', + help: 'Selects the test backend.', + allowedHelp: { + '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', - help: 'The seed to randomize the execution order of test cases.\n' - 'Must be a 32bit unsigned integer or "random".\n' - 'If "random", pick a random seed to use.\n' - 'If not passed, do not randomize test case execution order.', + help: 'The seed to randomize the execution order of test cases within test files. ' + 'Must be a 32bit unsigned integer or the string "random", ' + 'which indicates that a seed should be selected randomly. ' + 'By default, tests run in the order they are declared.', ) ..addFlag('enable-vmservice', defaultsTo: false, hide: !verboseHelp, - help: 'Enables the vmservice without --start-paused. This flag is ' - 'intended for use with tests that will use dart:developer to ' - 'interact with the vmservice at runtime.\n' - 'This flag is ignored if --start-paused or coverage are requested. ' - 'The vmservice will be enabled no matter what in those cases.' + help: 'Enables the VM service without "--start-paused". This flag is ' + 'intended for use with tests that will use "dart:developer" to ' + 'interact with the VM service at runtime.\n' + 'This flag is ignored if "--start-paused" or coverage are requested, as ' + 'the VM service will be enabled in those cases regardless.' ) ..addOption('reporter', abbr: 'r', defaultsTo: 'compact', - help: 'Set how to print test results.\n' - '[compact] (default) A single line, updated continuously.\n' - '[expanded] A separate line for each update.\n' - '[json] A machine-readable format (see https://dart.dev/go/test-docs/json_reporter.md).\n') + help: 'Set how to print test results.', + allowed: ['compact', 'expanded', 'json'], + allowedHelp: { + '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', - 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', ); addDdsOptions(verboseHelp: verboseHelp); diff --git a/packages/flutter_tools/lib/src/commands/update_packages.dart b/packages/flutter_tools/lib/src/commands/update_packages.dart index 3fad59bdb8..1edf628d16 100644 --- a/packages/flutter_tools/lib/src/commands/update_packages.dart +++ b/packages/flutter_tools/lib/src/commands/update_packages.dart @@ -86,19 +86,19 @@ class UpdatePackagesCommand extends FlutterCommand { ..addFlag( 'paths', 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, negatable: false, ) ..addOption( '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.', ) ..addOption( 'to', - help: 'Used with flag --dependency-path. Specifies the package that the ' - 'sought after dependency path leads to.', + help: 'Used with "--dependency-path". Specifies the package that the ' + 'sought-after dependency path leads to.', ) ..addFlag( 'transitive-closure', @@ -110,20 +110,20 @@ class UpdatePackagesCommand extends FlutterCommand { ..addFlag( 'consumer-only', help: 'Only prints the dependency graph that is the transitive closure ' - 'that a consumer of the Flutter SDK will observe (When combined ' - 'with transitive-closure)', + 'that a consumer of the Flutter SDK will observe (when combined ' + 'with transitive-closure).', defaultsTo: false, negatable: false, ) ..addFlag( 'verify-only', - help: 'verifies the package checksum without changing or updating deps', + help: 'Verifies the package checksum without changing or updating deps.', defaultsTo: false, negatable: false, ) ..addFlag( 'offline', - help: 'Use cached packages instead of accessing the network', + help: 'Use cached packages instead of accessing the network.', defaultsTo: false, negatable: false, ); diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart index 957568dff5..da1992f74c 100644 --- a/packages/flutter_tools/lib/src/commands/upgrade.dart +++ b/packages/flutter_tools/lib/src/commands/upgrade.dart @@ -18,7 +18,10 @@ import '../runner/flutter_command.dart'; import '../version.dart'; class UpgradeCommand extends FlutterCommand { - UpgradeCommand([UpgradeCommandRunner commandRunner]) + UpgradeCommand({ + @required bool verboseHelp, + UpgradeCommandRunner commandRunner, + }) : _commandRunner = commandRunner ?? UpgradeCommandRunner() { argParser ..addFlag( @@ -29,20 +32,22 @@ class UpgradeCommand extends FlutterCommand { ) ..addFlag( 'continue', - hide: true, + hide: !verboseHelp, negatable: false, - help: 'For the second half of the upgrade flow requiring the new ' - 'version of Flutter. Should not be invoked manually, but ' - 're-entrantly by the standard upgrade command.', + help: 'Trigger the second half of the upgrade flow. This should not be invoked ' + 'manually. It is used re-entrantly by the standard upgrade command after ' + 'the new version of Flutter is available, to hand off the upgrade process ' + 'from the old version to the new version.', ) ..addOption( 'working-directory', - hide: true, - help: 'Override the upgrade working directory for integration testing.' + hide: !verboseHelp, + help: 'Override the upgrade working directory. ' + 'This is only intended to enable integration testing of the tool itself.' ) ..addFlag( '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, ); } @@ -138,7 +143,7 @@ class UpgradeCommandRunner { throwToolExit( 'Unknown flutter tag. Abandoning upgrade to avoid destroying local ' '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 { '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 ' 'branch. If it is okay to remove local changes, then re-run this ' - 'command with --force.' + 'command with "--force".' ); } recordState(flutterVersion); @@ -211,8 +216,8 @@ class UpgradeCommandRunner { '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. ' 'If it is okay to ignore potential local changes, then re-run this ' - 'command with --force.' - '\nError: $error.' + 'command with "--force".\n' + 'Error: $error.' ); } return false; diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 36bdcedad8..7bd5f7337e 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -20,6 +20,7 @@ import '../base/user_messages.dart'; import '../base/utils.dart'; import '../build_info.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 '../bundle.dart' as bundle; import '../cache.dart'; @@ -194,7 +195,7 @@ abstract class FlutterCommand extends Command { _requiresPubspecYaml = true; } - void usesWebOptions({ bool hide = true }) { + void usesWebOptions({ @required bool verboseHelp }) { argParser.addOption('web-hostname', defaultsTo: 'localhost', help: @@ -202,13 +203,13 @@ abstract class FlutterCommand extends Command { '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 ' 'IPV4 for either the Chrome or web-server device.', - hide: hide, + hide: !verboseHelp, ); argParser.addOption('web-port', defaultsTo: null, help: 'The host port to serve the web application from. If not provided, the tool ' 'will select a random open port on the host.', - hide: hide, + hide: !verboseHelp, ); argParser.addOption('web-server-debug-protocol', allowed: ['sse', 'ws'], @@ -217,7 +218,7 @@ abstract class FlutterCommand extends Command { 'when using the Web Server device and Dart Debug extension. ' 'This is useful for editors/debug adapters that do not support debugging ' 'over SSE (the default protocol for Web Server/Dart Debugger extension).', - hide: hide, + hide: !verboseHelp, ); argParser.addOption('web-server-debug-backend-protocol', allowed: ['sse', 'ws'], @@ -226,31 +227,31 @@ abstract class FlutterCommand extends Command { 'backend service when using the Web Server device. ' 'Using WebSockets can improve performance but may fail when connecting through ' 'some proxy servers.', - hide: hide, + hide: !verboseHelp, ); argParser.addFlag('web-allow-expose-url', defaultsTo: false, help: 'Enables daemon-to-editor requests (app.exposeUrl) for exposing URLs ' 'when running on remote machines.', - hide: hide, + hide: !verboseHelp, ); argParser.addFlag('web-run-headless', defaultsTo: false, help: 'Launches the browser in headless mode. Currently only Chrome ' 'supports this option.', - hide: true, + hide: !verboseHelp, ); argParser.addOption('web-browser-debug-port', help: 'The debug port the browser should use. If not specified, a ' 'random port is selected. Currently only Chrome supports this option. ' 'It serves the Chrome DevTools Protocol ' '(https://chromedevtools.github.io/devtools-protocol/).', - hide: true, + hide: !verboseHelp, ); argParser.addFlag('web-enable-expression-evaluation', defaultsTo: true, help: 'Enables expression evaluation in the debugger.', - hide: hide, + hide: !verboseHelp, ); } @@ -259,7 +260,7 @@ abstract class FlutterCommand extends Command { abbr: 't', defaultsTo: bundle.defaultMainPath, 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.', valueHelp: 'path'); _usesTargetOption = true; @@ -285,8 +286,8 @@ abstract class FlutterCommand extends Command { /// Adds flags for using a specific filesystem root and scheme. /// - /// [hide] indicates whether or not to hide these options when the user asks - /// for help. + /// The `hide` argument indicates whether or not to hide these options when + /// the user asks for help. void usesFilesystemOptions({ @required bool hide }) { argParser ..addOption('output-dill', @@ -295,27 +296,28 @@ abstract class FlutterCommand extends Command { ) ..addMultiOption(FlutterOptions.kFileSystemRoot, hide: hide, - help: 'Specify the path, that is used as root in a virtual file system\n' - 'for compilation. Input file name should be specified as Uri in\n' - 'filesystem-scheme scheme. Use only in Dart 2 mode.\n' - 'Requires --output-dill option to be explicitly specified.\n', + help: 'Specify the path that is used as the root of a virtual file system ' + 'during compilation. The input file name should be specified as a URL ' + 'using the scheme given in "--${FlutterOptions.kFileSystemScheme}".\n' + 'Requires the "--output-dill" option to be explicitly specified.', ) ..addOption(FlutterOptions.kFileSystemScheme, defaultsTo: 'org-dartlang-root', hide: hide, - help: 'Specify the scheme that is used for virtual file system used in\n' - 'compilation. See more details on filesystem-root option.\n', + help: 'Specify the scheme that is used for virtual file system used in ' + 'compilation. See also the "--${FlutterOptions.kFileSystemRoot}" option.', ); } /// Adds options for connecting to the Dart VM observatory port. - void usesPortOptions() { + void usesPortOptions({ @required bool verboseHelp }) { 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' - '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 ' 'of the Observatory instance advertised on the command line.', + hide: !verboseHelp, ); argParser.addOption('device-vmservice-port', help: 'Look for vmservice connections only from the specified port.\n' @@ -335,16 +337,16 @@ abstract class FlutterCommand extends Command { kEnableDevTools, hide: !verboseHelp, 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. ' - 'If specified, --$kDevToolsServerAddress is ignored.' + 'If specified, "--$kDevToolsServerAddress" is ignored.' ); argParser.addOption( kDevToolsServerAddress, hide: !verboseHelp, 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 ' - '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 { bool get disablePortPublication => !boolArg('publish-port'); - void usesIpv6Flag() { + void usesIpv6Flag({@required bool verboseHelp}) { argParser.addFlag(ipv6Flag, - hide: true, negatable: false, help: 'Binds to IPv6 localhost instead of IPv4 when the flutter tool ' '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; } @@ -471,8 +473,8 @@ abstract class FlutterCommand extends Command { help: 'An identifier used as an internal version number.\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' - "On Android it is used as 'versionCode'.\n" - "On Xcode builds it is used as 'CFBundleVersion'", + 'On Android it is used as "versionCode".\n' + 'On Xcode builds it is used as "CFBundleVersion".', ); } @@ -480,18 +482,18 @@ abstract class FlutterCommand extends Command { argParser.addOption('build-name', 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' - "On Android it is used as 'versionName'.\n" - "On Xcode builds it is used as 'CFBundleShortVersionString'", + 'On Android it is used as "versionName".\n' + 'On Xcode builds it is used as "CFBundleShortVersionString".', valueHelp: 'x.y.z'); } - void usesDartDefineOption() { + void usesDartDefineOption({ bool useLegacyNames = false }) { argParser.addMultiOption( - FlutterOptions.kDartDefinesOption, + useLegacyNames ? kDartDefines : FlutterOptions.kDartDefinesOption, help: 'Additional key-value pairs that will be available as constants ' 'from the String.fromEnvironment, bool.fromEnvironment, int.fromEnvironment, ' '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', splitCommas: false, ); @@ -501,10 +503,12 @@ abstract class FlutterCommand extends Command { argParser.addOption('web-renderer', defaultsTo: 'auto', allowed: ['auto', 'canvaskit', 'html'], - help: 'The renderer implementation to use when building for the web. Possible values are:\n' - 'html - always use the HTML renderer. This renderer uses a combination of HTML, CSS, SVG, 2D Canvas, and WebGL. This is the default.\n' - 'canvaskit - always use the CanvasKit renderer. This renderer uses WebGL and WebAssembly to render graphics.\n' - 'auto - use the HTML renderer on mobile devices, and CanvasKit on desktop devices.', + help: 'The renderer implementation to use when building for the web.', + allowedHelp: { + 'html': 'Always use the HTML renderer. This renderer uses a combination of HTML, CSS, SVG, 2D Canvas, and WebGL. This is the default.', + '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 { && argResults.wasParsed(FlutterOptions.kDeviceTimeout)) { final int timeoutSeconds = int.tryParse(stringArg(FlutterOptions.kDeviceTimeout)); 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); } @@ -543,8 +547,8 @@ abstract class FlutterCommand extends Command { Duration _deviceDiscoveryTimeout; void addBuildModeFlags({ + @required bool verboseHelp, bool defaultToRelease = true, - bool verboseHelp = false, bool excludeDebug = false, bool excludeRelease = false, }) { @@ -576,13 +580,13 @@ abstract class FlutterCommand extends Command { void addSplitDebugInfoOption() { argParser.addOption(FlutterOptions.kSplitDebugInfoOption, 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 ' - 'application. The value of the flag should be a directory where program ' - 'symbol files can be stored for later use. These symbol files contain ' - 'the information needed to symbolize Dart stack traces. For an app built ' - "with this flag, the 'flutter symbolize' command with the right program " - 'symbol file is required to obtain a human readable stack trace.\n' - 'This flag cannot be combined with --analyze-size', + '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 ' + 'symbol files can be stored for later use. These symbol files contain ' + 'the information needed to symbolize Dart stack traces. For an app built ' + 'with this flag, the "flutter symbolize" command with the right program ' + 'symbol file is required to obtain a human readable stack trace.\n' + 'This flag cannot be combined with "--${FlutterOptions.kAnalyzeSize}".', valueHelp: 'v1.2.3/', ); } @@ -590,17 +594,18 @@ abstract class FlutterCommand extends Command { void addDartObfuscationOption() { argParser.addFlag(FlutterOptions.kDartObfuscationOption, help: 'In a release build, this flag removes identifiers and replaces them ' - 'with randomized values for the purposes of source code obfuscation. This ' - 'flag must always be combined with "--split-debug-info" option, 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 ' - 'flag, the \'flutter symbolize\' command with the right program ' - 'symbol file is required to obtain a human readable stack trace.\n\n' - 'Because all identifiers are renamed, methods like Object.runtimeType, ' - 'Type.toString, Enum.toString, Stacktrace.toString, Symbol.toString ' - '(for constant symbols or those generated by runtime system) will ' - 'return obfuscated results. Any code or tests that rely on exact names ' - 'will break.' + 'with randomized values for the purposes of source code obfuscation. This ' + 'flag must always be combined with "--${FlutterOptions.kSplitDebugInfoOption}" option, 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 ' + 'flag, the "flutter symbolize" command with the right program ' + 'symbol file is required to obtain a human readable stack trace.\n' + '\n' + 'Because all identifiers are renamed, methods like Object.runtimeType, ' + 'Type.toString, Enum.toString, Stacktrace.toString, Symbol.toString ' + '(for constant symbols or those generated by runtime system) will ' + 'return obfuscated results. Any code or tests that rely on exact names ' + 'will break.' ); } @@ -625,11 +630,11 @@ abstract class FlutterCommand extends Command { ); } - void addShrinkingFlag() { + void addShrinkingFlag({ @required bool verboseHelp }) { argParser.addFlag('shrink', negatable: true, - hide: true, - help: 'This flag is deprecated. Code shrinking is always enabled in release builds. ' + hide: !verboseHelp, + 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' ); } @@ -655,21 +660,28 @@ abstract class FlutterCommand extends Command { /// Enables support for the hidden options --extra-front-end-options and /// --extra-gen-snapshot-options. - void usesExtraDartFlagOptions() { - argParser.addMultiOption(FlutterOptions.kExtraFrontEndOptions, + void usesExtraDartFlagOptions({ @required bool verboseHelp, bool useLegacyNames = false }) { + 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, - 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, - hide: true, + hide: !verboseHelp, ); } void usesFuchsiaOptions({ bool hide = false }) { argParser.addOption( 'target-model', - help: 'Target model that determines what core libraries are available', + help: 'Target model that determines what core libraries are available.', defaultsTo: 'flutter', hide: hide, allowed: const ['flutter', 'flutter_runner'], @@ -678,7 +690,7 @@ abstract class FlutterCommand extends Command { 'module', abbr: 'm', 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', ); } @@ -687,9 +699,8 @@ abstract class FlutterCommand extends Command { argParser.addMultiOption( FlutterOptions.kEnableExperiment, help: - 'The name of an experimental Dart feature to enable. For more info ' - 'see: https://github.com/dart-lang/sdk/blob/master/docs/process/' - 'experimental-flags.md', + 'The name of an experimental Dart feature to enable. For more information see: ' + 'https://github.com/dart-lang/sdk/blob/master/docs/process/experimental-flags.md', hide: hide, ); } @@ -708,10 +719,10 @@ abstract class FlutterCommand extends Command { argParser.addFlag( FlutterOptions.kAndroidGradleDaemon, 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 ' - ' 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 " - 'process to terminate after the build is completed', + '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 ' + '"--no-daemon" to the gradle wrapper script. This flag will cause the daemon ' + 'process to terminate after the build is completed.', defaultsTo: true, hide: hide, ); @@ -725,13 +736,13 @@ abstract class FlutterCommand extends Command { '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 ' '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 ' - 'https://github.com/dart-lang/sdk/issues/labels/web-libraries .' + 'dart:html or the other dart web libraries, please file a bug at: ' + 'https://github.com/dart-lang/sdk/issues/labels/web-libraries' ); } /// Adds build options common to all of the desktop build commands. - void addCommonDesktopBuildOptions({ bool verboseHelp = false }) { + void addCommonDesktopBuildOptions({ @required bool verboseHelp }) { addBuildModeFlags(verboseHelp: verboseHelp); addBuildPerformanceFile(hide: !verboseHelp); addBundleSkSLPathOption(hide: !verboseHelp); @@ -742,7 +753,7 @@ abstract class FlutterCommand extends Command { addTreeShakeIconsFlag(); usesAnalyzeSizeFlag(); usesDartDefineOption(); - usesExtraDartFlagOptions(); + usesExtraDartFlagOptions(verboseHelp: verboseHelp); usesPubOption(); usesTargetOption(); usesTrackWidgetCreation(verboseHelp: verboseHelp); @@ -765,8 +776,8 @@ abstract class FlutterCommand extends Command { releaseResult, ]; if (modeFlags.where((bool flag) => flag).length > 1) { - throw UsageException('Only one of --debug, --profile, --jit-release, ' - 'or --release can be specified.', null); + throw UsageException('Only one of "--debug", "--profile", "--jit-release", ' + 'or "--release" can be specified.', null); } if (debugResult) { return BuildMode.debug; @@ -807,10 +818,10 @@ abstract class FlutterCommand extends Command { FlutterOptions.kAnalyzeSize, defaultsTo: false, 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 ' - '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' - 'This flag cannot be combined with --split-debug-info.' + '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, ' + 'only the symbols from the arm64 architecture are used to analyze code size.\n' + 'This flag cannot be combined with "--${FlutterOptions.kSplitDebugInfoOption}".' ); } @@ -914,10 +925,10 @@ abstract class FlutterCommand extends Command { } final BuildMode buildMode = forcedBuildMode ?? getBuildMode(); 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) { - 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') diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart index 2ec90fedc1..ba2bca126f 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart @@ -45,10 +45,13 @@ class FlutterCommandRunner extends CommandRunner { abbr: 'v', negatable: false, 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', negatable: false, - hide: true, + help: 'Causes lines sent to stderr to be prefixed with "ERROR:".', + hide: !verboseHelp, defaultsTo: false); argParser.addFlag('quiet', negatable: false, @@ -62,8 +65,8 @@ class FlutterCommandRunner extends CommandRunner { argParser.addOption('wrap-column', hide: !verboseHelp, 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 ' - 'when connected to a terminal.', + 'wrapping occurs if not writing to a terminal. Use "--no-wrap" to turn off wrapping ' + 'when connected to a terminal.', defaultsTo: null); argParser.addOption('device-id', abbr: 'd', @@ -74,7 +77,7 @@ class FlutterCommandRunner extends CommandRunner { argParser.addFlag('machine', negatable: false, 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', negatable: true, hide: !verboseHelp, @@ -106,7 +109,7 @@ class FlutterCommandRunner extends CommandRunner { hide: !verboseHelp, 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' - '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) { argParser.addSeparator('Options for testing the "flutter" tool itself:'); @@ -114,12 +117,12 @@ class FlutterCommandRunner extends CommandRunner { argParser.addFlag('show-test-device', negatable: false, hide: !verboseHelp, - help: "List the special 'flutter-tester' device in device listings. " - 'This headless device is used to\ntest Flutter tooling.'); + help: 'List the special "flutter-tester" device in device listings. ' + 'This headless device is used to test Flutter tooling.'); argParser.addFlag('show-web-server-device', negatable: false, 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 { } 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); }, diff --git a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart index 579a755556..91be117436 100644 --- a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart +++ b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart @@ -434,7 +434,10 @@ void main() { }); testUsingContext('upgrade continue prints welcome message', () async { - final UpgradeCommand upgradeCommand = UpgradeCommand(fakeCommandRunner); + final UpgradeCommand upgradeCommand = UpgradeCommand( + verboseHelp: false, + commandRunner: fakeCommandRunner, + ); await createTestCommandRunner(upgradeCommand).run( [ diff --git a/packages/flutter_tools/test/general.shard/args_test.dart b/packages/flutter_tools/test/general.shard/args_test.dart new file mode 100644 index 0000000000..52e978f9b2 --- /dev/null +++ b/packages/flutter_tools/test/general.shard/args_test.dart @@ -0,0 +1,92 @@ +// 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 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 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