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',
);
}
......
......@@ -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.'
);
}
......
......@@ -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;
......
......@@ -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<String> 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,
......
......@@ -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;
......
......@@ -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<void> {
_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<void> {
'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: <String>['sse', 'ws'],
......@@ -217,7 +218,7 @@ abstract class FlutterCommand extends Command<void> {
'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: <String>['sse', 'ws'],
......@@ -226,31 +227,31 @@ abstract class FlutterCommand extends Command<void> {
'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<void> {
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<void> {
/// 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<void> {
)
..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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
argParser.addOption('web-renderer',
defaultsTo: 'auto',
allowed: <String>['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: <String, String>{
'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<void> {
&& 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<void> {
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> {
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> {
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> {
);
}
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<void> {
/// 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 <String>['flutter', 'flutter_runner'],
......@@ -678,7 +690,7 @@ abstract class FlutterCommand extends Command<void> {
'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<void> {
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<void> {
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<void> {
'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<void> {
addTreeShakeIconsFlag();
usesAnalyzeSizeFlag();
usesDartDefineOption();
usesExtraDartFlagOptions();
usesExtraDartFlagOptions(verboseHelp: verboseHelp);
usesPubOption();
usesTargetOption();
usesTrackWidgetCreation(verboseHelp: verboseHelp);
......@@ -765,8 +776,8 @@ abstract class FlutterCommand extends Command<void> {
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<void> {
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<void> {
}
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')
......
......@@ -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