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

Side by Side Diff: pkg/analyzer/lib/src/context/context.dart

Issue 1127483002: More fixes to the new analysis context implementation (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/context/cache.dart ('k') | pkg/analyzer/test/src/context/context_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698