| Index: pkg/analyzer_cli/lib/src/driver.dart
|
| diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
|
| deleted file mode 100644
|
| index 752cb1e87597f572754ca4169c4936a35a1a6f7d..0000000000000000000000000000000000000000
|
| --- a/pkg/analyzer_cli/lib/src/driver.dart
|
| +++ /dev/null
|
| @@ -1,641 +0,0 @@
|
| -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -library analyzer_cli.src.driver;
|
| -
|
| -import 'dart:async';
|
| -import 'dart:convert';
|
| -import 'dart:io';
|
| -
|
| -import 'package:analyzer/file_system/file_system.dart' as fileSystem;
|
| -import 'package:analyzer/file_system/physical_file_system.dart';
|
| -import 'package:analyzer/plugin/options.dart';
|
| -import 'package:analyzer/source/analysis_options_provider.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/source/sdk_ext.dart';
|
| -import 'package:analyzer/src/generated/constant.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_engine.dart';
|
| -import 'package:analyzer/src/generated/java_io.dart';
|
| -import 'package:analyzer/src/generated/sdk_io.dart';
|
| -import 'package:analyzer/src/generated/source.dart';
|
| -import 'package:analyzer/src/generated/source_io.dart';
|
| -import 'package:analyzer/src/services/lint.dart';
|
| -import 'package:analyzer/src/task/options.dart';
|
| -import 'package:analyzer_cli/src/analyzer_impl.dart';
|
| -import 'package:analyzer_cli/src/options.dart';
|
| -import 'package:linter/src/plugin/linter_plugin.dart';
|
| -import 'package:package_config/discovery.dart' as pkgDiscovery;
|
| -import 'package:package_config/packages.dart' show Packages;
|
| -import 'package:package_config/packages_file.dart' as pkgfile show parse;
|
| -import 'package:package_config/src/packages_impl.dart' show MapPackages;
|
| -import 'package:path/path.dart' as path;
|
| -import 'package:plugin/plugin.dart';
|
| -import 'package:yaml/yaml.dart';
|
| -
|
| -/// The maximum number of sources for which AST structures should be kept in the
|
| -/// cache.
|
| -const int _maxCacheSize = 512;
|
| -
|
| -/// Shared IO sink for standard error reporting.
|
| -///
|
| -/// *Visible for testing.*
|
| -StringSink errorSink = stderr;
|
| -
|
| -/// Shared IO sink for standard out reporting.
|
| -///
|
| -/// *Visible for testing.*
|
| -StringSink outSink = stdout;
|
| -
|
| -/// Test this option map to see if it specifies lint rules.
|
| -bool containsLintRuleEntry(Map<String, YamlNode> options) {
|
| - var linterNode = options['linter'];
|
| - return linterNode is YamlMap && linterNode.containsKey('rules');
|
| -}
|
| -
|
| -typedef ErrorSeverity _BatchRunnerHandler(List<String> args);
|
| -
|
| -class Driver {
|
| - /// The plugins that are defined outside the `analyzer_cli` package.
|
| - List<Plugin> _userDefinedPlugins = <Plugin>[];
|
| -
|
| - /// Indicates whether the analyzer is running in batch mode.
|
| - bool _isBatch;
|
| -
|
| - /// The context that was most recently created by a call to [_analyzeAll], or
|
| - /// `null` if [_analyzeAll] hasn't been called yet.
|
| - AnalysisContext _context;
|
| -
|
| - /// If [_context] is not `null`, the [CommandLineOptions] that guided its
|
| - /// creation.
|
| - CommandLineOptions _previousOptions;
|
| -
|
| - /// This Driver's current analysis context.
|
| - ///
|
| - /// *Visible for testing.*
|
| - AnalysisContext get context => _context;
|
| -
|
| - /// Set the [plugins] that are defined outside the `analyzer_cli` package.
|
| - void set userDefinedPlugins(List<Plugin> plugins) {
|
| - _userDefinedPlugins = plugins == null ? <Plugin>[] : plugins;
|
| - }
|
| -
|
| - /// Use the given command-line [args] to start this analysis driver.
|
| - void start(List<String> args) {
|
| - StringUtilities.INTERNER = new MappedInterner();
|
| -
|
| - _processPlugins();
|
| -
|
| - // Parse commandline options.
|
| - CommandLineOptions options = CommandLineOptions.parse(args);
|
| -
|
| - // Cache options of interest to inform analysis.
|
| - _setupEnv(options);
|
| -
|
| - // Do analysis.
|
| - if (_isBatch) {
|
| - _BatchRunner.runAsBatch(args, (List<String> args) {
|
| - CommandLineOptions options = CommandLineOptions.parse(args);
|
| - return _analyzeAll(options);
|
| - });
|
| - } else {
|
| - ErrorSeverity severity = _analyzeAll(options);
|
| - // In case of error propagate exit code.
|
| - if (severity == ErrorSeverity.ERROR) {
|
| - exitCode = severity.ordinal;
|
| - }
|
| - }
|
| - }
|
| -
|
| - /// Perform analysis according to the given [options].
|
| - ErrorSeverity _analyzeAll(CommandLineOptions options) {
|
| - if (!options.machineFormat) {
|
| - outSink.writeln("Analyzing ${options.sourceFiles}...");
|
| - }
|
| -
|
| - // Create a context, or re-use the previous one.
|
| - try {
|
| - _createAnalysisContext(options);
|
| - } on _DriverError catch (error) {
|
| - outSink.writeln(error.msg);
|
| - return ErrorSeverity.ERROR;
|
| - }
|
| -
|
| - // Add all the files to be analyzed en masse to the context. Skip any
|
| - // files that were added earlier (whether explicitly or implicitly) to
|
| - // avoid causing those files to be unnecessarily re-read.
|
| - Set<Source> knownSources = _context.sources.toSet();
|
| - List<Source> sourcesToAnalyze = <Source>[];
|
| - ChangeSet changeSet = new ChangeSet();
|
| - for (String sourcePath in options.sourceFiles) {
|
| - sourcePath = sourcePath.trim();
|
| - // Check that file exists.
|
| - if (!new File(sourcePath).existsSync()) {
|
| - errorSink.writeln('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)) {
|
| - errorSink.writeln('$sourcePath is not a Dart file');
|
| - exitCode = ErrorSeverity.ERROR.ordinal;
|
| - // Fail fast; don't analyze more files.
|
| - return ErrorSeverity.ERROR;
|
| - }
|
| - Source source = _computeLibrarySource(sourcePath);
|
| - if (!knownSources.contains(source)) {
|
| - changeSet.addedSource(source);
|
| - }
|
| - sourcesToAnalyze.add(source);
|
| - }
|
| - _context.applyChanges(changeSet);
|
| -
|
| - // Analyze the libraries.
|
| - ErrorSeverity allResult = ErrorSeverity.NONE;
|
| - var libUris = <Uri>[];
|
| - var parts = <Source>[];
|
| - for (Source source in sourcesToAnalyze) {
|
| - if (context.computeKindOf(source) == SourceKind.PART) {
|
| - parts.add(source);
|
| - continue;
|
| - }
|
| - ErrorSeverity status = _runAnalyzer(source, options);
|
| - allResult = allResult.max(status);
|
| - libUris.add(source.uri);
|
| - }
|
| -
|
| - // Check that each part has a corresponding source in the input list.
|
| - for (Source part in parts) {
|
| - bool found = false;
|
| - for (var lib in context.getLibrariesContaining(part)) {
|
| - if (libUris.contains(lib.uri)) {
|
| - found = true;
|
| - }
|
| - }
|
| - if (!found) {
|
| - errorSink.writeln("${part.fullName} is a part and cannot be analyzed.");
|
| - errorSink.writeln("Please pass in a library that contains this part.");
|
| - exitCode = ErrorSeverity.ERROR.ordinal;
|
| - allResult = allResult.max(ErrorSeverity.ERROR);
|
| - }
|
| - }
|
| -
|
| - return allResult;
|
| - }
|
| -
|
| - /// Determine whether the context created during a previous call to
|
| - /// [_analyzeAll] can be re-used in order to analyze using [options].
|
| - bool _canContextBeReused(CommandLineOptions options) {
|
| - // TODO(paulberry): add a command-line option that disables context re-use.
|
| - if (_context == null) {
|
| - return false;
|
| - }
|
| - if (options.packageRootPath != _previousOptions.packageRootPath) {
|
| - return false;
|
| - }
|
| - if (options.packageConfigPath != _previousOptions.packageConfigPath) {
|
| - return false;
|
| - }
|
| - if (!_equalMaps(
|
| - options.definedVariables, _previousOptions.definedVariables)) {
|
| - return false;
|
| - }
|
| - if (options.log != _previousOptions.log) {
|
| - return false;
|
| - }
|
| - if (options.disableHints != _previousOptions.disableHints) {
|
| - return false;
|
| - }
|
| - if (options.enableStrictCallChecks !=
|
| - _previousOptions.enableStrictCallChecks) {
|
| - return false;
|
| - }
|
| - if (options.showPackageWarnings != _previousOptions.showPackageWarnings) {
|
| - return false;
|
| - }
|
| - if (options.showSdkWarnings != _previousOptions.showSdkWarnings) {
|
| - return false;
|
| - }
|
| - if (options.lints != _previousOptions.lints) {
|
| - return false;
|
| - }
|
| - if (options.strongMode != _previousOptions.strongMode) {
|
| - return false;
|
| - }
|
| - if (options.enableSuperMixins != _previousOptions.enableSuperMixins) {
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - /// Decide on the appropriate policy for which files need to be fully parsed
|
| - /// and which files need to be diet parsed, based on [options], and return an
|
| - /// [AnalyzeFunctionBodiesPredicate] that implements this policy.
|
| - AnalyzeFunctionBodiesPredicate _chooseDietParsingPolicy(
|
| - CommandLineOptions options) {
|
| - if (_isBatch) {
|
| - // As analyzer is currently implemented, once a file has been diet
|
| - // parsed, it can't easily be un-diet parsed without creating a brand new
|
| - // context and losing caching. In batch mode, we can't predict which
|
| - // files we'll need to generate errors and warnings for in the future, so
|
| - // we can't safely diet parse anything.
|
| - return (Source source) => true;
|
| - }
|
| -
|
| - // Determine the set of packages requiring a full parse. Use null to
|
| - // represent the case where all packages require a full parse.
|
| - Set<String> packagesRequiringFullParse;
|
| - if (options.showPackageWarnings) {
|
| - // We are showing warnings from all packages so all packages require a
|
| - // full parse.
|
| - packagesRequiringFullParse = null;
|
| - } else {
|
| - // We aren't showing warnings for dependent packages, but we may still
|
| - // need to show warnings for "self" packages, so we need to do a full
|
| - // parse in any package containing files mentioned on the command line.
|
| - // TODO(paulberry): implement this. As a temporary workaround, we're
|
| - // fully parsing all packages.
|
| - packagesRequiringFullParse = null;
|
| - }
|
| - return (Source source) {
|
| - if (source.uri.scheme == 'dart') {
|
| - return options.showSdkWarnings;
|
| - } else if (source.uri.scheme == 'package') {
|
| - if (packagesRequiringFullParse == null) {
|
| - return true;
|
| - } else if (source.uri.pathSegments.length == 0) {
|
| - // We should never see a URI like this, but fully parse it to be
|
| - // safe.
|
| - return true;
|
| - } else {
|
| - return packagesRequiringFullParse
|
| - .contains(source.uri.pathSegments[0]);
|
| - }
|
| - } else {
|
| - return true;
|
| - }
|
| - };
|
| - }
|
| -
|
| - /// Decide on the appropriate method for resolving URIs based on the given
|
| - /// [options] and [customUrlMappings] settings, and return a
|
| - /// [SourceFactory] that has been configured accordingly.
|
| - SourceFactory _chooseUriResolutionPolicy(CommandLineOptions options) {
|
| - Packages packages;
|
| - Map<String, List<fileSystem.Folder>> packageMap;
|
| - UriResolver packageUriResolver;
|
| -
|
| - // Process options, caching package resolution details.
|
| - if (options.packageConfigPath != null) {
|
| - String packageConfigPath = options.packageConfigPath;
|
| - Uri fileUri = new Uri.file(packageConfigPath);
|
| - try {
|
| - File configFile = new File.fromUri(fileUri).absolute;
|
| - List<int> bytes = configFile.readAsBytesSync();
|
| - Map<String, Uri> map = pkgfile.parse(bytes, configFile.uri);
|
| - packages = new MapPackages(map);
|
| - packageMap = _getPackageMap(packages);
|
| - } catch (e) {
|
| - printAndFail(
|
| - 'Unable to read package config data from $packageConfigPath: $e');
|
| - }
|
| - } else if (options.packageRootPath != null) {
|
| - packageMap = _PackageRootPackageMapBuilder
|
| - .buildPackageMap(options.packageRootPath);
|
| -
|
| - JavaFile packageDirectory = new JavaFile(options.packageRootPath);
|
| - packageUriResolver = new PackageUriResolver([packageDirectory]);
|
| - } else {
|
| - fileSystem.Resource cwd =
|
| - PhysicalResourceProvider.INSTANCE.getResource('.');
|
| -
|
| - // Look for .packages.
|
| - packages = _discoverPackagespec(new Uri.directory(cwd.path));
|
| -
|
| - if (packages != null) {
|
| - packageMap = _getPackageMap(packages);
|
| - } else {
|
| - // Fall back to pub list-package-dirs.
|
| -
|
| - PubPackageMapProvider pubPackageMapProvider =
|
| - new PubPackageMapProvider(PhysicalResourceProvider.INSTANCE, sdk);
|
| - PackageMapInfo packageMapInfo =
|
| - pubPackageMapProvider.computePackageMap(cwd);
|
| - packageMap = packageMapInfo.packageMap;
|
| -
|
| - // Only create a packageUriResolver if pub list-package-dirs succeeded.
|
| - // If it failed, that's not a problem; it simply means we have no way
|
| - // to resolve packages.
|
| - if (packageMapInfo.packageMap != null) {
|
| - packageUriResolver = new PackageMapUriResolver(
|
| - PhysicalResourceProvider.INSTANCE, packageMap);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Now, build our resolver list.
|
| -
|
| - // 'dart:' URIs come first.
|
| - List<UriResolver> resolvers = [new DartUriResolver(sdk)];
|
| -
|
| - // Next SdkExts.
|
| - if (packageMap != null) {
|
| - resolvers.add(new SdkExtUriResolver(packageMap));
|
| - }
|
| -
|
| - // Then package URIs.
|
| - if (packageUriResolver != null) {
|
| - resolvers.add(packageUriResolver);
|
| - }
|
| -
|
| - // Finally files.
|
| - resolvers.add(new FileUriResolver());
|
| -
|
| - return new SourceFactory(resolvers, packages);
|
| - }
|
| -
|
| - /// Convert the given [sourcePath] (which may be relative to the current
|
| - /// working directory) to a [Source] object that can be fed to the analysis
|
| - /// context.
|
| - Source _computeLibrarySource(String sourcePath) {
|
| - sourcePath = _normalizeSourcePath(sourcePath);
|
| - JavaFile sourceFile = new JavaFile(sourcePath);
|
| - Source source = sdk.fromFileUri(sourceFile.toURI());
|
| - if (source != null) {
|
| - return source;
|
| - }
|
| - source = new FileBasedSource(sourceFile, sourceFile.toURI());
|
| - Uri uri = _context.sourceFactory.restoreUri(source);
|
| - if (uri == null) {
|
| - return source;
|
| - }
|
| - return new FileBasedSource(sourceFile, uri);
|
| - }
|
| -
|
| - /// Create an analysis context that is prepared to analyze sources according
|
| - /// to the given [options], and store it in [_context].
|
| - void _createAnalysisContext(CommandLineOptions options) {
|
| - if (_canContextBeReused(options)) {
|
| - return;
|
| - }
|
| - _previousOptions = options;
|
| - // Choose a package resolution policy and a diet parsing policy based on
|
| - // the command-line options.
|
| - SourceFactory sourceFactory = _chooseUriResolutionPolicy(options);
|
| - AnalyzeFunctionBodiesPredicate dietParsingPolicy =
|
| - _chooseDietParsingPolicy(options);
|
| - // Create a context using these policies.
|
| - AnalysisContext 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);
|
| - });
|
| - }
|
| -
|
| - if (options.log) {
|
| - AnalysisEngine.instance.logger = new StdLogger();
|
| - }
|
| -
|
| - // Set context options.
|
| - AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
|
| - contextOptions.cacheSize = _maxCacheSize;
|
| - contextOptions.hint = !options.disableHints;
|
| - contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
|
| - contextOptions.enableSuperMixins = options.enableSuperMixins;
|
| - contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy;
|
| - contextOptions.generateImplicitErrors = options.showPackageWarnings;
|
| - contextOptions.generateSdkErrors = options.showSdkWarnings;
|
| - contextOptions.lint = options.lints;
|
| - contextOptions.strongMode = options.strongMode;
|
| - context.analysisOptions = contextOptions;
|
| - _context = context;
|
| -
|
| - // Process analysis options file (and notify all interested parties).
|
| - _processAnalysisOptions(options, context);
|
| - }
|
| -
|
| - /// Return discovered packagespec, or `null` if none is found.
|
| - Packages _discoverPackagespec(Uri root) {
|
| - try {
|
| - Packages packages = pkgDiscovery.findPackagesFromFile(root);
|
| - if (packages != Packages.noPackages) {
|
| - return packages;
|
| - }
|
| - } catch (_) {
|
| - // Ignore and fall through to null.
|
| - }
|
| -
|
| - return null;
|
| - }
|
| -
|
| - fileSystem.File _getOptionsFile(CommandLineOptions options) {
|
| - fileSystem.File file;
|
| - String filePath = options.analysisOptionsFile;
|
| - if (filePath != null) {
|
| - file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
|
| - if (!file.exists) {
|
| - printAndFail('Options file not found: $filePath',
|
| - exitCode: ErrorSeverity.ERROR.ordinal);
|
| - }
|
| - } else {
|
| - filePath = AnalysisEngine.ANALYSIS_OPTIONS_FILE;
|
| - file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
|
| - }
|
| - return file;
|
| - }
|
| -
|
| - Map<String, List<fileSystem.Folder>> _getPackageMap(Packages packages) {
|
| - if (packages == null) {
|
| - return null;
|
| - }
|
| -
|
| - Map<String, List<fileSystem.Folder>> folderMap =
|
| - new Map<String, List<fileSystem.Folder>>();
|
| - packages.asMap().forEach((String packagePath, Uri uri) {
|
| - folderMap[packagePath] = [
|
| - PhysicalResourceProvider.INSTANCE.getFolder(path.fromUri(uri))
|
| - ];
|
| - });
|
| - return folderMap;
|
| - }
|
| -
|
| - void _processAnalysisOptions(
|
| - CommandLineOptions options, AnalysisContext context) {
|
| - fileSystem.File file = _getOptionsFile(options);
|
| - List<OptionsProcessor> optionsProcessors =
|
| - AnalysisEngine.instance.optionsPlugin.optionsProcessors;
|
| - try {
|
| - AnalysisOptionsProvider analysisOptionsProvider =
|
| - new AnalysisOptionsProvider();
|
| - Map<String, YamlNode> optionMap =
|
| - analysisOptionsProvider.getOptionsFromFile(file);
|
| - optionsProcessors.forEach(
|
| - (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
|
| -
|
| - // Fill in lint rule defaults in case lints are enabled and rules are
|
| - // not specified in an options file.
|
| - if (options.lints && !containsLintRuleEntry(optionMap)) {
|
| - setLints(context, linterPlugin.contributedRules);
|
| - }
|
| -
|
| - // Ask engine to further process options.
|
| - if (optionMap != null) {
|
| - configureContextOptions(context, optionMap);
|
| - }
|
| - } on Exception catch (e) {
|
| - optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
|
| - }
|
| - }
|
| -
|
| - void _processPlugins() {
|
| - List<Plugin> plugins = <Plugin>[];
|
| - plugins.add(linterPlugin);
|
| - plugins.addAll(_userDefinedPlugins);
|
| - AnalysisEngine.instance.userDefinedPlugins = plugins;
|
| -
|
| - // This ensures that AE extension manager processes plugins.
|
| - AnalysisEngine.instance.taskManager;
|
| - }
|
| -
|
| - /// Analyze a single source.
|
| - ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) {
|
| - int startTime = currentTimeMillis();
|
| - AnalyzerImpl analyzer =
|
| - new AnalyzerImpl(_context, source, options, startTime);
|
| - var errorSeverity = analyzer.analyzeSync();
|
| - if (errorSeverity == ErrorSeverity.ERROR) {
|
| - exitCode = errorSeverity.ordinal;
|
| - }
|
| - if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) {
|
| - exitCode = errorSeverity.ordinal;
|
| - }
|
| - return errorSeverity;
|
| - }
|
| -
|
| - void _setupEnv(CommandLineOptions options) {
|
| - // In batch mode, SDK is specified on the main command line rather than in
|
| - // the command lines sent to stdin. So process it before deciding whether
|
| - // to activate batch mode.
|
| - if (sdk == null) {
|
| - sdk = new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath));
|
| - }
|
| - _isBatch = options.shouldBatch;
|
| - }
|
| -
|
| - /// Perform a deep comparison of two string maps.
|
| - static bool _equalMaps(Map<String, String> m1, Map<String, String> m2) {
|
| - if (m1.length != m2.length) {
|
| - return false;
|
| - }
|
| - for (String key in m1.keys) {
|
| - if (!m2.containsKey(key) || m1[key] != m2[key]) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - /// Convert [sourcePath] into an absolute path.
|
| - static String _normalizeSourcePath(String sourcePath) =>
|
| - path.normalize(new File(sourcePath).absolute.path);
|
| -}
|
| -
|
| -/// 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) {
|
| - outSink.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) {
|
| - // Maybe finish.
|
| - if (line.isEmpty) {
|
| - var time = stopwatch.elapsedMilliseconds;
|
| - outSink.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.
|
| - errorSink.writeln('>>> EOF STDERR');
|
| - String resultPassString = resultPass ? 'PASS' : 'FAIL';
|
| - outSink.writeln(
|
| - '>>> TEST $resultPassString ${stopwatch.elapsedMilliseconds}ms');
|
| - } catch (e, stackTrace) {
|
| - errorSink.writeln(e);
|
| - errorSink.writeln(stackTrace);
|
| - errorSink.writeln('>>> EOF STDERR');
|
| - outSink.writeln('>>> TEST CRASH');
|
| - }
|
| - });
|
| - }
|
| -}
|
| -
|
| -class _DriverError implements Exception {
|
| - String msg;
|
| - _DriverError(this.msg);
|
| -}
|
| -
|
| -/// [SdkExtUriResolver] needs a Map from package name to folder. In the case
|
| -/// that the analyzer is invoked with a --package-root option, we need to
|
| -/// manually create this mapping. Given [packageRootPath],
|
| -/// [_PackageRootPackageMapBuilder] creates a simple mapping from package name
|
| -/// to full path on disk (resolving any symbolic links).
|
| -class _PackageRootPackageMapBuilder {
|
| - static Map<String, List<fileSystem.Folder>> buildPackageMap(
|
| - String packageRootPath) {
|
| - var packageRoot = new Directory(packageRootPath);
|
| - if (!packageRoot.existsSync()) {
|
| - throw new _DriverError(
|
| - 'Package root directory ($packageRootPath) does not exist.');
|
| - }
|
| - var packages = packageRoot.listSync(followLinks: false);
|
| - var result = new Map<String, List<fileSystem.Folder>>();
|
| - for (var package in packages) {
|
| - var packageName = path.basename(package.path);
|
| - var realPath = package.resolveSymbolicLinksSync();
|
| - result[packageName] = [
|
| - PhysicalResourceProvider.INSTANCE.getFolder(realPath)
|
| - ];
|
| - }
|
| - return result;
|
| - }
|
| -}
|
|
|