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

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

Issue 2446083003: Verify one changed file at a time. (Closed)
Patch Set: Created 4 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | 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) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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:async';
6 import 'dart:collection'; 6 import 'dart:collection';
7 import 'dart:convert'; 7 import 'dart:convert';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 * [getResult] to the [Completer]s to report the result. 112 * [getResult] to the [Completer]s to report the result.
113 */ 113 */
114 final _requestedFiles = <String, List<Completer<AnalysisResult>>>{}; 114 final _requestedFiles = <String, List<Completer<AnalysisResult>>>{};
115 115
116 /** 116 /**
117 * The set of explicitly analyzed files. 117 * The set of explicitly analyzed files.
118 */ 118 */
119 final _explicitFiles = new LinkedHashSet<String>(); 119 final _explicitFiles = new LinkedHashSet<String>();
120 120
121 /** 121 /**
122 * The set of files were reported as changed through [changeFile] and for 122 * The set of files were reported as changed through [changeFile] and not
123 * which API signatures should be recomputed and compared before performing 123 * checked for actual changes yet.
124 * any other analysis.
125 */ 124 */
126 final _filesToVerifyUnlinkedSignature = new Set<String>(); 125 final _changedFiles = new LinkedHashSet<String>();
127 126
128 /** 127 /**
129 * The set of files that are currently scheduled for analysis. 128 * The set of files that are currently scheduled for analysis.
130 */ 129 */
131 final _filesToAnalyze = new LinkedHashSet<String>(); 130 final _filesToAnalyze = new LinkedHashSet<String>();
132 131
133 /** 132 /**
134 * Cache of URI resolution. The outer map key is the absolute URI of the 133 * Cache of URI resolution. The outer map key is the absolute URI of the
135 * containing file. The inner map key is the URI text of a directive 134 * containing file. The inner map key is the URI text of a directive
136 * contained in that file. The inner map value is the [Source] object which 135 * contained in that file. The inner map value is the [Source] object which
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 * More than one result might be produced for the same file, even if the 197 * More than one result might be produced for the same file, even if the
199 * client does not change the state of the files. 198 * client does not change the state of the files.
200 * 199 *
201 * Results might be produced even for files that have never been added 200 * Results might be produced even for files that have never been added
202 * using [addFile], for example when [getResult] was called for a file. 201 * using [addFile], for example when [getResult] was called for a file.
203 */ 202 */
204 Stream<AnalysisResult> get results async* { 203 Stream<AnalysisResult> get results async* {
205 try { 204 try {
206 PerformanceLogSection analysisSection = null; 205 PerformanceLogSection analysisSection = null;
207 while (true) { 206 while (true) {
208 // TODO(scheglov) implement state transitioning
209 await _hasWork.signal; 207 await _hasWork.signal;
210 208
209 // TODO(scheglov) implement state transitioning
211 if (analysisSection == null) { 210 if (analysisSection == null) {
212 analysisSection = _logger.enter('Analyzing'); 211 analysisSection = _logger.enter('Analyzing');
213 } 212 }
214 213
215 // TODO(scheglov) verify one file at a time 214 // Verify all changed files one at a time.
216 _verifyUnlinkedSignatureOfChangedFiles(); 215 if (_changedFiles.isNotEmpty) {
216 String path = _removeFirst(_changedFiles);
217 _verifyApiSignatureOfChangedFile(path);
218 // Repeat the processing loop.
219 _hasWork.notify();
220 continue;
221 }
217 222
218 // Analyze the first file in the general queue. 223 // Analyze the first file in the general queue.
219 if (_filesToAnalyze.isNotEmpty) { 224 if (_filesToAnalyze.isNotEmpty) {
220 String path = _filesToAnalyze.first; 225 String path = _removeFirst(_filesToAnalyze);
221 _filesToAnalyze.remove(path);
222 _File file = _fileForPath(path); 226 _File file = _fileForPath(path);
223 AnalysisResult result = _computeAnalysisResult(file); 227 AnalysisResult result = _computeAnalysisResult(file);
224 yield result; 228 yield result;
229 // Repeat the processing loop.
230 _hasWork.notify();
231 continue;
225 } 232 }
226 233
227 // If there is work to do, notify the monitor. 234 // There is nothing to do.
228 if (_filesToAnalyze.isNotEmpty) { 235 analysisSection.exit();
229 _hasWork.notify(); 236 analysisSection = null;
230 } else {
231 analysisSection.exit();
232 analysisSection = null;
233 }
234 } 237 }
235 // TODO(scheglov) implement 238 // TODO(scheglov) implement
236 } finally { 239 } finally {
237 print('The stream was cancelled.'); 240 print('The stream was cancelled.');
238 } 241 }
239 } 242 }
240 243
241 /** 244 /**
242 * Add the file with the given [path] to the set of files to analyze. 245 * Add the file with the given [path] to the set of files to analyze.
243 * 246 *
(...skipping 19 matching lines...) Expand all
263 * that state already). Schedules the file contents for [path] to be read 266 * that state already). Schedules the file contents for [path] to be read
264 * into the current file state prior to the next time the analysis state 267 * into the current file state prior to the next time the analysis state
265 * transitions to "idle". 268 * transitions to "idle".
266 * 269 *
267 * Invocation of this method will not prevent a [Future] returned from 270 * Invocation of this method will not prevent a [Future] returned from
268 * [getResult] from completing with a result, but the result is not 271 * [getResult] from completing with a result, but the result is not
269 * guaranteed to be consistent with the new current file state after this 272 * guaranteed to be consistent with the new current file state after this
270 * [changeFile] invocation. 273 * [changeFile] invocation.
271 */ 274 */
272 void changeFile(String path) { 275 void changeFile(String path) {
273 _filesToVerifyUnlinkedSignature.add(path); 276 _changedFiles.add(path);
274 _filesToAnalyze.add(path); 277 _filesToAnalyze.add(path);
275 _hasWork.notify(); 278 _hasWork.notify();
276 } 279 }
277 280
278 /** 281 /**
279 * Return the [Future] that completes with a [AnalysisResult] for the file 282 * Return the [Future] that completes with a [AnalysisResult] for the file
280 * with the given [path]. 283 * with the given [path].
281 * 284 *
282 * The [path] must be absolute and normalized. 285 * The [path] must be absolute and normalized.
283 * 286 *
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 * Return the [_File] for the given [path] in [_sourceFactory]. 513 * Return the [_File] for the given [path] in [_sourceFactory].
511 */ 514 */
512 _File _fileForPath(String path) { 515 _File _fileForPath(String path) {
513 Source fileSource = _resourceProvider.getFile(path).createSource(); 516 Source fileSource = _resourceProvider.getFile(path).createSource();
514 Uri uri = _sourceFactory.restoreUri(fileSource); 517 Uri uri = _sourceFactory.restoreUri(fileSource);
515 Source source = _resourceProvider.getFile(path).createSource(uri); 518 Source source = _resourceProvider.getFile(path).createSource(uri);
516 return new _File.forResolution(this, source); 519 return new _File.forResolution(this, source);
517 } 520 }
518 521
519 /** 522 /**
520 * Verify the API signatures for the changed files, and decide which linked 523 * Verify the API signature for the file with the given [path], and decide
521 * libraries should be invalidated, and files reanalyzed. 524 * which linked libraries should be invalidated, and files reanalyzed.
522 * 525 *
523 * TODO(scheglov) I see that adding a local var changes (full) API signature. 526 * TODO(scheglov) I see that adding a local var changes (full) API signature.
524 */ 527 */
525 void _verifyUnlinkedSignatureOfChangedFiles() { 528 void _verifyApiSignatureOfChangedFile(String path) {
526 if (_filesToVerifyUnlinkedSignature.isEmpty) { 529 _logger.run('Verify API signature of $path', () {
527 return; 530 String oldSignature = _fileApiSignatureMap[path];
528 } 531 // Compute the new API signature.
529 int numOfFiles = _filesToVerifyUnlinkedSignature.length; 532 // _File.forResolution() also updates the content hash in the cache.
530 _logger.run('Verify API signatures of $numOfFiles files', () { 533 _File newFile = _fileForPath(path);
531 bool hasMismatch = false; 534 String newSignature = newFile.unlinked.apiSignature;
532 for (String path in _filesToVerifyUnlinkedSignature) { 535 // If the old API signature is not null, then the file was used to
533 String oldSignature = _fileApiSignatureMap[path]; 536 // compute at least one dependency signature. If the new API signature
534 // Compute the new API signature. 537 // is different, then potentially all dependency signatures and
535 // _File.forResolution() also updates the content hash in the cache. 538 // resolution results are invalid.
536 _File newFile = _fileForPath(path); 539 if (oldSignature != null && oldSignature != newSignature) {
537 String newSignature = newFile.unlinked.apiSignature; 540 _logger.writeln('API signatures mismatch found for $newFile');
538 // If the old API signature is not null, then the file was used to
539 // compute at least one dependency signature. If the new API signature
540 // is different, then potentially all dependency signatures and
541 // resolution results are invalid.
542 if (oldSignature != null && oldSignature != newSignature) {
543 _logger.writeln('API signature mismatch found for $newFile.');
544 hasMismatch = true;
545 }
546 }
547 if (hasMismatch) {
548 _dependencySignatureMap.clear(); 541 _dependencySignatureMap.clear();
549 _filesToAnalyze.addAll(_explicitFiles); 542 _filesToAnalyze.addAll(_explicitFiles);
550 } else {
551 _logger.writeln('All API signatures match.');
552 } 543 }
553 _filesToVerifyUnlinkedSignature.clear();
554 }); 544 });
555 } 545 }
546
547 /**
548 * Remove and return the first item in the given [set].
549 */
550 static Object/*=T*/ _removeFirst/*<T>*/(LinkedHashSet<Object/*=T*/ > set) {
551 Object/*=T*/ element = set.first;
552 set.remove(element);
553 return element;
554 }
556 } 555 }
557 556
558 /** 557 /**
559 * The result of analyzing of a single file. 558 * The result of analyzing of a single file.
560 * 559 *
561 * These results are self-consistent, i.e. [content], [contentHash], the 560 * These results are self-consistent, i.e. [content], [contentHash], the
562 * resolved [unit] correspond to each other. All referenced elements, even 561 * resolved [unit] correspond to each other. All referenced elements, even
563 * external ones, are also self-consistent. But none of the results is 562 * external ones, are also self-consistent. But none of the results is
564 * guaranteed to be consistent with the state of the files. 563 * guaranteed to be consistent with the state of the files.
565 * 564 *
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 } 992 }
994 } 993 }
995 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { 994 for (UnlinkedExportPublic export in unit.publicNamespace.exports) {
996 referenced.exported.add(export.uri); 995 referenced.exported.add(export.uri);
997 } 996 }
998 return referenced; 997 return referenced;
999 } 998 }
1000 999
1001 _ReferencedUris._(); 1000 _ReferencedUris._();
1002 } 1001 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698