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

Unified Diff: pkg/analyzer/lib/src/lint/analysis.dart

Issue 2559773002: Reapply "Move the linter core to the analyzer package" (Closed)
Patch Set: Created 4 years 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/analysis_server/test/services/linter/linter_test.dart ('k') | pkg/analyzer/lib/src/lint/config.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/lint/analysis.dart
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f779e5451bfc32353ac607a33a049b782a189d20
--- /dev/null
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -0,0 +1,262 @@
+// 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.
+
+import 'dart:collection';
+import 'dart:io' as io;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/file_system/file_system.dart'
+ show File, Folder, ResourceProvider, ResourceUriResolver;
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/lint/io.dart';
+import 'package:analyzer/src/lint/linter.dart';
+import 'package:analyzer/src/lint/project.dart';
+import 'package:analyzer/src/lint/registry.dart';
+import 'package:analyzer/src/services/lint.dart';
+import 'package:cli_util/cli_util.dart' as cli_util;
+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 p;
+import 'package:plugin/manager.dart';
+import 'package:plugin/plugin.dart';
+
+Source createSource(Uri sourceUri) {
+ return PhysicalResourceProvider.INSTANCE
+ .getFile(sourceUri.toFilePath())
+ .createSource(sourceUri);
+}
+
+/// Print the given message and exit with the given [exitCode]
+void printAndFail(String message, {int exitCode: 15}) {
+ print(message);
+ io.exit(exitCode);
+}
+
+AnalysisOptions _buildAnalyzerOptions(DriverOptions options) {
+ AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
+ analysisOptions.strongMode = options.strongMode;
+ analysisOptions.hint = false;
+ analysisOptions.lint = options.enableLints;
+ analysisOptions.generateSdkErrors = options.showSdkWarnings;
+ analysisOptions.enableTiming = options.enableTiming;
+ return analysisOptions;
+}
+
+class AnalysisDriver {
+ /// The sources which have been analyzed so far. This is used to avoid
+ /// analyzing a source more than once, and to compute the total number of
+ /// sources analyzed for statistics.
+ Set<Source> _sourcesAnalyzed = new HashSet<Source>();
+
+ final LinterOptions options;
+
+ AnalysisDriver(this.options) {
+ _processPlugins();
+ }
+
+ /// Return the number of sources that have been analyzed so far.
+ int get numSourcesAnalyzed => _sourcesAnalyzed.length;
+
+ List<UriResolver> get resolvers {
+ // TODO(brianwilkerson) Use the context builder to compute all of the resolvers.
+ ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
+ ContextBuilder builder = new ContextBuilder(resourceProvider, null, null);
+
+ DartSdk sdk = options.mockSdk ??
+ new FolderBasedDartSdk(
+ resourceProvider, resourceProvider.getFolder(sdkDir));
+
+ List<UriResolver> resolvers = [new DartUriResolver(sdk)];
+
+ if (options.packageRootPath != null) {
+ // TODO(brianwilkerson) After 0.30.0 is published, clean up the following.
+ try {
+ // Try to use the post 0.30.0 API.
+ (builder as dynamic).builderOptions.defaultPackagesDirectoryPath =
+ options.packageRootPath;
+ } catch (_) {
+ // If that fails, fall back to the pre 0.30.0 API.
+ (builder as dynamic).defaultPackagesDirectoryPath =
+ options.packageRootPath;
+ }
+ Map<String, List<Folder>> packageMap =
+ builder.convertPackagesToMap(builder.createPackageMap(null));
+ resolvers.add(new PackageMapUriResolver(resourceProvider, packageMap));
+ }
+
+ // File URI resolver must come last so that files inside "/lib" are
+ // are analyzed via "package:" URI's.
+ resolvers.add(new ResourceUriResolver(resourceProvider));
+ return resolvers;
+ }
+
+ String get sdkDir {
+ if (options.dartSdkPath != null) {
+ return options.dartSdkPath;
+ }
+ // In case no SDK has been specified, fall back to inferring it
+ // TODO: pass args to cli_util
+ return cli_util.getSdkDir().path;
+ }
+
+ List<AnalysisErrorInfo> analyze(Iterable<io.File> files) {
+ AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+ context.analysisOptions = _buildAnalyzerOptions(options);
+ registerLinters(context);
+
+ Packages packages = _getPackageConfig();
+
+ context.sourceFactory = new SourceFactory(resolvers, packages);
+ AnalysisEngine.instance.logger = new StdLogger();
+
+ List<Source> sources = [];
+ ChangeSet changeSet = new ChangeSet();
+ for (io.File file in files) {
+ File sourceFile = PhysicalResourceProvider.INSTANCE
+ .getFile(p.normalize(file.absolute.path));
+ Source source = sourceFile.createSource();
+ Uri uri = context.sourceFactory.restoreUri(source);
+ if (uri != null) {
+ // Ensure that we analyze the file using its canonical URI (e.g. if
+ // it's in "/lib", analyze it using a "package:" URI).
+ source = sourceFile.createSource(uri);
+ }
+ sources.add(source);
+ changeSet.addedSource(source);
+ }
+ context.applyChanges(changeSet);
+
+ // Temporary location
+ var project = new DartProject(context, sources);
+ // This will get pushed into the generator (or somewhere comparable) when
+ // we have a proper plugin.
+ Registry.ruleRegistry.forEach((lint) {
+ if (lint is ProjectVisitor) {
+ (lint as ProjectVisitor).visit(project);
+ }
+ });
+
+ List<AnalysisErrorInfo> errors = [];
+
+ for (Source source in sources) {
+ context.computeErrors(source);
+ errors.add(context.getErrors(source));
+ _sourcesAnalyzed.add(source);
+ }
+
+ if (options.visitTransitiveClosure) {
+ // In the process of computing errors for all the sources in [sources],
+ // the analyzer has visited the transitive closure of all libraries
+ // referenced by those sources. So now we simply need to visit all
+ // library sources known to the analysis context, and all parts they
+ // refer to.
+ for (Source librarySource in context.librarySources) {
+ for (Source source in _getAllUnitSources(context, librarySource)) {
+ if (!_sourcesAnalyzed.contains(source)) {
+ context.computeErrors(source);
+ errors.add(context.getErrors(source));
+ _sourcesAnalyzed.add(source);
+ }
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ void registerLinters(AnalysisContext context) {
+ if (options.enableLints) {
+ setLints(context, options.enabledLints?.toList(growable: false));
+ }
+ }
+
+ /// Yield the sources for all the compilation units constituting
+ /// [librarySource] (including the defining compilation unit).
+ Iterable<Source> _getAllUnitSources(
+ AnalysisContext context, Source librarySource) {
+ List<Source> result = <Source>[librarySource];
+ result.addAll(context
+ .getLibraryElement(librarySource)
+ .parts
+ .map((CompilationUnitElement e) => e.source));
+ return result;
+ }
+
+ Packages _getPackageConfig() {
+ if (options.packageConfigPath != null) {
+ String packageConfigPath = options.packageConfigPath;
+ Uri fileUri = new Uri.file(packageConfigPath);
+ try {
+ io.File configFile = new io.File.fromUri(fileUri).absolute;
+ List<int> bytes = configFile.readAsBytesSync();
+ Map<String, Uri> map = pkgfile.parse(bytes, configFile.uri);
+ return new MapPackages(map);
+ } catch (e) {
+ printAndFail(
+ 'Unable to read package config data from $packageConfigPath: $e');
+ }
+ }
+ return null;
+ }
+
+ void _processPlugins() {
+ List<Plugin> plugins = <Plugin>[];
+ plugins.addAll(AnalysisEngine.instance.requiredPlugins);
+ plugins.add(AnalysisEngine.instance.commandLinePlugin);
+ plugins.add(AnalysisEngine.instance.optionsPlugin);
+ ExtensionManager manager = new ExtensionManager();
+ manager.processPlugins(plugins);
+ }
+}
+
+class DriverOptions {
+ /// The maximum number of sources for which AST structures should be kept
+ /// in the cache. The default is 512.
+ int cacheSize = 512;
+
+ /// The path to the dart SDK.
+ String dartSdkPath;
+
+ /// Whether to show lint warnings.
+ bool enableLints = true;
+
+ /// Whether to gather timing data during analysis.
+ bool enableTiming = false;
+
+ /// The path to a `.packages` configuration file
+ String packageConfigPath;
+
+ /// The path to the package root.
+ String packageRootPath;
+
+ /// Whether to show SDK warnings.
+ bool showSdkWarnings = false;
+
+ /// Whether to use Dart's Strong Mode analyzer.
+ bool strongMode = true;
+
+ /// The mock SDK (to speed up testing) or `null` to use the actual SDK.
+ DartSdk mockSdk;
+
+ /// Whether to show lints for the transitive closure of imported and exported
+ /// libraries.
+ bool visitTransitiveClosure = false;
+}
+
+/// Prints logging information comments to the [outSink] and error messages to
+/// [errorSink].
+class StdLogger extends Logger {
+ @override
+ void logError(String message, [exception]) => errorSink.writeln(message);
+ @override
+ void logInformation(String message, [exception]) => outSink.writeln(message);
+}
« no previous file with comments | « pkg/analysis_server/test/services/linter/linter_test.dart ('k') | pkg/analyzer/lib/src/lint/config.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698