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

Side by Side Diff: pkg/analyzer/lib/src/lint/analysis.dart

Issue 2992463003: Update linter engine to use driver (linter#743). (Closed)
Patch Set: Created 3 years, 5 months 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 unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/lint/linter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async';
5 import 'dart:collection'; 6 import 'dart:collection';
6 import 'dart:io' as io; 7 import 'dart:io' as io;
7 8
8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:analyzer/file_system/file_system.dart' 9 import 'package:analyzer/file_system/file_system.dart'
10 show File, Folder, ResourceProvider, ResourceUriResolver; 10 show File, Folder, ResourceProvider, ResourceUriResolver;
11 import 'package:analyzer/file_system/physical_file_system.dart'; 11 import 'package:analyzer/file_system/physical_file_system.dart';
12 import 'package:analyzer/source/package_map_resolver.dart'; 12 import 'package:analyzer/source/package_map_resolver.dart';
13 import 'package:analyzer/src/context/builder.dart'; 13 import 'package:analyzer/src/context/builder.dart';
14 import 'package:analyzer/src/dart/analysis/driver.dart';
15 import 'package:analyzer/src/dart/analysis/file_state.dart';
14 import 'package:analyzer/src/dart/sdk/sdk.dart'; 16 import 'package:analyzer/src/dart/sdk/sdk.dart';
15 import 'package:analyzer/src/generated/engine.dart'; 17 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
16 import 'package:analyzer/src/generated/sdk.dart'; 18 import 'package:analyzer/src/generated/sdk.dart';
17 import 'package:analyzer/src/generated/source.dart'; 19 import 'package:analyzer/src/generated/source.dart';
18 import 'package:analyzer/src/generated/source_io.dart'; 20 import 'package:analyzer/src/generated/source_io.dart';
19 import 'package:analyzer/src/lint/io.dart'; 21 import 'package:analyzer/src/lint/io.dart';
20 import 'package:analyzer/src/lint/linter.dart'; 22 import 'package:analyzer/src/lint/linter.dart';
21 import 'package:analyzer/src/lint/project.dart'; 23 import 'package:analyzer/src/lint/project.dart';
22 import 'package:analyzer/src/lint/registry.dart'; 24 import 'package:analyzer/src/lint/registry.dart';
23 import 'package:analyzer/src/services/lint.dart'; 25 import 'package:analyzer/src/services/lint.dart';
24 import 'package:analyzer/src/util/sdk.dart'; 26 import 'package:analyzer/src/util/sdk.dart';
27 import 'package:front_end/src/base/performace_logger.dart';
28 import 'package:front_end/src/incremental/byte_store.dart';
25 import 'package:package_config/packages.dart' show Packages; 29 import 'package:package_config/packages.dart' show Packages;
26 import 'package:package_config/packages_file.dart' as pkgfile show parse; 30 import 'package:package_config/packages_file.dart' as pkgfile show parse;
27 import 'package:package_config/src/packages_impl.dart' show MapPackages; 31 import 'package:package_config/src/packages_impl.dart' show MapPackages;
28 import 'package:path/path.dart' as p; 32 import 'package:path/path.dart' as p;
29 import 'package:plugin/manager.dart'; 33 import 'package:plugin/manager.dart';
30 import 'package:plugin/plugin.dart'; 34 import 'package:plugin/plugin.dart';
31 35
32 Source createSource(Uri sourceUri) { 36 Source createSource(Uri sourceUri) {
33 return PhysicalResourceProvider.INSTANCE 37 return PhysicalResourceProvider.INSTANCE
34 .getFile(sourceUri.toFilePath()) 38 .getFile(sourceUri.toFilePath())
35 .createSource(sourceUri); 39 .createSource(sourceUri);
36 } 40 }
37 41
38 /// Print the given message and exit with the given [exitCode] 42 /// Print the given message and exit with the given [exitCode]
39 void printAndFail(String message, {int exitCode: 15}) { 43 void printAndFail(String message, {int exitCode: 15}) {
40 print(message); 44 print(message);
41 io.exit(exitCode); 45 io.exit(exitCode);
42 } 46 }
43 47
44 AnalysisOptions _buildAnalyzerOptions(DriverOptions options) { 48 AnalysisOptions _buildAnalyzerOptions(LinterOptions options) {
45 AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl(); 49 AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
46 analysisOptions.strongMode = options.strongMode; 50 analysisOptions.strongMode = options.strongMode;
47 analysisOptions.hint = false; 51 analysisOptions.hint = false;
48 analysisOptions.lint = options.enableLints; 52 analysisOptions.lint = options.enableLints;
49 analysisOptions.generateSdkErrors = options.showSdkWarnings; 53 analysisOptions.generateSdkErrors = options.showSdkWarnings;
50 analysisOptions.enableAssertInitializer = options.enableAssertInitializer; 54 analysisOptions.enableAssertInitializer = options.enableAssertInitializer;
51 analysisOptions.enableTiming = options.enableTiming; 55 analysisOptions.enableTiming = options.enableTiming;
56 analysisOptions.lintRules = options.enabledLints?.toList(growable: false);
52 return analysisOptions; 57 return analysisOptions;
53 } 58 }
54 59
55 class DriverOptions { 60 class DriverOptions {
56 /// The maximum number of sources for which AST structures should be kept 61 /// The maximum number of sources for which AST structures should be kept
57 /// in the cache. The default is 512. 62 /// in the cache. The default is 512.
58 int cacheSize = 512; 63 int cacheSize = 512;
59 64
60 /// The path to the dart SDK. 65 /// The path to the dart SDK.
61 String dartSdkPath; 66 String dartSdkPath;
(...skipping 15 matching lines...) Expand all
77 String packageRootPath; 82 String packageRootPath;
78 83
79 /// Whether to show SDK warnings. 84 /// Whether to show SDK warnings.
80 bool showSdkWarnings = false; 85 bool showSdkWarnings = false;
81 86
82 /// Whether to use Dart's Strong Mode analyzer. 87 /// Whether to use Dart's Strong Mode analyzer.
83 bool strongMode = true; 88 bool strongMode = true;
84 89
85 /// The mock SDK (to speed up testing) or `null` to use the actual SDK. 90 /// The mock SDK (to speed up testing) or `null` to use the actual SDK.
86 DartSdk mockSdk; 91 DartSdk mockSdk;
87
88 /// Whether to show lints for the transitive closure of imported and exported
89 /// libraries.
90 bool visitTransitiveClosure = false;
91 } 92 }
92 93
93 class LintDriver { 94 class LintDriver {
94 /// The sources which have been analyzed so far. This is used to avoid 95 /// The sources which have been analyzed so far. This is used to avoid
95 /// analyzing a source more than once, and to compute the total number of 96 /// analyzing a source more than once, and to compute the total number of
96 /// sources analyzed for statistics. 97 /// sources analyzed for statistics.
97 Set<Source> _sourcesAnalyzed = new HashSet<Source>(); 98 Set<Source> _sourcesAnalyzed = new HashSet<Source>();
98 99
99 final LinterOptions options; 100 final LinterOptions options;
100 101
101 LintDriver(this.options) { 102 LintDriver(this.options) {
102 _processPlugins(); 103 _processPlugins();
103 } 104 }
104 105
105 /// Return the number of sources that have been analyzed so far. 106 /// Return the number of sources that have been analyzed so far.
106 int get numSourcesAnalyzed => _sourcesAnalyzed.length; 107 int get numSourcesAnalyzed => _sourcesAnalyzed.length;
107 108
108 List<UriResolver> get resolvers { 109 List<UriResolver> get resolvers {
109 // TODO(brianwilkerson) Use the context builder to compute all of the resolv ers. 110 // TODO(brianwilkerson) Use the context builder to compute all of the resolv ers.
110 ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; 111 ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
111 ContextBuilder builder = new ContextBuilder(resourceProvider, null, null); 112 ContextBuilder builder = new ContextBuilder(resourceProvider, null, null);
112 113
113 DartSdk sdk = options.mockSdk ?? 114 DartSdk sdk = options.mockSdk ??
114 new FolderBasedDartSdk( 115 new FolderBasedDartSdk(resourceProvider,
115 resourceProvider, resourceProvider.getFolder(sdkDir)); 116 resourceProvider.getFolder(sdkDir), options.strongMode);
116 117
117 List<UriResolver> resolvers = [new DartUriResolver(sdk)]; 118 List<UriResolver> resolvers = [new DartUriResolver(sdk)];
118 119
119 if (options.packageRootPath != null) { 120 if (options.packageRootPath != null) {
120 // TODO(brianwilkerson) After 0.30.0 is published, clean up the following. 121 // TODO(brianwilkerson) After 0.30.0 is published, clean up the following.
121 try { 122 try {
122 // Try to use the post 0.30.0 API. 123 // Try to use the post 0.30.0 API.
123 (builder as dynamic).builderOptions.defaultPackagesDirectoryPath = 124 (builder as dynamic).builderOptions.defaultPackagesDirectoryPath =
124 options.packageRootPath; 125 options.packageRootPath;
125 } catch (_) { 126 } catch (_) {
126 // If that fails, fall back to the pre 0.30.0 API. 127 // If that fails, fall back to the pre 0.30.0 API.
127 (builder as dynamic).defaultPackagesDirectoryPath = 128 (builder as dynamic).defaultPackagesDirectoryPath =
128 options.packageRootPath; 129 options.packageRootPath;
129 } 130 }
130 Map<String, List<Folder>> packageMap = 131 Map<String, List<Folder>> packageMap =
131 builder.convertPackagesToMap(builder.createPackageMap(null)); 132 builder.convertPackagesToMap(builder.createPackageMap(null));
132 resolvers.add(new PackageMapUriResolver(resourceProvider, packageMap)); 133 resolvers.add(new PackageMapUriResolver(resourceProvider, packageMap));
133 } 134 }
134 135
135 // File URI resolver must come last so that files inside "/lib" are 136 // File URI resolver must come last so that files inside "/lib" are
136 // are analyzed via "package:" URI's. 137 // are analyzed via "package:" URI's.
137 resolvers.add(new ResourceUriResolver(resourceProvider)); 138 resolvers.add(new ResourceUriResolver(resourceProvider));
138 return resolvers; 139 return resolvers;
139 } 140 }
140 141
142 ResourceProvider get resourceProvider => options.resourceProvider;
143
141 String get sdkDir { 144 String get sdkDir {
142 // In case no SDK has been specified, fall back to inferring it. 145 // In case no SDK has been specified, fall back to inferring it.
143 return options.dartSdkPath ?? getSdkPath(); 146 return options.dartSdkPath ?? getSdkPath();
144 } 147 }
145 148
146 List<AnalysisErrorInfo> analyze(Iterable<io.File> files) { 149 Future<List<AnalysisErrorInfo>> analyze(Iterable<io.File> files) async {
147 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
148 context.analysisOptions = _buildAnalyzerOptions(options);
149 registerLinters(context);
150
151 Packages packages = _getPackageConfig();
152
153 context.sourceFactory = new SourceFactory(resolvers, packages);
154 AnalysisEngine.instance.logger = new StdLogger(); 150 AnalysisEngine.instance.logger = new StdLogger();
155 151
152 SourceFactory sourceFactory =
153 new SourceFactory(resolvers, _getPackageConfig());
154
155 PerformanceLog log = new PerformanceLog(null);
156 AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(log);
157 AnalysisDriver analysisDriver = new AnalysisDriver(
158 scheduler,
159 log,
160 resourceProvider,
161 new MemoryByteStore(),
162 new FileContentOverlay(),
163 null,
164 sourceFactory,
165 _buildAnalyzerOptions(options));
166 analysisDriver.results.listen((_) {});
167 analysisDriver.exceptions.listen((_) {});
168 scheduler.start();
169
156 List<Source> sources = []; 170 List<Source> sources = [];
157 ChangeSet changeSet = new ChangeSet();
158 for (io.File file in files) { 171 for (io.File file in files) {
159 File sourceFile = PhysicalResourceProvider.INSTANCE 172 File sourceFile =
160 .getFile(p.normalize(file.absolute.path)); 173 resourceProvider.getFile(p.normalize(file.absolute.path));
161 Source source = sourceFile.createSource(); 174 Source source = sourceFile.createSource();
162 Uri uri = context.sourceFactory.restoreUri(source); 175 Uri uri = sourceFactory.restoreUri(source);
163 if (uri != null) { 176 if (uri != null) {
164 // Ensure that we analyze the file using its canonical URI (e.g. if 177 // Ensure that we analyze the file using its canonical URI (e.g. if
165 // it's in "/lib", analyze it using a "package:" URI). 178 // it's in "/lib", analyze it using a "package:" URI).
166 source = sourceFile.createSource(uri); 179 source = sourceFile.createSource(uri);
167 } 180 }
181
168 sources.add(source); 182 sources.add(source);
169 changeSet.addedSource(source); 183 analysisDriver.addFile(source.fullName);
170 } 184 }
171 context.applyChanges(changeSet);
172 185
173 // Temporary location 186 DartProject project = await DartProject.create(analysisDriver, sources);
174 var project = new DartProject(context, sources);
175 // This will get pushed into the generator (or somewhere comparable) when
176 // we have a proper plugin.
177 Registry.ruleRegistry.forEach((lint) { 187 Registry.ruleRegistry.forEach((lint) {
178 if (lint is ProjectVisitor) { 188 if (lint is ProjectVisitor) {
179 (lint as ProjectVisitor).visit(project); 189 (lint as ProjectVisitor).visit(project);
180 } 190 }
181 }); 191 });
182 192
183 List<AnalysisErrorInfo> errors = []; 193 List<AnalysisErrorInfo> errors = [];
184
185 for (Source source in sources) { 194 for (Source source in sources) {
186 context.computeErrors(source); 195 ErrorsResult errorsResult =
187 errors.add(context.getErrors(source)); 196 await analysisDriver.getErrors(source.fullName);
197 errors.add(new AnalysisErrorInfoImpl(
198 errorsResult.errors, errorsResult.lineInfo));
188 _sourcesAnalyzed.add(source); 199 _sourcesAnalyzed.add(source);
189 } 200 }
190 201
191 if (options.visitTransitiveClosure) {
192 // In the process of computing errors for all the sources in [sources],
193 // the analyzer has visited the transitive closure of all libraries
194 // referenced by those sources. So now we simply need to visit all
195 // library sources known to the analysis context, and all parts they
196 // refer to.
197 for (Source librarySource in context.librarySources) {
198 for (Source source in _getAllUnitSources(context, librarySource)) {
199 if (!_sourcesAnalyzed.contains(source)) {
200 context.computeErrors(source);
201 errors.add(context.getErrors(source));
202 _sourcesAnalyzed.add(source);
203 }
204 }
205 }
206 }
207
208 return errors; 202 return errors;
209 } 203 }
210 204
211 void registerLinters(AnalysisContext context) { 205 void registerLinters(AnalysisContext context) {
212 if (options.enableLints) { 206 if (options.enableLints) {
213 setLints(context, options.enabledLints?.toList(growable: false)); 207 setLints(context, options.enabledLints?.toList(growable: false));
214 } 208 }
215 } 209 }
216 210
217 /// Yield the sources for all the compilation units constituting
218 /// [librarySource] (including the defining compilation unit).
219 Iterable<Source> _getAllUnitSources(
220 AnalysisContext context, Source librarySource) {
221 List<Source> result = <Source>[librarySource];
222 result.addAll(context
223 .getLibraryElement(librarySource)
224 .parts
225 .map((CompilationUnitElement e) => e.source));
226 return result;
227 }
228
229 Packages _getPackageConfig() { 211 Packages _getPackageConfig() {
230 if (options.packageConfigPath != null) { 212 if (options.packageConfigPath != null) {
231 String packageConfigPath = options.packageConfigPath; 213 String packageConfigPath = options.packageConfigPath;
232 Uri fileUri = new Uri.file(packageConfigPath); 214 Uri fileUri = new Uri.file(packageConfigPath);
233 try { 215 try {
234 io.File configFile = new io.File.fromUri(fileUri).absolute; 216 io.File configFile = new io.File.fromUri(fileUri).absolute;
235 List<int> bytes = configFile.readAsBytesSync(); 217 List<int> bytes = configFile.readAsBytesSync();
236 Map<String, Uri> map = pkgfile.parse(bytes, configFile.uri); 218 Map<String, Uri> map = pkgfile.parse(bytes, configFile.uri);
237 return new MapPackages(map); 219 return new MapPackages(map);
238 } catch (e) { 220 } catch (e) {
(...skipping 13 matching lines...) Expand all
252 } 234 }
253 235
254 /// Prints logging information comments to the [outSink] and error messages to 236 /// Prints logging information comments to the [outSink] and error messages to
255 /// [errorSink]. 237 /// [errorSink].
256 class StdLogger extends Logger { 238 class StdLogger extends Logger {
257 @override 239 @override
258 void logError(String message, [exception]) => errorSink.writeln(message); 240 void logError(String message, [exception]) => errorSink.writeln(message);
259 @override 241 @override
260 void logInformation(String message, [exception]) => outSink.writeln(message); 242 void logInformation(String message, [exception]) => outSink.writeln(message);
261 } 243 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/lint/linter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698