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

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: Address comments 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 12 matching lines...) Expand all
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
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
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
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
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
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
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
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
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
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
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
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 }
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