mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:31:20 +00:00
Analyzer CLI removal.
CLI now lives in dedicated `analyzer_cli` package. R=brianwilkerson@google.com Review URL: https://codereview.chromium.org//1102613002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45362 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
434ba369f9
commit
49d0f16a2a
|
@ -1,3 +1,13 @@
|
|||
## 0.24.7
|
||||
|
||||
* Commandline interface moved to dedicated `analyzer_cli` package. Files moved:
|
||||
** `bin/analyzer.dart`
|
||||
** `lib/analyzer.dart`
|
||||
** `lib/options.dart`
|
||||
** `lib/src/analyzer_impl.dart`
|
||||
** `lib/src/error_formatter.dart`
|
||||
* Removed dependency on `args` package.
|
||||
|
||||
## 0.22.1
|
||||
|
||||
* Changes in the async/await support.
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
#!/usr/bin/env dart
|
||||
// Copyright (c) 2013, 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.
|
||||
|
||||
/** The entry point for the analyzer. */
|
||||
library analyzer;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:analyzer/options.dart';
|
||||
import 'package:analyzer/src/analyzer_impl.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart';
|
||||
import 'package:analyzer/src/generated/error.dart';
|
||||
import 'package:analyzer/src/generated/interner.dart';
|
||||
import 'package:analyzer/src/generated/java_core.dart' show JavaSystem;
|
||||
import 'package:analyzer/src/generated/java_engine.dart';
|
||||
import 'package:analyzer/src/generated/utilities_general.dart';
|
||||
|
||||
void main(List<String> args) {
|
||||
StringUtilities.INTERNER = new MappedInterner();
|
||||
CommandLineOptions options = CommandLineOptions.parse(args);
|
||||
if (options.shouldBatch) {
|
||||
BatchRunner.runAsBatch(args, (List<String> args) {
|
||||
CommandLineOptions options = CommandLineOptions.parse(args);
|
||||
return _analyzeAll(options, true);
|
||||
});
|
||||
} else {
|
||||
_analyzeAll(options, false);
|
||||
}
|
||||
}
|
||||
|
||||
_analyzeAll(CommandLineOptions options, bool isBatch) {
|
||||
if (!options.machineFormat) {
|
||||
stdout.writeln("Analyzing ${options.sourceFiles}...");
|
||||
}
|
||||
ErrorSeverity allResult = ErrorSeverity.NONE;
|
||||
for (String sourcePath in options.sourceFiles) {
|
||||
sourcePath = sourcePath.trim();
|
||||
// check that file exists
|
||||
if (!new File(sourcePath).existsSync()) {
|
||||
print('File not found: $sourcePath');
|
||||
exitCode = ErrorSeverity.ERROR.ordinal;
|
||||
// fail fast; don't analyze more files
|
||||
return ErrorSeverity.ERROR;
|
||||
}
|
||||
// check that file is Dart file
|
||||
if (!AnalysisEngine.isDartFileName(sourcePath)) {
|
||||
print('$sourcePath is not a Dart file');
|
||||
exitCode = ErrorSeverity.ERROR.ordinal;
|
||||
// fail fast; don't analyze more files
|
||||
return ErrorSeverity.ERROR;
|
||||
}
|
||||
ErrorSeverity status = _runAnalyzer(options, sourcePath, isBatch);
|
||||
allResult = allResult.max(status);
|
||||
}
|
||||
return allResult;
|
||||
}
|
||||
|
||||
_runAnalyzer(CommandLineOptions options, String sourcePath, bool isBatch) {
|
||||
if (options.warmPerf) {
|
||||
int startTime = JavaSystem.currentTimeMillis();
|
||||
AnalyzerImpl analyzer =
|
||||
new AnalyzerImpl(sourcePath, options, startTime, isBatch);
|
||||
analyzer.analyzeSync(printMode: 2);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
startTime = JavaSystem.currentTimeMillis();
|
||||
analyzer = new AnalyzerImpl(sourcePath, options, startTime, isBatch);
|
||||
analyzer.analyzeSync(printMode: 0);
|
||||
}
|
||||
|
||||
PerformanceTag.reset();
|
||||
startTime = JavaSystem.currentTimeMillis();
|
||||
analyzer = new AnalyzerImpl(sourcePath, options, startTime, isBatch);
|
||||
return analyzer.analyzeSync();
|
||||
}
|
||||
int startTime = JavaSystem.currentTimeMillis();
|
||||
AnalyzerImpl analyzer =
|
||||
new AnalyzerImpl(sourcePath, options, startTime, isBatch);
|
||||
var errorSeverity = analyzer.analyzeSync();
|
||||
if (errorSeverity == ErrorSeverity.ERROR) {
|
||||
exitCode = errorSeverity.ordinal;
|
||||
}
|
||||
if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) {
|
||||
exitCode = errorSeverity.ordinal;
|
||||
}
|
||||
return errorSeverity;
|
||||
}
|
||||
|
||||
typedef ErrorSeverity BatchRunnerHandler(List<String> args);
|
||||
|
||||
/// Provides a framework to read command line options from stdin and feed them to a callback.
|
||||
class BatchRunner {
|
||||
/**
|
||||
* Run the tool in 'batch' mode, receiving command lines through stdin and returning pass/fail
|
||||
* status through stdout. This feature is intended for use in unit testing.
|
||||
*/
|
||||
static void runAsBatch(List<String> sharedArgs, BatchRunnerHandler handler) {
|
||||
stdout.writeln('>>> BATCH START');
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.start();
|
||||
int testsFailed = 0;
|
||||
int totalTests = 0;
|
||||
ErrorSeverity batchResult = ErrorSeverity.NONE;
|
||||
// read line from stdin
|
||||
Stream cmdLine =
|
||||
stdin.transform(UTF8.decoder).transform(new LineSplitter());
|
||||
cmdLine.listen((String line) {
|
||||
// may be finish
|
||||
if (line.isEmpty) {
|
||||
var time = stopwatch.elapsedMilliseconds;
|
||||
stdout.writeln(
|
||||
'>>> BATCH END (${totalTests - testsFailed}/$totalTests) ${time}ms');
|
||||
exitCode = batchResult.ordinal;
|
||||
}
|
||||
// prepare aruments
|
||||
var args;
|
||||
{
|
||||
var lineArgs = line.split(new RegExp('\\s+'));
|
||||
args = new List<String>();
|
||||
args.addAll(sharedArgs);
|
||||
args.addAll(lineArgs);
|
||||
args.remove('-b');
|
||||
args.remove('--batch');
|
||||
}
|
||||
// analyze single set of arguments
|
||||
try {
|
||||
totalTests++;
|
||||
ErrorSeverity result = handler(args);
|
||||
bool resultPass = result != ErrorSeverity.ERROR;
|
||||
if (!resultPass) {
|
||||
testsFailed++;
|
||||
}
|
||||
batchResult = batchResult.max(result);
|
||||
// Write stderr end token and flush.
|
||||
stderr.writeln('>>> EOF STDERR');
|
||||
String resultPassString = resultPass ? 'PASS' : 'FAIL';
|
||||
stdout.writeln(
|
||||
'>>> TEST $resultPassString ${stopwatch.elapsedMilliseconds}ms');
|
||||
} catch (e, stackTrace) {
|
||||
stderr.writeln(e);
|
||||
stderr.writeln(stackTrace);
|
||||
stderr.writeln('>>> EOF STDERR');
|
||||
stdout.writeln('>>> TEST CRASH');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,443 +0,0 @@
|
|||
// Copyright (c) 2013, 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 options;
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
|
||||
const _BINARY_NAME = 'dartanalyzer';
|
||||
|
||||
/**
|
||||
* Analyzer commandline configuration options.
|
||||
*/
|
||||
class CommandLineOptions {
|
||||
/** The path to the dart SDK */
|
||||
final 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 treat type mismatches found during constant evaluation as
|
||||
* errors.
|
||||
*/
|
||||
final bool enableTypeChecks;
|
||||
|
||||
/** Whether to ignore unrecognized flags */
|
||||
final bool ignoreUnrecognizedFlags;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Whether to show performance statistics */
|
||||
final bool perf;
|
||||
|
||||
/** 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 show both cold and hot performance statistics */
|
||||
final bool warmPerf;
|
||||
|
||||
/** Whether to treat warnings as fatal */
|
||||
final bool warningsAreFatal;
|
||||
|
||||
/** A table mapping library URIs to the file system path where the library
|
||||
* source is located.
|
||||
*/
|
||||
final Map<String, String> customUrlMappings;
|
||||
|
||||
/**
|
||||
* Initialize options from the given parsed [args].
|
||||
*/
|
||||
CommandLineOptions._fromArgs(ArgResults args,
|
||||
Map<String, String> definedVariables,
|
||||
Map<String, String> customUrlMappings)
|
||||
: dartSdkPath = args['dart-sdk'],
|
||||
this.definedVariables = definedVariables,
|
||||
disableHints = args['no-hints'],
|
||||
displayVersion = args['version'],
|
||||
enableNullAwareOperators = args['enable-null-aware-operators'],
|
||||
enableStrictCallChecks = args['enable-strict-call-checks'],
|
||||
enableTypeChecks = args['enable_type_checks'],
|
||||
ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'],
|
||||
log = args['log'],
|
||||
machineFormat = args['machine'] || args['format'] == 'machine',
|
||||
packageRootPath = args['package-root'],
|
||||
perf = args['perf'],
|
||||
shouldBatch = args['batch'],
|
||||
showPackageWarnings = args['show-package-warnings'] ||
|
||||
args['package-warnings'],
|
||||
showSdkWarnings = args['show-sdk-warnings'] || args['warnings'],
|
||||
sourceFiles = args.rest,
|
||||
warmPerf = args['warm-perf'],
|
||||
warningsAreFatal = args['fatal-warnings'],
|
||||
this.customUrlMappings = customUrlMappings;
|
||||
|
||||
/**
|
||||
* Parse [args] into [CommandLineOptions] describing the specified
|
||||
* analyzer options. In case of a format error, prints error and exists.
|
||||
*/
|
||||
static CommandLineOptions parse(List<String> args) {
|
||||
CommandLineOptions options = _parse(args);
|
||||
// check SDK
|
||||
{
|
||||
var sdkPath = options.dartSdkPath;
|
||||
// check that SDK is specified
|
||||
if (sdkPath == null) {
|
||||
print('Usage: $_BINARY_NAME: no Dart SDK found.');
|
||||
exit(15);
|
||||
}
|
||||
// check that SDK is existing directory
|
||||
if (!(new Directory(sdkPath)).existsSync()) {
|
||||
print('Usage: $_BINARY_NAME: invalid Dart SDK path: $sdkPath');
|
||||
exit(15);
|
||||
}
|
||||
}
|
||||
// OK
|
||||
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: 'Run in batch mode',
|
||||
defaultsTo: false,
|
||||
negatable: false)
|
||||
..addOption('dart-sdk', help: 'The path to the Dart SDK')
|
||||
..addOption('package-root',
|
||||
abbr: 'p',
|
||||
help: 'The path to the package root. The flag package-root is deprecated. Remove to use package information computed by pub.')
|
||||
..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('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-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('perf',
|
||||
help: 'Show performance statistics',
|
||||
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)
|
||||
//
|
||||
// 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('log',
|
||||
help: 'Log additional messages and exceptions',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
hide: true)
|
||||
..addFlag('warm-perf',
|
||||
help: 'Show both cold and warm performance statistics',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
hide: true)
|
||||
..addFlag('enable_type_checks',
|
||||
help: 'Check types in constant evaluation',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
hide: true);
|
||||
|
||||
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) {
|
||||
print('No source files expected in the batch mode.');
|
||||
_showUsage(parser);
|
||||
exit(15);
|
||||
}
|
||||
} else if (results['version']) {
|
||||
print('$_BINARY_NAME version ${_getVersion()}');
|
||||
exit(0);
|
||||
} else {
|
||||
if (results.rest.isEmpty) {
|
||||
_showUsage(parser);
|
||||
exit(15);
|
||||
}
|
||||
}
|
||||
Map<String, String> customUrlMappings = <String, String>{};
|
||||
for (String mapping in results['url-mapping']) {
|
||||
List<String> splitMapping = mapping.split(',');
|
||||
if (splitMapping.length != 2) {
|
||||
_showUsage(parser);
|
||||
exit(15);
|
||||
}
|
||||
customUrlMappings[splitMapping[0]] = splitMapping[1];
|
||||
}
|
||||
return new CommandLineOptions._fromArgs(
|
||||
results, definedVariables, customUrlMappings);
|
||||
} on FormatException catch (e) {
|
||||
print(e.message);
|
||||
_showUsage(parser);
|
||||
exit(15);
|
||||
}
|
||||
}
|
||||
|
||||
static _showUsage(parser) {
|
||||
print('Usage: $_BINARY_NAME [options...] <libraries to analyze...>');
|
||||
print(parser.getUsage());
|
||||
print('');
|
||||
print('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}) {
|
||||
_knownFlags.add(name);
|
||||
_parser.addOption(name,
|
||||
abbr: abbr,
|
||||
help: help,
|
||||
allowed: allowed,
|
||||
allowedHelp: allowedHelp,
|
||||
defaultsTo: defaultsTo,
|
||||
callback: callback,
|
||||
allowMultiple: allowMultiple);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)) {
|
||||
//print('remove: $arg');
|
||||
//"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;
|
||||
}
|
||||
}
|
||||
|
||||
_getNextFlagIndex(args, i) {
|
||||
for (; i < args.length; ++i) {
|
||||
if (args[i].startsWith('--')) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
|
@ -1,498 +0,0 @@
|
|||
// Copyright (c) 2013, 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_impl;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:analyzer/file_system/file_system.dart' show Folder;
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
import 'package:analyzer/source/package_map_provider.dart';
|
||||
import 'package:analyzer/source/package_map_resolver.dart';
|
||||
import 'package:analyzer/source/pub_package_map_provider.dart';
|
||||
import 'package:analyzer/src/error_formatter.dart';
|
||||
import 'package:analyzer/src/generated/java_core.dart' show JavaSystem;
|
||||
import 'package:analyzer/src/generated/java_engine.dart';
|
||||
import 'package:analyzer/src/generated/utilities_general.dart';
|
||||
|
||||
import '../options.dart';
|
||||
import 'generated/constant.dart';
|
||||
import 'generated/element.dart';
|
||||
import 'generated/engine.dart';
|
||||
import 'generated/error.dart';
|
||||
import 'generated/java_io.dart';
|
||||
import 'generated/sdk_io.dart';
|
||||
import 'generated/source_io.dart';
|
||||
|
||||
DirectoryBasedDartSdk sdk;
|
||||
|
||||
/**
|
||||
* The maximum number of sources for which AST structures should be kept in the cache.
|
||||
*/
|
||||
const int _MAX_CACHE_SIZE = 512;
|
||||
|
||||
/// Analyzes single library [File].
|
||||
class AnalyzerImpl {
|
||||
final String sourcePath;
|
||||
|
||||
final CommandLineOptions options;
|
||||
final int startTime;
|
||||
|
||||
/**
|
||||
* True if the analyzer is running in batch mode.
|
||||
*/
|
||||
final bool isBatch;
|
||||
|
||||
ContentCache contentCache = new ContentCache();
|
||||
|
||||
SourceFactory sourceFactory;
|
||||
AnalysisContext context;
|
||||
Source librarySource;
|
||||
/// All [Source]s references by the analyzed library.
|
||||
final Set<Source> sources = new Set<Source>();
|
||||
|
||||
/// All [AnalysisErrorInfo]s in the analyzed library.
|
||||
final List<AnalysisErrorInfo> errorInfos = new List<AnalysisErrorInfo>();
|
||||
|
||||
/// [HashMap] between sources and analysis error infos.
|
||||
final HashMap<Source, AnalysisErrorInfo> sourceErrorsMap =
|
||||
new HashMap<Source, AnalysisErrorInfo>();
|
||||
|
||||
/**
|
||||
* If the file specified on the command line is part of a package, the name
|
||||
* of that package. Otherwise `null`. This allows us to analyze the file
|
||||
* specified on the command line as though it is reached via a "package:"
|
||||
* URI, but avoid suppressing its output in the event that the user has not
|
||||
* specified the "--package-warnings" option.
|
||||
*/
|
||||
String _selfPackageName;
|
||||
|
||||
AnalyzerImpl(String sourcePath, this.options, this.startTime, this.isBatch)
|
||||
: sourcePath = _normalizeSourcePath(sourcePath) {
|
||||
if (sdk == null) {
|
||||
sdk = new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath));
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the maximal [ErrorSeverity] of the recorded errors.
|
||||
ErrorSeverity get maxErrorSeverity {
|
||||
var status = ErrorSeverity.NONE;
|
||||
for (AnalysisErrorInfo errorInfo in errorInfos) {
|
||||
for (AnalysisError error in errorInfo.errors) {
|
||||
if (!_isDesiredError(error)) {
|
||||
continue;
|
||||
}
|
||||
var severity = computeSeverity(error, options.enableTypeChecks);
|
||||
status = status.max(severity);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void addCompilationUnitSource(CompilationUnitElement unit,
|
||||
Set<LibraryElement> libraries, Set<CompilationUnitElement> units) {
|
||||
if (unit == null || units.contains(unit)) {
|
||||
return;
|
||||
}
|
||||
units.add(unit);
|
||||
sources.add(unit.source);
|
||||
}
|
||||
|
||||
void addLibrarySources(LibraryElement library, Set<LibraryElement> libraries,
|
||||
Set<CompilationUnitElement> units) {
|
||||
if (library == null || !libraries.add(library)) {
|
||||
return;
|
||||
}
|
||||
// may be skip library
|
||||
{
|
||||
UriKind uriKind = library.source.uriKind;
|
||||
// Optionally skip package: libraries.
|
||||
if (!options.showPackageWarnings && _isOtherPackage(library.source.uri)) {
|
||||
return;
|
||||
}
|
||||
// Optionally skip SDK libraries.
|
||||
if (!options.showSdkWarnings && uriKind == UriKind.DART_URI) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// add compilation units
|
||||
addCompilationUnitSource(library.definingCompilationUnit, libraries, units);
|
||||
for (CompilationUnitElement child in library.parts) {
|
||||
addCompilationUnitSource(child, libraries, units);
|
||||
}
|
||||
// add referenced libraries
|
||||
for (LibraryElement child in library.importedLibraries) {
|
||||
addLibrarySources(child, libraries, units);
|
||||
}
|
||||
for (LibraryElement child in library.exportedLibraries) {
|
||||
addLibrarySources(child, libraries, units);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Treats the [sourcePath] as the top level library and analyzes it using a
|
||||
* asynchronous algorithm over the analysis engine.
|
||||
*/
|
||||
void analyzeAsync() {
|
||||
setupForAnalysis();
|
||||
_analyzeAsync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Treats the [sourcePath] as the top level library and analyzes it using a
|
||||
* synchronous algorithm over the analysis engine. If [printMode] is `0`,
|
||||
* then no error or performance information is printed. If [printMode] is `1`,
|
||||
* then both will be printed. If [printMode] is `2`, then only performance
|
||||
* information will be printed, and it will be marked as being for a cold VM.
|
||||
*/
|
||||
ErrorSeverity analyzeSync({int printMode: 1}) {
|
||||
setupForAnalysis();
|
||||
return _analyzeSync(printMode);
|
||||
}
|
||||
|
||||
Source computeLibrarySource() {
|
||||
JavaFile sourceFile = new JavaFile(sourcePath);
|
||||
Source source = sdk.fromFileUri(sourceFile.toURI());
|
||||
if (source != null) {
|
||||
return source;
|
||||
}
|
||||
source = new FileBasedSource.con2(sourceFile.toURI(), sourceFile);
|
||||
Uri uri = context.sourceFactory.restoreUri(source);
|
||||
if (uri == null) {
|
||||
return source;
|
||||
}
|
||||
return new FileBasedSource.con2(uri, sourceFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return the source factory to be used by the analysis context.
|
||||
*/
|
||||
SourceFactory createSourceFactory() {
|
||||
List<UriResolver> resolvers = [
|
||||
new CustomUriResolver(options.customUrlMappings),
|
||||
new DartUriResolver(sdk)
|
||||
];
|
||||
if (options.packageRootPath != null) {
|
||||
JavaFile packageDirectory = new JavaFile(options.packageRootPath);
|
||||
resolvers.add(new PackageUriResolver([packageDirectory]));
|
||||
} else {
|
||||
PubPackageMapProvider pubPackageMapProvider =
|
||||
new PubPackageMapProvider(PhysicalResourceProvider.INSTANCE, sdk);
|
||||
PackageMapInfo packageMapInfo = pubPackageMapProvider.computePackageMap(
|
||||
PhysicalResourceProvider.INSTANCE.getResource('.'));
|
||||
Map<String, List<Folder>> packageMap = packageMapInfo.packageMap;
|
||||
if (packageMap != null) {
|
||||
resolvers.add(new PackageMapUriResolver(
|
||||
PhysicalResourceProvider.INSTANCE, packageMap));
|
||||
}
|
||||
}
|
||||
resolvers.add(new FileUriResolver());
|
||||
return new SourceFactory(resolvers);
|
||||
}
|
||||
|
||||
void prepareAnalysisContext() {
|
||||
sourceFactory = createSourceFactory();
|
||||
context = AnalysisEngine.instance.createAnalysisContext();
|
||||
context.sourceFactory = sourceFactory;
|
||||
Map<String, String> definedVariables = options.definedVariables;
|
||||
if (!definedVariables.isEmpty) {
|
||||
DeclaredVariables declaredVariables = context.declaredVariables;
|
||||
definedVariables.forEach((String variableName, String value) {
|
||||
declaredVariables.define(variableName, value);
|
||||
});
|
||||
}
|
||||
// Uncomment the following to have errors reported on stdout and stderr
|
||||
AnalysisEngine.instance.logger = new StdLogger(options.log);
|
||||
|
||||
// set options for context
|
||||
AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
|
||||
contextOptions.cacheSize = _MAX_CACHE_SIZE;
|
||||
contextOptions.hint = !options.disableHints;
|
||||
contextOptions.enableNullAwareOperators = options.enableNullAwareOperators;
|
||||
contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
|
||||
contextOptions.analyzeFunctionBodiesPredicate =
|
||||
_analyzeFunctionBodiesPredicate;
|
||||
contextOptions.generateImplicitErrors = options.showPackageWarnings;
|
||||
contextOptions.generateSdkErrors = options.showSdkWarnings;
|
||||
context.analysisOptions = contextOptions;
|
||||
|
||||
librarySource = computeLibrarySource();
|
||||
|
||||
Uri libraryUri = librarySource.uri;
|
||||
if (libraryUri.scheme == 'package' && libraryUri.pathSegments.length > 0) {
|
||||
_selfPackageName = libraryUri.pathSegments[0];
|
||||
}
|
||||
|
||||
// Create and add a ChangeSet
|
||||
ChangeSet changeSet = new ChangeSet();
|
||||
changeSet.addedSource(librarySource);
|
||||
context.applyChanges(changeSet);
|
||||
}
|
||||
|
||||
/// Fills [errorInfos] using [sources].
|
||||
void prepareErrors() {
|
||||
for (Source source in sources) {
|
||||
context.computeErrors(source);
|
||||
var sourceErrors = context.getErrors(source);
|
||||
errorInfos.add(sourceErrors);
|
||||
}
|
||||
}
|
||||
|
||||
/// Fills [sources].
|
||||
void prepareSources(LibraryElement library) {
|
||||
var units = new Set<CompilationUnitElement>();
|
||||
var libraries = new Set<LibraryElement>();
|
||||
addLibrarySources(library, libraries, units);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup local fields such as the analysis context for analysis.
|
||||
*/
|
||||
void setupForAnalysis() {
|
||||
sources.clear();
|
||||
errorInfos.clear();
|
||||
if (sourcePath == null) {
|
||||
throw new ArgumentError("sourcePath cannot be null");
|
||||
}
|
||||
// prepare context
|
||||
prepareAnalysisContext();
|
||||
}
|
||||
|
||||
/// The async version of the analysis
|
||||
void _analyzeAsync() {
|
||||
new Future(context.performAnalysisTask).then((AnalysisResult result) {
|
||||
List<ChangeNotice> notices = result.changeNotices;
|
||||
if (result.hasMoreWork) {
|
||||
// There is more work, record the set of sources, and then call self
|
||||
// again to perform next task
|
||||
for (ChangeNotice notice in notices) {
|
||||
sources.add(notice.source);
|
||||
sourceErrorsMap[notice.source] = notice;
|
||||
}
|
||||
return _analyzeAsync();
|
||||
}
|
||||
//
|
||||
// There are not any more tasks, set error code and print performance
|
||||
// numbers.
|
||||
//
|
||||
// prepare errors
|
||||
sourceErrorsMap.forEach((k, v) {
|
||||
errorInfos.add(sourceErrorsMap[k]);
|
||||
});
|
||||
|
||||
// print errors and performance numbers
|
||||
_printErrorsAndPerf();
|
||||
|
||||
// compute max severity and set exitCode
|
||||
ErrorSeverity status = maxErrorSeverity;
|
||||
if (status == ErrorSeverity.WARNING && options.warningsAreFatal) {
|
||||
status = ErrorSeverity.ERROR;
|
||||
}
|
||||
exitCode = status.ordinal;
|
||||
}).catchError((ex, st) {
|
||||
AnalysisEngine.instance.logger.logError("$ex\n$st");
|
||||
});
|
||||
}
|
||||
|
||||
bool _analyzeFunctionBodiesPredicate(Source source) {
|
||||
// TODO(paulberry): This function will need to be updated when we add the
|
||||
// ability to suppress errors, warnings, and hints for files reached via
|
||||
// custom URI's using the "--url-mapping" flag.
|
||||
if (source.uri.scheme == 'dart') {
|
||||
if (isBatch) {
|
||||
// When running in batch mode, the SDK files are cached from one
|
||||
// analysis run to the next. So we need to parse function bodies even
|
||||
// if the user hasn't asked for errors/warnings from the SDK, since
|
||||
// they might ask for errors/warnings from the SDK in the future.
|
||||
return true;
|
||||
}
|
||||
return options.showSdkWarnings;
|
||||
}
|
||||
if (_isOtherPackage(source.uri)) {
|
||||
return options.showPackageWarnings;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// The sync version of analysis.
|
||||
ErrorSeverity _analyzeSync(int printMode) {
|
||||
// don't try to analyze parts
|
||||
if (context.computeKindOf(librarySource) == SourceKind.PART) {
|
||||
print("Only libraries can be analyzed.");
|
||||
print("$sourcePath is a part and can not be analyzed.");
|
||||
return ErrorSeverity.ERROR;
|
||||
}
|
||||
// resolve library
|
||||
var libraryElement = context.computeLibraryElement(librarySource);
|
||||
// prepare source and errors
|
||||
prepareSources(libraryElement);
|
||||
prepareErrors();
|
||||
|
||||
// print errors and performance numbers
|
||||
if (printMode == 1) {
|
||||
_printErrorsAndPerf();
|
||||
} else if (printMode == 2) {
|
||||
_printColdPerf();
|
||||
}
|
||||
|
||||
// compute max severity and set exitCode
|
||||
ErrorSeverity status = maxErrorSeverity;
|
||||
if (status == ErrorSeverity.WARNING && options.warningsAreFatal) {
|
||||
status = ErrorSeverity.ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool _isDesiredError(AnalysisError error) {
|
||||
if (error.errorCode.type == ErrorType.TODO) {
|
||||
return false;
|
||||
}
|
||||
if (computeSeverity(error, options.enableTypeChecks) ==
|
||||
ErrorSeverity.INFO &&
|
||||
options.disableHints) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given URI refers to a package other than the package
|
||||
* being analyzed.
|
||||
*/
|
||||
bool _isOtherPackage(Uri uri) {
|
||||
if (uri.scheme != 'package') {
|
||||
return false;
|
||||
}
|
||||
if (_selfPackageName != null &&
|
||||
uri.pathSegments.length > 0 &&
|
||||
uri.pathSegments[0] == _selfPackageName) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_printColdPerf() {
|
||||
// print cold VM performance numbers
|
||||
int totalTime = JavaSystem.currentTimeMillis() - startTime;
|
||||
int otherTime = totalTime;
|
||||
for (PerformanceTag tag in PerformanceTag.all) {
|
||||
if (tag != PerformanceTag.UNKNOWN) {
|
||||
int tagTime = tag.elapsedMs;
|
||||
stdout.writeln('${tag.label}-cold:$tagTime');
|
||||
otherTime -= tagTime;
|
||||
}
|
||||
}
|
||||
stdout.writeln('other-cold:$otherTime');
|
||||
stdout.writeln("total-cold:$totalTime");
|
||||
}
|
||||
|
||||
_printErrorsAndPerf() {
|
||||
// The following is a hack. We currently print out to stderr to ensure that
|
||||
// when in batch mode we print to stderr, this is because the prints from
|
||||
// batch are made to stderr. The reason that options.shouldBatch isn't used
|
||||
// is because when the argument flags are constructed in BatchRunner and
|
||||
// passed in from batch mode which removes the batch flag to prevent the
|
||||
// "cannot have the batch flag and source file" error message.
|
||||
IOSink sink = options.machineFormat ? stderr : stdout;
|
||||
|
||||
// print errors
|
||||
ErrorFormatter formatter =
|
||||
new ErrorFormatter(sink, options, _isDesiredError);
|
||||
formatter.formatErrors(errorInfos);
|
||||
|
||||
// print performance numbers
|
||||
if (options.perf || options.warmPerf) {
|
||||
int totalTime = JavaSystem.currentTimeMillis() - startTime;
|
||||
int otherTime = totalTime;
|
||||
for (PerformanceTag tag in PerformanceTag.all) {
|
||||
if (tag != PerformanceTag.UNKNOWN) {
|
||||
int tagTime = tag.elapsedMs;
|
||||
stdout.writeln('${tag.label}:$tagTime');
|
||||
otherTime -= tagTime;
|
||||
}
|
||||
}
|
||||
stdout.writeln('other:$otherTime');
|
||||
stdout.writeln("total:$totalTime");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the severity of the error; however, if
|
||||
* [enableTypeChecks] is false, then de-escalate checked-mode compile time
|
||||
* errors to a severity of [ErrorSeverity.INFO].
|
||||
*/
|
||||
static ErrorSeverity computeSeverity(
|
||||
AnalysisError error, bool enableTypeChecks) {
|
||||
if (!enableTypeChecks &&
|
||||
error.errorCode.type == ErrorType.CHECKED_MODE_COMPILE_TIME_ERROR) {
|
||||
return ErrorSeverity.INFO;
|
||||
}
|
||||
return error.errorCode.errorSeverity;
|
||||
}
|
||||
|
||||
static JavaFile getPackageDirectoryFor(JavaFile sourceFile) {
|
||||
// we are going to ask parent file, so get absolute path
|
||||
sourceFile = sourceFile.getAbsoluteFile();
|
||||
// look in the containing directories
|
||||
JavaFile dir = sourceFile.getParentFile();
|
||||
while (dir != null) {
|
||||
JavaFile packagesDir = new JavaFile.relative(dir, "packages");
|
||||
if (packagesDir.exists()) {
|
||||
return packagesDir;
|
||||
}
|
||||
dir = dir.getParentFile();
|
||||
}
|
||||
// not found
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert [sourcePath] into an absolute path.
|
||||
*/
|
||||
static String _normalizeSourcePath(String sourcePath) {
|
||||
return new File(sourcePath).absolute.path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This [Logger] prints out information comments to [stdout] and error messages
|
||||
* to [stderr].
|
||||
*/
|
||||
class StdLogger extends Logger {
|
||||
final bool log;
|
||||
|
||||
StdLogger(this.log);
|
||||
|
||||
@override
|
||||
void logError(String message, [CaughtException exception]) {
|
||||
stderr.writeln(message);
|
||||
if (exception != null) {
|
||||
stderr.writeln(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void logError2(String message, Object exception) {
|
||||
stderr.writeln(message);
|
||||
}
|
||||
|
||||
@override
|
||||
void logInformation(String message, [CaughtException exception]) {
|
||||
if (log) {
|
||||
stdout.writeln(message);
|
||||
if (exception != null) {
|
||||
stderr.writeln(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void logInformation2(String message, Object exception) {
|
||||
if (log) {
|
||||
stdout.writeln(message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
// Copyright (c) 2013, 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 error_formatter;
|
||||
|
||||
import 'package:analyzer/src/analyzer_impl.dart';
|
||||
|
||||
import '../options.dart';
|
||||
import 'generated/engine.dart';
|
||||
import 'generated/error.dart';
|
||||
import 'generated/source_io.dart';
|
||||
|
||||
/// Allows any [AnalysisError].
|
||||
bool _anyError(AnalysisError error) => true;
|
||||
|
||||
/// Returns `true` if [AnalysisError] should be printed.
|
||||
typedef bool _ErrorFilter(AnalysisError error);
|
||||
|
||||
/**
|
||||
* Helper for formatting [AnalysisError]s.
|
||||
* The two format options are a user consumable format and a machine consumable format.
|
||||
*/
|
||||
class ErrorFormatter {
|
||||
final StringSink out;
|
||||
final CommandLineOptions options;
|
||||
final _ErrorFilter errorFilter;
|
||||
|
||||
ErrorFormatter(this.out, this.options, [this.errorFilter = _anyError]);
|
||||
|
||||
void formatError(
|
||||
Map<AnalysisError, LineInfo> errorToLine, AnalysisError error) {
|
||||
Source source = error.source;
|
||||
LineInfo_Location location = errorToLine[error].getLocation(error.offset);
|
||||
int length = error.length;
|
||||
ErrorSeverity severity =
|
||||
AnalyzerImpl.computeSeverity(error, options.enableTypeChecks);
|
||||
if (options.machineFormat) {
|
||||
if (severity == ErrorSeverity.WARNING && options.warningsAreFatal) {
|
||||
severity = ErrorSeverity.ERROR;
|
||||
}
|
||||
out.write(severity);
|
||||
out.write('|');
|
||||
out.write(error.errorCode.type);
|
||||
out.write('|');
|
||||
out.write(error.errorCode.name);
|
||||
out.write('|');
|
||||
out.write(escapePipe(source.fullName));
|
||||
out.write('|');
|
||||
out.write(location.lineNumber);
|
||||
out.write('|');
|
||||
out.write(location.columnNumber);
|
||||
out.write('|');
|
||||
out.write(length);
|
||||
out.write('|');
|
||||
out.write(escapePipe(error.message));
|
||||
} else {
|
||||
String errorType = severity.displayName;
|
||||
if (error.errorCode.type == ErrorType.HINT ||
|
||||
error.errorCode.type == ErrorType.LINT) {
|
||||
errorType = error.errorCode.type.displayName;
|
||||
}
|
||||
// [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2)
|
||||
out.write('[$errorType] ${error.message} ');
|
||||
out.write('(${source.fullName}');
|
||||
out.write(', line ${location.lineNumber}, col ${location.columnNumber})');
|
||||
}
|
||||
out.writeln();
|
||||
}
|
||||
|
||||
void formatErrors(List<AnalysisErrorInfo> errorInfos) {
|
||||
var errors = new List<AnalysisError>();
|
||||
var errorToLine = new Map<AnalysisError, LineInfo>();
|
||||
for (AnalysisErrorInfo errorInfo in errorInfos) {
|
||||
for (AnalysisError error in errorInfo.errors) {
|
||||
if (errorFilter(error)) {
|
||||
errors.add(error);
|
||||
errorToLine[error] = errorInfo.lineInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
// sort errors
|
||||
errors.sort((AnalysisError error1, AnalysisError error2) {
|
||||
// severity
|
||||
ErrorSeverity severity1 =
|
||||
AnalyzerImpl.computeSeverity(error1, options.enableTypeChecks);
|
||||
ErrorSeverity severity2 =
|
||||
AnalyzerImpl.computeSeverity(error2, options.enableTypeChecks);
|
||||
int compare = severity2.compareTo(severity1);
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
// path
|
||||
compare = Comparable.compare(error1.source.fullName.toLowerCase(),
|
||||
error2.source.fullName.toLowerCase());
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
// offset
|
||||
return error1.offset - error2.offset;
|
||||
});
|
||||
// format errors
|
||||
int errorCount = 0;
|
||||
int warnCount = 0;
|
||||
int hintCount = 0;
|
||||
int lintCount = 0;
|
||||
for (AnalysisError error in errors) {
|
||||
ErrorSeverity severity =
|
||||
AnalyzerImpl.computeSeverity(error, options.enableTypeChecks);
|
||||
if (severity == ErrorSeverity.ERROR) {
|
||||
errorCount++;
|
||||
} else if (severity == ErrorSeverity.WARNING) {
|
||||
if (options.warningsAreFatal) {
|
||||
errorCount++;
|
||||
} else {
|
||||
if (error.errorCode.type == ErrorType.HINT) {
|
||||
hintCount++;
|
||||
} else {
|
||||
warnCount++;
|
||||
}
|
||||
}
|
||||
} else if (error.errorCode.type == ErrorType.LINT) {
|
||||
lintCount++;
|
||||
}
|
||||
formatError(errorToLine, error);
|
||||
}
|
||||
// print statistics
|
||||
if (!options.machineFormat) {
|
||||
var hasErrors = errorCount != 0;
|
||||
var hasWarns = warnCount != 0;
|
||||
var hasHints = hintCount != 0;
|
||||
var hasLints = lintCount != 0;
|
||||
bool hasContent = false;
|
||||
if (hasErrors) {
|
||||
out.write(errorCount);
|
||||
out.write(' ');
|
||||
out.write(pluralize("error", errorCount));
|
||||
hasContent = true;
|
||||
}
|
||||
if (hasWarns) {
|
||||
if (hasContent) {
|
||||
if (!hasHints && !hasLints) {
|
||||
out.write(' and ');
|
||||
} else {
|
||||
out.write(", ");
|
||||
}
|
||||
}
|
||||
out.write(warnCount);
|
||||
out.write(' ');
|
||||
out.write(pluralize("warning", warnCount));
|
||||
hasContent = true;
|
||||
}
|
||||
if (hasHints) {
|
||||
if (hasContent) {
|
||||
if (!hasLints) {
|
||||
out.write(' and ');
|
||||
} else {
|
||||
out.write(", ");
|
||||
}
|
||||
}
|
||||
out.write(hintCount);
|
||||
out.write(' ');
|
||||
out.write(pluralize("hint", hintCount));
|
||||
hasContent = true;
|
||||
}
|
||||
if (hasLints) {
|
||||
if (hasContent) {
|
||||
out.write(" and ");
|
||||
}
|
||||
out.write(lintCount);
|
||||
out.write(' ');
|
||||
out.write(pluralize("lint", lintCount));
|
||||
hasContent = true;
|
||||
}
|
||||
if (hasContent) {
|
||||
out.writeln(" found.");
|
||||
} else {
|
||||
out.writeln("No issues found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String escapePipe(String input) {
|
||||
var result = new StringBuffer();
|
||||
for (var c in input.codeUnits) {
|
||||
if (c == '\\' || c == '|') {
|
||||
result.write('\\');
|
||||
}
|
||||
result.writeCharCode(c);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
static String pluralize(String word, int count) {
|
||||
if (count == 1) {
|
||||
return word;
|
||||
} else {
|
||||
return word + "s";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ homepage: http://www.dartlang.org
|
|||
environment:
|
||||
sdk: '>=0.8.10+6 <2.0.0'
|
||||
dependencies:
|
||||
args: '>=0.12.1 <0.13.0'
|
||||
path: '>=0.9.0 <2.0.0'
|
||||
watcher: '>=0.9.0 <0.10.0'
|
||||
dev_dependencies:
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright (c) 2013, 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 test.error;
|
||||
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import 'utils.dart';
|
||||
|
||||
void main() {
|
||||
test("a valid Dart file doesn't throw any errors", () {
|
||||
expect(errorsForFile('void main() => print("Hello, world!");'), isNull);
|
||||
});
|
||||
|
||||
test("an empty Dart file doesn't throw any errors", () {
|
||||
expect(errorsForFile(''), isNull);
|
||||
});
|
||||
|
||||
test("an error on the first line", () {
|
||||
expect(errorsForFile('void foo;\n'),
|
||||
equals("Error in test.dart: Variables cannot have a type of 'void'\n"));
|
||||
});
|
||||
|
||||
test("an error on the last line", () {
|
||||
expect(errorsForFile('\nvoid foo;'),
|
||||
equals("Error in test.dart: Variables cannot have a type of 'void'\n"));
|
||||
});
|
||||
|
||||
test("an error in the middle", () {
|
||||
expect(errorsForFile('\nvoid foo;\n'),
|
||||
equals("Error in test.dart: Variables cannot have a type of 'void'\n"));
|
||||
});
|
||||
|
||||
var veryLongString = new List.filled(107, ' ').join('');
|
||||
|
||||
test("an error at the end of a very long line", () {
|
||||
expect(errorsForFile('$veryLongString void foo;'),
|
||||
equals("Error in test.dart: Variables cannot have a type of 'void'\n"));
|
||||
});
|
||||
|
||||
test("an error at the beginning of a very long line", () {
|
||||
expect(errorsForFile('void foo; $veryLongString'),
|
||||
equals("Error in test.dart: Variables cannot have a type of 'void'\n"));
|
||||
});
|
||||
|
||||
test("an error in the middle of a very long line", () {
|
||||
expect(errorsForFile('$veryLongString void foo;$veryLongString'),
|
||||
equals("Error in test.dart: Variables cannot have a type of 'void'\n"));
|
||||
});
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
// Copyright (c) 2013, 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 options_test;
|
||||
|
||||
import 'package:analyzer/options.dart';
|
||||
import 'package:args/args.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
|
||||
import 'reflective_tests.dart';
|
||||
|
||||
main() {
|
||||
group('AnalyzerOptions.parse()', () {
|
||||
test('defaults', () {
|
||||
CommandLineOptions options =
|
||||
CommandLineOptions.parse(['--dart-sdk', '.', 'foo.dart']);
|
||||
expect(options, isNotNull);
|
||||
expect(options.dartSdkPath, isNotNull);
|
||||
expect(options.disableHints, isFalse);
|
||||
expect(options.displayVersion, isFalse);
|
||||
expect(options.enableStrictCallChecks, isFalse);
|
||||
expect(options.enableTypeChecks, isFalse);
|
||||
expect(options.ignoreUnrecognizedFlags, isFalse);
|
||||
expect(options.log, isFalse);
|
||||
expect(options.machineFormat, isFalse);
|
||||
expect(options.packageRootPath, isNull);
|
||||
expect(options.perf, isFalse);
|
||||
expect(options.shouldBatch, isFalse);
|
||||
expect(options.showPackageWarnings, isFalse);
|
||||
expect(options.showSdkWarnings, isFalse);
|
||||
expect(options.sourceFiles, equals(['foo.dart']));
|
||||
expect(options.warmPerf, isFalse);
|
||||
expect(options.warningsAreFatal, isFalse);
|
||||
expect(options.customUrlMappings, isNotNull);
|
||||
expect(options.customUrlMappings.isEmpty, isTrue);
|
||||
});
|
||||
|
||||
test('batch', () {
|
||||
CommandLineOptions options =
|
||||
CommandLineOptions.parse(['--dart-sdk', '.', '--batch']);
|
||||
expect(options.shouldBatch, isTrue);
|
||||
});
|
||||
|
||||
test('defined variables', () {
|
||||
CommandLineOptions options = CommandLineOptions
|
||||
.parse(['--dart-sdk', '.', '-Dfoo=bar', 'foo.dart']);
|
||||
expect(options.definedVariables['foo'], equals('bar'));
|
||||
expect(options.definedVariables['bar'], isNull);
|
||||
});
|
||||
|
||||
test('enable strict call checks', () {
|
||||
CommandLineOptions options = CommandLineOptions.parse(
|
||||
['--dart-sdk', '.', '--enable-strict-call-checks', 'foo.dart']);
|
||||
expect(options.enableStrictCallChecks, isTrue);
|
||||
});
|
||||
|
||||
test('enable type checks', () {
|
||||
CommandLineOptions options = CommandLineOptions
|
||||
.parse(['--dart-sdk', '.', '--enable_type_checks', 'foo.dart']);
|
||||
expect(options.enableTypeChecks, isTrue);
|
||||
});
|
||||
|
||||
test('log', () {
|
||||
CommandLineOptions options =
|
||||
CommandLineOptions.parse(['--dart-sdk', '.', '--log', 'foo.dart']);
|
||||
expect(options.log, isTrue);
|
||||
});
|
||||
|
||||
test('machine format', () {
|
||||
CommandLineOptions options = CommandLineOptions
|
||||
.parse(['--dart-sdk', '.', '--format=machine', 'foo.dart']);
|
||||
expect(options.machineFormat, isTrue);
|
||||
});
|
||||
|
||||
test('no-hints', () {
|
||||
CommandLineOptions options = CommandLineOptions
|
||||
.parse(['--dart-sdk', '.', '--no-hints', 'foo.dart']);
|
||||
expect(options.disableHints, isTrue);
|
||||
});
|
||||
|
||||
test('package root', () {
|
||||
CommandLineOptions options = CommandLineOptions
|
||||
.parse(['--dart-sdk', '.', '-p', 'bar', 'foo.dart']);
|
||||
expect(options.packageRootPath, equals('bar'));
|
||||
});
|
||||
|
||||
test('package warnings', () {
|
||||
CommandLineOptions options = CommandLineOptions
|
||||
.parse(['--dart-sdk', '.', '--package-warnings', 'foo.dart']);
|
||||
expect(options.showPackageWarnings, isTrue);
|
||||
});
|
||||
|
||||
test('perf', () {
|
||||
CommandLineOptions options =
|
||||
CommandLineOptions.parse(['--dart-sdk', '.', '--perf', 'foo.dart']);
|
||||
expect(options.perf, isTrue);
|
||||
});
|
||||
|
||||
test('sdk warnings', () {
|
||||
CommandLineOptions options = CommandLineOptions
|
||||
.parse(['--dart-sdk', '.', '--warnings', 'foo.dart']);
|
||||
expect(options.showSdkWarnings, isTrue);
|
||||
});
|
||||
|
||||
test('sourceFiles', () {
|
||||
CommandLineOptions options = CommandLineOptions.parse(
|
||||
['--dart-sdk', '.', '--log', 'foo.dart', 'foo2.dart', 'foo3.dart']);
|
||||
expect(
|
||||
options.sourceFiles, equals(['foo.dart', 'foo2.dart', 'foo3.dart']));
|
||||
});
|
||||
|
||||
test('warningsAreFatal', () {
|
||||
CommandLineOptions options = CommandLineOptions
|
||||
.parse(['--dart-sdk', '.', '--fatal-warnings', 'foo.dart']);
|
||||
expect(options.warningsAreFatal, isTrue);
|
||||
});
|
||||
|
||||
test('customUrlMappings', () {
|
||||
CommandLineOptions options = CommandLineOptions.parse([
|
||||
'--dart-sdk',
|
||||
'.',
|
||||
'--url-mapping',
|
||||
'dart:dummy,/path/to/dummy.dart',
|
||||
'foo.dart'
|
||||
]);
|
||||
expect(options.customUrlMappings, isNotNull);
|
||||
expect(options.customUrlMappings.isEmpty, isFalse);
|
||||
expect(options.customUrlMappings['dart:dummy'],
|
||||
equals('/path/to/dummy.dart'));
|
||||
});
|
||||
|
||||
// test('notice unrecognized flags', () {
|
||||
// CommandLineOptions options = CommandLineOptions.parse(['--bar', '--baz',
|
||||
// 'foo.dart']);
|
||||
// expect(options, isNull);
|
||||
// });
|
||||
|
||||
test('ignore unrecognized flags', () {
|
||||
CommandLineOptions options = CommandLineOptions.parse([
|
||||
'--ignore-unrecognized-flags',
|
||||
'--bar',
|
||||
'--baz',
|
||||
'--dart-sdk',
|
||||
'.',
|
||||
'foo.dart'
|
||||
]);
|
||||
expect(options, isNotNull);
|
||||
expect(options.sourceFiles, equals(['foo.dart']));
|
||||
});
|
||||
});
|
||||
|
||||
runReflectiveTests(CommandLineParserTest);
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class CommandLineParserTest {
|
||||
test_ignoreUnrecognizedOptions() {
|
||||
CommandLineParser parser =
|
||||
new CommandLineParser(alwaysIgnoreUnrecognized: true);
|
||||
parser.addOption('optionA');
|
||||
parser.addFlag('flagA');
|
||||
ArgResults argResults =
|
||||
parser.parse(['--optionA=1', '--optionB=2', '--flagA'], {});
|
||||
expect(argResults['optionA'], '1');
|
||||
expect(argResults['flagA'], isTrue);
|
||||
}
|
||||
}
|
|
@ -8,11 +8,9 @@ import 'package:unittest/unittest.dart';
|
|||
|
||||
import 'cancelable_future_test.dart' as cancelable_future_test;
|
||||
import 'enum_test.dart' as enum_test;
|
||||
import 'error_test.dart' as error;
|
||||
import 'file_system/test_all.dart' as file_system;
|
||||
import 'generated/test_all.dart' as generated;
|
||||
import 'instrumentation/test_all.dart' as instrumentation;
|
||||
import 'options_test.dart' as options;
|
||||
import 'parse_compilation_unit_test.dart' as parse_compilation_unit;
|
||||
import 'plugin/test_all.dart' as plugin_test_all;
|
||||
import 'source/test_all.dart' as source;
|
||||
|
@ -25,11 +23,9 @@ main() {
|
|||
group('analysis engine', () {
|
||||
cancelable_future_test.main();
|
||||
enum_test.main();
|
||||
error.main();
|
||||
file_system.main();
|
||||
generated.main();
|
||||
instrumentation.main();
|
||||
options.main();
|
||||
parse_compilation_unit.main();
|
||||
plugin_test_all.main();
|
||||
source.main();
|
||||
|
|
|
@ -197,7 +197,6 @@ analyzer2dart/test/sexpr_test: Crash # Instance of 'TypeOperator': unimplemented
|
|||
analyzer2dart/test/tree_shaker_test: Crash # cannot compile methods that need interceptor calling convention.
|
||||
analyzer/test/cancelable_future_test: Crash # Unhandled node
|
||||
analyzer/test/enum_test: Crash # Unhandled node
|
||||
analyzer/test/error_test: Crash # cannot compile methods that need interceptor calling convention.
|
||||
analyzer/test/file_system/memory_file_system_test: Crash # Unhandled node
|
||||
analyzer/test/file_system/physical_resource_provider_test: Crash # Unhandled node
|
||||
analyzer/test/file_system/resource_uri_resolver_test: Crash # Unhandled node
|
||||
|
@ -217,7 +216,6 @@ analyzer/test/generated/static_type_warning_code_test: Crash # Unhandled node
|
|||
analyzer/test/generated/static_warning_code_test: Crash # Unhandled node
|
||||
analyzer/test/generated/utilities_test: Crash # Unhandled node
|
||||
analyzer/test/instrumentation/instrumentation_test: Crash # try/finally
|
||||
analyzer/test/options_test: Crash # Unhandled node
|
||||
analyzer/test/parse_compilation_unit_test: Crash # cannot compile methods that need interceptor calling convention.
|
||||
analyzer/test/plugin/plugin_impl_test: Crash # try/finally
|
||||
analyzer/test/source/package_map_provider_test: Crash # try/finally
|
||||
|
|
Loading…
Reference in a new issue