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

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

Issue 2818623003: Add a flag for caching all analysis results in the driver. (Closed)
Patch Set: Created 3 years, 8 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/base.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) 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:typed_data'; 7 import 'dart:typed_data';
8 8
9 import 'package:analyzer/context/context_root.dart'; 9 import 'package:analyzer/context/context_root.dart';
10 import 'package:analyzer/context/declared_variables.dart'; 10 import 'package:analyzer/context/declared_variables.dart';
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 Search _search; 231 Search _search;
232 232
233 AnalysisDriverTestView _testView; 233 AnalysisDriverTestView _testView;
234 234
235 /** 235 /**
236 * The [FileTracker] used by this driver. 236 * The [FileTracker] used by this driver.
237 */ 237 */
238 FileTracker _fileTracker; 238 FileTracker _fileTracker;
239 239
240 /** 240 /**
241 * When this flag is set to `true`, the set of analyzed files must not change,
242 * and all [AnalysisResult]s are cached infinitely.
243 *
244 * The flag is intended to be used for non-interactive clients, like DDC,
245 * which start a new analysis session, load a set of files, resolve all of
246 * them, process the resolved units, and then throw away that whole session.
247 *
248 * The key problem that this flag is solving is that the driver analyzes the
249 * whole library when the result for a unit of the library is requested. So,
250 * when the client requests sequentially the defining unit, then the first
251 * part, then the second part, the driver has to perform analysis of the
252 * library three times and every time throw away all the units except the one
253 * which was requested. With this flag set to `true`, the driver can analyze
254 * once and cache all the resolved units.
255 */
256 final bool disableChangesAndCacheAllResults;
257
258 /**
259 * The cache to use with [disableChangesAndCacheAllResults].
260 */
261 final Map<String, AnalysisResult> _allCachedResults = {};
262
263 /**
241 * Create a new instance of [AnalysisDriver]. 264 * Create a new instance of [AnalysisDriver].
242 * 265 *
243 * The given [SourceFactory] is cloned to ensure that it does not contain a 266 * The given [SourceFactory] is cloned to ensure that it does not contain a
244 * reference to a [AnalysisContext] in which it could have been used. 267 * reference to a [AnalysisContext] in which it could have been used.
245 */ 268 */
246 AnalysisDriver( 269 AnalysisDriver(
247 this._scheduler, 270 this._scheduler,
248 PerformanceLog logger, 271 PerformanceLog logger,
249 this._resourceProvider, 272 this._resourceProvider,
250 this._byteStore, 273 this._byteStore,
251 this._contentOverlay, 274 this._contentOverlay,
252 this.contextRoot, 275 this.contextRoot,
253 SourceFactory sourceFactory, 276 SourceFactory sourceFactory,
254 this._analysisOptions, 277 this._analysisOptions,
255 {PackageBundle sdkBundle}) 278 {PackageBundle sdkBundle,
279 this.disableChangesAndCacheAllResults: false})
256 : _logger = logger, 280 : _logger = logger,
257 _sourceFactory = sourceFactory.clone(), 281 _sourceFactory = sourceFactory.clone(),
258 _sdkBundle = sdkBundle { 282 _sdkBundle = sdkBundle {
259 _onResults = _resultController.stream.asBroadcastStream(); 283 _onResults = _resultController.stream.asBroadcastStream();
260 _testView = new AnalysisDriverTestView(this); 284 _testView = new AnalysisDriverTestView(this);
261 _createFileTracker(logger); 285 _createFileTracker(logger);
262 _scheduler.add(this); 286 _scheduler.add(this);
263 _search = new Search(this); 287 _search = new Search(this);
264 } 288 }
265 289
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 * that state already). Schedules the file contents for [path] to be read 476 * that state already). Schedules the file contents for [path] to be read
453 * into the current file state prior to the next time the analysis state 477 * into the current file state prior to the next time the analysis state
454 * transitions to "idle". 478 * transitions to "idle".
455 * 479 *
456 * Invocation of this method will not prevent a [Future] returned from 480 * Invocation of this method will not prevent a [Future] returned from
457 * [getResult] from completing with a result, but the result is not 481 * [getResult] from completing with a result, but the result is not
458 * guaranteed to be consistent with the new current file state after this 482 * guaranteed to be consistent with the new current file state after this
459 * [changeFile] invocation. 483 * [changeFile] invocation.
460 */ 484 */
461 void changeFile(String path) { 485 void changeFile(String path) {
486 _throwIfChangesAreNotAllowed();
462 _fileTracker.changeFile(path); 487 _fileTracker.changeFile(path);
463 _priorityResults.clear(); 488 _priorityResults.clear();
464 } 489 }
465 490
466 /** 491 /**
467 * Some state on which analysis depends has changed, so the driver needs to be 492 * Some state on which analysis depends has changed, so the driver needs to be
468 * re-configured with the new state. 493 * re-configured with the new state.
469 * 494 *
470 * At least one of the optional parameters should be provided, but only those 495 * At least one of the optional parameters should be provided, but only those
471 * that represent state that has actually changed need be provided. 496 * that represent state that has actually changed need be provided.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 * time the analysis state transitions to "idle". 609 * time the analysis state transitions to "idle".
585 */ 610 */
586 Future<AnalysisResult> getResult(String path) { 611 Future<AnalysisResult> getResult(String path) {
587 if (!_fileTracker.fsState.hasUri(path)) { 612 if (!_fileTracker.fsState.hasUri(path)) {
588 return new Future.value(); 613 return new Future.value();
589 } 614 }
590 615
591 // Return the cached result. 616 // Return the cached result.
592 { 617 {
593 AnalysisResult result = _priorityResults[path]; 618 AnalysisResult result = _priorityResults[path];
619 if (disableChangesAndCacheAllResults) {
620 result ??= _allCachedResults[path];
621 }
594 if (result != null) { 622 if (result != null) {
595 return new Future.value(result); 623 return new Future.value(result);
596 } 624 }
597 } 625 }
598 626
599 // Schedule analysis. 627 // Schedule analysis.
600 var completer = new Completer<AnalysisResult>(); 628 var completer = new Completer<AnalysisResult>();
601 _requestedFiles 629 _requestedFiles
602 .putIfAbsent(path, () => <Completer<AnalysisResult>>[]) 630 .putIfAbsent(path, () => <Completer<AnalysisResult>>[])
603 .add(completer); 631 .add(completer);
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 /** 908 /**
881 * Remove the file with the given [path] from the list of files to analyze. 909 * Remove the file with the given [path] from the list of files to analyze.
882 * 910 *
883 * The [path] must be absolute and normalized. 911 * The [path] must be absolute and normalized.
884 * 912 *
885 * The results of analysis of the file might still be produced by the 913 * The results of analysis of the file might still be produced by the
886 * [results] stream. The driver will try to stop producing these results, 914 * [results] stream. The driver will try to stop producing these results,
887 * but does not guarantee this. 915 * but does not guarantee this.
888 */ 916 */
889 void removeFile(String path) { 917 void removeFile(String path) {
918 _throwIfChangesAreNotAllowed();
890 _fileTracker.removeFile(path); 919 _fileTracker.removeFile(path);
891 _priorityResults.clear(); 920 _priorityResults.clear();
892 } 921 }
893 922
894 /** 923 /**
895 * Handles a notification from the [FileTracker] that there has been a change 924 * Handles a notification from the [FileTracker] that there has been a change
896 * of state. 925 * of state.
897 */ 926 */
898 void _changeHook() { 927 void _changeHook() {
899 _priorityResults.clear(); 928 _priorityResults.clear();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
949 if (bytes != null) { 978 if (bytes != null) {
950 return _getAnalysisResultFromBytes(file, signature, bytes); 979 return _getAnalysisResultFromBytes(file, signature, bytes);
951 } 980 }
952 } 981 }
953 982
954 // We need the fully resolved unit, or the result is not cached. 983 // We need the fully resolved unit, or the result is not cached.
955 return _logger.run('Compute analysis result for $path', () { 984 return _logger.run('Compute analysis result for $path', () {
956 try { 985 try {
957 LibraryContext libraryContext = _createLibraryContext(library); 986 LibraryContext libraryContext = _createLibraryContext(library);
958 try { 987 try {
988 _testView.numOfAnalyzedLibraries++;
959 LibraryAnalyzer analyzer = new LibraryAnalyzer( 989 LibraryAnalyzer analyzer = new LibraryAnalyzer(
960 analysisOptions, 990 analysisOptions,
961 declaredVariables, 991 declaredVariables,
962 sourceFactory, 992 sourceFactory,
963 _fileTracker.fsState, 993 _fileTracker.fsState,
964 libraryContext.store, 994 libraryContext.store,
965 library); 995 library);
966 Map<FileState, UnitAnalysisResult> results = analyzer.analyze(); 996 Map<FileState, UnitAnalysisResult> results = analyzer.analyze();
967 997
968 List<int> bytes; 998 List<int> bytes;
969 CompilationUnit resolvedUnit; 999 CompilationUnit resolvedUnit;
970 for (FileState unitFile in results.keys) { 1000 for (FileState unitFile in results.keys) {
971 UnitAnalysisResult unitResult = results[unitFile]; 1001 UnitAnalysisResult unitResult = results[unitFile];
972 List<int> unitBytes = 1002 List<int> unitBytes =
973 _serializeResolvedUnit(unitResult.unit, unitResult.errors); 1003 _serializeResolvedUnit(unitResult.unit, unitResult.errors);
974 String unitSignature = _getResolvedUnitSignature(library, unitFile); 1004 String unitSignature = _getResolvedUnitSignature(library, unitFile);
975 String unitKey = _getResolvedUnitKey(unitSignature); 1005 String unitKey = _getResolvedUnitKey(unitSignature);
976 _byteStore.put(unitKey, unitBytes); 1006 _byteStore.put(unitKey, unitBytes);
977 if (unitFile == file) { 1007 if (unitFile == file) {
978 bytes = unitBytes; 1008 bytes = unitBytes;
979 resolvedUnit = unitResult.unit; 1009 resolvedUnit = unitResult.unit;
980 } 1010 }
1011 if (disableChangesAndCacheAllResults) {
1012 AnalysisResult result = _getAnalysisResultFromBytes(
1013 unitFile, unitSignature, unitBytes,
1014 content: unitFile.content, resolvedUnit: unitResult.unit);
1015 _allCachedResults[unitFile.path] = result;
1016 }
981 } 1017 }
982 1018
983 // Return the result, full or partial. 1019 // Return the result, full or partial.
984 _logger.writeln('Computed new analysis result.'); 1020 _logger.writeln('Computed new analysis result.');
985 AnalysisResult result = _getAnalysisResultFromBytes( 1021 AnalysisResult result = _getAnalysisResultFromBytes(
986 file, signature, bytes, 1022 file, signature, bytes,
987 content: withUnit ? file.content : null, 1023 content: withUnit ? file.content : null,
988 resolvedUnit: withUnit ? resolvedUnit : null); 1024 resolvedUnit: withUnit ? resolvedUnit : null);
989 if (withUnit && _priorityFiles.contains(path)) { 1025 if (withUnit && _priorityFiles.contains(path)) {
990 _priorityResults[path] = result; 1026 _priorityResults[path] = result;
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1230 String key = 'exception_${time.year}$m$d' '_$h$min$sec' + '_$ms'; 1266 String key = 'exception_${time.year}$m$d' '_$h$min$sec' + '_$ms';
1231 1267
1232 _byteStore.put(key, bytes); 1268 _byteStore.put(key, bytes);
1233 return key; 1269 return key;
1234 } catch (_) { 1270 } catch (_) {
1235 return null; 1271 return null;
1236 } 1272 }
1237 } 1273 }
1238 1274
1239 /** 1275 /**
1276 * If the driver is used in the read-only mode with infinite cache,
1277 * we should not allow invocations that change files.
1278 */
1279 void _throwIfChangesAreNotAllowed() {
1280 if (disableChangesAndCacheAllResults) {
1281 throw new StateError('Changing files is not allowed for this driver.');
1282 }
1283 }
1284
1285 /**
1240 * Given the list of [errors] for the [file], update the [file]'s 1286 * Given the list of [errors] for the [file], update the [file]'s
1241 * [FileState.hasErrorOrWarning] flag. 1287 * [FileState.hasErrorOrWarning] flag.
1242 */ 1288 */
1243 void _updateHasErrorOrWarningFlag( 1289 void _updateHasErrorOrWarningFlag(
1244 FileState file, List<AnalysisError> errors) { 1290 FileState file, List<AnalysisError> errors) {
1245 for (AnalysisError error in errors) { 1291 for (AnalysisError error in errors) {
1246 ErrorSeverity severity = error.errorCode.errorSeverity; 1292 ErrorSeverity severity = error.errorCode.errorSeverity;
1247 if (severity == ErrorSeverity.ERROR || 1293 if (severity == ErrorSeverity.ERROR ||
1248 severity == ErrorSeverity.WARNING) { 1294 severity == ErrorSeverity.WARNING) {
1249 file.hasErrorOrWarning = true; 1295 file.hasErrorOrWarning = true;
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1471 return new Future.value(); 1517 return new Future.value();
1472 } 1518 }
1473 return new Future.delayed(Duration.ZERO, () => _pumpEventQueue(times - 1)); 1519 return new Future.delayed(Duration.ZERO, () => _pumpEventQueue(times - 1));
1474 } 1520 }
1475 } 1521 }
1476 1522
1477 @visibleForTesting 1523 @visibleForTesting
1478 class AnalysisDriverTestView { 1524 class AnalysisDriverTestView {
1479 final AnalysisDriver driver; 1525 final AnalysisDriver driver;
1480 1526
1527 int numOfAnalyzedLibraries = 0;
1528
1481 AnalysisDriverTestView(this.driver); 1529 AnalysisDriverTestView(this.driver);
1482 1530
1483 FileTracker get fileTracker => driver._fileTracker; 1531 FileTracker get fileTracker => driver._fileTracker;
1484 1532
1485 Map<String, AnalysisResult> get priorityResults => driver._priorityResults; 1533 Map<String, AnalysisResult> get priorityResults => driver._priorityResults;
1486 } 1534 }
1487 1535
1488 /** 1536 /**
1489 * The result of analyzing of a single file. 1537 * The result of analyzing of a single file.
1490 * 1538 *
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
2006 libraryDeclarations.add(new TopLevelDeclarationInSource( 2054 libraryDeclarations.add(new TopLevelDeclarationInSource(
2007 file.source, declaration, isExported)); 2055 file.source, declaration, isExported));
2008 } 2056 }
2009 } 2057 }
2010 } 2058 }
2011 2059
2012 // We're not done yet. 2060 // We're not done yet.
2013 return false; 2061 return false;
2014 } 2062 }
2015 } 2063 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/dart/analysis/base.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698