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

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

Issue 2679073003: Compute constants in non-task analyzer. (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/test/src/dart/analysis/driver_test.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) 2017, the Dart project authors. Please see the AUTHORS file 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 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 'package:analyzer/dart/ast/ast.dart'; 5 import 'package:analyzer/dart/ast/ast.dart';
6 import 'package:analyzer/dart/ast/token.dart'; 6 import 'package:analyzer/dart/ast/token.dart';
7 import 'package:analyzer/dart/element/element.dart'; 7 import 'package:analyzer/dart/element/element.dart';
8 import 'package:analyzer/error/error.dart'; 8 import 'package:analyzer/error/error.dart';
9 import 'package:analyzer/error/listener.dart'; 9 import 'package:analyzer/error/listener.dart';
10 import 'package:analyzer/src/context/context.dart'; 10 import 'package:analyzer/src/context/context.dart';
11 import 'package:analyzer/src/dart/analysis/file_state.dart'; 11 import 'package:analyzer/src/dart/analysis/file_state.dart';
12 import 'package:analyzer/src/dart/ast/ast.dart'; 12 import 'package:analyzer/src/dart/ast/ast.dart';
13 import 'package:analyzer/src/dart/constant/evaluation.dart';
14 import 'package:analyzer/src/dart/constant/utilities.dart';
13 import 'package:analyzer/src/dart/element/element.dart'; 15 import 'package:analyzer/src/dart/element/element.dart';
14 import 'package:analyzer/src/dart/scanner/scanner.dart'; 16 import 'package:analyzer/src/dart/scanner/scanner.dart';
15 import 'package:analyzer/src/error/codes.dart'; 17 import 'package:analyzer/src/error/codes.dart';
16 import 'package:analyzer/src/error/pending_error.dart'; 18 import 'package:analyzer/src/error/pending_error.dart';
17 import 'package:analyzer/src/generated/declaration_resolver.dart'; 19 import 'package:analyzer/src/generated/declaration_resolver.dart';
18 import 'package:analyzer/src/generated/engine.dart'; 20 import 'package:analyzer/src/generated/engine.dart';
19 import 'package:analyzer/src/generated/error_verifier.dart'; 21 import 'package:analyzer/src/generated/error_verifier.dart';
20 import 'package:analyzer/src/generated/parser.dart'; 22 import 'package:analyzer/src/generated/parser.dart';
21 import 'package:analyzer/src/generated/resolver.dart'; 23 import 'package:analyzer/src/generated/resolver.dart';
22 import 'package:analyzer/src/generated/source.dart'; 24 import 'package:analyzer/src/generated/source.dart';
23 import 'package:analyzer/src/summary/package_bundle_reader.dart'; 25 import 'package:analyzer/src/summary/package_bundle_reader.dart';
24 import 'package:analyzer/src/task/dart.dart'; 26 import 'package:analyzer/src/task/dart.dart';
25 import 'package:analyzer/src/task/strong/checker.dart'; 27 import 'package:analyzer/src/task/strong/checker.dart';
28 import 'package:front_end/src/dependency_walker.dart';
26 import 'package:front_end/src/scanner/reader.dart'; 29 import 'package:front_end/src/scanner/reader.dart';
27 30
28 /** 31 /**
29 * Analyzer of Dart files. 32 * Analyzer of Dart files.
30 * 33 *
31 * Work in progress, not ready to be used. 34 * Work in progress, not ready to be used.
32 */ 35 */
33 class AnalyzerImpl { 36 class AnalyzerImpl {
34 final AnalysisOptions analysisOptions; 37 final AnalysisOptions analysisOptions;
35 final SourceFactory sourceFactory; 38 final SourceFactory sourceFactory;
36 final FileSystemState fsState; 39 final FileSystemState fsState;
37 final SummaryDataStore store; 40 final SummaryDataStore store;
38 41
39 AnalysisContextImpl analysisContext; 42 AnalysisContextImpl analysisContext;
40 TypeProvider typeProvider; 43 TypeProvider typeProvider;
41 StoreBasedSummaryResynthesizer resynthesizer; 44 StoreBasedSummaryResynthesizer resynthesizer;
42 final Map<FileState, RecordingErrorListener> _errorListeners = {}; 45 final Map<FileState, RecordingErrorListener> _errorListeners = {};
43 final Map<FileState, ErrorReporter> _errorReporters = {}; 46 final Map<FileState, ErrorReporter> _errorReporters = {};
44 final List<UsedImportedElements> usedImportedElementsList = []; 47 final List<UsedImportedElements> usedImportedElementsList = [];
45 final List<UsedLocalElements> usedLocalElementsList = []; 48 final List<UsedLocalElements> usedLocalElementsList = [];
49 final List<ConstantEvaluationTarget> _constants = [];
46 50
47 AnalyzerImpl( 51 AnalyzerImpl(
48 this.analysisOptions, this.sourceFactory, this.fsState, this.store); 52 this.analysisOptions, this.sourceFactory, this.fsState, this.store);
49 53
50 /** 54 /**
51 * Compute analysis results for all units of the [library]. 55 * Compute analysis results for all units of the [library].
52 */ 56 */
53 Map<FileState, UnitAnalysisResult> analyze(FileState library) { 57 Map<FileState, UnitAnalysisResult> analyze(FileState library) {
54 Map<FileState, CompilationUnit> units = {}; 58 Map<FileState, CompilationUnit> units = {};
55 59
(...skipping 13 matching lines...) Expand all
69 try { 73 try {
70 resynthesizer = new StoreBasedSummaryResynthesizer( 74 resynthesizer = new StoreBasedSummaryResynthesizer(
71 analysisContext, sourceFactory, analysisOptions.strongMode, store); 75 analysisContext, sourceFactory, analysisOptions.strongMode, store);
72 typeProvider = resynthesizer.typeProvider; 76 typeProvider = resynthesizer.typeProvider;
73 analysisContext.typeProvider = typeProvider; 77 analysisContext.typeProvider = typeProvider;
74 78
75 units.forEach((file, unit) { 79 units.forEach((file, unit) {
76 _resolveFile(analysisContext, library, file, unit); 80 _resolveFile(analysisContext, library, file, unit);
77 }); 81 });
78 82
83 _computeConstants();
84
79 units.forEach((file, unit) { 85 units.forEach((file, unit) {
80 LibraryElement libraryElement = unit.element.library; 86 LibraryElement libraryElement = unit.element.library;
81 { 87 {
82 var visitor = new GatherUsedLocalElementsVisitor(libraryElement); 88 var visitor = new GatherUsedLocalElementsVisitor(libraryElement);
83 unit.accept(visitor); 89 unit.accept(visitor);
84 usedLocalElementsList.add(visitor.usedElements); 90 usedLocalElementsList.add(visitor.usedElements);
85 } 91 }
86 { 92 {
87 var visitor = new GatherUsedImportedElementsVisitor(libraryElement); 93 var visitor = new GatherUsedImportedElementsVisitor(libraryElement);
88 unit.accept(visitor); 94 unit.accept(visitor);
(...skipping 10 matching lines...) Expand all
99 105
100 // Return full results. 106 // Return full results.
101 Map<FileState, UnitAnalysisResult> results = {}; 107 Map<FileState, UnitAnalysisResult> results = {};
102 units.forEach((file, unit) { 108 units.forEach((file, unit) {
103 List<AnalysisError> errors = _getErrorListener(file).errors; 109 List<AnalysisError> errors = _getErrorListener(file).errors;
104 results[file] = new UnitAnalysisResult(file, unit, errors); 110 results[file] = new UnitAnalysisResult(file, unit, errors);
105 }); 111 });
106 return results; 112 return results;
107 } 113 }
108 114
115 /**
116 * Compute [_constants] in all units.
117 */
118 void _computeConstants() {
119 ConstantEvaluationEngine evaluationEngine = new ConstantEvaluationEngine(
120 analysisContext.typeProvider, analysisContext.declaredVariables,
121 typeSystem: analysisContext.typeSystem);
122
123 List<_ConstantNode> nodes = [];
124 Map<ConstantEvaluationTarget, _ConstantNode> nodeMap = {};
125 for (ConstantEvaluationTarget constant in _constants) {
126 var node = new _ConstantNode(evaluationEngine, nodeMap, constant);
127 nodes.add(node);
128 nodeMap[constant] = node;
129 }
130
131 for (_ConstantNode node in nodes) {
132 if (!node.isEvaluated) {
133 new _ConstantWalker(evaluationEngine).walk(node);
134 }
135 }
136 }
137
109 void _computeVerifyErrorsAndHints(AnalysisContext analysisContext, 138 void _computeVerifyErrorsAndHints(AnalysisContext analysisContext,
110 FileState libraryFile, FileState file, CompilationUnit unit) { 139 FileState libraryFile, FileState file, CompilationUnit unit) {
111 RecordingErrorListener errorListener = _getErrorListener(file); 140 RecordingErrorListener errorListener = _getErrorListener(file);
112 CompilationUnitElement unitElement = unit.element; 141 CompilationUnitElement unitElement = unit.element;
113 LibraryElement libraryElement = unitElement.library; 142 LibraryElement libraryElement = unitElement.library;
114 143
144 //
145 // Use the ErrorVerifier to compute errors.
146 //
147 List<PendingError> pendingErrors;
148 {
149 RequiredConstantsComputer computer =
150 new RequiredConstantsComputer(file.source);
151 unit.accept(computer);
152 pendingErrors = computer.pendingErrors;
153 List<ConstantEvaluationTarget> requiredConstants =
154 computer.requiredConstants;
155 }
156
157 if (analysisOptions.strongMode) {
158 AnalysisOptionsImpl options = analysisOptions as AnalysisOptionsImpl;
159 CodeChecker checker = new CodeChecker(
160 typeProvider,
161 new StrongTypeSystemImpl(typeProvider,
162 implicitCasts: options.implicitCasts,
163 nonnullableTypes: options.nonnullableTypes),
164 errorListener,
165 options);
166 checker.visitCompilationUnit(unit);
167 }
168
169 var errorReporter = _getErrorReporter(file);
170
171 //
172 // Validate the directives.
173 //
174 _validateUriBasedDirectives(file, unit);
175
176 //
177 // Use the ConstantVerifier to compute errors.
178 //
179 ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter,
180 libraryElement, typeProvider, analysisContext.declaredVariables);
181 unit.accept(constantVerifier);
182
183 //
184 // Use the ErrorVerifier to compute errors.
185 //
186 ErrorVerifier errorVerifier = new ErrorVerifier(
187 errorReporter,
188 libraryElement,
189 typeProvider,
190 new InheritanceManager(libraryElement),
191 analysisOptions.enableSuperMixins);
192 unit.accept(errorVerifier);
193
194 //
195 // Convert the pending errors into actual errors.
196 //
197 for (PendingError pendingError in pendingErrors) {
198 errorListener.onError(pendingError.toAnalysisError());
199 }
200
201 //
202 // Find dead code.
203 //
204 unit.accept(new DeadCodeVerifier(errorReporter,
205 typeSystem: analysisContext.typeSystem));
206
207 // Dart2js analysis.
208 if (analysisOptions.dart2jsHint) {
209 unit.accept(new Dart2JSVerifier(errorReporter));
210 }
211
212 InheritanceManager inheritanceManager = new InheritanceManager(
213 libraryElement,
214 includeAbstractFromSuperclasses: true);
215
216 unit.accept(new BestPracticesVerifier(
217 errorReporter, typeProvider, libraryElement, inheritanceManager,
218 typeSystem: analysisContext.typeSystem));
219
220 unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
221
222 new ToDoFinder(errorReporter).findIn(unit);
223
115 // Verify imports. 224 // Verify imports.
116 { 225 {
117 ImportsVerifier verifier = new ImportsVerifier(); 226 ImportsVerifier verifier = new ImportsVerifier();
118 verifier.addImports(unit); 227 verifier.addImports(unit);
119 usedImportedElementsList.forEach(verifier.removeUsedElements); 228 usedImportedElementsList.forEach(verifier.removeUsedElements);
120 ErrorReporter errorReporter = _getErrorReporter(file); 229 ErrorReporter errorReporter = _getErrorReporter(file);
121 verifier.generateDuplicateImportHints(errorReporter); 230 verifier.generateDuplicateImportHints(errorReporter);
122 verifier.generateUnusedImportHints(errorReporter); 231 verifier.generateUnusedImportHints(errorReporter);
123 verifier.generateUnusedShownNameHints(errorReporter); 232 verifier.generateUnusedShownNameHints(errorReporter);
124 } 233 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 Parser parser = new Parser(file.source, errorListener); 282 Parser parser = new Parser(file.source, errorListener);
174 parser.parseGenericMethodComments = analysisOptions.strongMode; 283 parser.parseGenericMethodComments = analysisOptions.strongMode;
175 CompilationUnit unit = parser.parseCompilationUnit(token); 284 CompilationUnit unit = parser.parseCompilationUnit(token);
176 unit.lineInfo = lineInfo; 285 unit.lineInfo = lineInfo;
177 return unit; 286 return unit;
178 } 287 }
179 288
180 void _resolveFile(AnalysisContext analysisContext, FileState library, 289 void _resolveFile(AnalysisContext analysisContext, FileState library,
181 FileState file, CompilationUnit unit) { 290 FileState file, CompilationUnit unit) {
182 if (!file.exists) { 291 if (!file.exists) {
183 var unitElement = new CompilationUnitElementImpl(file.source.shortName); 292 Source source = file.source;
293 var unitElement = new CompilationUnitElementImpl(source.shortName);
184 var libraryElement = new LibraryElementImpl(analysisContext, null, -1, 0); 294 var libraryElement = new LibraryElementImpl(analysisContext, null, -1, 0);
295 unitElement.source = source;
296 unitElement.librarySource = source;
185 libraryElement.definingCompilationUnit = unitElement; 297 libraryElement.definingCompilationUnit = unitElement;
186 unit.element = unitElement; 298 unit.element = unitElement;
187 return; 299 return;
188 } 300 }
189 301
190 RecordingErrorListener errorListener = _getErrorListener(file); 302 RecordingErrorListener errorListener = _getErrorListener(file);
191 303
192 String libraryUri = library.uri.toString(); 304 String libraryUri = library.uri.toString();
193 String unitUri = file.uri.toString(); 305 String unitUri = file.uri.toString();
194 CompilationUnitElement unitElement = resynthesizer.getElement( 306 CompilationUnitElement unitElement = resynthesizer.getElement(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 unit.accept(new PartialResolverVisitor(libraryElement, unitElement.source, 343 unit.accept(new PartialResolverVisitor(libraryElement, unitElement.source,
232 typeProvider, AnalysisErrorListener.NULL_LISTENER)); 344 typeProvider, AnalysisErrorListener.NULL_LISTENER));
233 345
234 // Nothing for RESOLVED_UNIT8? 346 // Nothing for RESOLVED_UNIT8?
235 // Nothing for RESOLVED_UNIT9? 347 // Nothing for RESOLVED_UNIT9?
236 // Nothing for RESOLVED_UNIT10? 348 // Nothing for RESOLVED_UNIT10?
237 349
238 unit.accept(new ResolverVisitor( 350 unit.accept(new ResolverVisitor(
239 libraryElement, unitElement.source, typeProvider, errorListener)); 351 libraryElement, unitElement.source, typeProvider, errorListener));
240 352
241 // TODO(scheglov) RESOLVED_UNIT12: compute constants
242
243 // 353 //
244 // Use the ErrorVerifier to compute errors. 354 // Find constants to compute.
245 // 355 //
246 List<PendingError> pendingErrors;
247 { 356 {
248 RequiredConstantsComputer computer = 357 ConstantFinder constantFinder = new ConstantFinder();
249 new RequiredConstantsComputer(file.source); 358 unit.accept(constantFinder);
250 unit.accept(computer); 359 _constants.addAll(constantFinder.constantsToCompute);
251 pendingErrors = computer.pendingErrors;
252 List<ConstantEvaluationTarget> requiredConstants =
253 computer.requiredConstants;
254 } 360 }
255
256 if (analysisOptions.strongMode) {
257 AnalysisOptionsImpl options = analysisOptions as AnalysisOptionsImpl;
258 CodeChecker checker = new CodeChecker(
259 typeProvider,
260 new StrongTypeSystemImpl(typeProvider,
261 implicitCasts: options.implicitCasts,
262 nonnullableTypes: options.nonnullableTypes),
263 errorListener,
264 options);
265 checker.visitCompilationUnit(unit);
266 }
267
268 var errorReporter = _getErrorReporter(file);
269
270 //
271 // Validate the directives.
272 //
273 _validateUriBasedDirectives(file, unit);
274
275 //
276 // Use the ConstantVerifier to compute errors.
277 //
278 ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter,
279 libraryElement, typeProvider, analysisContext.declaredVariables);
280 unit.accept(constantVerifier);
281
282 //
283 // Use the ErrorVerifier to compute errors.
284 //
285 ErrorVerifier errorVerifier = new ErrorVerifier(
286 errorReporter,
287 libraryElement,
288 typeProvider,
289 new InheritanceManager(libraryElement),
290 analysisOptions.enableSuperMixins);
291 unit.accept(errorVerifier);
292
293 //
294 // Convert the pending errors into actual errors.
295 //
296 for (PendingError pendingError in pendingErrors) {
297 errorListener.onError(pendingError.toAnalysisError());
298 }
299
300 //
301 // Find dead code.
302 //
303 unit.accept(new DeadCodeVerifier(errorReporter,
304 typeSystem: analysisContext.typeSystem));
305
306 // Dart2js analysis.
307 if (analysisOptions.dart2jsHint) {
308 unit.accept(new Dart2JSVerifier(errorReporter));
309 }
310
311 InheritanceManager inheritanceManager = new InheritanceManager(
312 libraryElement,
313 includeAbstractFromSuperclasses: true);
314
315 unit.accept(new BestPracticesVerifier(
316 errorReporter, typeProvider, libraryElement, inheritanceManager,
317 typeSystem: analysisContext.typeSystem));
318
319 unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
320
321 new ToDoFinder(errorReporter).findIn(unit);
322 } 361 }
323 362
324 /** 363 /**
325 * Return the result of resolve the given [uriContent], reporting errors 364 * Return the result of resolve the given [uriContent], reporting errors
326 * against the [uriLiteral]. 365 * against the [uriLiteral].
327 */ 366 */
328 Source _resolveUri(FileState file, bool isImport, StringLiteral uriLiteral, 367 Source _resolveUri(FileState file, bool isImport, StringLiteral uriLiteral,
329 String uriContent) { 368 String uriContent) {
330 UriValidationCode code = 369 UriValidationCode code =
331 UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent); 370 UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 */ 472 */
434 class UnitAnalysisResult { 473 class UnitAnalysisResult {
435 final FileState file; 474 final FileState file;
436 final CompilationUnit unit; 475 final CompilationUnit unit;
437 final List<AnalysisError> errors; 476 final List<AnalysisError> errors;
438 477
439 UnitAnalysisResult(this.file, this.unit, this.errors); 478 UnitAnalysisResult(this.file, this.unit, this.errors);
440 } 479 }
441 480
442 /** 481 /**
482 * [Node] that is used to compute constants in dependency order.
483 */
484 class _ConstantNode extends Node<_ConstantNode> {
485 final ConstantEvaluationEngine evaluationEngine;
486 final Map<ConstantEvaluationTarget, _ConstantNode> nodeMap;
487 final ConstantEvaluationTarget constant;
488
489 List<_ConstantNode> _dependencies = null;
490
491 bool isEvaluated = false;
492
493 _ConstantNode(this.evaluationEngine, this.nodeMap, this.constant);
494
495 @override
496 List<_ConstantNode> computeDependencies() {
497 if (_dependencies == null) {
498 List<ConstantEvaluationTarget> targets = [];
499 evaluationEngine.computeDependencies(constant, targets.add);
500 _dependencies = targets.map(_getNode).toList();
501 }
502 return _dependencies;
503 }
504
505 _ConstantNode _getNode(ConstantEvaluationTarget constant) {
506 return nodeMap.putIfAbsent(
507 constant, () => new _ConstantNode(evaluationEngine, nodeMap, constant));
508 }
509 }
510
511 /**
512 * [DependencyWalker] for computing constants and detecting cycles.
513 */
514 class _ConstantWalker extends DependencyWalker<_ConstantNode> {
515 final ConstantEvaluationEngine evaluationEngine;
516
517 _ConstantWalker(this.evaluationEngine);
518
519 @override
520 void evaluate(_ConstantNode node) {
521 evaluationEngine.computeConstantValue(node.constant);
522 node.isEvaluated = true;
523 }
524
525 @override
526 void evaluateScc(List<_ConstantNode> scc) {
527 var constantsInCycle = scc.map((node) => node.constant);
528 for (_ConstantNode node in scc) {
529 evaluationEngine.generateCycleError(constantsInCycle, node.constant);
530 node.isEvaluated = true;
531 }
532 }
533 }
534
535 /**
443 * [ContentCache] wrapper around [FileContentOverlay]. 536 * [ContentCache] wrapper around [FileContentOverlay].
444 */ 537 */
445 class _ContentCacheWrapper implements ContentCache { 538 class _ContentCacheWrapper implements ContentCache {
446 final FileSystemState fsState; 539 final FileSystemState fsState;
447 540
448 _ContentCacheWrapper(this.fsState); 541 _ContentCacheWrapper(this.fsState);
449 542
450 @override 543 @override
451 void accept(ContentCacheVisitor visitor) { 544 void accept(ContentCacheVisitor visitor) {
452 throw new UnimplementedError(); 545 throw new UnimplementedError();
(...skipping 17 matching lines...) Expand all
470 @override 563 @override
471 String setContents(Source source, String contents) { 564 String setContents(Source source, String contents) {
472 throw new UnimplementedError(); 565 throw new UnimplementedError();
473 } 566 }
474 567
475 FileState _getFileForSource(Source source) { 568 FileState _getFileForSource(Source source) {
476 String path = source.fullName; 569 String path = source.fullName;
477 return fsState.getFileForPath(path); 570 return fsState.getFileForPath(path);
478 } 571 }
479 } 572 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/dart/analysis/driver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698