| Index: pkg/analyzer_cli/lib/src/options.dart
|
| diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ee683e2d084e7eb1a190f6aa8a6ff833fa297fc3
|
| --- /dev/null
|
| +++ b/pkg/analyzer_cli/lib/src/options.dart
|
| @@ -0,0 +1,485 @@
|
| +// 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.
|
| +
|
| +library analyzer_cli.src.options;
|
| +
|
| +import 'dart:io';
|
| +
|
| +import 'package:analyzer_cli/src/driver.dart';
|
| +import 'package:args/args.dart';
|
| +import 'package:cli_util/cli_util.dart' show getSdkDir;
|
| +
|
| +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 {
|
| + /// The path to an analysis options file
|
| + final String analysisOptionsFile;
|
| +
|
| + /// The path to the dart SDK
|
| + String dartSdkPath;
|
| +
|
| + /// A table mapping the names of defined variables to their values.
|
| + final Map<String, String> definedVariables;
|
| +
|
| + /// Whether to report hints
|
| + final bool disableHints;
|
| +
|
| + /// Whether to display version information
|
| + final bool displayVersion;
|
| +
|
| + /// Whether to enable null-aware operators (DEP 9).
|
| + final bool enableNullAwareOperators;
|
| +
|
| + /// Whether to strictly follow the specification when generating warnings on
|
| + /// "call" methods (fixes dartbug.com/21938).
|
| + final bool enableStrictCallChecks;
|
| +
|
| + /// Whether to relax restrictions on mixins (DEP 34).
|
| + final bool enableSuperMixins;
|
| +
|
| + /// Whether to treat type mismatches found during constant evaluation as
|
| + /// errors.
|
| + final bool enableTypeChecks;
|
| +
|
| + /// Whether to treat hints as fatal
|
| + final bool hintsAreFatal;
|
| +
|
| + /// 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 the package root
|
| + final String packageRootPath;
|
| +
|
| + /// The path to a `.packages` configuration file
|
| + final String packageConfigPath;
|
| +
|
| + /// Batch mode (for unit testing)
|
| + final bool shouldBatch;
|
| +
|
| + /// Whether to show package: warnings
|
| + final bool showPackageWarnings;
|
| +
|
| + /// Whether to show SDK warnings
|
| + final bool showSdkWarnings;
|
| +
|
| + /// The source files to analyze
|
| + final List<String> sourceFiles;
|
| +
|
| + /// Whether to treat warnings as fatal
|
| + final bool warningsAreFatal;
|
| +
|
| + /// Whether to use strong static checking.
|
| + final bool strongMode;
|
| +
|
| + /// Initialize options from the given parsed [args].
|
| + CommandLineOptions._fromArgs(
|
| + ArgResults args, Map<String, String> definedVariables)
|
| + : dartSdkPath = args['dart-sdk'],
|
| + this.definedVariables = definedVariables,
|
| + analysisOptionsFile = args['options'],
|
| + disableHints = args['no-hints'],
|
| + displayVersion = args['version'],
|
| + enableNullAwareOperators = args['enable-null-aware-operators'],
|
| + enableStrictCallChecks = args['enable-strict-call-checks'],
|
| + enableSuperMixins = args['supermixin'],
|
| + enableTypeChecks = args['enable_type_checks'],
|
| + hintsAreFatal = args['fatal-hints'],
|
| + ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
|
| + lints = args['lints'],
|
| + log = args['log'],
|
| + machineFormat = args['machine'] || args['format'] == 'machine',
|
| + packageConfigPath = args['packages'],
|
| + packageRootPath = args['package-root'],
|
| + shouldBatch = args['batch'],
|
| + showPackageWarnings =
|
| + args['show-package-warnings'] || args['package-warnings'],
|
| + showSdkWarnings = args['show-sdk-warnings'] || args['warnings'],
|
| + sourceFiles = args.rest,
|
| + warningsAreFatal = args['fatal-warnings'],
|
| + strongMode = args['strong'];
|
| +
|
| + /// 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 = printAndFail]) {
|
| + CommandLineOptions options = _parse(args);
|
| + // Check SDK.
|
| + {
|
| + // Infer if unspecified.
|
| + if (options.dartSdkPath == null) {
|
| + Directory sdkDir = getSdkDir(args);
|
| + if (sdkDir != null) {
|
| + options.dartSdkPath = sdkDir.path;
|
| + }
|
| + }
|
| +
|
| + var sdkPath = options.dartSdkPath;
|
| +
|
| + // Check that SDK is specified.
|
| + if (sdkPath == null) {
|
| + printAndFail('No Dart SDK found.');
|
| + }
|
| + // Check that SDK is existing directory.
|
| + if (!(new Directory(sdkPath)).existsSync()) {
|
| + printAndFail('Invalid Dart SDK path: $sdkPath');
|
| + }
|
| + }
|
| +
|
| + // Check package config.
|
| + {
|
| + if (options.packageRootPath != null &&
|
| + options.packageConfigPath != null) {
|
| + printAndFail("Cannot specify both '--package-root' and '--packages.");
|
| + }
|
| + }
|
| +
|
| + // OK. Report deprecated options.
|
| + if (options.enableNullAwareOperators) {
|
| + stderr.writeln(
|
| + "Info: Option '--enable-null-aware-operators' is no longer needed. Null aware operators are supported by default.");
|
| + }
|
| +
|
| + 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 = args.expand((String arg) => arg.split('=')).toList();
|
| + var parser = new CommandLineParser()
|
| + ..addFlag('batch',
|
| + abbr: 'b',
|
| + help: 'Read commands from standard input (for testing).',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addOption('dart-sdk', help: 'The path to the Dart SDK.')
|
| + ..addOption('packages',
|
| + help:
|
| + 'Path to the package resolution configuration file, which supplies a mapping of package names to paths. This option cannot be used with --package-root.')
|
| + ..addOption('package-root',
|
| + abbr: 'p',
|
| + help:
|
| + 'Path to a package root directory (deprecated). This option cannot be used with --packages.')
|
| + ..addOption('options', help: 'Path to an analysis options file.')
|
| + ..addOption('format',
|
| + help: 'Specifies the format in which errors are displayed.')
|
| + ..addFlag('machine',
|
| + help: 'Print errors in a format suitable for parsing (deprecated).',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('version',
|
| + help: 'Print the analyzer version.',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('lints',
|
| + help: 'Show lint results.', defaultsTo: false, negatable: false)
|
| + ..addFlag('no-hints',
|
| + help: 'Do not show hint results.',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('ignore-unrecognized-flags',
|
| + help: 'Ignore unrecognized command line flags.',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('fatal-hints',
|
| + help: 'Treat hints as fatal.', defaultsTo: false, negatable: false)
|
| + ..addFlag('fatal-warnings',
|
| + help: 'Treat non-type warnings as fatal.',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('package-warnings',
|
| + help: 'Show warnings from package: imports.',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('show-package-warnings',
|
| + help: 'Show warnings from package: imports (deprecated).',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('warnings',
|
| + help: 'Show warnings from SDK imports.',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('show-sdk-warnings',
|
| + help: 'Show warnings from SDK imports (deprecated).',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addFlag('help',
|
| + abbr: 'h',
|
| + help: 'Display this help message.',
|
| + defaultsTo: false,
|
| + negatable: false)
|
| + ..addOption('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".',
|
| + allowMultiple: true,
|
| + splitCommas: false)
|
| + //
|
| + // Hidden flags.
|
| + //
|
| + ..addFlag('enable-async',
|
| + help: 'Enable support for the proposed async feature.',
|
| + defaultsTo: false,
|
| + negatable: false,
|
| + hide: true)
|
| + ..addFlag('enable-enum',
|
| + help: 'Enable support for the proposed enum feature.',
|
| + defaultsTo: false,
|
| + negatable: false,
|
| + hide: true)
|
| + ..addFlag('enable-null-aware-operators',
|
| + help: 'Enable support for null-aware operators (DEP 9).',
|
| + defaultsTo: false,
|
| + negatable: false,
|
| + hide: true)
|
| + ..addFlag('enable-strict-call-checks',
|
| + help: 'Fix issue 21938.',
|
| + defaultsTo: false,
|
| + negatable: false,
|
| + hide: true)
|
| + ..addFlag('enable-new-task-model',
|
| + help: 'Ennable new task model.',
|
| + defaultsTo: false,
|
| + negatable: false,
|
| + hide: true)
|
| + ..addFlag('supermixin',
|
| + help: 'Relax restrictions on mixins (DEP 34).',
|
| + defaultsTo: false,
|
| + negatable: false,
|
| + hide: true)
|
| + ..addFlag('log',
|
| + help: 'Log additional messages and exceptions.',
|
| + defaultsTo: false,
|
| + negatable: false,
|
| + hide: true)
|
| + ..addFlag('enable_type_checks',
|
| + help: 'Check types in constant evaluation.',
|
| + defaultsTo: false,
|
| + negatable: false,
|
| + hide: true)
|
| + ..addFlag('strong',
|
| + help: 'Enable strong static checks (https://goo.gl/DqcBsw)');
|
| +
|
| + try {
|
| + // TODO(scheglov) https://code.google.com/p/dart/issues/detail?id=11061
|
| + args =
|
| + args.map((String arg) => arg == '-batch' ? '--batch' : arg).toList();
|
| + Map<String, String> definedVariables = <String, String>{};
|
| + var results = parser.parse(args, definedVariables);
|
| + // Help requests.
|
| + if (results['help']) {
|
| + _showUsage(parser);
|
| + exit(0);
|
| + }
|
| + // Batch mode and input files.
|
| + if (results['batch']) {
|
| + if (results.rest.isNotEmpty) {
|
| + stderr.writeln('No source files expected in the batch mode.');
|
| + _showUsage(parser);
|
| + exit(15);
|
| + }
|
| + } else if (results['version']) {
|
| + print('$_binaryName version ${_getVersion()}');
|
| + exit(0);
|
| + } else {
|
| + if (results.rest.isEmpty) {
|
| + _showUsage(parser);
|
| + exit(15);
|
| + }
|
| + }
|
| + return new CommandLineOptions._fromArgs(results, definedVariables);
|
| + } on FormatException catch (e) {
|
| + stderr.writeln(e.message);
|
| + _showUsage(parser);
|
| + exit(15);
|
| + }
|
| + }
|
| +
|
| + static _showUsage(parser) {
|
| + stderr
|
| + .writeln('Usage: $_binaryName [options...] <libraries to analyze...>');
|
| + stderr.writeln(parser.getUsage());
|
| + stderr.writeln('');
|
| + stderr.writeln(
|
| + 'For more information, see http://www.dartlang.org/tools/analyzer.');
|
| + }
|
| +}
|
| +
|
| +/// Commandline argument parser.
|
| +///
|
| +/// TODO(pquitslund): when the args package supports ignoring unrecognized
|
| +/// options/flags, this class can be replaced with a simple [ArgParser]
|
| +/// instance.
|
| +class CommandLineParser {
|
| + final List<String> _knownFlags;
|
| + final bool _alwaysIgnoreUnrecognized;
|
| + final ArgParser _parser;
|
| +
|
| + /// Creates a new command line parser.
|
| + CommandLineParser({bool alwaysIgnoreUnrecognized: false})
|
| + : _knownFlags = <String>[],
|
| + _alwaysIgnoreUnrecognized = alwaysIgnoreUnrecognized,
|
| + _parser = new ArgParser(allowTrailingOptions: true);
|
| +
|
| + ArgParser get parser => _parser;
|
| +
|
| + /// Defines a flag.
|
| + /// See [ArgParser.addFlag()].
|
| + void addFlag(String name,
|
| + {String abbr,
|
| + String help,
|
| + bool defaultsTo: false,
|
| + bool negatable: true,
|
| + void callback(bool value),
|
| + bool hide: false}) {
|
| + _knownFlags.add(name);
|
| + _parser.addFlag(name,
|
| + abbr: abbr,
|
| + help: help,
|
| + defaultsTo: defaultsTo,
|
| + negatable: negatable,
|
| + callback: callback,
|
| + hide: hide);
|
| + }
|
| +
|
| + /// Defines a value-taking option.
|
| + /// See [ArgParser.addOption()].
|
| + void addOption(String name,
|
| + {String abbr,
|
| + String help,
|
| + List<String> allowed,
|
| + Map<String, String> allowedHelp,
|
| + String defaultsTo,
|
| + void callback(value),
|
| + bool allowMultiple: false,
|
| + bool splitCommas}) {
|
| + _knownFlags.add(name);
|
| + _parser.addOption(name,
|
| + abbr: abbr,
|
| + help: help,
|
| + allowed: allowed,
|
| + allowedHelp: allowedHelp,
|
| + defaultsTo: defaultsTo,
|
| + callback: callback,
|
| + allowMultiple: allowMultiple,
|
| + splitCommas: splitCommas);
|
| + }
|
| +
|
| + /// Generates a string displaying usage information for the defined options.
|
| + /// See [ArgParser.usage].
|
| + String getUsage() => _parser.usage;
|
| +
|
| + /// Parses [args], a list of command-line arguments, matches them against the
|
| + /// flags and options defined by this parser, and returns the result. The
|
| + /// values of any defined variables are captured in the given map.
|
| + /// See [ArgParser].
|
| + ArgResults parse(List<String> args, Map<String, String> definedVariables) =>
|
| + _parser.parse(
|
| + _filterUnknowns(parseDefinedVariables(args, definedVariables)));
|
| +
|
| + List<String> parseDefinedVariables(
|
| + List<String> args, Map<String, String> definedVariables) {
|
| + int count = args.length;
|
| + List<String> remainingArgs = <String>[];
|
| + for (int i = 0; i < count; i++) {
|
| + String arg = args[i];
|
| + if (arg == '--') {
|
| + while (i < count) {
|
| + remainingArgs.add(args[i++]);
|
| + }
|
| + } else if (arg.startsWith("-D")) {
|
| + definedVariables[arg.substring(2)] = args[++i];
|
| + } else {
|
| + remainingArgs.add(arg);
|
| + }
|
| + }
|
| + return remainingArgs;
|
| + }
|
| +
|
| + List<String> _filterUnknowns(List<String> args) {
|
| + // Only filter args if the ignore flag is specified, or if
|
| + // _alwaysIgnoreUnrecognized was set to true.
|
| + if (_alwaysIgnoreUnrecognized ||
|
| + args.contains('--ignore-unrecognized-flags')) {
|
| + //TODO(pquitslund): replace w/ the following once library skew issues are
|
| + // sorted out
|
| + //return args.where((arg) => !arg.startsWith('--') ||
|
| + // _knownFlags.contains(arg.substring(2)));
|
| +
|
| + // Filter all unrecognized flags and options.
|
| + List<String> filtered = <String>[];
|
| + for (int i = 0; i < args.length; ++i) {
|
| + String arg = args[i];
|
| + if (arg.startsWith('--') && arg.length > 2) {
|
| + String option = arg.substring(2);
|
| + // strip the last '=value'
|
| + int equalsOffset = option.lastIndexOf('=');
|
| + if (equalsOffset != -1) {
|
| + option = option.substring(0, equalsOffset);
|
| + }
|
| + // Check the option
|
| + if (!_knownFlags.contains(option)) {
|
| + //"eat" params by advancing to the next flag/option
|
| + i = _getNextFlagIndex(args, i);
|
| + } else {
|
| + filtered.add(arg);
|
| + }
|
| + } else {
|
| + filtered.add(arg);
|
| + }
|
| + }
|
| +
|
| + return filtered;
|
| + } else {
|
| + return args;
|
| + }
|
| + }
|
| +
|
| + int _getNextFlagIndex(args, i) {
|
| + for (; i < args.length; ++i) {
|
| + if (args[i].startsWith('--')) {
|
| + return i;
|
| + }
|
| + }
|
| + return i;
|
| + }
|
| +}
|
|
|