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

All arguments must be documented. (#75888)

parent 696e4f70
......@@ -80,7 +80,7 @@ add_custom_command(
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
......
......@@ -89,96 +89,108 @@ Future<void> main(List<String> args) async {
userMessages: UserMessages(),
);
await runner.run(args, () => <FlutterCommand>[
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: <Type, Generator>{
// The web runner is not supported in google3 because it depends
// on dwds.
WebRunnerFactory: () => DwdsWebRunnerFactory(),
// The mustache dependency is different in google3
TemplateRenderer: () => const MustacheTemplateRenderer(),
// The devtools launcher is not supported in google3 because it depends on
// devtools source code.
DevtoolsLauncher: () => DevtoolsServerLauncher(
processManager: globals.processManager,
pubExecutable: globals.artifacts.getArtifactPath(Artifact.pubExecutable),
logger: globals.logger,
platform: globals.platform,
persistentToolState: globals.persistentToolState,
),
Logger: () {
final LoggerFactory loggerFactory = LoggerFactory(
outputPreferences: globals.outputPreferences,
terminal: globals.terminal,
stdio: globals.stdio,
);
return loggerFactory.createLogger(
daemon: daemon,
machine: runMachine,
verbose: verbose && !muteCommandLogging,
prefixedErrors: prefixedErrors,
windows: globals.platform.isWindows,
);
}
});
verbose: verbose,
muteCommandLogging: muteCommandLogging,
verboseHelp: verboseHelp,
overrides: <Type, Generator>{
// The web runner is not supported in google3 because it depends
// on dwds.
WebRunnerFactory: () => DwdsWebRunnerFactory(),
// The mustache dependency is different in google3
TemplateRenderer: () => const MustacheTemplateRenderer(),
// The devtools launcher is not supported in google3 because it depends on
// devtools source code.
DevtoolsLauncher: () => DevtoolsServerLauncher(
processManager: globals.processManager,
pubExecutable: globals.artifacts.getArtifactPath(Artifact.pubExecutable),
logger: globals.logger,
platform: globals.platform,
persistentToolState: globals.persistentToolState,
),
Logger: () {
final LoggerFactory loggerFactory = LoggerFactory(
outputPreferences: globals.outputPreferences,
terminal: globals.terminal,
stdio: globals.stdio,
);
return loggerFactory.createLogger(
daemon: daemon,
machine: runMachine,
verbose: verbose && !muteCommandLogging,
prefixedErrors: prefixedErrors,
windows: globals.platform.isWindows,
);
},
},
);
}
List<FlutterCommand> generateCommands({
@required bool verboseHelp,
@required bool verbose,
}) => <FlutterCommand>[
AnalyzeCommand(
verboseHelp: verboseHelp,
fileSystem: globals.fs,
platform: globals.platform,
processManager: globals.processManager,
logger: globals.logger,
terminal: globals.terminal,
artifacts: globals.artifacts,
),
AssembleCommand(verboseHelp: verboseHelp),
AttachCommand(verboseHelp: verboseHelp),
BuildCommand(verboseHelp: verboseHelp),
ChannelCommand(verboseHelp: verboseHelp),
CleanCommand(verbose: verbose),
ConfigCommand(verboseHelp: verboseHelp),
CreateCommand(verboseHelp: verboseHelp),
DaemonCommand(hidden: !verboseHelp),
DevicesCommand(verboseHelp: verboseHelp),
DoctorCommand(verbose: verbose),
DowngradeCommand(verboseHelp: verboseHelp),
DriveCommand(verboseHelp: verboseHelp,
fileSystem: globals.fs,
logger: globals.logger,
),
EmulatorsCommand(),
FormatCommand(),
GenerateCommand(),
GenerateLocalizationsCommand(
fileSystem: globals.fs,
logger: globals.logger,
),
InstallCommand(),
LogsCommand(),
MakeHostAppEditableCommand(),
PackagesCommand(),
PrecacheCommand(
verboseHelp: verboseHelp,
cache: globals.cache,
logger: globals.logger,
platform: globals.platform,
featureFlags: featureFlags,
),
RunCommand(verboseHelp: verboseHelp),
ScreenshotCommand(),
ShellCompletionCommand(),
TestCommand(verboseHelp: verboseHelp),
UpgradeCommand(verboseHelp: verboseHelp),
SymbolizeCommand(
stdio: globals.stdio,
fileSystem: globals.fs,
),
// Development-only commands. These are always hidden,
IdeConfigCommand(),
UpdatePackagesCommand(),
];
/// An abstraction for instantiation of the correct logger type.
///
/// Our logger class hierarchy and runtime requirements are overly complicated.
......
......@@ -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<FlutterCommand>` or `List<FlutterCommand> Function()`.
// TODO(jonahwilliams): update command type once g3 has rolled.
Future<int> run(
List<String> args,
List<FlutterCommand> Function() commands, {
......
......@@ -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.',
......
......@@ -73,14 +73,20 @@ const List<Target> _kDefaultTargets = <Target>[
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<String>).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<String>).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<String>).join(',');
}
return results;
}
......
......@@ -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,
......
......@@ -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 '<current-directory>android/build'. ",
'By default, this is "<current-directory>android/build".',
);
}
......
......@@ -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);
......
......@@ -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);
......
......@@ -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 <String>[
......@@ -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();
......
......@@ -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);
......
......@@ -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,
);
}
......
......@@ -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: <String>[
kOfflineFirst,
kNoneWorker,
]
],
allowedHelp: <String, String>{
kOfflineFirst: 'Attempt to cache the application shell eagerly and '
'then lazily cache all subsequent assets as they are loaded. When '
'making a network request for an asset, the offline cache will be '
'preferred.',
kNoneWorker: 'Generate a service worker with no body. This is useful for '
'local testing or in cases where the service worker caching functionality '
'is not desirable',
},
);
}
......
......@@ -22,7 +22,7 @@ class ConfigCommand extends FlutterCommand {
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,
......
......@@ -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 .'
);
......
......@@ -32,13 +32,15 @@ const List<String> _kAvailablePlatforms = <String>[
];
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: <String>['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: <String>['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,
);
}
......
......@@ -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<void> 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();
}
......
......@@ -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<FlutterCommandResult> runCommand() async {
// Note: commands do not necessarily have access to the correct zone injected
// Commands do not necessarily have access to the correct zone injected
// values when being created. Fields must be lazily instantiated in runCommand,
// at least until the zone injection is refactored.
_terminal ??= globals.terminal;
......
......@@ -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: <String>[
'android-chrome',
'chrome',
......@@ -111,24 +110,31 @@ class DriveCommand extends RunCommandBase {
'ios-safari',
'safari',
],
allowedHelp: <String, String>{
'android-chrome': 'Chrome on Android (see also "--android-emulator").',
'chrome': 'Google Chrome on this computer (see also "--chrome-binary").',
'edge': 'Microsoft Edge on this computer (Windows only).',
'firefox': 'Mozilla Firefox on this computer.',
'ios-safari': 'Apple Safari on an iOS device.',
'safari': 'Apple Safari on this computer (macOS only).',
},
)
..addOption('browser-dimension',
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.');
}
......
......@@ -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
......
......@@ -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',
);
}
......
......@@ -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.',
);
}
......
......@@ -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;
......
......@@ -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 <String>[_kDeviceType, _kSkiaType, _kRasterizerType],
allowedHelp: const <String, String>{
_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,
);
......
......@@ -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.'
);
}
......
......@@ -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 <String>['tester', 'chrome'],
hide: true,
hide: !verboseHelp,
defaultsTo: 'tester',
help: 'Selects the test backend.',
allowedHelp: <String, String>{
'tester': 'Run tests using the default VM-based test environment.',
'chrome': '(deprecated) Run tests using the Google Chrome web browser. '
'This value is intended for testing the Flutter framework '
'itself and may be removed at any time.',
},
)
..addOption('test-randomize-ordering-seed',
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: <String>['compact', 'expanded', 'json'],
allowedHelp: <String, String>{
'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);
......
......@@ -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,
);
......
......@@ -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;
......
......@@ -45,10 +45,13 @@ class FlutterCommandRunner extends CommandRunner<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
}
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);
},
......
......@@ -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(
<String>[
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:flutter_tools/executable.dart' as executable;
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
import '../src/common.dart';
import '../src/testbed.dart';
void main() {
test('Help for command line arguments is consistently styled and complete', () => Testbed().run(() {
final FlutterCommandRunner runner = FlutterCommandRunner(verboseHelp: true);
executable.generateCommands(
verboseHelp: true,
verbose: true,
).forEach(runner.addCommand);
verifyCommandRunner(runner);
}));
}
void verifyCommandRunner(CommandRunner<Object> runner) {
expect(runner.argParser, isNotNull, reason: '${runner.runtimeType} has no argParser');
expect(runner.argParser.allowsAnything, isFalse, reason: '${runner.runtimeType} allows anything');
expect(runner.argParser.allowTrailingOptions, isFalse, reason: '${runner.runtimeType} allows trailing options');
verifyOptions('the global argument "', runner.argParser.options.values);
runner.commands.values.forEach(verifyCommand);
}
void verifyCommand(Command<Object> runner) {
expect(runner.argParser, isNotNull, reason: 'command ${runner.name} has no argParser');
verifyOptions('"flutter ${runner.name} ', runner.argParser.options.values);
runner.subcommands.values.forEach(verifyCommand);
}
// Patterns for arguments names.
// The "ExtraFrontEndOptions", "ExtraGenSnapshotOptions", and "DartDefines" cases are special cases
// that we should remove; search for "useLegacyNames" in commands/assemble.dart and other files.
// TODO(ianh): consider changing all underscores to hyphens in argument names when we can do aliases.
// That depends on being able to have argument aliases: https://github.com/dart-lang/args/issues/181
final RegExp _allowedArgumentNamePattern = RegExp(r'^([-a-z0-9_]+|ExtraFrontEndOptions|ExtraGenSnapshotOptions|DartDefines)$');
// Patterns for help messages.
final RegExp _bannedLeadingPatterns = RegExp(r'^[-a-z]', multiLine: true);
final RegExp _allowedTrailingPatterns = RegExp(r'([^ ][.!:]\)?|: https?://[^ ]+[^.]|^)$');
final RegExp _bannedQuotePatterns = RegExp(r" '|' |'\.|\('|'\)|`");
final RegExp _bannedArgumentReferencePatterns = RegExp(r'[^"=]--[^ ]');
final RegExp _questionablePatterns = RegExp(r'[a-z]\.[A-Z]');
const String _needHelp = 'Every option must have help explaining what it does, even if it\'s '
'for testing purposes, because this is the bare minimum of '
'documentation we can add just for ourselves. If it is not intended '
'for developers, then use "hide: !verboseHelp" to only show the '
'help when people run with "--help --verbose".';
const String _header = ' Comment: ';
void verifyOptions(String command, Iterable<Option> options) {
assert(command.contains('"'));
for (final Option option in options) {
// If you think you need to add an exception here, please ask Hixie (but he'll say no).
expect(option.name, matches(_allowedArgumentNamePattern), reason: '$_header$command--${option.name}" is not a valid name for a command line argument. (Is it all lowercase?)');
expect(option.hide, isFalse, reason: '${_header}Help for $command--${option.name}" is always hidden. $_needHelp');
expect(option.help, isNotNull, reason: '${_header}Help for $command--${option.name}" has null help. $_needHelp');
expect(option.help, isNotEmpty, reason: '${_header}Help for $command--${option.name}" has empty help. $_needHelp');
expect(option.help, isNot(matches(_bannedLeadingPatterns)), reason: '${_header}A line in the help for $command--${option.name}" starts with a lowercase letter. For stylistic consistency, all help messages must start with a capital letter.');
expect(option.help, isNot(startsWith('(Deprecated')), reason: '${_header}Help for $command--${option.name}" should start with lowercase "(deprecated)" for consistency with other deprecated commands.');
expect(option.help, isNot(startsWith('(Required')), reason: '${_header}Help for $command--${option.name}" should start with lowercase "(required)" for consistency with other deprecated commands.');
expect(option.help, isNot(contains('?')), reason: '${_header}Help for $command--${option.name}" has a question mark. Generally we prefer the passive voice for help messages.');
expect(option.help, isNot(contains('Note:')), reason: '${_header}Help for $command--${option.name}" uses "Note:". See our style guide entry about "empty prose".');
expect(option.help, isNot(contains('Note that')), reason: '${_header}Help for $command--${option.name}" uses "Note that". See our style guide entry about "empty prose".');
expect(option.help, isNot(matches(_bannedQuotePatterns)), reason: '${_header}Help for $command--${option.name}" uses single quotes or backticks instead of double quotes in the help message. For consistency we use double quotes throughout.');
expect(option.help, isNot(matches(_questionablePatterns)), reason: '${_header}Help for $command--${option.name}" may have a typo. (If it does not you may have to update args_test.dart, sorry. Search for "_questionablePatterns")');
if (option.defaultsTo != null) {
expect(option.help, isNot(contains('Default')), reason: '${_header}Help for $command--${option.name}" mentions the default value but that is redundant with the defaultsTo option which is also specified (and preferred).');
}
expect(option.help, isNot(matches(_bannedArgumentReferencePatterns)), reason: '${_header}Help for $command--${option.name}" contains the string "--" in an unexpected way. If it\'s trying to mention another argument, it should be quoted, as in "--foo".');
for (final String line in option.help.split('\n')) {
if (!line.startsWith(' ')) {
expect(line, isNot(contains(' ')), reason: '${_header}Help for $command--${option.name}" has excessive whitespace (check e.g. for double spaces after periods or round line breaks in the source).');
expect(line, matches(_allowedTrailingPatterns), reason: '${_header}A line in the help for $command--${option.name}" does not end with the expected period that a full sentence should end with. (If the help ends with a URL, place it after a colon, don\'t leave a trailing period; if it\'s sample code, prefix the line with four spaces.)');
}
}
expect(option.help, isNot(endsWith(':')), reason: '${_header}Help for $command--${option.name}" ends with a colon, which seems unlikely to be correct.');
// TODO(ianh): add some checking for embedded URLs to make sure we're consistent on how we format those.
// TODO(ianh): arguably we should ban help text that starts with "Whether to..." since by definition a flag is to enable a feature, so the "whether to" is redundant.
// TODO(ianh): consider looking for strings that use the term "URI" instead of "URL".
}
}
......@@ -96,7 +96,7 @@ void main() {
print(result.stdout);
print(result.stderr);
expect(result.stderr.toString(), contains('--analyze-size can only be used on release builds'));
expect(result.stderr.toString(), contains('"--analyze-size" can only be used on release builds'));
expect(result.exitCode, 1);
});
......@@ -113,7 +113,7 @@ void main() {
'--split-debug-info=infos'
], workingDirectory: fileSystem.path.join(getFlutterRoot(), 'examples', 'hello_world'));
expect(result.stderr.toString(), contains('--analyze-size cannot be combined with --split-debug-info'));
expect(result.stderr.toString(), contains('"--analyze-size" cannot be combined with "--split-debug-info"'));
expect(result.exitCode, 1);
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment