| Index: pkg/analyzer/lib/src/context/cache.dart
|
| diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
|
| index 7dbe3984feeeee6bbe2c9395cb8f28686416b8d4..130beb41ee5029250f3d73b91e1c5d3feece13a2 100644
|
| --- a/pkg/analyzer/lib/src/context/cache.dart
|
| +++ b/pkg/analyzer/lib/src/context/cache.dart
|
| @@ -54,6 +54,7 @@ class AnalysisCache {
|
| */
|
| AnalysisCache(this._partitions) {
|
| for (CachePartition partition in _partitions) {
|
| + partition.containingCaches.add(this);
|
| ReentrantSynchronousStreamSubscription<InvalidatedResult> subscription =
|
| partition.onResultInvalidated.listen((InvalidatedResult event) {
|
| onResultInvalidated.add(event);
|
| @@ -96,6 +97,9 @@ class AnalysisCache {
|
| in onResultInvalidatedPartitionSubscriptions) {
|
| subscription.cancel();
|
| }
|
| + for (CachePartition partition in _partitions) {
|
| + partition.containingCaches.remove(this);
|
| + }
|
| }
|
|
|
| /**
|
| @@ -349,12 +353,18 @@ class CacheEntry {
|
| * Notifies the entry that the client is going to stop using it.
|
| */
|
| void dispose() {
|
| - _resultMap.forEach((descriptor, data) {
|
| + _resultMap.forEach((ResultDescriptor descriptor, ResultData data) {
|
| TargetedResult result = new TargetedResult(target, descriptor);
|
| for (TargetedResult dependedOnResult in data.dependedOnResults) {
|
| - ResultData dependedOnData = _partition._getDataFor(dependedOnResult);
|
| - if (dependedOnData != null) {
|
| - dependedOnData.dependentResults.remove(result);
|
| + for (AnalysisCache cache in _partition.containingCaches) {
|
| + CacheEntry entry = cache.get(dependedOnResult.target);
|
| + if (entry != null) {
|
| + ResultData data =
|
| + entry.getResultDataOrNull(dependedOnResult.result);
|
| + if (data != null) {
|
| + data.dependentResults.remove(result);
|
| + }
|
| + }
|
| }
|
| }
|
| });
|
| @@ -375,14 +385,21 @@ class CacheEntry {
|
| }
|
|
|
| /**
|
| - * Look up the [ResultData] of [descriptor], or add a new one if it isn't
|
| - * there.
|
| + * Return the result data associated with the [descriptor], creating one if it
|
| + * isn't there.
|
| */
|
| ResultData getResultData(ResultDescriptor descriptor) {
|
| return _resultMap.putIfAbsent(descriptor, () => new ResultData(descriptor));
|
| }
|
|
|
| /**
|
| + * Return the result data associated with the [descriptor], or `null` if there
|
| + * is no data currently associated with the descriptor.
|
| + */
|
| + ResultData getResultDataOrNull(ResultDescriptor descriptor) =>
|
| + _resultMap[descriptor];
|
| +
|
| + /**
|
| * Return the state of the result represented by the given [descriptor].
|
| */
|
| CacheState getState(ResultDescriptor descriptor) {
|
| @@ -584,11 +601,19 @@ class CacheEntry {
|
| // }
|
| }
|
| // Stop depending on other results.
|
| - TargetedResult thisResult = new TargetedResult(target, descriptor);
|
| - for (TargetedResult dependedOnResult in thisData.dependedOnResults) {
|
| - ResultData data = _partition._getDataFor(dependedOnResult);
|
| - if (data != null && deltaResult != DeltaResult.KEEP_CONTINUE) {
|
| - data.dependentResults.remove(thisResult);
|
| + if (deltaResult != DeltaResult.KEEP_CONTINUE) {
|
| + TargetedResult thisResult = new TargetedResult(target, descriptor);
|
| + for (TargetedResult dependedOnResult in thisData.dependedOnResults) {
|
| + for (AnalysisCache cache in _partition.containingCaches) {
|
| + CacheEntry entry = cache.get(dependedOnResult.target);
|
| + if (entry != null) {
|
| + ResultData data =
|
| + entry.getResultDataOrNull(dependedOnResult.result);
|
| + if (data != null) {
|
| + data.dependentResults.remove(thisResult);
|
| + }
|
| + }
|
| + }
|
| }
|
| }
|
| // Invalidate results that depend on this result.
|
| @@ -621,11 +646,15 @@ class CacheEntry {
|
| */
|
| void _invalidateDependentResults(
|
| int id, ResultData thisData, Delta delta, int level) {
|
| + // It is necessary to copy the results to a list to avoid a concurrent
|
| + // modification of the set of dependent results.
|
| List<TargetedResult> dependentResults = thisData.dependentResults.toList();
|
| for (TargetedResult dependentResult in dependentResults) {
|
| - CacheEntry entry = _partition.get(dependentResult.target);
|
| - if (entry != null) {
|
| - entry._invalidate(id, dependentResult.result, delta, level);
|
| + for (AnalysisCache cache in _partition.containingCaches) {
|
| + CacheEntry entry = cache.get(dependentResult.target);
|
| + if (entry != null) {
|
| + entry._invalidate(id, dependentResult.result, delta, level);
|
| + }
|
| }
|
| }
|
| }
|
| @@ -645,16 +674,26 @@ class CacheEntry {
|
| void _setDependedOnResults(ResultData thisData, TargetedResult thisResult,
|
| List<TargetedResult> dependedOn) {
|
| thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) {
|
| - ResultData data = _partition._getDataFor(dependedOnResult);
|
| - if (data != null) {
|
| - data.dependentResults.remove(thisResult);
|
| + for (AnalysisCache cache in _partition.containingCaches) {
|
| + CacheEntry entry = cache.get(dependedOnResult.target);
|
| + if (entry != null) {
|
| + ResultData data = entry.getResultDataOrNull(dependedOnResult.result);
|
| + if (data != null) {
|
| + data.dependentResults.remove(thisResult);
|
| + }
|
| + }
|
| }
|
| });
|
| thisData.dependedOnResults = dependedOn;
|
| thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) {
|
| - ResultData data = _partition._getDataFor(dependedOnResult);
|
| - if (data != null) {
|
| - data.dependentResults.add(thisResult);
|
| + for (AnalysisCache cache in _partition.containingCaches) {
|
| + CacheEntry entry = cache.get(dependedOnResult.target);
|
| + if (entry != null) {
|
| + ResultData data = entry.getResultDataOrNull(dependedOnResult.result);
|
| + if (data != null) {
|
| + data.dependentResults.add(thisResult);
|
| + }
|
| + }
|
| }
|
| });
|
| }
|
| @@ -671,8 +710,12 @@ class CacheEntry {
|
| thisData.value = descriptor.defaultValue;
|
| // Propagate the error state.
|
| thisData.dependentResults.forEach((TargetedResult dependentResult) {
|
| - CacheEntry entry = _partition.get(dependentResult.target);
|
| - entry._setErrorState(dependentResult.result, exception);
|
| + for (AnalysisCache cache in _partition.containingCaches) {
|
| + CacheEntry entry = cache.get(dependentResult.target);
|
| + if (entry != null) {
|
| + entry._setErrorState(dependentResult.result, exception);
|
| + }
|
| + }
|
| });
|
| }
|
|
|
| @@ -865,6 +908,12 @@ abstract class CachePartition {
|
| final InternalAnalysisContext context;
|
|
|
| /**
|
| + * A list of the caches that contain this partition. This includes the cache
|
| + * associated with the context that owns this partition.
|
| + */
|
| + final List<AnalysisCache> containingCaches = <AnalysisCache>[];
|
| +
|
| + /**
|
| * A table mapping caching policies to the cache flush managers.
|
| */
|
| final HashMap<ResultCachingPolicy, CacheFlushManager> _flushManagerMap =
|
| @@ -1013,11 +1062,6 @@ abstract class CachePartition {
|
| }
|
| }
|
|
|
| - ResultData _getDataFor(TargetedResult result) {
|
| - CacheEntry entry = context.analysisCache.get(result.target);
|
| - return entry != null ? entry._resultMap[result.result] : null;
|
| - }
|
| -
|
| /**
|
| * Return the [CacheFlushManager] for the given [descriptor], not `null`.
|
| */
|
|
|