| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |