Chromium Code Reviews| 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 90 /** | 90 /** |
| 91 * A list containing sources for which data should not be flushed. | 91 * A list containing sources for which data should not be flushed. |
| 92 */ | 92 */ |
| 93 List<Source> _priorityOrder = Source.EMPTY_ARRAY; | 93 List<Source> _priorityOrder = Source.EMPTY_ARRAY; |
| 94 | 94 |
| 95 /** | 95 /** |
| 96 * A map from all sources for which there are futures pending to a list of | 96 * 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 | 97 * the corresponding PendingFuture objects. These sources will be analyzed |
| 98 * in the same way as priority sources, except with higher priority. | 98 * in the same way as priority sources, except with higher priority. |
| 99 */ | 99 */ |
| 100 HashMap<Source, List<PendingFuture>> _pendingFutureSources = | 100 HashMap<AnalysisTarget, List<PendingFuture>> _pendingFutureSources = |
|
scheglov
2015/05/02 16:35:48
Rename it?
Brian Wilkerson
2015/05/03 15:05:39
Done, thanks!
| |
| 101 new HashMap<Source, List<PendingFuture>>(); | 101 new HashMap<AnalysisTarget, List<PendingFuture>>(); |
| 102 | 102 |
| 103 /** | 103 /** |
| 104 * A table mapping sources to the change notices that are waiting to be | 104 * A table mapping sources to the change notices that are waiting to be |
| 105 * returned related to that source. | 105 * returned related to that source. |
| 106 */ | 106 */ |
| 107 HashMap<Source, ChangeNoticeImpl> _pendingNotices = | 107 HashMap<Source, ChangeNoticeImpl> _pendingNotices = |
| 108 new HashMap<Source, ChangeNoticeImpl>(); | 108 new HashMap<Source, ChangeNoticeImpl>(); |
| 109 | 109 |
| 110 /** | 110 /** |
| 111 * Cached information used in incremental analysis or `null` if none. | 111 * 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 | 294 @override |
| 295 List<Source> get librarySources => _getSources(SourceKind.LIBRARY); | 295 List<Source> get librarySources => _getSources(SourceKind.LIBRARY); |
| 296 | 296 |
| 297 @override | 297 @override |
| 298 Stream<SourcesChangedEvent> get onSourcesChanged => | 298 Stream<SourcesChangedEvent> get onSourcesChanged => |
| 299 _onSourcesChangedController.stream; | 299 _onSourcesChangedController.stream; |
| 300 | 300 |
| 301 /** | 301 /** |
| 302 * Make _pendingFutureSources available to unit tests. | 302 * Make _pendingFutureSources available to unit tests. |
| 303 */ | 303 */ |
| 304 HashMap<Source, List<PendingFuture>> get pendingFutureSources_forTesting => | 304 HashMap<AnalysisTarget, List<PendingFuture>> get pendingFutureSources_forTesti ng => |
| 305 _pendingFutureSources; | 305 _pendingFutureSources; |
| 306 | 306 |
| 307 @override | 307 @override |
| 308 List<Source> get prioritySources => _priorityOrder; | 308 List<Source> get prioritySources => _priorityOrder; |
| 309 | 309 |
| 310 @override | 310 @override |
| 311 List<AnalysisTarget> get priorityTargets => prioritySources; | 311 List<AnalysisTarget> get priorityTargets => prioritySources; |
| 312 | 312 |
| 313 @override | 313 @override |
| 314 SourceFactory get sourceFactory => _sourceFactory; | 314 SourceFactory get sourceFactory => _sourceFactory; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 return _typeProvider; | 410 return _typeProvider; |
| 411 } | 411 } |
| 412 | 412 |
| 413 /** | 413 /** |
| 414 * Sets the [TypeProvider] for this context. | 414 * Sets the [TypeProvider] for this context. |
| 415 */ | 415 */ |
| 416 void set typeProvider(TypeProvider typeProvider) { | 416 void set typeProvider(TypeProvider typeProvider) { |
| 417 _typeProvider = typeProvider; | 417 _typeProvider = typeProvider; |
| 418 } | 418 } |
| 419 | 419 |
| 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 | 420 @override |
| 426 void addListener(AnalysisListener listener) { | 421 void addListener(AnalysisListener listener) { |
| 427 if (!_listeners.contains(listener)) { | 422 if (!_listeners.contains(listener)) { |
| 428 _listeners.add(listener); | 423 _listeners.add(listener); |
| 429 } | 424 } |
| 430 } | 425 } |
| 431 | 426 |
| 432 @override | 427 @override |
| 433 void addSourceInfo(Source source, SourceEntry info) { | 428 void addSourceInfo(Source source, SourceEntry info) { |
| 434 // TODO(brianwilkerson) This method needs to be replaced by something that | 429 // 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 | 554 |
| 560 @override | 555 @override |
| 561 @deprecated | 556 @deprecated |
| 562 CompilationUnit computeResolvableCompilationUnit(Source source) { | 557 CompilationUnit computeResolvableCompilationUnit(Source source) { |
| 563 return null; | 558 return null; |
| 564 } | 559 } |
| 565 | 560 |
| 566 @override | 561 @override |
| 567 CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync( | 562 CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync( |
| 568 Source unitSource, Source librarySource) { | 563 Source unitSource, Source librarySource) { |
| 569 // TODO(brianwilkerson) Implement this. | 564 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || |
| 570 return new CancelableFuture<CompilationUnit>(() => null); | 565 !AnalysisEngine.isDartFileName(librarySource.shortName)) { |
| 571 // return new _AnalysisFutureHelper<CompilationUnit>(this).computeAsync( | 566 return new CancelableFuture.error(new AnalysisNotScheduledError()); |
| 572 // unitSource, (SourceEntry sourceEntry) { | 567 } |
| 573 // if (sourceEntry is DartEntry) { | 568 return new _AnalysisFutureHelper<CompilationUnit>(this).computeAsync( |
| 574 // if (sourceEntry.getStateInLibrary( | 569 new LibrarySpecificUnit(librarySource, unitSource), (cache.CacheEntry en try) { |
| 575 // DartEntry.RESOLVED_UNIT, librarySource) == | 570 CacheState state = entry.getState(RESOLVED_UNIT); |
| 576 // CacheState.ERROR) { | 571 if (state == CacheState.ERROR) { |
| 577 // throw sourceEntry.exception; | 572 throw entry.exception; |
| 578 // } | 573 } else if (state == CacheState.INVALID) { |
| 579 // return sourceEntry.getValueInLibrary( | 574 return null; |
| 580 // DartEntry.RESOLVED_UNIT, librarySource); | 575 } |
| 581 // } | 576 return entry.getValue(RESOLVED_UNIT); |
| 582 // throw new AnalysisNotScheduledError(); | 577 }); |
| 583 // }); | |
| 584 } | 578 } |
| 585 | 579 |
| 586 /** | 580 /** |
| 587 * Create an analysis cache based on the given source [factory]. | 581 * Create an analysis cache based on the given source [factory]. |
| 588 */ | 582 */ |
| 589 cache.AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { | 583 cache.AnalysisCache createCacheFromSourceFactory(SourceFactory factory) { |
| 590 if (factory == null) { | 584 if (factory == null) { |
| 591 return new cache.AnalysisCache(<cache.CachePartition>[_privatePartition]); | 585 return new cache.AnalysisCache(<cache.CachePartition>[_privatePartition]); |
| 592 } | 586 } |
| 593 DartSdk sdk = factory.dartSdk; | 587 DartSdk sdk = factory.dartSdk; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 739 } | 733 } |
| 740 } catch (exception) { | 734 } catch (exception) { |
| 741 // If the location cannot be decoded for some reason then the underlying | 735 // 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 | 736 // cause should have been logged already and we can fall though to return |
| 743 // null. | 737 // null. |
| 744 } | 738 } |
| 745 return null; | 739 return null; |
| 746 } | 740 } |
| 747 | 741 |
| 748 @override | 742 @override |
| 749 AnalysisErrorInfo getErrors(Source source) => _getResult(source, DART_ERRORS); | 743 AnalysisErrorInfo getErrors(Source source) { |
| 744 List<AnalysisError> errors = _getResult(source, DART_ERRORS); | |
| 745 LineInfo lineInfo = _getResult(source, LINE_INFO); | |
| 746 return new AnalysisErrorInfoImpl(errors, lineInfo); | |
| 747 } | |
| 750 | 748 |
| 751 @override | 749 @override |
| 752 HtmlElement getHtmlElement(Source source) { | 750 HtmlElement getHtmlElement(Source source) { |
| 753 // TODO(brianwilkerson) Implement this. | 751 // TODO(brianwilkerson) Implement this. |
| 754 // SourceEntry sourceEntry = getReadableSourceEntryOrNull(source); | 752 // SourceEntry sourceEntry = getReadableSourceEntryOrNull(source); |
| 755 // if (sourceEntry is HtmlEntry) { | 753 // if (sourceEntry is HtmlEntry) { |
| 756 // return sourceEntry.getValue(HtmlEntry.ELEMENT); | 754 // return sourceEntry.getValue(HtmlEntry.ELEMENT); |
| 757 // } | 755 // } |
| 758 return null; | 756 return null; |
| 759 } | 757 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 879 /** | 877 /** |
| 880 * Return the cache entry associated with the given [source], or `null` if | 878 * Return the cache entry associated with the given [source], or `null` if |
| 881 * there is no entry associated with the source. | 879 * there is no entry associated with the source. |
| 882 */ | 880 */ |
| 883 cache.CacheEntry getReadableSourceEntryOrNull(Source source) => | 881 cache.CacheEntry getReadableSourceEntryOrNull(Source source) => |
| 884 _cache.get(source); | 882 _cache.get(source); |
| 885 | 883 |
| 886 @override | 884 @override |
| 887 CompilationUnit getResolvedCompilationUnit( | 885 CompilationUnit getResolvedCompilationUnit( |
| 888 Source unitSource, LibraryElement library) { | 886 Source unitSource, LibraryElement library) { |
| 889 if (library == null) { | 887 if (library == null || !AnalysisEngine.isDartFileName(unitSource.shortName)) { |
| 890 return null; | 888 return null; |
| 891 } | 889 } |
| 892 return getResolvedCompilationUnit2(unitSource, library.source); | 890 return getResolvedCompilationUnit2(unitSource, library.source); |
| 893 } | 891 } |
| 894 | 892 |
| 895 @override | 893 @override |
| 896 CompilationUnit getResolvedCompilationUnit2( | 894 CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source libraryS ource) { |
| 897 Source unitSource, Source librarySource) => _getResult( | 895 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || !AnalysisEngine. isDartFileName(librarySource.shortName)) { |
| 896 return null; | |
| 897 } | |
| 898 return _getResult( | |
| 898 new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT); | 899 new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT); |
| 900 } | |
| 899 | 901 |
| 900 @override | 902 @override |
| 901 ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) { | 903 ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) { |
| 902 // TODO(brianwilkerson) Implement this. | 904 // TODO(brianwilkerson) Implement this. |
| 903 // SourceEntry sourceEntry = getReadableSourceEntryOrNull(htmlSource); | 905 // SourceEntry sourceEntry = getReadableSourceEntryOrNull(htmlSource); |
| 904 // if (sourceEntry is HtmlEntry) { | 906 // if (sourceEntry is HtmlEntry) { |
| 905 // HtmlEntry htmlEntry = sourceEntry; | 907 // HtmlEntry htmlEntry = sourceEntry; |
| 906 // return htmlEntry.getValue(HtmlEntry.RESOLVED_UNIT); | 908 // return htmlEntry.getValue(HtmlEntry.RESOLVED_UNIT); |
| 907 // } | 909 // } |
| 908 return null; | 910 return null; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1105 CompilationUnit resolveCompilationUnit( | 1107 CompilationUnit resolveCompilationUnit( |
| 1106 Source unitSource, LibraryElement library) { | 1108 Source unitSource, LibraryElement library) { |
| 1107 if (library == null) { | 1109 if (library == null) { |
| 1108 return null; | 1110 return null; |
| 1109 } | 1111 } |
| 1110 return resolveCompilationUnit2(unitSource, library.source); | 1112 return resolveCompilationUnit2(unitSource, library.source); |
| 1111 } | 1113 } |
| 1112 | 1114 |
| 1113 @override | 1115 @override |
| 1114 CompilationUnit resolveCompilationUnit2( | 1116 CompilationUnit resolveCompilationUnit2( |
| 1115 Source unitSource, Source librarySource) => _computeResult( | 1117 Source unitSource, Source librarySource) { |
| 1118 if (!AnalysisEngine.isDartFileName(unitSource.shortName) || !AnalysisEngine. isDartFileName(librarySource.shortName)) { | |
| 1119 return null; | |
| 1120 } | |
| 1121 return _computeResult( | |
| 1116 new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT); | 1122 new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT); |
| 1123 } | |
| 1117 | 1124 |
| 1118 @override | 1125 @override |
| 1119 ht.HtmlUnit resolveHtmlUnit(Source htmlSource) { | 1126 ht.HtmlUnit resolveHtmlUnit(Source htmlSource) { |
| 1120 computeHtmlElement(htmlSource); | 1127 computeHtmlElement(htmlSource); |
| 1121 return parseHtmlUnit(htmlSource); | 1128 return parseHtmlUnit(htmlSource); |
| 1122 } | 1129 } |
| 1123 | 1130 |
| 1124 @override | 1131 @override |
| 1125 void setChangedContents(Source source, String contents, int offset, | 1132 void setChangedContents(Source source, String contents, int offset, |
| 1126 int oldLength, int newLength) { | 1133 int oldLength, int newLength) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1138 @override | 1145 @override |
| 1139 void visitCacheItems(void callback(Source source, SourceEntry dartEntry, | 1146 void visitCacheItems(void callback(Source source, SourceEntry dartEntry, |
| 1140 DataDescriptor rowDesc, CacheState state)) { | 1147 DataDescriptor rowDesc, CacheState state)) { |
| 1141 // TODO(brianwilkerson) Figure out where this is used and adjust the call | 1148 // TODO(brianwilkerson) Figure out where this is used and adjust the call |
| 1142 // sites to use CacheEntry's. | 1149 // sites to use CacheEntry's. |
| 1143 // bool hintsEnabled = _options.hint; | 1150 // bool hintsEnabled = _options.hint; |
| 1144 // bool lintsEnabled = _options.lint; | 1151 // bool lintsEnabled = _options.lint; |
| 1145 // MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator() ; | 1152 // MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator() ; |
| 1146 // while (iterator.moveNext()) { | 1153 // while (iterator.moveNext()) { |
| 1147 // Source source = iterator.key; | 1154 // Source source = iterator.key; |
| 1148 // cache.CacheEntry sourceEntry = iterator.value; | 1155 // cache.CacheEntry entry = iterator.value; |
| 1149 // for (DataDescriptor descriptor in sourceEntry.descriptors) { | 1156 // for (DataDescriptor descriptor in entry.descriptors) { |
| 1150 // if (descriptor == DartEntry.SOURCE_KIND) { | 1157 // if (descriptor == DartEntry.SOURCE_KIND) { |
| 1151 // // The source kind is always valid, so the state isn't interesting. | 1158 // // The source kind is always valid, so the state isn't interesting. |
| 1152 // continue; | 1159 // continue; |
| 1153 // } else if (descriptor == DartEntry.CONTAINING_LIBRARIES) { | 1160 // } else if (descriptor == DartEntry.CONTAINING_LIBRARIES) { |
| 1154 // // The list of containing libraries is always valid, so the state | 1161 // // The list of containing libraries is always valid, so the state |
| 1155 // // isn't interesting. | 1162 // // isn't interesting. |
| 1156 // continue; | 1163 // continue; |
| 1157 // } else if (descriptor == DartEntry.PUBLIC_NAMESPACE) { | 1164 // } else if (descriptor == DartEntry.PUBLIC_NAMESPACE) { |
| 1158 // // The public namespace isn't computed by performAnalysisTask() | 1165 // // The public namespace isn't computed by performAnalysisTask() |
| 1159 // // and therefore isn't interesting. | 1166 // // and therefore isn't interesting. |
| 1160 // continue; | 1167 // continue; |
| 1161 // } else if (descriptor == HtmlEntry.HINTS) { | 1168 // } else if (descriptor == HtmlEntry.HINTS) { |
| 1162 // // We are not currently recording any hints related to HTML. | 1169 // // We are not currently recording any hints related to HTML. |
| 1163 // continue; | 1170 // continue; |
| 1164 // } | 1171 // } |
| 1165 // callback( | 1172 // callback( |
| 1166 // source, sourceEntry, descriptor, sourceEntry.getState(descriptor)) ; | 1173 // source, entry, descriptor, entry.getState(descriptor)); |
| 1167 // } | 1174 // } |
| 1168 // if (sourceEntry is DartEntry) { | 1175 // if (entry is DartEntry) { |
| 1169 // // get library-specific values | 1176 // // get library-specific values |
| 1170 // List<Source> librarySources = getLibrariesContaining(source); | 1177 // List<Source> librarySources = getLibrariesContaining(source); |
| 1171 // for (Source librarySource in librarySources) { | 1178 // for (Source librarySource in librarySources) { |
| 1172 // for (DataDescriptor descriptor in sourceEntry.libraryDescriptors) { | 1179 // for (DataDescriptor descriptor in entry.libraryDescriptors) { |
| 1173 // if (descriptor == DartEntry.BUILT_ELEMENT || | 1180 // if (descriptor == DartEntry.BUILT_ELEMENT || |
| 1174 // descriptor == DartEntry.BUILT_UNIT) { | 1181 // descriptor == DartEntry.BUILT_UNIT) { |
| 1175 // // These values are not currently being computed, so their state | 1182 // // These values are not currently being computed, so their state |
| 1176 // // is not interesting. | 1183 // // is not interesting. |
| 1177 // continue; | 1184 // continue; |
| 1178 // } else if (!sourceEntry.explicitlyAdded && | 1185 // } else if (!entry.explicitlyAdded && |
| 1179 // !_generateImplicitErrors && | 1186 // !_generateImplicitErrors && |
| 1180 // (descriptor == DartEntry.VERIFICATION_ERRORS || | 1187 // (descriptor == DartEntry.VERIFICATION_ERRORS || |
| 1181 // descriptor == DartEntry.HINTS || | 1188 // descriptor == DartEntry.HINTS || |
| 1182 // descriptor == DartEntry.LINTS)) { | 1189 // descriptor == DartEntry.LINTS)) { |
| 1183 // continue; | 1190 // continue; |
| 1184 // } else if (source.isInSystemLibrary && | 1191 // } else if (source.isInSystemLibrary && |
| 1185 // !_generateSdkErrors && | 1192 // !_generateSdkErrors && |
| 1186 // (descriptor == DartEntry.VERIFICATION_ERRORS || | 1193 // (descriptor == DartEntry.VERIFICATION_ERRORS || |
| 1187 // descriptor == DartEntry.HINTS || | 1194 // descriptor == DartEntry.HINTS || |
| 1188 // descriptor == DartEntry.LINTS)) { | 1195 // descriptor == DartEntry.LINTS)) { |
| 1189 // continue; | 1196 // continue; |
| 1190 // } else if (!hintsEnabled && descriptor == DartEntry.HINTS) { | 1197 // } else if (!hintsEnabled && descriptor == DartEntry.HINTS) { |
| 1191 // continue; | 1198 // continue; |
| 1192 // } else if (!lintsEnabled && descriptor == DartEntry.LINTS) { | 1199 // } else if (!lintsEnabled && descriptor == DartEntry.LINTS) { |
| 1193 // continue; | 1200 // continue; |
| 1194 // } | 1201 // } |
| 1195 // callback(librarySource, sourceEntry, descriptor, | 1202 // callback(librarySource, entry, descriptor, |
| 1196 // sourceEntry.getStateInLibrary(descriptor, librarySource)); | 1203 // entry.getStateInLibrary(descriptor, librarySource)); |
| 1197 // } | 1204 // } |
| 1198 // } | 1205 // } |
| 1199 // } | 1206 // } |
| 1200 // } | 1207 // } |
| 1201 } | 1208 } |
| 1202 | 1209 |
| 1203 /** | 1210 /** |
| 1204 * Visit all entries of the content cache. | 1211 * Visit all entries of the content cache. |
| 1205 */ | 1212 */ |
| 1206 void visitContentCache(ContentCacheVisitor visitor) { | 1213 void visitContentCache(ContentCacheVisitor visitor) { |
| 1207 _contentCache.accept(visitor); | 1214 _contentCache.accept(visitor); |
| 1208 } | 1215 } |
| 1209 | 1216 |
| 1210 /** | 1217 /** |
| 1211 * Add all of the sources contained in the given source [container] to the | 1218 * Add all of the sources contained in the given source [container] to the |
| 1212 * given list of [sources]. | 1219 * given list of [sources]. |
| 1213 */ | 1220 */ |
| 1214 void _addSourcesInContainer(List<Source> sources, SourceContainer container) { | 1221 void _addSourcesInContainer(List<Source> sources, SourceContainer container) { |
| 1215 MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator(); | 1222 MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator(); |
| 1216 while (iterator.moveNext()) { | 1223 while (iterator.moveNext()) { |
| 1217 Source source = iterator.key; | 1224 Source source = iterator.key; |
| 1218 if (container.contains(source)) { | 1225 if (container.contains(source)) { |
| 1219 sources.add(source); | 1226 sources.add(source); |
| 1220 } | 1227 } |
| 1221 } | 1228 } |
| 1222 } | 1229 } |
| 1223 | 1230 |
| 1224 /** | 1231 /** |
| 1232 * Remove the given [pendingFuture] from [_pendingFutureSources], since the | |
| 1233 * client has indicated its computation is not needed anymore. | |
| 1234 */ | |
| 1235 void _cancelFuture(PendingFuture pendingFuture) { | |
| 1236 List<PendingFuture> pendingFutures = | |
| 1237 _pendingFutureSources[pendingFuture.target]; | |
| 1238 if (pendingFutures != null) { | |
| 1239 pendingFutures.remove(pendingFuture); | |
| 1240 if (pendingFutures.isEmpty) { | |
| 1241 _pendingFutureSources.remove(pendingFuture.target); | |
| 1242 } | |
| 1243 } | |
| 1244 } | |
| 1245 | |
| 1246 /** | |
| 1225 * Return the priority that should be used when the source associated with | 1247 * Return the priority that should be used when the source associated with |
| 1226 * the given [entry] is added to the work manager. | 1248 * the given [entry] is added to the work manager. |
| 1227 */ | 1249 */ |
| 1228 SourcePriority _computePriority(cache.CacheEntry entry) { | 1250 SourcePriority _computePriority(cache.CacheEntry entry) { |
| 1229 // Used in commented out code. | 1251 // Used in commented out code. |
| 1230 SourceKind kind = entry.getValue(SOURCE_KIND); | 1252 SourceKind kind = entry.getValue(SOURCE_KIND); |
| 1231 if (kind == SourceKind.LIBRARY) { | 1253 if (kind == SourceKind.LIBRARY) { |
| 1232 return SourcePriority.LIBRARY; | 1254 return SourcePriority.LIBRARY; |
| 1233 } else if (kind == SourceKind.PART) { | 1255 } else if (kind == SourceKind.PART) { |
| 1234 return SourcePriority.NORMAL_PART; | 1256 return SourcePriority.NORMAL_PART; |
| 1235 } | 1257 } |
| 1236 return SourcePriority.UNKNOWN; | 1258 return SourcePriority.UNKNOWN; |
| 1237 } | 1259 } |
| 1238 | 1260 |
| 1239 Object /*V*/ _computeResult( | 1261 Object /*V*/ _computeResult( |
| 1240 AnalysisTarget target, ResultDescriptor /*<V>*/ descriptor) { | 1262 AnalysisTarget target, ResultDescriptor /*<V>*/ descriptor) { |
| 1241 cache.CacheEntry entry = _cache.get(target); | 1263 cache.CacheEntry entry = getCacheEntry(target); |
| 1242 if (entry == null) { | |
| 1243 return descriptor.defaultValue; | |
| 1244 } | |
| 1245 if (descriptor is CompositeResultDescriptor) { | 1264 if (descriptor is CompositeResultDescriptor) { |
| 1246 List compositeResults = []; | 1265 List compositeResults = []; |
| 1247 for (ResultDescriptor descriptor in descriptor.contributors) { | 1266 for (ResultDescriptor descriptor in descriptor.contributors) { |
| 1248 List value = _computeResult(target, descriptor); | 1267 List value = _computeResult(target, descriptor); |
| 1249 compositeResults.addAll(value); | 1268 compositeResults.addAll(value); |
| 1250 } | 1269 } |
| 1251 return compositeResults; | 1270 return compositeResults; |
| 1252 } | 1271 } |
| 1253 CacheState state = entry.getState(descriptor); | 1272 CacheState state = entry.getState(descriptor); |
| 1254 if (state == CacheState.FLUSHED || state == CacheState.INVALID) { | 1273 if (state == CacheState.FLUSHED || state == CacheState.INVALID) { |
| 1255 _driver.computeResult(target, descriptor); | 1274 _driver.computeResult(target, descriptor); |
| 1256 } | 1275 } |
| 1276 state = entry.getState(descriptor); | |
| 1277 if (state == CacheState.ERROR) { | |
| 1278 throw new AnalysisException('Cannot compute $descriptor for $target', entr y.exception); | |
| 1279 } | |
| 1257 return entry.getValue(descriptor); | 1280 return entry.getValue(descriptor); |
| 1258 } | 1281 } |
| 1259 | 1282 |
| 1260 /** | 1283 /** |
| 1261 * Given the encoded form of a source ([encoding]), use the source factory to | 1284 * Given the encoded form of a source ([encoding]), use the source factory to |
| 1262 * reconstitute the original source. | 1285 * reconstitute the original source. |
| 1263 */ | 1286 */ |
| 1264 Source _computeSourceFromEncoding(String encoding) => | 1287 Source _computeSourceFromEncoding(String encoding) => |
| 1265 _sourceFactory.fromEncoding(encoding); | 1288 _sourceFactory.fromEncoding(encoding); |
| 1266 | 1289 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1377 ChangeNoticeImpl notice = _pendingNotices[source]; | 1400 ChangeNoticeImpl notice = _pendingNotices[source]; |
| 1378 if (notice == null) { | 1401 if (notice == null) { |
| 1379 notice = new ChangeNoticeImpl(source); | 1402 notice = new ChangeNoticeImpl(source); |
| 1380 _pendingNotices[source] = notice; | 1403 _pendingNotices[source] = notice; |
| 1381 } | 1404 } |
| 1382 return notice; | 1405 return notice; |
| 1383 } | 1406 } |
| 1384 | 1407 |
| 1385 Object _getResult(AnalysisTarget target, ResultDescriptor descriptor) { | 1408 Object _getResult(AnalysisTarget target, ResultDescriptor descriptor) { |
| 1386 cache.CacheEntry entry = _cache.get(target); | 1409 cache.CacheEntry entry = _cache.get(target); |
| 1387 if (entry != null && entry.isValid(descriptor)) { | 1410 if (entry == null) { |
| 1411 return descriptor.defaultValue; | |
| 1412 } | |
| 1413 if (descriptor is CompositeResultDescriptor) { | |
| 1414 List compositeResults = []; | |
| 1415 for (ResultDescriptor descriptor in descriptor.contributors) { | |
| 1416 List value = _getResult(target, descriptor); | |
| 1417 compositeResults.addAll(value); | |
| 1418 } | |
| 1419 return compositeResults; | |
| 1420 } | |
| 1421 if (entry.isValid(descriptor)) { | |
| 1388 return entry.getValue(descriptor); | 1422 return entry.getValue(descriptor); |
| 1389 } | 1423 } |
| 1390 return descriptor.defaultValue; | 1424 return descriptor.defaultValue; |
| 1391 } | 1425 } |
| 1392 | 1426 |
| 1393 /** | 1427 /** |
| 1394 * Return a list containing all of the sources known to this context that have | 1428 * Return a list containing all of the sources known to this context that have |
| 1395 * the given [kind]. | 1429 * the given [kind]. |
| 1396 */ | 1430 */ |
| 1397 List<Source> _getSources(SourceKind kind) { | 1431 List<Source> _getSources(SourceKind kind) { |
| 1398 List<Source> sources = new List<Source>(); | 1432 List<Source> sources = new List<Source>(); |
| 1399 MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator(); | 1433 MapIterator<AnalysisTarget, cache.CacheEntry> iterator = _cache.iterator(); |
| 1400 while (iterator.moveNext()) { | 1434 while (iterator.moveNext()) { |
| 1401 if (iterator.value.getValue(SOURCE_KIND) == kind && | 1435 if (iterator.value.getValue(SOURCE_KIND) == kind && |
| 1402 iterator.key is Source) { | 1436 iterator.key is Source) { |
| 1403 sources.add(iterator.key); | 1437 sources.add(iterator.key); |
| 1404 } | 1438 } |
| 1405 } | 1439 } |
| 1406 return sources; | 1440 return sources; |
| 1407 } | 1441 } |
| 1408 | 1442 |
| 1409 /** | 1443 /** |
| 1410 * Look at the given [source] to see whether a task needs to be performed | 1444 * 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 | 1445 * 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. | 1446 * processed. This method is intended to be used for testing purposes only. |
| 1413 */ | 1447 */ |
| 1414 void _getSourcesNeedingProcessing(Source source, cache.CacheEntry sourceEntry, | 1448 void _getSourcesNeedingProcessing(Source source, cache.CacheEntry entry, |
| 1415 bool isPriority, bool hintsEnabled, bool lintsEnabled, | 1449 bool isPriority, bool hintsEnabled, bool lintsEnabled, |
| 1416 HashSet<Source> sources) { | 1450 HashSet<Source> sources) { |
| 1417 CacheState state = sourceEntry.getState(CONTENT); | 1451 CacheState state = entry.getState(CONTENT); |
| 1418 if (state == CacheState.INVALID || | 1452 if (state == CacheState.INVALID || |
| 1419 (isPriority && state == CacheState.FLUSHED)) { | 1453 (isPriority && state == CacheState.FLUSHED)) { |
| 1420 sources.add(source); | 1454 sources.add(source); |
| 1421 return; | 1455 return; |
| 1422 } else if (state == CacheState.ERROR) { | 1456 } else if (state == CacheState.ERROR) { |
| 1423 return; | 1457 return; |
| 1424 } | 1458 } |
| 1425 state = sourceEntry.getState(SOURCE_KIND); | 1459 state = entry.getState(SOURCE_KIND); |
| 1426 if (state == CacheState.INVALID || | 1460 if (state == CacheState.INVALID || |
| 1427 (isPriority && state == CacheState.FLUSHED)) { | 1461 (isPriority && state == CacheState.FLUSHED)) { |
| 1428 sources.add(source); | 1462 sources.add(source); |
| 1429 return; | 1463 return; |
| 1430 } else if (state == CacheState.ERROR) { | 1464 } else if (state == CacheState.ERROR) { |
| 1431 return; | 1465 return; |
| 1432 } | 1466 } |
| 1433 SourceKind kind = sourceEntry.getValue(SOURCE_KIND); | 1467 SourceKind kind = entry.getValue(SOURCE_KIND); |
| 1434 if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) { | 1468 if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) { |
| 1435 state = sourceEntry.getState(SCAN_ERRORS); | 1469 state = entry.getState(SCAN_ERRORS); |
| 1436 if (state == CacheState.INVALID || | 1470 if (state == CacheState.INVALID || |
| 1437 (isPriority && state == CacheState.FLUSHED)) { | 1471 (isPriority && state == CacheState.FLUSHED)) { |
| 1438 sources.add(source); | 1472 sources.add(source); |
| 1439 return; | 1473 return; |
| 1440 } else if (state == CacheState.ERROR) { | 1474 } else if (state == CacheState.ERROR) { |
| 1441 return; | 1475 return; |
| 1442 } | 1476 } |
| 1443 state = sourceEntry.getState(PARSE_ERRORS); | 1477 state = entry.getState(PARSE_ERRORS); |
| 1444 if (state == CacheState.INVALID || | 1478 if (state == CacheState.INVALID || |
| 1445 (isPriority && state == CacheState.FLUSHED)) { | 1479 (isPriority && state == CacheState.FLUSHED)) { |
| 1446 sources.add(source); | 1480 sources.add(source); |
| 1447 return; | 1481 return; |
| 1448 } else if (state == CacheState.ERROR) { | 1482 } else if (state == CacheState.ERROR) { |
| 1449 return; | 1483 return; |
| 1450 } | 1484 } |
| 1451 // if (isPriority) { | 1485 // if (isPriority) { |
| 1452 // if (!sourceEntry.hasResolvableCompilationUnit) { | 1486 // if (!entry.hasResolvableCompilationUnit) { |
| 1453 // sources.add(source); | 1487 // sources.add(source); |
| 1454 // return; | 1488 // return; |
| 1455 // } | 1489 // } |
| 1456 // } | 1490 // } |
| 1457 for (Source librarySource in getLibrariesContaining(source)) { | 1491 for (Source librarySource in getLibrariesContaining(source)) { |
| 1458 cache.CacheEntry libraryEntry = _cache.get(librarySource); | 1492 cache.CacheEntry libraryEntry = _cache.get(librarySource); |
| 1459 state = libraryEntry.getState(LIBRARY_ELEMENT); | 1493 state = libraryEntry.getState(LIBRARY_ELEMENT); |
| 1460 if (state == CacheState.INVALID || | 1494 if (state == CacheState.INVALID || |
| 1461 (isPriority && state == CacheState.FLUSHED)) { | 1495 (isPriority && state == CacheState.FLUSHED)) { |
| 1462 sources.add(source); | 1496 sources.add(source); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1499 // (isPriority && state == CacheState.FLUSHED)) { | 1533 // (isPriority && state == CacheState.FLUSHED)) { |
| 1500 // sources.add(source); | 1534 // sources.add(source); |
| 1501 // return; | 1535 // return; |
| 1502 // } else if (state == CacheState.ERROR) { | 1536 // } else if (state == CacheState.ERROR) { |
| 1503 // return; | 1537 // return; |
| 1504 // } | 1538 // } |
| 1505 // } | 1539 // } |
| 1506 } | 1540 } |
| 1507 } | 1541 } |
| 1508 // } else if (kind == SourceKind.HTML) { | 1542 // } else if (kind == SourceKind.HTML) { |
| 1509 // CacheState parsedUnitState = sourceEntry.getState(HtmlEntry.PARSED_UNIT) ; | 1543 // CacheState parsedUnitState = entry.getState(HtmlEntry.PARSED_UNIT); |
| 1510 // if (parsedUnitState == CacheState.INVALID || | 1544 // if (parsedUnitState == CacheState.INVALID || |
| 1511 // (isPriority && parsedUnitState == CacheState.FLUSHED)) { | 1545 // (isPriority && parsedUnitState == CacheState.FLUSHED)) { |
| 1512 // sources.add(source); | 1546 // sources.add(source); |
| 1513 // return; | 1547 // return; |
| 1514 // } | 1548 // } |
| 1515 // CacheState resolvedUnitState = | 1549 // CacheState resolvedUnitState = |
| 1516 // sourceEntry.getState(HtmlEntry.RESOLVED_UNIT); | 1550 // entry.getState(HtmlEntry.RESOLVED_UNIT); |
| 1517 // if (resolvedUnitState == CacheState.INVALID || | 1551 // if (resolvedUnitState == CacheState.INVALID || |
| 1518 // (isPriority && resolvedUnitState == CacheState.FLUSHED)) { | 1552 // (isPriority && resolvedUnitState == CacheState.FLUSHED)) { |
| 1519 // sources.add(source); | 1553 // sources.add(source); |
| 1520 // return; | 1554 // return; |
| 1521 // } | 1555 // } |
| 1522 } | 1556 } |
| 1523 } | 1557 } |
| 1524 | 1558 |
| 1525 /** | 1559 /** |
| 1526 * Invalidate all of the resolution results computed by this context. The flag | 1560 * 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. | 1986 // Check cache for an existing partition. |
| 1953 cache.SdkCachePartition partition = _sdkPartitions[sdk]; | 1987 cache.SdkCachePartition partition = _sdkPartitions[sdk]; |
| 1954 if (partition == null) { | 1988 if (partition == null) { |
| 1955 partition = | 1989 partition = |
| 1956 new cache.SdkCachePartition(sdkContext, _DEFAULT_SDK_CACHE_SIZE); | 1990 new cache.SdkCachePartition(sdkContext, _DEFAULT_SDK_CACHE_SIZE); |
| 1957 _sdkPartitions[sdk] = partition; | 1991 _sdkPartitions[sdk] = partition; |
| 1958 } | 1992 } |
| 1959 return partition; | 1993 return partition; |
| 1960 } | 1994 } |
| 1961 } | 1995 } |
| 1996 | |
| 1997 /** | |
| 1998 * Representation of a pending computation which is based on the results of | |
| 1999 * analysis that may or may not have been completed. | |
| 2000 */ | |
| 2001 class PendingFuture<T> { | |
| 2002 /** | |
| 2003 * The context in which this computation runs. | |
| 2004 */ | |
| 2005 final AnalysisContextImpl _context; | |
| 2006 | |
| 2007 /** | |
| 2008 * The target used by this computation to compute its value. | |
| 2009 */ | |
| 2010 final AnalysisTarget target; | |
| 2011 | |
| 2012 /** | |
| 2013 * The function which implements the computation. | |
| 2014 */ | |
| 2015 final PendingFutureComputer<T> _computeValue; | |
| 2016 | |
| 2017 /** | |
| 2018 * The completer that should be completed once the computation has succeeded. | |
| 2019 */ | |
| 2020 CancelableCompleter<T> _completer; | |
| 2021 | |
| 2022 PendingFuture(this._context, this.target, this._computeValue) { | |
| 2023 _completer = new CancelableCompleter<T>(_onCancel); | |
| 2024 } | |
| 2025 | |
| 2026 /** | |
| 2027 * Retrieve the future which will be completed when this object is | |
| 2028 * successfully evaluated. | |
| 2029 */ | |
| 2030 CancelableFuture<T> get future => _completer.future; | |
| 2031 | |
| 2032 /** | |
| 2033 * Execute [_computeValue], passing it the given [entry], and complete | |
| 2034 * the pending future if it's appropriate to do so. If the pending future is | |
| 2035 * completed by this call, true is returned; otherwise false is returned. | |
| 2036 * | |
| 2037 * Once this function has returned true, it should not be called again. | |
| 2038 * | |
| 2039 * Other than completing the future, this method is free of side effects. | |
| 2040 * Note that any code the client has attached to the future will be executed | |
| 2041 * in a microtask, so there is no danger of side effects occurring due to | |
| 2042 * client callbacks. | |
| 2043 */ | |
| 2044 bool evaluate(cache.CacheEntry entry) { | |
| 2045 assert(!_completer.isCompleted); | |
| 2046 try { | |
| 2047 T result = _computeValue(entry); | |
| 2048 if (result == null) { | |
| 2049 return false; | |
| 2050 } else { | |
| 2051 _completer.complete(result); | |
| 2052 return true; | |
| 2053 } | |
| 2054 } catch (exception, stackTrace) { | |
| 2055 _completer.completeError(exception, stackTrace); | |
| 2056 return true; | |
| 2057 } | |
| 2058 } | |
| 2059 | |
| 2060 /** | |
| 2061 * No further analysis updates are expected which affect this future, so | |
| 2062 * complete it with an AnalysisNotScheduledError in order to avoid | |
| 2063 * deadlocking the client. | |
| 2064 */ | |
| 2065 void forciblyComplete() { | |
| 2066 try { | |
| 2067 throw new AnalysisNotScheduledError(); | |
| 2068 } catch (exception, stackTrace) { | |
| 2069 _completer.completeError(exception, stackTrace); | |
| 2070 } | |
| 2071 } | |
| 2072 | |
| 2073 void _onCancel() { | |
| 2074 _context._cancelFuture(this); | |
| 2075 } | |
| 2076 } | |
| 2077 | |
| 2078 /** | |
| 2079 * Type of callback functions used by PendingFuture. Functions of this type | |
| 2080 * should perform a computation based on the data in [entry] and return it. If | |
| 2081 * the computation can't be performed yet because more analysis is needed, | |
| 2082 * `null` should be returned. | |
| 2083 * | |
| 2084 * The function may also throw an exception, in which case the corresponding | |
| 2085 * future will be completed with failure. | |
| 2086 * | |
| 2087 * Because this function is called while the state of analysis is being updated, | |
| 2088 * it should be free of side effects so that it doesn't cause reentrant changes | |
| 2089 * to the analysis state. | |
| 2090 */ | |
| 2091 typedef T PendingFutureComputer<T>(cache.CacheEntry entry); | |
| 2092 | |
| 2093 /** | |
| 2094 * A helper class used to create futures for AnalysisContextImpl. Using a helper | |
| 2095 * class allows us to preserve the generic parameter T. | |
| 2096 */ | |
| 2097 class _AnalysisFutureHelper<T> { | |
| 2098 final AnalysisContextImpl _context; | |
| 2099 | |
| 2100 _AnalysisFutureHelper(this._context); | |
| 2101 | |
| 2102 /** | |
| 2103 * Return a future that will be completed with the result of calling | |
| 2104 * [computeValue]. If [computeValue] returns non-`null`, the future will be | |
| 2105 * completed immediately with the resulting value. If it returns `null`, then | |
| 2106 * it will be re-executed in the future, after the next time the cached | |
| 2107 * information for [target] has changed. If [computeValue] throws an | |
| 2108 * exception, the future will fail with that exception. | |
| 2109 * | |
| 2110 * If the [computeValue] still returns `null` after there is no further | |
| 2111 * analysis to be done for [target], then the future will be completed with | |
| 2112 * the error AnalysisNotScheduledError. | |
| 2113 * | |
| 2114 * Since [computeValue] will be called while the state of analysis is being | |
| 2115 * updated, it should be free of side effects so that it doesn't cause | |
| 2116 * reentrant changes to the analysis state. | |
| 2117 */ | |
| 2118 CancelableFuture<T> computeAsync( | |
| 2119 AnalysisTarget target, T computeValue(cache.CacheEntry entry)) { | |
| 2120 if (_context.isDisposed) { | |
| 2121 // No further analysis is expected, so return a future that completes | |
| 2122 // immediately with AnalysisNotScheduledError. | |
| 2123 return new CancelableFuture.error(new AnalysisNotScheduledError()); | |
| 2124 } | |
| 2125 cache.CacheEntry entry = _context.getReadableSourceEntryOrNull(target); | |
| 2126 if (entry == null) { | |
| 2127 return new CancelableFuture.error(new AnalysisNotScheduledError()); | |
| 2128 } | |
| 2129 PendingFuture pendingFuture = | |
| 2130 new PendingFuture<T>(_context, target, computeValue); | |
| 2131 if (!pendingFuture.evaluate(entry)) { | |
| 2132 _context._pendingFutureSources | |
| 2133 .putIfAbsent(target, () => <PendingFuture>[]) | |
| 2134 .add(pendingFuture); | |
| 2135 } | |
| 2136 return pendingFuture.future; | |
| 2137 } | |
| 2138 } | |
| OLD | NEW |