Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Unified Diff: pkg/analyzer_cli/lib/src/driver.dart

Issue 1462143002: Revert "Move `analyzer_cli` into the SDK." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer_cli/lib/src/bootloader.dart ('k') | pkg/analyzer_cli/lib/src/error_formatter.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
- }
-}
« no previous file with comments | « pkg/analyzer_cli/lib/src/bootloader.dart ('k') | pkg/analyzer_cli/lib/src/error_formatter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698