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

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

Issue 2678193002: Not task based analysis. (Closed)
Patch Set: Created 3 years, 10 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/dart/analysis/driver.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
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.
4
5 import 'package:analyzer/dart/ast/ast.dart';
6 import 'package:analyzer/dart/ast/token.dart';
7 import 'package:analyzer/dart/element/element.dart';
8 import 'package:analyzer/error/error.dart';
9 import 'package:analyzer/error/listener.dart';
10 import 'package:analyzer/src/context/context.dart';
11 import 'package:analyzer/src/dart/analysis/file_state.dart';
12 import 'package:analyzer/src/dart/ast/ast.dart';
13 import 'package:analyzer/src/dart/element/element.dart';
14 import 'package:analyzer/src/dart/scanner/scanner.dart';
15 import 'package:analyzer/src/error/codes.dart';
16 import 'package:analyzer/src/error/pending_error.dart';
17 import 'package:analyzer/src/generated/declaration_resolver.dart';
18 import 'package:analyzer/src/generated/engine.dart';
19 import 'package:analyzer/src/generated/error_verifier.dart';
20 import 'package:analyzer/src/generated/parser.dart';
21 import 'package:analyzer/src/generated/resolver.dart';
22 import 'package:analyzer/src/generated/source.dart';
23 import 'package:analyzer/src/summary/package_bundle_reader.dart';
24 import 'package:analyzer/src/task/dart.dart';
25 import 'package:analyzer/src/task/strong/checker.dart';
26 import 'package:front_end/src/scanner/reader.dart';
27
28 /**
29 * Analyzer of Dart files.
30 *
31 * Work in progress, not ready to be used.
32 */
33 class AnalyzerImpl {
34 final AnalysisOptions analysisOptions;
35 final SourceFactory sourceFactory;
36 final FileSystemState fsState;
37 final SummaryDataStore store;
38
39 AnalysisContextImpl analysisContext;
40 TypeProvider typeProvider;
41 StoreBasedSummaryResynthesizer resynthesizer;
42 final Map<FileState, RecordingErrorListener> _errorListeners = {};
43 final Map<FileState, ErrorReporter> _errorReporters = {};
44 final List<UsedImportedElements> usedImportedElementsList = [];
45
46 AnalyzerImpl(
47 this.analysisOptions, this.sourceFactory, this.fsState, this.store);
48
49 /**
50 * Compute analysis results for all units of the [library].
51 */
52 Map<FileState, UnitAnalysisResult> analyze(FileState library) {
53 Map<FileState, CompilationUnit> units = {};
54
55 // Parse all files.
56 units[library] = _parse(library);
57 for (FileState part in library.partedFiles) {
58 units[part] = _parse(part);
59 }
60
61 // Resolve directives.
62 units.forEach((file, unit) {
63 _resolveUriBasedDirectives(file, unit);
64 });
65
66 _createAnalysisContext();
67
68 try {
69 resynthesizer = new StoreBasedSummaryResynthesizer(
70 analysisContext, sourceFactory, analysisOptions.strongMode, store);
71 typeProvider = resynthesizer.typeProvider;
72 analysisContext.typeProvider = typeProvider;
73
74 units.forEach((file, unit) {
75 _resolveFile(analysisContext, library, file, unit);
76 });
77
78 List<UsedLocalElements> usedLocalElementsList = [];
79 units.forEach((file, unit) {
80 GatherUsedLocalElementsVisitor visitor =
81 new GatherUsedLocalElementsVisitor(unit.element.library);
82 unit.accept(visitor);
83 usedLocalElementsList.add(visitor.usedElements);
84 });
85
86 units.forEach((file, unit) {
Paul Berry 2017/02/06 22:44:36 Can we merge this loop with the loop above? It se
87 LibraryElement libraryElement = unit.element.library;
88 var visitor = new GatherUsedImportedElementsVisitor(libraryElement);
89 unit.accept(visitor);
90 usedImportedElementsList.add(visitor.usedElements);
91 });
92
93 units.forEach((file, unit) {
94 _computeVerifyErrorsAndHints(
95 analysisContext, library, usedLocalElementsList, file, unit);
96 });
97 } finally {
98 analysisContext.dispose();
99 }
100
101 // Return full results.
102 Map<FileState, UnitAnalysisResult> results = {};
103 units.forEach((file, unit) {
104 List<AnalysisError> errors = _getErrorListener(file).errors;
105 results[file] = new UnitAnalysisResult(file, unit, errors);
106 });
107 return results;
108 }
109
110 void _computeVerifyErrorsAndHints(
111 AnalysisContext analysisContext,
112 FileState libraryFile,
113 List<UsedLocalElements> usedLocalElementsList,
114 FileState file,
115 CompilationUnit unit) {
116 RecordingErrorListener errorListener = _getErrorListener(file);
117 CompilationUnitElement unitElement = unit.element;
118 LibraryElement libraryElement = unitElement.library;
119
120 // Verify imports.
121 {
122 ImportsVerifier verifier = new ImportsVerifier();
123 verifier.addImports(unit);
124 usedImportedElementsList.forEach(verifier.removeUsedElements);
125 ErrorReporter errorReporter = _getErrorReporter(file);
126 verifier.generateDuplicateImportHints(errorReporter);
127 verifier.generateUnusedImportHints(errorReporter);
128 verifier.generateUnusedShownNameHints(errorReporter);
129 }
130
131 {
132 GatherUsedLocalElementsVisitor visitor =
133 new GatherUsedLocalElementsVisitor(libraryElement);
134 unit.accept(visitor);
135 }
136
137 // Unused local elements.
138 {
139 UsedLocalElements usedElements =
140 new UsedLocalElements.merge(usedLocalElementsList);
141 UnusedLocalElementsVerifier visitor =
142 new UnusedLocalElementsVerifier(errorListener, usedElements);
143 unitElement.accept(visitor);
144 }
145 }
146
147 void _createAnalysisContext() {
148 AnalysisContextImpl analysisContext =
149 AnalysisEngine.instance.createAnalysisContext();
150 analysisContext.analysisOptions = analysisOptions;
151 analysisContext.sourceFactory = sourceFactory.clone();
152 analysisContext.contentCache = new _ContentCacheWrapper(fsState);
153 this.analysisContext = analysisContext;
154 }
155
156 RecordingErrorListener _getErrorListener(FileState file) =>
157 _errorListeners.putIfAbsent(file, () => new RecordingErrorListener());
158
159 ErrorReporter _getErrorReporter(FileState file) {
160 return _errorReporters.putIfAbsent(file, () {
161 RecordingErrorListener listener = _getErrorListener(file);
162 return new ErrorReporter(listener, file.source);
163 });
164 }
165
166 /**
167 * Return a new parsed unresolved [CompilationUnit].
168 */
169 CompilationUnit _parse(FileState file) {
170 RecordingErrorListener errorListener = _getErrorListener(file);
171
172 CharSequenceReader reader = new CharSequenceReader(file.content);
173 Scanner scanner = new Scanner(file.source, reader, errorListener);
174 scanner.scanGenericMethodComments = analysisOptions.strongMode;
175 Token token = scanner.tokenize();
176 LineInfo lineInfo = new LineInfo(scanner.lineStarts);
177
178 Parser parser = new Parser(file.source, errorListener);
179 parser.parseGenericMethodComments = analysisOptions.strongMode;
180 CompilationUnit unit = parser.parseCompilationUnit(token);
181 unit.lineInfo = lineInfo;
182 return unit;
183 }
184
185 void _resolveFile(AnalysisContext analysisContext, FileState library,
186 FileState file, CompilationUnit unit) {
187 if (!file.exists) {
188 var unitElement = new CompilationUnitElementImpl(file.source.shortName);
189 var libraryElement = new LibraryElementImpl(analysisContext, null, -1, 0);
190 libraryElement.definingCompilationUnit = unitElement;
191 unit.element = unitElement;
192 return;
193 }
194
195 RecordingErrorListener errorListener = _getErrorListener(file);
196
197 String libraryUri = library.uri.toString();
198 String unitUri = file.uri.toString();
199 CompilationUnitElement unitElement = resynthesizer.getElement(
200 new ElementLocationImpl.con3(<String>[libraryUri, unitUri]));
201 LibraryElement libraryElement = unitElement.library;
202
203 // TODO(scheglov) Hack: set types for top-level variables
204 // Otherwise TypeResolverVisitor will set declared types, and because we
205 // don't run InferStaticVariableTypeTask, we will stuck with these declared
206 // types. And we don't need to run this task - resynthesized elements have
207 // inferred types.
208 for (var e in unitElement.topLevelVariables) {
209 if (!e.isSynthetic) {
210 e.type;
211 }
212 }
213
214 new DeclarationResolver().resolve(unit, unitElement);
215
216 if (file == library) {
217 // TODO(scheglov) fill these maps?
218 DirectiveResolver resolver = new DirectiveResolver({}, {}, {});
219 unit.accept(resolver);
220 }
221
222 unit.accept(new EnumMemberBuilder(typeProvider));
223
224 new TypeParameterBoundsResolver(
225 typeProvider, libraryElement, unitElement.source, errorListener)
226 .resolveTypeBounds(unit);
227
228 unit.accept(new TypeResolverVisitor(
229 libraryElement, unitElement.source, typeProvider, errorListener));
230
231 LibraryScope libraryScope = new LibraryScope(libraryElement);
232 unit.accept(new VariableResolverVisitor(
233 libraryElement, unitElement.source, typeProvider, errorListener,
234 nameScope: libraryScope));
235
236 unit.accept(new PartialResolverVisitor(libraryElement, unitElement.source,
237 typeProvider, AnalysisErrorListener.NULL_LISTENER));
238
239 // Nothing for RESOLVED_UNIT8?
240 // Nothing for RESOLVED_UNIT9?
241 // Nothing for RESOLVED_UNIT10?
242
243 unit.accept(new ResolverVisitor(
244 libraryElement, unitElement.source, typeProvider, errorListener));
245
246 // TODO(scheglov) RESOLVED_UNIT12: compute constants
247
248 //
249 // Use the ErrorVerifier to compute errors.
250 //
251 List<PendingError> pendingErrors;
252 {
253 RequiredConstantsComputer computer =
254 new RequiredConstantsComputer(file.source);
255 unit.accept(computer);
256 pendingErrors = computer.pendingErrors;
257 List<ConstantEvaluationTarget> requiredConstants =
258 computer.requiredConstants;
259 }
260
261 if (analysisOptions.strongMode) {
262 AnalysisOptionsImpl options = analysisOptions as AnalysisOptionsImpl;
263 CodeChecker checker = new CodeChecker(
264 typeProvider,
265 new StrongTypeSystemImpl(typeProvider,
266 implicitCasts: options.implicitCasts,
267 nonnullableTypes: options.nonnullableTypes),
268 errorListener,
269 options);
270 checker.visitCompilationUnit(unit);
271 }
272
273 var errorReporter = _getErrorReporter(file);
274
275 //
276 // Validate the directives.
277 //
278 _validateUriBasedDirectives(file, unit);
279
280 //
281 // Use the ConstantVerifier to compute errors.
282 //
283 ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter,
284 libraryElement, typeProvider, analysisContext.declaredVariables);
285 unit.accept(constantVerifier);
286
287 //
288 // Use the ErrorVerifier to compute errors.
289 //
290 ErrorVerifier errorVerifier = new ErrorVerifier(
291 errorReporter,
292 libraryElement,
293 typeProvider,
294 new InheritanceManager(libraryElement),
295 analysisOptions.enableSuperMixins);
296 unit.accept(errorVerifier);
297
298 //
299 // Convert the pending errors into actual errors.
300 //
301 for (PendingError pendingError in pendingErrors) {
302 errorListener.onError(pendingError.toAnalysisError());
303 }
304
305 //
306 // Find dead code.
307 //
308 unit.accept(new DeadCodeVerifier(errorReporter,
309 typeSystem: analysisContext.typeSystem));
310
311 // Dart2js analysis.
312 if (analysisOptions.dart2jsHint) {
313 unit.accept(new Dart2JSVerifier(errorReporter));
314 }
315
316 InheritanceManager inheritanceManager = new InheritanceManager(
317 libraryElement,
318 includeAbstractFromSuperclasses: true);
319
320 unit.accept(new BestPracticesVerifier(
321 errorReporter, typeProvider, libraryElement, inheritanceManager,
322 typeSystem: analysisContext.typeSystem));
323
324 unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
325
326 new ToDoFinder(errorReporter).findIn(unit);
327 }
328
329 /**
330 * Return the result of resolve the given [uriContent], reporting errors
331 * against the [uriLiteral].
332 */
333 Source _resolveUri(FileState file, bool isImport, StringLiteral uriLiteral,
334 String uriContent) {
335 UriValidationCode code =
336 UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent);
337 if (code == null) {
338 try {
339 Uri.parse(uriContent);
340 } on FormatException {
341 return null;
342 }
343 return sourceFactory.resolveUri(file.source, uriContent);
344 } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
345 return null;
346 } else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
347 _getErrorReporter(file).reportErrorForNode(
348 CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
349 return null;
350 } else if (code == UriValidationCode.INVALID_URI) {
351 _getErrorReporter(file).reportErrorForNode(
352 CompileTimeErrorCode.INVALID_URI, uriLiteral, [uriContent]);
353 return null;
354 }
355 return null;
356 }
357
358 void _resolveUriBasedDirectives(FileState file, CompilationUnit unit) {
359 for (Directive directive in unit.directives) {
360 if (directive is UriBasedDirective) {
361 StringLiteral uriLiteral = directive.uri;
362 String uriContent = uriLiteral.stringValue?.trim();
363 directive.uriContent = uriContent;
364 Source defaultSource = _resolveUri(
365 file, directive is ImportDirective, uriLiteral, uriContent);
366 directive.uriSource = defaultSource;
367 }
368 }
369 }
370
371 /**
372 * Check the given [directive] to see if the referenced source exists and
373 * report an error if it does not.
374 */
375 void _validateUriBasedDirective(
376 FileState file, UriBasedDirectiveImpl directive) {
377 Source source = directive.uriSource;
378 if (source != null) {
379 if (analysisContext.exists(source)) {
380 return;
381 }
382 } else {
383 // Don't report errors already reported by ParseDartTask.resolveDirective
384 if (directive.validate() != null) {
385 return;
386 }
387 }
388 StringLiteral uriLiteral = directive.uri;
389 CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
390 if (_isGenerated(source)) {
391 errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
392 }
393 _getErrorReporter(file)
394 .reportErrorForNode(errorCode, uriLiteral, [directive.uriContent]);
395 }
396
397 /**
398 * Check each directive in the given [unit] to see if the referenced source
399 * exists and report an error if it does not.
400 */
401 void _validateUriBasedDirectives(FileState file, CompilationUnit unit) {
402 for (Directive directive in unit.directives) {
403 if (directive is UriBasedDirective) {
404 _validateUriBasedDirective(file, directive);
405 }
406 }
407 }
408
409 /**
410 * Return `true` if the given [source] refers to a file that is assumed to be
411 * generated.
412 */
413 static bool _isGenerated(Source source) {
414 if (source == null) {
415 return false;
416 }
417 // TODO(brianwilkerson) Generalize this mechanism.
418 const List<String> suffixes = const <String>[
419 '.g.dart',
420 '.pb.dart',
421 '.pbenum.dart',
422 '.pbserver.dart',
423 '.pbjson.dart',
424 '.template.dart'
425 ];
426 String fullName = source.fullName;
427 for (String suffix in suffixes) {
428 if (fullName.endsWith(suffix)) {
429 return true;
430 }
431 }
432 return false;
433 }
434 }
435
436 /**
437 * Analysis result for single file.
438 */
439 class UnitAnalysisResult {
440 final FileState file;
441 final CompilationUnit unit;
442 final List<AnalysisError> errors;
443
444 UnitAnalysisResult(this.file, this.unit, this.errors);
445 }
446
447 /**
448 * [ContentCache] wrapper around [FileContentOverlay].
449 */
450 class _ContentCacheWrapper implements ContentCache {
451 final FileSystemState fsState;
452
453 _ContentCacheWrapper(this.fsState);
454
455 @override
456 void accept(ContentCacheVisitor visitor) {
457 throw new UnimplementedError();
458 }
459
460 @override
461 String getContents(Source source) {
462 return _getFileForSource(source).content;
463 }
464
465 @override
466 bool getExists(Source source) {
467 return _getFileForSource(source).exists;
468 }
469
470 @override
471 int getModificationStamp(Source source) {
472 return _getFileForSource(source).exists ? 0 : -1;
473 }
474
475 @override
476 String setContents(Source source, String contents) {
477 throw new UnimplementedError();
478 }
479
480 FileState _getFileForSource(Source source) {
481 String path = source.fullName;
482 return fsState.getFileForPath(path);
483 }
484 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/dart/analysis/driver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698