1d184ace7b
Mostly addOption() -> addMultiOption(). Change-Id: Iab40059aab45a371e0def89fbdfcd08bd1487d47 Reviewed-on: https://dart-review.googlesource.com/47121 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
639 lines
22 KiB
Dart
639 lines
22 KiB
Dart
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:io';
|
|
|
|
import 'package:analyzer/file_system/physical_file_system.dart';
|
|
import 'package:analyzer/src/command_line/arguments.dart';
|
|
import 'package:analyzer/src/context/builder.dart';
|
|
import 'package:analyzer/src/util/sdk.dart';
|
|
import 'package:analyzer_cli/src/ansi.dart' as ansi;
|
|
import 'package:analyzer_cli/src/driver.dart';
|
|
import 'package:args/args.dart';
|
|
import 'package:telemetry/telemetry.dart' as telemetry;
|
|
|
|
const _binaryName = 'dartanalyzer';
|
|
|
|
/// Shared exit handler.
|
|
///
|
|
/// *Visible for testing.*
|
|
ExitHandler exitHandler = exit;
|
|
|
|
/// Print the given [message] to stderr and exit with the given [exitCode].
|
|
void printAndFail(String message, {int exitCode: 15}) {
|
|
errorSink.writeln(message);
|
|
exitHandler(exitCode);
|
|
}
|
|
|
|
/// Exit handler.
|
|
///
|
|
/// *Visible for testing.*
|
|
typedef void ExitHandler(int code);
|
|
|
|
/// Analyzer commandline configuration options.
|
|
class CommandLineOptions {
|
|
final bool enableNewAnalysisDriver = true;
|
|
|
|
/// Whether declaration casts are enabled (in strong mode)
|
|
final bool declarationCasts;
|
|
|
|
/// The path to output analysis results when in build mode.
|
|
final String buildAnalysisOutput;
|
|
|
|
/// Whether to use build mode.
|
|
final bool buildMode;
|
|
|
|
/// Whether to use build mode as a Bazel persistent worker.
|
|
final bool buildModePersistentWorker;
|
|
|
|
/// List of summary file paths to use in build mode.
|
|
final List<String> buildSummaryInputs;
|
|
|
|
/// List of unlinked summary file paths to use in build mode.
|
|
final List<String> buildSummaryUnlinkedInputs;
|
|
|
|
/// Whether to skip analysis when creating summaries in build mode.
|
|
final bool buildSummaryOnly;
|
|
|
|
/// Whether to only produce unlinked summaries instead of linked summaries.
|
|
/// Must be used in combination with `buildSummaryOnly`.
|
|
final bool buildSummaryOnlyUnlinked;
|
|
|
|
/// The path to output the summary when creating summaries in build mode.
|
|
final String buildSummaryOutput;
|
|
|
|
/// The path to output the semantic-only summary when creating summaries in
|
|
/// build mode.
|
|
final String buildSummaryOutputSemantic;
|
|
|
|
/// Whether to suppress a nonzero exit code in build mode.
|
|
final bool buildSuppressExitCode;
|
|
|
|
/// The options defining the context in which analysis is performed.
|
|
final ContextBuilderOptions contextBuilderOptions;
|
|
|
|
/// The path to the dart SDK.
|
|
String dartSdkPath;
|
|
|
|
/// The path to the folder with the 'vm_platform.dill' file.
|
|
String dartSdkPlatformBinariesPath;
|
|
|
|
/// The path to the dart SDK summary file.
|
|
String dartSdkSummaryPath;
|
|
|
|
/// Whether to disable cache flushing. This option can improve analysis
|
|
/// speed at the expense of memory usage. It may also be useful for working
|
|
/// around bugs.
|
|
final bool disableCacheFlushing;
|
|
|
|
/// Whether to report hints
|
|
final bool disableHints;
|
|
|
|
/// Whether to display version information
|
|
final bool displayVersion;
|
|
|
|
/// Whether to treat type mismatches found during constant evaluation as
|
|
/// errors.
|
|
final bool enableTypeChecks;
|
|
|
|
/// Whether to ignore unrecognized flags
|
|
final bool ignoreUnrecognizedFlags;
|
|
|
|
/// Whether to report lints
|
|
final bool lints;
|
|
|
|
/// Whether to log additional analysis messages and exceptions
|
|
final bool log;
|
|
|
|
/// Whether to use machine format for error display
|
|
final bool machineFormat;
|
|
|
|
/// The path to a file to write a performance log.
|
|
/// (Or null if not enabled.)
|
|
final String perfReport;
|
|
|
|
/// Whether to enable the Dart 2.0 Common Front End.
|
|
final bool useCFE;
|
|
|
|
/// Whether to enable the Dart 2.0 Preview.
|
|
final bool previewDart2;
|
|
|
|
/// Batch mode (for unit testing)
|
|
final bool batchMode;
|
|
|
|
/// Whether to show package: warnings
|
|
final bool showPackageWarnings;
|
|
|
|
/// If not null, show package: warnings only for matching packages.
|
|
final String showPackageWarningsPrefix;
|
|
|
|
/// Whether to show SDK warnings
|
|
final bool showSdkWarnings;
|
|
|
|
/// The source files to analyze
|
|
List<String> _sourceFiles;
|
|
|
|
/// Whether to treat warnings as fatal
|
|
final bool warningsAreFatal;
|
|
|
|
/// Whether to treat info level items as fatal
|
|
final bool infosAreFatal;
|
|
|
|
/// Whether to use strong static checking.
|
|
final bool strongMode;
|
|
|
|
/// Whether implicit casts are enabled (in strong mode)
|
|
final bool implicitCasts;
|
|
|
|
/// Whether implicit dynamic is enabled (mainly for strong mode users)
|
|
final bool implicitDynamic;
|
|
|
|
// TODO(devoncarew): Deprecate and remove this flag.
|
|
/// Whether to treat lints as fatal
|
|
final bool lintsAreFatal;
|
|
|
|
/// Whether to use memory byte store for analysis driver.
|
|
final bool useAnalysisDriverMemoryByteStore;
|
|
|
|
/// Emit output in a verbose mode.
|
|
final bool verbose;
|
|
|
|
/// Use ANSI color codes for output.
|
|
final bool color;
|
|
|
|
/// Initialize options from the given parsed [args].
|
|
CommandLineOptions._fromArgs(ArgResults args)
|
|
: buildAnalysisOutput = args['build-analysis-output'],
|
|
buildMode = args['build-mode'],
|
|
buildModePersistentWorker = args['persistent_worker'],
|
|
buildSummaryInputs =
|
|
(args['build-summary-input'] as List).cast<String>(),
|
|
buildSummaryUnlinkedInputs =
|
|
(args['build-summary-unlinked-input'] as List).cast<String>(),
|
|
buildSummaryOnly = args['build-summary-only'],
|
|
buildSummaryOnlyUnlinked = args['build-summary-only-unlinked'],
|
|
buildSummaryOutput = args['build-summary-output'],
|
|
buildSummaryOutputSemantic = args['build-summary-output-semantic'],
|
|
buildSuppressExitCode = args['build-suppress-exit-code'],
|
|
contextBuilderOptions = createContextBuilderOptions(args),
|
|
dartSdkPath = args['dart-sdk'],
|
|
dartSdkSummaryPath = args['dart-sdk-summary'],
|
|
declarationCasts = args.wasParsed(declarationCastsFlag)
|
|
? args[declarationCastsFlag]
|
|
: args[implicitCastsFlag],
|
|
disableCacheFlushing = args['disable-cache-flushing'],
|
|
disableHints = args['no-hints'],
|
|
displayVersion = args['version'],
|
|
enableTypeChecks = args['enable_type_checks'],
|
|
ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
|
|
lints = args[lintsFlag],
|
|
log = args['log'],
|
|
machineFormat = args['format'] == 'machine',
|
|
perfReport = args['x-perf-report'],
|
|
useCFE = args['use-cfe'],
|
|
previewDart2 =
|
|
args.wasParsed('preview-dart-2') ? args['preview-dart-2'] : null,
|
|
batchMode = args['batch'],
|
|
showPackageWarnings = args['show-package-warnings'] ||
|
|
args['package-warnings'] ||
|
|
args['x-package-warnings-prefix'] != null,
|
|
showPackageWarningsPrefix = args['x-package-warnings-prefix'],
|
|
showSdkWarnings = args['sdk-warnings'],
|
|
_sourceFiles = args.rest,
|
|
infosAreFatal = args['fatal-infos'] || args['fatal-hints'],
|
|
warningsAreFatal = args['fatal-warnings'],
|
|
lintsAreFatal = args['fatal-lints'],
|
|
strongMode = args['strong'],
|
|
implicitCasts = args[implicitCastsFlag],
|
|
implicitDynamic = !args['no-implicit-dynamic'],
|
|
useAnalysisDriverMemoryByteStore =
|
|
args['use-analysis-driver-memory-byte-store'],
|
|
verbose = args['verbose'],
|
|
color = args['color'];
|
|
|
|
/// The path to an analysis options file
|
|
String get analysisOptionsFile =>
|
|
contextBuilderOptions.defaultAnalysisOptionsFilePath;
|
|
|
|
/// A table mapping the names of defined variables to their values.
|
|
Map<String, String> get definedVariables =>
|
|
contextBuilderOptions.declaredVariables;
|
|
|
|
/// Whether to relax restrictions on mixins (DEP 34).
|
|
bool get enableSuperMixins =>
|
|
contextBuilderOptions.defaultOptions.enableSuperMixins;
|
|
|
|
/// The path to a `.packages` configuration file
|
|
String get packageConfigPath => contextBuilderOptions.defaultPackageFilePath;
|
|
|
|
/// The path to the package root
|
|
String get packageRootPath =>
|
|
contextBuilderOptions.defaultPackagesDirectoryPath;
|
|
|
|
/// The source files to analyze
|
|
List<String> get sourceFiles => _sourceFiles;
|
|
|
|
/// Replace the sourceFiles parsed from the command line.
|
|
void rewriteSourceFiles(List<String> newSourceFiles) {
|
|
_sourceFiles = newSourceFiles;
|
|
}
|
|
|
|
/// Parse [args] into [CommandLineOptions] describing the specified
|
|
/// analyzer options. In case of a format error, calls [printAndFail], which
|
|
/// by default prints an error message to stderr and exits.
|
|
static CommandLineOptions parse(List<String> args,
|
|
{printAndFail(String msg) = printAndFail}) {
|
|
CommandLineOptions options = _parse(args);
|
|
|
|
/// Only happens in testing.
|
|
if (options == null) {
|
|
return null;
|
|
}
|
|
|
|
// Check SDK.
|
|
if (!options.buildModePersistentWorker) {
|
|
// Infer if unspecified.
|
|
options.dartSdkPath ??= getSdkPath(args);
|
|
|
|
String sdkPath = options.dartSdkPath;
|
|
|
|
// Check that SDK is specified.
|
|
if (sdkPath == null) {
|
|
printAndFail('No Dart SDK found.');
|
|
return null; // Only reachable in testing.
|
|
}
|
|
// Check that SDK is existing directory.
|
|
if (!(new Directory(sdkPath)).existsSync()) {
|
|
printAndFail('Invalid Dart SDK path: $sdkPath');
|
|
return null; // Only reachable in testing.
|
|
}
|
|
|
|
options.dartSdkPlatformBinariesPath =
|
|
computePlatformBinariesPath(sdkPath);
|
|
}
|
|
|
|
// Check package config.
|
|
{
|
|
if (options.packageRootPath != null &&
|
|
options.packageConfigPath != null) {
|
|
printAndFail("Cannot specify both '--package-root' and '--packages.");
|
|
return null; // Only reachable in testing.
|
|
}
|
|
}
|
|
|
|
// Build mode.
|
|
if (options.buildModePersistentWorker && !options.buildMode) {
|
|
printAndFail('The option --persisten_worker can be used only '
|
|
'together with --build-mode.');
|
|
return null; // Only reachable in testing.
|
|
}
|
|
|
|
if (options.buildSummaryOnlyUnlinked) {
|
|
if (!options.buildSummaryOnly) {
|
|
printAndFail(
|
|
'The option --build-summary-only-unlinked can be used only '
|
|
'together with --build-summary-only.');
|
|
return null; // Only reachable in testing.
|
|
}
|
|
if (options.buildSummaryInputs.isNotEmpty ||
|
|
options.buildSummaryUnlinkedInputs.isNotEmpty) {
|
|
printAndFail('No summaries should be provided in combination with '
|
|
'--build-summary-only-unlinked, they aren\'t needed.');
|
|
return null; // Only reachable in testing.
|
|
}
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
static String _getVersion() {
|
|
try {
|
|
// This is relative to bin/snapshot, so ../..
|
|
String versionPath =
|
|
Platform.script.resolve('../../version').toFilePath();
|
|
File versionFile = new File(versionPath);
|
|
return versionFile.readAsStringSync().trim();
|
|
} catch (_) {
|
|
// This happens when the script is not running in the context of an SDK.
|
|
return "<unknown>";
|
|
}
|
|
}
|
|
|
|
static CommandLineOptions _parse(List<String> args) {
|
|
args = preprocessArgs(PhysicalResourceProvider.INSTANCE, args);
|
|
|
|
bool verbose = args.contains('-v') || args.contains('--verbose');
|
|
bool hide = !verbose;
|
|
|
|
ArgParser parser = new ArgParser(allowTrailingOptions: true);
|
|
|
|
if (!hide) {
|
|
parser.addSeparator('General options:');
|
|
}
|
|
|
|
// TODO(devoncarew): This defines some hidden flags, which would be better
|
|
// defined with the rest of the hidden flags below (to group well with the
|
|
// other flags).
|
|
defineAnalysisArguments(parser, hide: hide);
|
|
|
|
parser
|
|
..addOption('format',
|
|
help: 'Specifies the format in which errors are displayed; the only '
|
|
'currently allowed value is \'machine\'.')
|
|
..addFlag('version',
|
|
help: 'Print the analyzer version.',
|
|
defaultsTo: false,
|
|
negatable: false)
|
|
..addFlag('no-hints',
|
|
help: 'Do not show hint results.',
|
|
defaultsTo: false,
|
|
negatable: false)
|
|
..addFlag('fatal-infos',
|
|
help: 'Treat infos as fatal.', defaultsTo: false, negatable: false)
|
|
..addFlag('fatal-warnings',
|
|
help: 'Treat non-type warnings as fatal.',
|
|
defaultsTo: false,
|
|
negatable: false)
|
|
..addFlag('help',
|
|
abbr: 'h',
|
|
help:
|
|
'Display this help message. Add --verbose to show hidden options.',
|
|
defaultsTo: false,
|
|
negatable: false)
|
|
..addFlag('verbose',
|
|
abbr: 'v',
|
|
defaultsTo: false,
|
|
help: 'Verbose output.',
|
|
negatable: false);
|
|
|
|
if (telemetry.SHOW_ANALYTICS_UI) {
|
|
parser.addFlag('analytics',
|
|
help: 'Enable or disable sending analytics information to Google.');
|
|
}
|
|
|
|
// Build mode options.
|
|
if (!hide) {
|
|
parser.addSeparator('Build mode flags:');
|
|
}
|
|
|
|
parser
|
|
..addFlag('persistent_worker',
|
|
help: 'Enable Bazel persistent worker mode.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addOption('build-analysis-output',
|
|
help:
|
|
'Specifies the path to the file where analysis results should be written.',
|
|
hide: hide)
|
|
..addFlag('build-mode',
|
|
// TODO(paulberry): add more documentation.
|
|
help: 'Enable build mode.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addMultiOption('build-summary-input',
|
|
help: 'Path to a linked summary file that contains information from '
|
|
'a previous analysis run; may be specified multiple times.',
|
|
hide: hide)
|
|
..addMultiOption('build-summary-unlinked-input',
|
|
help: 'Path to an unlinked summary file that contains information '
|
|
'from a previous analysis run; may be specified multiple times.',
|
|
hide: hide)
|
|
..addOption('build-summary-output',
|
|
help: 'Specifies the path to the file where the full summary '
|
|
'information should be written.',
|
|
hide: hide)
|
|
..addOption('build-summary-output-semantic',
|
|
help: 'Specifies the path to the file where the semantic summary '
|
|
'information should be written.',
|
|
hide: hide)
|
|
..addFlag('build-summary-only',
|
|
help: 'Disable analysis (only generate summaries).',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('build-summary-only-unlinked',
|
|
help: 'Only output the unlinked summary.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('build-suppress-exit-code',
|
|
help: 'Exit with code 0 even if errors are found.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('color',
|
|
help: 'Use ansi colors when printing messages.',
|
|
defaultsTo: ansi.terminalSupportsAnsi(),
|
|
hide: hide);
|
|
|
|
// Hidden flags.
|
|
if (!hide) {
|
|
parser.addSeparator('Less frequently used flags:');
|
|
}
|
|
|
|
parser
|
|
..addFlag('batch',
|
|
help: 'Read commands from standard input (for testing).',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag(ignoreUnrecognizedFlagsFlag,
|
|
help: 'Ignore unrecognized command line flags.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('disable-cache-flushing', defaultsTo: false, hide: hide)
|
|
..addOption('x-perf-report',
|
|
help: 'Writes a performance report to the given file (experimental).',
|
|
hide: hide)
|
|
..addOption('x-package-warnings-prefix',
|
|
help:
|
|
'Show warnings from package: imports that match the given prefix.',
|
|
hide: hide)
|
|
..addFlag('enable-conditional-directives',
|
|
help:
|
|
'deprecated -- Enable support for conditional directives (DEP 40).',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('show-package-warnings',
|
|
help: 'Show warnings from package: imports (deprecated).',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('sdk-warnings',
|
|
help: 'Show warnings from SDK imports.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('log',
|
|
help: 'Log additional messages and exceptions.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('enable_type_checks',
|
|
help: 'Check types in constant evaluation.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
// TODO(brianwilkerson) Remove the following option after we're sure that
|
|
// it's no longer being used.
|
|
..addFlag('enable-assert-initializers',
|
|
help: 'Enable parsing of asserts in constructor initializers.',
|
|
defaultsTo: null,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('use-analysis-driver-memory-byte-store',
|
|
help: 'Use memory byte store, not the file system cache.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('fatal-hints',
|
|
help: 'Treat hints as fatal (deprecated: use --fatal-infos).',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('fatal-lints',
|
|
help: 'Treat lints as fatal.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('package-warnings',
|
|
help: 'Show warnings from package: imports.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addMultiOption('url-mapping',
|
|
help: '--url-mapping=libraryUri,/path/to/library.dart directs the '
|
|
'analyzer to use "library.dart" as the source for an import '
|
|
'of "libraryUri".',
|
|
splitCommas: false,
|
|
hide: hide)
|
|
..addFlag('use-cfe',
|
|
help: 'Enable the Dart 2.0 Common Front End implementation.',
|
|
defaultsTo: false,
|
|
negatable: false,
|
|
hide: hide)
|
|
..addFlag('preview-dart-2',
|
|
help: 'Enable the Dart 2.0 preview.', hide: hide);
|
|
|
|
try {
|
|
if (args.contains('--$ignoreUnrecognizedFlagsFlag')) {
|
|
args = filterUnknownArguments(args, parser);
|
|
}
|
|
ArgResults results = parser.parse(args);
|
|
|
|
// Persistent worker.
|
|
if (args.contains('--persistent_worker')) {
|
|
bool hasBuildMode = args.contains('--build-mode');
|
|
bool onlyDartSdkArg = args.length == 2 ||
|
|
(args.length == 3 && args.any((a) => a.startsWith('--dart-sdk'))) ||
|
|
(args.length == 4 && args.contains('--dart-sdk'));
|
|
if (!(hasBuildMode && onlyDartSdkArg)) {
|
|
printAndFail('The --persistent_worker flag should be used with and '
|
|
'only with the --build-mode flag, and possibly the --dart-sdk '
|
|
'option. Got: $args');
|
|
return null; // Only reachable in testing.
|
|
}
|
|
return new CommandLineOptions._fromArgs(results);
|
|
}
|
|
|
|
// Help requests.
|
|
if (results['help']) {
|
|
_showUsage(parser, analytics, fromHelp: true);
|
|
exitHandler(0);
|
|
return null; // Only reachable in testing.
|
|
}
|
|
|
|
// Enable / disable analytics.
|
|
if (telemetry.SHOW_ANALYTICS_UI) {
|
|
if (results.wasParsed('analytics')) {
|
|
analytics.enabled = results['analytics'];
|
|
outSink.writeln(
|
|
telemetry.createAnalyticsStatusMessage(analytics.enabled));
|
|
exitHandler(0);
|
|
return null; // Only reachable in testing.
|
|
}
|
|
}
|
|
|
|
// Batch mode and input files.
|
|
if (results['batch']) {
|
|
if (results.rest.isNotEmpty) {
|
|
errorSink.writeln('No source files expected in the batch mode.');
|
|
_showUsage(parser, analytics);
|
|
exitHandler(15);
|
|
return null; // Only reachable in testing.
|
|
}
|
|
} else if (results['persistent_worker']) {
|
|
if (results.rest.isNotEmpty) {
|
|
errorSink.writeln(
|
|
'No source files expected in the persistent worker mode.');
|
|
_showUsage(parser, analytics);
|
|
exitHandler(15);
|
|
return null; // Only reachable in testing.
|
|
}
|
|
} else if (results['version']) {
|
|
outSink.writeln('$_binaryName version ${_getVersion()}');
|
|
exitHandler(0);
|
|
return null; // Only reachable in testing.
|
|
} else {
|
|
if (results.rest.isEmpty && !results['build-mode']) {
|
|
_showUsage(parser, analytics, fromHelp: true);
|
|
exitHandler(15);
|
|
return null; // Only reachable in testing.
|
|
}
|
|
}
|
|
return new CommandLineOptions._fromArgs(results);
|
|
} on FormatException catch (e) {
|
|
errorSink.writeln(e.message);
|
|
_showUsage(parser, null);
|
|
exitHandler(15);
|
|
return null; // Only reachable in testing.
|
|
}
|
|
}
|
|
|
|
static _showUsage(ArgParser parser, telemetry.Analytics analytics,
|
|
{bool fromHelp: false}) {
|
|
void printAnalyticsInfo() {
|
|
if (!telemetry.SHOW_ANALYTICS_UI) {
|
|
return;
|
|
}
|
|
|
|
if (fromHelp) {
|
|
errorSink.writeln('');
|
|
errorSink.writeln(telemetry.analyticsNotice);
|
|
}
|
|
|
|
if (analytics != null) {
|
|
errorSink.writeln('');
|
|
errorSink.writeln(telemetry.createAnalyticsStatusMessage(
|
|
analytics.enabled,
|
|
command: 'analytics'));
|
|
}
|
|
}
|
|
|
|
errorSink.writeln(
|
|
'Usage: $_binaryName [options...] <directory or list of files>');
|
|
|
|
// If it's our first run, we display the analytics info more prominently.
|
|
if (analytics != null && analytics.firstRun) {
|
|
printAnalyticsInfo();
|
|
}
|
|
|
|
errorSink.writeln('');
|
|
errorSink.writeln(parser.usage);
|
|
|
|
if (analytics != null && !analytics.firstRun) {
|
|
printAnalyticsInfo();
|
|
}
|
|
|
|
errorSink.writeln('');
|
|
errorSink.writeln('''
|
|
Run "dartanalyzer -h -v" for verbose help output, including less commonly used options.
|
|
For more information, see https://www.dartlang.org/tools/analyzer.\n''');
|
|
}
|
|
}
|