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:
pquitslund@google.com 2015-04-22 20:32:05 +00:00
parent 434ba369f9
commit 49d0f16a2a
10 changed files with 10 additions and 1519 deletions

View file

@ -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.

View file

@ -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');
}
});
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}
}

View file

@ -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";
}
}
}

View file

@ -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:

View file

@ -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"));
});
}

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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