| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library analyzer.src.context.context; | 5 library analyzer.src.context.context; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:analyzer/src/cancelable_future.dart'; | 10 import 'package:analyzer/src/cancelable_future.dart'; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 import 'package:analyzer/src/generated/source.dart'; | 23 import 'package:analyzer/src/generated/source.dart'; |
| 24 import 'package:analyzer/src/generated/utilities_collection.dart'; | 24 import 'package:analyzer/src/generated/utilities_collection.dart'; |
| 25 import 'package:analyzer/src/task/dart.dart'; | 25 import 'package:analyzer/src/task/dart.dart'; |
| 26 import 'package:analyzer/src/task/driver.dart'; | 26 import 'package:analyzer/src/task/driver.dart'; |
| 27 import 'package:analyzer/src/task/manager.dart'; | 27 import 'package:analyzer/src/task/manager.dart'; |
| 28 import 'package:analyzer/task/dart.dart'; | 28 import 'package:analyzer/task/dart.dart'; |
| 29 import 'package:analyzer/task/general.dart'; | 29 import 'package:analyzer/task/general.dart'; |
| 30 import 'package:analyzer/task/model.dart'; | 30 import 'package:analyzer/task/model.dart'; |
| 31 | 31 |
| 32 /** | 32 /** |
| 33 * Type of callback functions used by PendingFuture. Functions of this type |
| 34 * should perform a computation based on the data in [entry] and return it. If |
| 35 * the computation can't be performed yet because more analysis is needed, |
| 36 * `null` should be returned. |
| 37 * |
| 38 * The function may also throw an exception, in which case the corresponding |
| 39 * future will be completed with failure. |
| 40 * |
| 41 * Because this function is called while the state of analysis is being updated, |
| 42 * it should be free of side effects so that it doesn't cause reentrant changes |
| 43 * to the analysis state. |
| 44 */ |
| 45 typedef T PendingFutureComputer<T>(cache.CacheEntry entry); |
| 46 |
| 47 /** |
| 33 * An [AnalysisContext] in which analysis can be performed. | 48 * An [AnalysisContext] in which analysis can be performed. |
| 34 */ | 49 */ |
| 35 class AnalysisContextImpl implements InternalAnalysisContext { | 50 class AnalysisContextImpl implements InternalAnalysisContext { |
| 36 /** | 51 /** |
| 37 * A client-provided name used to identify this context, or `null` if the | 52 * A client-provided name used to identify this context, or `null` if the |
| 38 * client has not provided a name. | 53 * client has not provided a name. |
| 39 */ | 54 */ |
| 40 String name; | 55 String name; |
| 41 | 56 |
| 42 /** | 57 /** |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 /** | 105 /** |
| 91 * A list containing sources for which data should not be flushed. | 106 * A list containing sources for which data should not be flushed. |
| 92 */ | 107 */ |
| 93 List<Source> _priorityOrder = Source.EMPTY_ARRAY; | 108 List<Source> _priorityOrder = Source.EMPTY_ARRAY; |
| 94 | 109 |
| 95 /** | 110 /** |
| 96 * A map from all sources for which there are futures pending to a list of | 111 * A map from all sources for which there are futures pending to a list of |
| 97 * the corresponding PendingFuture objects. These sources will be analyzed | 112 * the corresponding PendingFuture objects. These sources will be analyzed |
| 98 * in the same way as priority sources, except with higher priority. | 113 * in the same way as priority sources, except with higher priority. |
| 99 */ | 114 */ |
| 100 HashMap<Source, List<PendingFuture>> _pendingFutureSources = | 115 HashMap<AnalysisTarget, List<PendingFuture>> _pendingFutureTargets = |
| 101 new HashMap<Source, List<PendingFuture>>(); | 116 new HashMap<AnalysisTarget, List<PendingFuture>>(); |
| 102 | 117 |
| 103 /** | 118 /** |
| 104 * A table mapping sources to the change notices that are waiting to be | 119 * A table mapping sources to the change notices that are waiting to be |
| 105 * returned related to that source. | 120 * returned related to that source. |
| 106 */ | 121 */ |
| 107 HashMap<Source, ChangeNoticeImpl> _pendingNotices = | 122 HashMap<Source, ChangeNoticeImpl> _pendingNotices = |
| 108 new HashMap<Source, ChangeNoticeImpl>(); | 123 new HashMap<Source, ChangeNoticeImpl>(); |
| 109 | 124 |
| 110 /** | 125 /** |
| 111 * Cached information used in incremental analysis or `null` if none. | 126 * Cached information used in incremental analysis or `null` if none. |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 @override | 309 @override |
| 295 List<Source> get librarySources => _getSources(SourceKind.LIBRARY); | 310 List<Source> get librarySources => _getSources(SourceKind.LIBRARY); |
| 296 | 311 |
| 297 @override | 312 @override |
| 298 Stream<SourcesChangedEvent> get onSourcesChanged => | 313 Stream<SourcesChangedEvent> get onSourcesChanged => |
| 299 _onSourcesChangedController.stream; | 314 _onSourcesChangedController.stream; |
| 300 | 315 |
| 301 /** | 316 /** |
| 302 * Make _pendingFutureSources available to unit tests. | 317 * Make _pendingFutureSources available to unit tests. |
| 303 */ | 318 */ |
| 304 HashMap<Source, List<PendingFuture>> get pendingFutureSources_forTesting => | 319 HashMap<AnalysisTarget, List<PendingFuture>> get pendingFutureSources_forTesti
ng => |
| 305 _pendingFutureSources; | 320 _pendingFutureTargets; |
| 306 | 321 |
| 307 @override | 322 @override |
| 308 List<Source> get prioritySources => _priorityOrder; | 323 List<Source> get prioritySources => _priorityOrder; |
| 309 | 324 |
| 310 @override | 325 @override |
| 311 List<AnalysisTarget> get priorityTargets => prioritySources; | 326 List<AnalysisTarget> get priorityTargets => prioritySources; |
| 312 | 327 |
| 313 @override | 328 @override |
| 314 SourceFactory get sourceFactory => _sourceFactory; | 329 SourceFactory get sourceFactory => _sourceFactory; |
| 315 | 330 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 return _typeProvider; | 425 return _typeProvider; |
| 411 } | 426 } |
| 412 | 427 |
| 413 /** | 428 /** |
| 414 * Sets the [TypeProvider] for this context. | 429 * Sets the [TypeProvider] for this context. |
| 415 */ | 430 */ |
| 416 void set typeProvider(TypeProvider typeProvider) { | 431 void set typeProvider(TypeProvider typeProvider) { |
| 417 _typeProvider = typeProvider; | 432 _typeProvider = typeProvider; |
| 418 } | 433 } |
| 419 | 434 |
| 420 /** | |
| 421 * Return `true` if the (new) task model should be used to perform analysis. | |
| 422 */ | |
| 423 bool get useTaskModel => AnalysisEngine.instance.useTaskModel; | |
| 424 | |
| 425 @override | 435 @override |
| 426 void addListener(AnalysisListener listener) { | 436 void addListener(AnalysisListener listener) { |
| 427 if (!_listeners.contains(listener)) { | 437 if (!_listeners.contains(listener)) { |
| 428 _listeners.add(listener); | 438 _listeners.add(listener); |
| 429 } | 439 } |
| 430 } | 440 } |
| 431 | 441 |
| 432 @override | 442 @override |
| 433 void addSourceInfo(Source source, SourceEntry info) { | 443 void addSourceInfo(Source source, SourceEntry info) { |
| 434 // TODO(brianwilkerson) This method needs to be replaced by something that | 444 // TODO(brianwilkerson) This method needs to be replaced by something that |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 | 569 |
| 560 @override | 570 @override |
| 561 @deprecated | 571 @deprecated |
| 562 CompilationUnit computeResolvableCompilationUnit(Source source) { | 572 CompilationUnit computeResolvableCompilationUnit(Source source) { |
| 563 return null; | 573 return null; |
| 564 } | 574 } |
| 565 | 575 |
| 566 @override | 576 @override |
| 567 CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync( | 577 CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync( |
| 568 Source unitSource, Source librarySource) { | 578 Source unitSource, Source librarySource) { |
| 569 // TODO(brianwilkerson) Implement this. | 579 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || |
| 570 return new CancelableFuture<CompilationUnit>(() => null); | 580 !AnalysisEngine.isDartFileName(librarySource.shortName)) { |
| 571 // return new _AnalysisFutureHelper<CompilationUnit>(this).computeAsync( | 581 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
| 572 // unitSource, (SourceEntry sourceEntry) { | 582 } |
| 573 // if (sourceEntry is DartEntry) { | 583 return new _AnalysisFutureHelper<CompilationUnit>(this).computeAsync( |
| 574 // if (sourceEntry.getStateInLibrary( | 584 new LibrarySpecificUnit(librarySource, unitSource), |
| 575 // DartEntry.RESOLVED_UNIT, librarySource) == | 585 (cache.CacheEntry entry) { |
| 576 // CacheState.ERROR) { | 586 CacheState state = entry.getState(RESOLVED_UNIT); |
| 577 // throw sourceEntry.exception; | 587 if (state == CacheState.ERROR) { |
| 578 // } | 588 throw entry.exception; |
| 579 // return sourceEntry.getValueInLibrary( | 589 } else if (state == CacheState.INVALID) { |
| 580 // DartEntry.RESOLVED_UNIT, librarySource); | 590 return null; |
| 581 // } | 591 } |
| 582 // throw new AnalysisNotScheduledError(); | 592 return entry.getValue(RESOLVED_UNIT); |
| 583 // }); | 593 }); |
| 584 } | 594 } |
| 585 | 595 |
| 586 /** | 596 /** |
| 587 * Create an analysis cache based on the given source [factory]. | 597 * Create an analysis cache based on the given source [factory]. |
| 588 */ | 598 */ |
| 589 cache.AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { | 599 cache.AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { |
| 590 if (factory == null) { | 600 if (factory == null) { |
| 591 return new cache.AnalysisCache(<cache.CachePartition>[_privatePartition]); | 601 return new cache.AnalysisCache(<cache.CachePartition>[_privatePartition]); |
| 592 } | 602 } |
| 593 DartSdk sdk = factory.dartSdk; | 603 DartSdk sdk = factory.dartSdk; |
| 594 if (sdk == null) { | 604 if (sdk == null) { |
| 595 return new cache.AnalysisCache(<cache.CachePartition>[_privatePartition]); | 605 return new cache.AnalysisCache(<cache.CachePartition>[_privatePartition]); |
| 596 } | 606 } |
| 597 return new cache.AnalysisCache(<cache.CachePartition>[ | 607 return new cache.AnalysisCache(<cache.CachePartition>[ |
| 598 AnalysisEngine.instance.partitionManager_new.forSdk(sdk), | 608 AnalysisEngine.instance.partitionManager_new.forSdk(sdk), |
| 599 _privatePartition | 609 _privatePartition |
| 600 ]); | 610 ]); |
| 601 } | 611 } |
| 602 | 612 |
| 603 @override | 613 @override |
| 604 void dispose() { | 614 void dispose() { |
| 605 _disposed = true; | 615 _disposed = true; |
| 606 for (List<PendingFuture> pendingFutures in _pendingFutureSources.values) { | 616 for (List<PendingFuture> pendingFutures in _pendingFutureTargets.values) { |
| 607 for (PendingFuture pendingFuture in pendingFutures) { | 617 for (PendingFuture pendingFuture in pendingFutures) { |
| 608 pendingFuture.forciblyComplete(); | 618 pendingFuture.forciblyComplete(); |
| 609 } | 619 } |
| 610 } | 620 } |
| 611 _pendingFutureSources.clear(); | 621 _pendingFutureTargets.clear(); |
| 612 } | 622 } |
| 613 | 623 |
| 614 @override | 624 @override |
| 615 List<CompilationUnit> ensureResolvedDartUnits(Source unitSource) { | 625 List<CompilationUnit> ensureResolvedDartUnits(Source unitSource) { |
| 616 // TODO(brianwilkerson) Implement this. | 626 // TODO(brianwilkerson) Implement this. |
| 617 return null; | 627 return null; |
| 618 // cache.CacheEntry entry = _cache.get(unitSource); | 628 // cache.CacheEntry entry = _cache.get(unitSource); |
| 619 // // Check every library. | 629 // // Check every library. |
| 620 // List<CompilationUnit> units = <CompilationUnit>[]; | 630 // List<CompilationUnit> units = <CompilationUnit>[]; |
| 621 // List<Source> containingLibraries = entry.containingLibraries; | 631 // List<Source> containingLibraries = entry.containingLibraries; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 } | 749 } |
| 740 } catch (exception) { | 750 } catch (exception) { |
| 741 // If the location cannot be decoded for some reason then the underlying | 751 // If the location cannot be decoded for some reason then the underlying |
| 742 // cause should have been logged already and we can fall though to return | 752 // cause should have been logged already and we can fall though to return |
| 743 // null. | 753 // null. |
| 744 } | 754 } |
| 745 return null; | 755 return null; |
| 746 } | 756 } |
| 747 | 757 |
| 748 @override | 758 @override |
| 749 AnalysisErrorInfo getErrors(Source source) => _getResult(source, DART_ERRORS); | 759 AnalysisErrorInfo getErrors(Source source) { |
| 760 List<AnalysisError> errors = _getResult(source, DART_ERRORS); |
| 761 LineInfo lineInfo = _getResult(source, LINE_INFO); |
| 762 return new AnalysisErrorInfoImpl(errors, lineInfo); |
| 763 } |
| 750 | 764 |
| 751 @override | 765 @override |
| 752 HtmlElement getHtmlElement(Source source) { | 766 HtmlElement getHtmlElement(Source source) { |
| 753 // TODO(brianwilkerson) Implement this. | 767 // TODO(brianwilkerson) Implement this. |
| 754 // SourceEntry sourceEntry = getReadableSourceEntryOrNull(source); | 768 // SourceEntry sourceEntry = getReadableSourceEntryOrNull(source); |
| 755 // if (sourceEntry is HtmlEntry) { | 769 // if (sourceEntry is HtmlEntry) { |
| 756 // return sourceEntry.getValue(HtmlEntry.ELEMENT); | 770 // return sourceEntry.getValue(HtmlEntry.ELEMENT); |
| 757 // } | 771 // } |
| 758 return null; | 772 return null; |
| 759 } | 773 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 /** | 893 /** |
| 880 * Return the cache entry associated with the given [source], or `null` if | 894 * Return the cache entry associated with the given [source], or `null` if |
| 881 * there is no entry associated with the source. | 895 * there is no entry associated with the source. |
| 882 */ | 896 */ |
| 883 cache.CacheEntry getReadableSourceEntryOrNull(Source source) => | 897 cache.CacheEntry getReadableSourceEntryOrNull(Source source) => |
| 884 _cache.get(source); | 898 _cache.get(source); |
| 885 | 899 |
| 886 @override | 900 @override |
| 887 CompilationUnit getResolvedCompilationUnit( | 901 CompilationUnit getResolvedCompilationUnit( |
| 888 Source unitSource, LibraryElement library) { | 902 Source unitSource, LibraryElement library) { |
| 889 if (library == null) { | 903 if (library == null || |
| 904 !AnalysisEngine.isDartFileName(unitSource.shortName)) { |
| 890 return null; | 905 return null; |
| 891 } | 906 } |
| 892 return getResolvedCompilationUnit2(unitSource, library.source); | 907 return getResolvedCompilationUnit2(unitSource, library.source); |
| 893 } | 908 } |
| 894 | 909 |
| 895 @override | 910 @override |
| 896 CompilationUnit getResolvedCompilationUnit2( | 911 CompilationUnit getResolvedCompilationUnit2( |
| 897 Source unitSource, Source librarySource) => _getResult( | 912 Source unitSource, Source librarySource) { |
| 898 new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT); | 913 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || |
| 914 !AnalysisEngine.isDartFileName(librarySource.shortName)) { |
| 915 return null; |
| 916 } |
| 917 return _getResult( |
| 918 new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT); |
| 919 } |
| 899 | 920 |
| 900 @override | 921 @override |
| 901 ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) { | 922 ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) { |
| 902 // TODO(brianwilkerson) Implement this. | 923 // TODO(brianwilkerson) Implement this. |
| 903 // SourceEntry sourceEntry = getReadableSourceEntryOrNull(htmlSource); | 924 // SourceEntry sourceEntry = getReadableSourceEntryOrNull(htmlSource); |
| 904 // if (sourceEntry is HtmlEntry) { | 925 // if (sourceEntry is HtmlEntry) { |
| 905 // HtmlEntry htmlEntry = sourceEntry; | 926 // HtmlEntry htmlEntry = sourceEntry; |
| 906 // return htmlEntry.getValue(HtmlEntry.RESOLVED_UNIT); | 927 // return htmlEntry.getValue(HtmlEntry.RESOLVED_UNIT); |
| 907 // } | 928 // } |
| 908 return null; | 929 return null; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1105 CompilationUnit resolveCompilationUnit( | 1126 CompilationUnit resolveCompilationUnit( |
| 1106 Source unitSource, LibraryElement library) { | 1127 Source unitSource, LibraryElement library) { |
| 1107 if (library == null) { | 1128 if (library == null) { |
| 1108 return null; | 1129 return null; |
| 1109 } | 1130 } |
| 1110 return resolveCompilationUnit2(unitSource, library.source); | 1131 return resolveCompilationUnit2(unitSource, library.source); |
| 1111 } | 1132 } |
| 1112 | 1133 |
| 1113 @override | 1134 @override |
| 1114 CompilationUnit resolveCompilationUnit2( | 1135 CompilationUnit resolveCompilationUnit2( |
| 1115 Source unitSource, Source librarySource) => _computeResult( | 1136 Source unitSource, Source librarySource) { |
| 1116 new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT); | 1137 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || |
| 1138 !AnalysisEngine.isDartFileName(librarySource.shortName)) { |
| 1139 return null; |
| 1140 } |
| 1141 return _computeResult( |
| 1142 new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT); |
| 1143 } |
| 1117 | 1144 |
| 1118 @override | 1145 @override |
| 1119 ht.HtmlUnit resolveHtmlUnit(Source htmlSource) { | 1146 ht.HtmlUnit resolveHtmlUnit(Source htmlSource) { |
| 1120 computeHtmlElement(htmlSource); | 1147 computeHtmlElement(htmlSource); |
| 1121 return parseHtmlUnit(htmlSource); | 1148 return parseHtmlUnit(htmlSource); |
| 1122 } | 1149 } |
| 1123 | 1150 |
| 1124 @override | 1151 @override |
| 1125 void setChangedContents(Source source, String contents, int offset, | 1152 void setChangedContents(Source source, String contents, int offset, |
| 1126 int oldLength, int newLength) { | 1153 int oldLength, int newLength) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1138 @override | 1165 @override |
| 1139 void visitCacheItems(void callback(Source source, SourceEntry dartEntry, | 1166 void visitCacheItems(void callback(Source source, SourceEntry dartEntry, |
| 1140 DataDescriptor rowDesc, CacheState state)) { | 1167 DataDescriptor rowDesc, CacheState state)) { |
| 1141 // TODO(brianwilkerson) Figure out where this is used and adjust the call | 1168 // TODO(brianwilkerson) Figure out where this is used and adjust the call |
| 1142 // sites to use CacheEntry's. | 1169 // sites to use CacheEntry's. |
| 1143 // bool hintsEnabled = _options.hint; | 1170 // bool hintsEnabled = _options.hint; |
| 1144 // bool lintsEnabled = _options.lint; | 1171 // bool lintsEnabled = _options.lint; |
| 1145 // MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator()
; | 1172 // MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator()
; |
| 1146 // while (iterator.moveNext()) { | 1173 // while (iterator.moveNext()) { |
| 1147 // Source source = iterator.key; | 1174 // Source source = iterator.key; |
| 1148 // cache.CacheEntry sourceEntry = iterator.value; | 1175 // cache.CacheEntry entry = iterator.value; |
| 1149 // for (DataDescriptor descriptor in sourceEntry.descriptors) { | 1176 // for (DataDescriptor descriptor in entry.descriptors) { |
| 1150 // if (descriptor == DartEntry.SOURCE_KIND) { | 1177 // if (descriptor == DartEntry.SOURCE_KIND) { |
| 1151 // // The source kind is always valid, so the state isn't interesting. | 1178 // // The source kind is always valid, so the state isn't interesting. |
| 1152 // continue; | 1179 // continue; |
| 1153 // } else if (descriptor == DartEntry.CONTAINING_LIBRARIES) { | 1180 // } else if (descriptor == DartEntry.CONTAINING_LIBRARIES) { |
| 1154 // // The list of containing libraries is always valid, so the state | 1181 // // The list of containing libraries is always valid, so the state |
| 1155 // // isn't interesting. | 1182 // // isn't interesting. |
| 1156 // continue; | 1183 // continue; |
| 1157 // } else if (descriptor == DartEntry.PUBLIC_NAMESPACE) { | 1184 // } else if (descriptor == DartEntry.PUBLIC_NAMESPACE) { |
| 1158 // // The public namespace isn't computed by performAnalysisTask() | 1185 // // The public namespace isn't computed by performAnalysisTask() |
| 1159 // // and therefore isn't interesting. | 1186 // // and therefore isn't interesting. |
| 1160 // continue; | 1187 // continue; |
| 1161 // } else if (descriptor == HtmlEntry.HINTS) { | 1188 // } else if (descriptor == HtmlEntry.HINTS) { |
| 1162 // // We are not currently recording any hints related to HTML. | 1189 // // We are not currently recording any hints related to HTML. |
| 1163 // continue; | 1190 // continue; |
| 1164 // } | 1191 // } |
| 1165 // callback( | 1192 // callback( |
| 1166 // source, sourceEntry, descriptor, sourceEntry.getState(descriptor))
; | 1193 // source, entry, descriptor, entry.getState(descriptor)); |
| 1167 // } | 1194 // } |
| 1168 // if (sourceEntry is DartEntry) { | 1195 // if (entry is DartEntry) { |
| 1169 // // get library-specific values | 1196 // // get library-specific values |
| 1170 // List<Source> librarySources = getLibrariesContaining(source); | 1197 // List<Source> librarySources = getLibrariesContaining(source); |
| 1171 // for (Source librarySource in librarySources) { | 1198 // for (Source librarySource in librarySources) { |
| 1172 // for (DataDescriptor descriptor in sourceEntry.libraryDescriptors) { | 1199 // for (DataDescriptor descriptor in entry.libraryDescriptors) { |
| 1173 // if (descriptor == DartEntry.BUILT_ELEMENT || | 1200 // if (descriptor == DartEntry.BUILT_ELEMENT || |
| 1174 // descriptor == DartEntry.BUILT_UNIT) { | 1201 // descriptor == DartEntry.BUILT_UNIT) { |
| 1175 // // These values are not currently being computed, so their state | 1202 // // These values are not currently being computed, so their state |
| 1176 // // is not interesting. | 1203 // // is not interesting. |
| 1177 // continue; | 1204 // continue; |
| 1178 // } else if (!sourceEntry.explicitlyAdded && | 1205 // } else if (!entry.explicitlyAdded && |
| 1179 // !_generateImplicitErrors && | 1206 // !_generateImplicitErrors && |
| 1180 // (descriptor == DartEntry.VERIFICATION_ERRORS || | 1207 // (descriptor == DartEntry.VERIFICATION_ERRORS || |
| 1181 // descriptor == DartEntry.HINTS || | 1208 // descriptor == DartEntry.HINTS || |
| 1182 // descriptor == DartEntry.LINTS)) { | 1209 // descriptor == DartEntry.LINTS)) { |
| 1183 // continue; | 1210 // continue; |
| 1184 // } else if (source.isInSystemLibrary && | 1211 // } else if (source.isInSystemLibrary && |
| 1185 // !_generateSdkErrors && | 1212 // !_generateSdkErrors && |
| 1186 // (descriptor == DartEntry.VERIFICATION_ERRORS || | 1213 // (descriptor == DartEntry.VERIFICATION_ERRORS || |
| 1187 // descriptor == DartEntry.HINTS || | 1214 // descriptor == DartEntry.HINTS || |
| 1188 // descriptor == DartEntry.LINTS)) { | 1215 // descriptor == DartEntry.LINTS)) { |
| 1189 // continue; | 1216 // continue; |
| 1190 // } else if (!hintsEnabled && descriptor == DartEntry.HINTS) { | 1217 // } else if (!hintsEnabled && descriptor == DartEntry.HINTS) { |
| 1191 // continue; | 1218 // continue; |
| 1192 // } else if (!lintsEnabled && descriptor == DartEntry.LINTS) { | 1219 // } else if (!lintsEnabled && descriptor == DartEntry.LINTS) { |
| 1193 // continue; | 1220 // continue; |
| 1194 // } | 1221 // } |
| 1195 // callback(librarySource, sourceEntry, descriptor, | 1222 // callback(librarySource, entry, descriptor, |
| 1196 // sourceEntry.getStateInLibrary(descriptor, librarySource)); | 1223 // entry.getStateInLibrary(descriptor, librarySource)); |
| 1197 // } | 1224 // } |
| 1198 // } | 1225 // } |
| 1199 // } | 1226 // } |
| 1200 // } | 1227 // } |
| 1201 } | 1228 } |
| 1202 | 1229 |
| 1203 /** | 1230 /** |
| 1204 * Visit all entries of the content cache. | 1231 * Visit all entries of the content cache. |
| 1205 */ | 1232 */ |
| 1206 void visitContentCache(ContentCacheVisitor visitor) { | 1233 void visitContentCache(ContentCacheVisitor visitor) { |
| 1207 _contentCache.accept(visitor); | 1234 _contentCache.accept(visitor); |
| 1208 } | 1235 } |
| 1209 | 1236 |
| 1210 /** | 1237 /** |
| 1211 * Add all of the sources contained in the given source [container] to the | 1238 * Add all of the sources contained in the given source [container] to the |
| 1212 * given list of [sources]. | 1239 * given list of [sources]. |
| 1213 */ | 1240 */ |
| 1214 void _addSourcesInContainer(List<Source> sources, SourceContainer container) { | 1241 void _addSourcesInContainer(List<Source> sources, SourceContainer container) { |
| 1215 MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator(); | 1242 MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator(); |
| 1216 while (iterator.moveNext()) { | 1243 while (iterator.moveNext()) { |
| 1217 Source source = iterator.key; | 1244 Source source = iterator.key; |
| 1218 if (container.contains(source)) { | 1245 if (container.contains(source)) { |
| 1219 sources.add(source); | 1246 sources.add(source); |
| 1220 } | 1247 } |
| 1221 } | 1248 } |
| 1222 } | 1249 } |
| 1223 | 1250 |
| 1224 /** | 1251 /** |
| 1252 * Remove the given [pendingFuture] from [_pendingFutureTargets], since the |
| 1253 * client has indicated its computation is not needed anymore. |
| 1254 */ |
| 1255 void _cancelFuture(PendingFuture pendingFuture) { |
| 1256 List<PendingFuture> pendingFutures = |
| 1257 _pendingFutureTargets[pendingFuture.target]; |
| 1258 if (pendingFutures != null) { |
| 1259 pendingFutures.remove(pendingFuture); |
| 1260 if (pendingFutures.isEmpty) { |
| 1261 _pendingFutureTargets.remove(pendingFuture.target); |
| 1262 } |
| 1263 } |
| 1264 } |
| 1265 |
| 1266 /** |
| 1225 * Return the priority that should be used when the source associated with | 1267 * Return the priority that should be used when the source associated with |
| 1226 * the given [entry] is added to the work manager. | 1268 * the given [entry] is added to the work manager. |
| 1227 */ | 1269 */ |
| 1228 SourcePriority _computePriority(cache.CacheEntry entry) { | 1270 SourcePriority _computePriority(cache.CacheEntry entry) { |
| 1229 // Used in commented out code. | 1271 // Used in commented out code. |
| 1230 SourceKind kind = entry.getValue(SOURCE_KIND); | 1272 SourceKind kind = entry.getValue(SOURCE_KIND); |
| 1231 if (kind == SourceKind.LIBRARY) { | 1273 if (kind == SourceKind.LIBRARY) { |
| 1232 return SourcePriority.LIBRARY; | 1274 return SourcePriority.LIBRARY; |
| 1233 } else if (kind == SourceKind.PART) { | 1275 } else if (kind == SourceKind.PART) { |
| 1234 return SourcePriority.NORMAL_PART; | 1276 return SourcePriority.NORMAL_PART; |
| 1235 } | 1277 } |
| 1236 return SourcePriority.UNKNOWN; | 1278 return SourcePriority.UNKNOWN; |
| 1237 } | 1279 } |
| 1238 | 1280 |
| 1239 Object /*V*/ _computeResult( | 1281 Object /*V*/ _computeResult( |
| 1240 AnalysisTarget target, ResultDescriptor /*<V>*/ descriptor) { | 1282 AnalysisTarget target, ResultDescriptor /*<V>*/ descriptor) { |
| 1241 cache.CacheEntry entry = _cache.get(target); | 1283 cache.CacheEntry entry = getCacheEntry(target); |
| 1242 if (entry == null) { | |
| 1243 return descriptor.defaultValue; | |
| 1244 } | |
| 1245 if (descriptor is CompositeResultDescriptor) { | 1284 if (descriptor is CompositeResultDescriptor) { |
| 1246 List compositeResults = []; | 1285 List compositeResults = []; |
| 1247 for (ResultDescriptor descriptor in descriptor.contributors) { | 1286 for (ResultDescriptor descriptor in descriptor.contributors) { |
| 1248 List value = _computeResult(target, descriptor); | 1287 List value = _computeResult(target, descriptor); |
| 1249 compositeResults.addAll(value); | 1288 compositeResults.addAll(value); |
| 1250 } | 1289 } |
| 1251 return compositeResults; | 1290 return compositeResults; |
| 1252 } | 1291 } |
| 1253 CacheState state = entry.getState(descriptor); | 1292 CacheState state = entry.getState(descriptor); |
| 1254 if (state == CacheState.FLUSHED || state == CacheState.INVALID) { | 1293 if (state == CacheState.FLUSHED || state == CacheState.INVALID) { |
| 1255 _driver.computeResult(target, descriptor); | 1294 _driver.computeResult(target, descriptor); |
| 1256 } | 1295 } |
| 1296 state = entry.getState(descriptor); |
| 1297 if (state == CacheState.ERROR) { |
| 1298 throw new AnalysisException( |
| 1299 'Cannot compute $descriptor for $target', entry.exception); |
| 1300 } |
| 1257 return entry.getValue(descriptor); | 1301 return entry.getValue(descriptor); |
| 1258 } | 1302 } |
| 1259 | 1303 |
| 1260 /** | 1304 /** |
| 1261 * Given the encoded form of a source ([encoding]), use the source factory to | 1305 * Given the encoded form of a source ([encoding]), use the source factory to |
| 1262 * reconstitute the original source. | 1306 * reconstitute the original source. |
| 1263 */ | 1307 */ |
| 1264 Source _computeSourceFromEncoding(String encoding) => | 1308 Source _computeSourceFromEncoding(String encoding) => |
| 1265 _sourceFactory.fromEncoding(encoding); | 1309 _sourceFactory.fromEncoding(encoding); |
| 1266 | 1310 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1377 ChangeNoticeImpl notice = _pendingNotices[source]; | 1421 ChangeNoticeImpl notice = _pendingNotices[source]; |
| 1378 if (notice == null) { | 1422 if (notice == null) { |
| 1379 notice = new ChangeNoticeImpl(source); | 1423 notice = new ChangeNoticeImpl(source); |
| 1380 _pendingNotices[source] = notice; | 1424 _pendingNotices[source] = notice; |
| 1381 } | 1425 } |
| 1382 return notice; | 1426 return notice; |
| 1383 } | 1427 } |
| 1384 | 1428 |
| 1385 Object _getResult(AnalysisTarget target, ResultDescriptor descriptor) { | 1429 Object _getResult(AnalysisTarget target, ResultDescriptor descriptor) { |
| 1386 cache.CacheEntry entry = _cache.get(target); | 1430 cache.CacheEntry entry = _cache.get(target); |
| 1387 if (entry != null && entry.isValid(descriptor)) { | 1431 if (entry == null) { |
| 1432 return descriptor.defaultValue; |
| 1433 } |
| 1434 if (descriptor is CompositeResultDescriptor) { |
| 1435 List compositeResults = []; |
| 1436 for (ResultDescriptor descriptor in descriptor.contributors) { |
| 1437 List value = _getResult(target, descriptor); |
| 1438 compositeResults.addAll(value); |
| 1439 } |
| 1440 return compositeResults; |
| 1441 } |
| 1442 if (entry.isValid(descriptor)) { |
| 1388 return entry.getValue(descriptor); | 1443 return entry.getValue(descriptor); |
| 1389 } | 1444 } |
| 1390 return descriptor.defaultValue; | 1445 return descriptor.defaultValue; |
| 1391 } | 1446 } |
| 1392 | 1447 |
| 1393 /** | 1448 /** |
| 1394 * Return a list containing all of the sources known to this context that have | 1449 * Return a list containing all of the sources known to this context that have |
| 1395 * the given [kind]. | 1450 * the given [kind]. |
| 1396 */ | 1451 */ |
| 1397 List<Source> _getSources(SourceKind kind) { | 1452 List<Source> _getSources(SourceKind kind) { |
| 1398 List<Source> sources = new List<Source>(); | 1453 List<Source> sources = new List<Source>(); |
| 1399 MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator(); | 1454 MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator(); |
| 1400 while (iterator.moveNext()) { | 1455 while (iterator.moveNext()) { |
| 1401 if (iterator.value.getValue(SOURCE_KIND) == kind && | 1456 if (iterator.value.getValue(SOURCE_KIND) == kind && |
| 1402 iterator.key is Source) { | 1457 iterator.key is Source) { |
| 1403 sources.add(iterator.key); | 1458 sources.add(iterator.key); |
| 1404 } | 1459 } |
| 1405 } | 1460 } |
| 1406 return sources; | 1461 return sources; |
| 1407 } | 1462 } |
| 1408 | 1463 |
| 1409 /** | 1464 /** |
| 1410 * Look at the given [source] to see whether a task needs to be performed | 1465 * Look at the given [source] to see whether a task needs to be performed |
| 1411 * related to it. If so, add the source to the set of sources that need to be | 1466 * related to it. If so, add the source to the set of sources that need to be |
| 1412 * processed. This method is intended to be used for testing purposes only. | 1467 * processed. This method is intended to be used for testing purposes only. |
| 1413 */ | 1468 */ |
| 1414 void _getSourcesNeedingProcessing(Source source, cache.CacheEntry sourceEntry, | 1469 void _getSourcesNeedingProcessing(Source source, cache.CacheEntry entry, |
| 1415 bool isPriority, bool hintsEnabled, bool lintsEnabled, | 1470 bool isPriority, bool hintsEnabled, bool lintsEnabled, |
| 1416 HashSet<Source> sources) { | 1471 HashSet<Source> sources) { |
| 1417 CacheState state = sourceEntry.getState(CONTENT); | 1472 CacheState state = entry.getState(CONTENT); |
| 1418 if (state == CacheState.INVALID || | 1473 if (state == CacheState.INVALID || |
| 1419 (isPriority && state == CacheState.FLUSHED)) { | 1474 (isPriority && state == CacheState.FLUSHED)) { |
| 1420 sources.add(source); | 1475 sources.add(source); |
| 1421 return; | 1476 return; |
| 1422 } else if (state == CacheState.ERROR) { | 1477 } else if (state == CacheState.ERROR) { |
| 1423 return; | 1478 return; |
| 1424 } | 1479 } |
| 1425 state = sourceEntry.getState(SOURCE_KIND); | 1480 state = entry.getState(SOURCE_KIND); |
| 1426 if (state == CacheState.INVALID || | 1481 if (state == CacheState.INVALID || |
| 1427 (isPriority && state == CacheState.FLUSHED)) { | 1482 (isPriority && state == CacheState.FLUSHED)) { |
| 1428 sources.add(source); | 1483 sources.add(source); |
| 1429 return; | 1484 return; |
| 1430 } else if (state == CacheState.ERROR) { | 1485 } else if (state == CacheState.ERROR) { |
| 1431 return; | 1486 return; |
| 1432 } | 1487 } |
| 1433 SourceKind kind = sourceEntry.getValue(SOURCE_KIND); | 1488 SourceKind kind = entry.getValue(SOURCE_KIND); |
| 1434 if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) { | 1489 if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) { |
| 1435 state = sourceEntry.getState(SCAN_ERRORS); | 1490 state = entry.getState(SCAN_ERRORS); |
| 1436 if (state == CacheState.INVALID || | 1491 if (state == CacheState.INVALID || |
| 1437 (isPriority && state == CacheState.FLUSHED)) { | 1492 (isPriority && state == CacheState.FLUSHED)) { |
| 1438 sources.add(source); | 1493 sources.add(source); |
| 1439 return; | 1494 return; |
| 1440 } else if (state == CacheState.ERROR) { | 1495 } else if (state == CacheState.ERROR) { |
| 1441 return; | 1496 return; |
| 1442 } | 1497 } |
| 1443 state = sourceEntry.getState(PARSE_ERRORS); | 1498 state = entry.getState(PARSE_ERRORS); |
| 1444 if (state == CacheState.INVALID || | 1499 if (state == CacheState.INVALID || |
| 1445 (isPriority && state == CacheState.FLUSHED)) { | 1500 (isPriority && state == CacheState.FLUSHED)) { |
| 1446 sources.add(source); | 1501 sources.add(source); |
| 1447 return; | 1502 return; |
| 1448 } else if (state == CacheState.ERROR) { | 1503 } else if (state == CacheState.ERROR) { |
| 1449 return; | 1504 return; |
| 1450 } | 1505 } |
| 1451 // if (isPriority) { | 1506 // if (isPriority) { |
| 1452 // if (!sourceEntry.hasResolvableCompilationUnit) { | 1507 // if (!entry.hasResolvableCompilationUnit) { |
| 1453 // sources.add(source); | 1508 // sources.add(source); |
| 1454 // return; | 1509 // return; |
| 1455 // } | 1510 // } |
| 1456 // } | 1511 // } |
| 1457 for (Source librarySource in getLibrariesContaining(source)) { | 1512 for (Source librarySource in getLibrariesContaining(source)) { |
| 1458 cache.CacheEntry libraryEntry = _cache.get(librarySource); | 1513 cache.CacheEntry libraryEntry = _cache.get(librarySource); |
| 1459 state = libraryEntry.getState(LIBRARY_ELEMENT); | 1514 state = libraryEntry.getState(LIBRARY_ELEMENT); |
| 1460 if (state == CacheState.INVALID || | 1515 if (state == CacheState.INVALID || |
| 1461 (isPriority && state == CacheState.FLUSHED)) { | 1516 (isPriority && state == CacheState.FLUSHED)) { |
| 1462 sources.add(source); | 1517 sources.add(source); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 // (isPriority && state == CacheState.FLUSHED)) { | 1554 // (isPriority && state == CacheState.FLUSHED)) { |
| 1500 // sources.add(source); | 1555 // sources.add(source); |
| 1501 // return; | 1556 // return; |
| 1502 // } else if (state == CacheState.ERROR) { | 1557 // } else if (state == CacheState.ERROR) { |
| 1503 // return; | 1558 // return; |
| 1504 // } | 1559 // } |
| 1505 // } | 1560 // } |
| 1506 } | 1561 } |
| 1507 } | 1562 } |
| 1508 // } else if (kind == SourceKind.HTML) { | 1563 // } else if (kind == SourceKind.HTML) { |
| 1509 // CacheState parsedUnitState = sourceEntry.getState(HtmlEntry.PARSED_UNIT)
; | 1564 // CacheState parsedUnitState = entry.getState(HtmlEntry.PARSED_UNIT); |
| 1510 // if (parsedUnitState == CacheState.INVALID || | 1565 // if (parsedUnitState == CacheState.INVALID || |
| 1511 // (isPriority && parsedUnitState == CacheState.FLUSHED)) { | 1566 // (isPriority && parsedUnitState == CacheState.FLUSHED)) { |
| 1512 // sources.add(source); | 1567 // sources.add(source); |
| 1513 // return; | 1568 // return; |
| 1514 // } | 1569 // } |
| 1515 // CacheState resolvedUnitState = | 1570 // CacheState resolvedUnitState = |
| 1516 // sourceEntry.getState(HtmlEntry.RESOLVED_UNIT); | 1571 // entry.getState(HtmlEntry.RESOLVED_UNIT); |
| 1517 // if (resolvedUnitState == CacheState.INVALID || | 1572 // if (resolvedUnitState == CacheState.INVALID || |
| 1518 // (isPriority && resolvedUnitState == CacheState.FLUSHED)) { | 1573 // (isPriority && resolvedUnitState == CacheState.FLUSHED)) { |
| 1519 // sources.add(source); | 1574 // sources.add(source); |
| 1520 // return; | 1575 // return; |
| 1521 // } | 1576 // } |
| 1522 } | 1577 } |
| 1523 } | 1578 } |
| 1524 | 1579 |
| 1525 /** | 1580 /** |
| 1526 * Invalidate all of the resolution results computed by this context. The flag | 1581 * Invalidate all of the resolution results computed by this context. The flag |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1952 // Check cache for an existing partition. | 2007 // Check cache for an existing partition. |
| 1953 cache.SdkCachePartition partition = _sdkPartitions[sdk]; | 2008 cache.SdkCachePartition partition = _sdkPartitions[sdk]; |
| 1954 if (partition == null) { | 2009 if (partition == null) { |
| 1955 partition = | 2010 partition = |
| 1956 new cache.SdkCachePartition(sdkContext, _DEFAULT_SDK_CACHE_SIZE); | 2011 new cache.SdkCachePartition(sdkContext, _DEFAULT_SDK_CACHE_SIZE); |
| 1957 _sdkPartitions[sdk] = partition; | 2012 _sdkPartitions[sdk] = partition; |
| 1958 } | 2013 } |
| 1959 return partition; | 2014 return partition; |
| 1960 } | 2015 } |
| 1961 } | 2016 } |
| 2017 |
| 2018 /** |
| 2019 * Representation of a pending computation which is based on the results of |
| 2020 * analysis that may or may not have been completed. |
| 2021 */ |
| 2022 class PendingFuture<T> { |
| 2023 /** |
| 2024 * The context in which this computation runs. |
| 2025 */ |
| 2026 final AnalysisContextImpl _context; |
| 2027 |
| 2028 /** |
| 2029 * The target used by this computation to compute its value. |
| 2030 */ |
| 2031 final AnalysisTarget target; |
| 2032 |
| 2033 /** |
| 2034 * The function which implements the computation. |
| 2035 */ |
| 2036 final PendingFutureComputer<T> _computeValue; |
| 2037 |
| 2038 /** |
| 2039 * The completer that should be completed once the computation has succeeded. |
| 2040 */ |
| 2041 CancelableCompleter<T> _completer; |
| 2042 |
| 2043 PendingFuture(this._context, this.target, this._computeValue) { |
| 2044 _completer = new CancelableCompleter<T>(_onCancel); |
| 2045 } |
| 2046 |
| 2047 /** |
| 2048 * Retrieve the future which will be completed when this object is |
| 2049 * successfully evaluated. |
| 2050 */ |
| 2051 CancelableFuture<T> get future => _completer.future; |
| 2052 |
| 2053 /** |
| 2054 * Execute [_computeValue], passing it the given [entry], and complete |
| 2055 * the pending future if it's appropriate to do so. If the pending future is |
| 2056 * completed by this call, true is returned; otherwise false is returned. |
| 2057 * |
| 2058 * Once this function has returned true, it should not be called again. |
| 2059 * |
| 2060 * Other than completing the future, this method is free of side effects. |
| 2061 * Note that any code the client has attached to the future will be executed |
| 2062 * in a microtask, so there is no danger of side effects occurring due to |
| 2063 * client callbacks. |
| 2064 */ |
| 2065 bool evaluate(cache.CacheEntry entry) { |
| 2066 assert(!_completer.isCompleted); |
| 2067 try { |
| 2068 T result = _computeValue(entry); |
| 2069 if (result == null) { |
| 2070 return false; |
| 2071 } else { |
| 2072 _completer.complete(result); |
| 2073 return true; |
| 2074 } |
| 2075 } catch (exception, stackTrace) { |
| 2076 _completer.completeError(exception, stackTrace); |
| 2077 return true; |
| 2078 } |
| 2079 } |
| 2080 |
| 2081 /** |
| 2082 * No further analysis updates are expected which affect this future, so |
| 2083 * complete it with an AnalysisNotScheduledError in order to avoid |
| 2084 * deadlocking the client. |
| 2085 */ |
| 2086 void forciblyComplete() { |
| 2087 try { |
| 2088 throw new AnalysisNotScheduledError(); |
| 2089 } catch (exception, stackTrace) { |
| 2090 _completer.completeError(exception, stackTrace); |
| 2091 } |
| 2092 } |
| 2093 |
| 2094 void _onCancel() { |
| 2095 _context._cancelFuture(this); |
| 2096 } |
| 2097 } |
| 2098 |
| 2099 /** |
| 2100 * A helper class used to create futures for AnalysisContextImpl. Using a helper |
| 2101 * class allows us to preserve the generic parameter T. |
| 2102 */ |
| 2103 class _AnalysisFutureHelper<T> { |
| 2104 final AnalysisContextImpl _context; |
| 2105 |
| 2106 _AnalysisFutureHelper(this._context); |
| 2107 |
| 2108 /** |
| 2109 * Return a future that will be completed with the result of calling |
| 2110 * [computeValue]. If [computeValue] returns non-`null`, the future will be |
| 2111 * completed immediately with the resulting value. If it returns `null`, then |
| 2112 * it will be re-executed in the future, after the next time the cached |
| 2113 * information for [target] has changed. If [computeValue] throws an |
| 2114 * exception, the future will fail with that exception. |
| 2115 * |
| 2116 * If the [computeValue] still returns `null` after there is no further |
| 2117 * analysis to be done for [target], then the future will be completed with |
| 2118 * the error AnalysisNotScheduledError. |
| 2119 * |
| 2120 * Since [computeValue] will be called while the state of analysis is being |
| 2121 * updated, it should be free of side effects so that it doesn't cause |
| 2122 * reentrant changes to the analysis state. |
| 2123 */ |
| 2124 CancelableFuture<T> computeAsync( |
| 2125 AnalysisTarget target, T computeValue(cache.CacheEntry entry)) { |
| 2126 if (_context.isDisposed) { |
| 2127 // No further analysis is expected, so return a future that completes |
| 2128 // immediately with AnalysisNotScheduledError. |
| 2129 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
| 2130 } |
| 2131 cache.CacheEntry entry = _context.getReadableSourceEntryOrNull(target); |
| 2132 if (entry == null) { |
| 2133 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
| 2134 } |
| 2135 PendingFuture pendingFuture = |
| 2136 new PendingFuture<T>(_context, target, computeValue); |
| 2137 if (!pendingFuture.evaluate(entry)) { |
| 2138 _context._pendingFutureTargets |
| 2139 .putIfAbsent(target, () => <PendingFuture>[]) |
| 2140 .add(pendingFuture); |
| 2141 } |
| 2142 return pendingFuture.future; |
| 2143 } |
| 2144 } |
| OLD | NEW |