diff --git a/platform/core-api/src/com/intellij/psi/util/CachedValuesManager.java b/platform/core-api/src/com/intellij/psi/util/CachedValuesManager.java index f43f3a2a581f..ae2729e8e317 100644 --- a/platform/core-api/src/com/intellij/psi/util/CachedValuesManager.java +++ b/platform/core-api/src/com/intellij/psi/util/CachedValuesManager.java @@ -69,7 +69,7 @@ public abstract class CachedValuesManager { return createCachedValue(provider, true); } - public T getParameterizedCachedValue(@NotNull D dataHolder, + public T getParameterizedCachedValue(@NotNull UserDataHolder dataHolder, @NotNull Key> key, @NotNull ParameterizedCachedValueProvider provider, boolean trackValue, @@ -85,6 +85,7 @@ public abstract class CachedValuesManager { } } else { + //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (dataHolder) { value = dataHolder.getUserData(key); if (value == null) { @@ -105,16 +106,16 @@ public abstract class CachedValuesManager { * @param trackValue if value tracking required. T should be trackable in this case. * @return up-to-date value. */ - public abstract T getCachedValue(@NotNull D dataHolder, - @NotNull Key> key, - @NotNull CachedValueProvider provider, - boolean trackValue); + public abstract T getCachedValue(@NotNull UserDataHolder dataHolder, + @NotNull Key> key, + @NotNull CachedValueProvider provider, + boolean trackValue); /** * Create a cached value with the given provider and non-tracked return value, store it in the first argument's user data. If it's already stored, reuse it. * @return The cached value */ - public T getCachedValue(@NotNull D dataHolder, @NotNull CachedValueProvider provider) { + public T getCachedValue(@NotNull UserDataHolder dataHolder, @NotNull CachedValueProvider provider) { return getCachedValue(dataHolder, this.getKeyForClass(provider.getClass()), provider, false); } diff --git a/platform/core-impl/src/com/intellij/util/CachedValuesManagerImpl.java b/platform/core-impl/src/com/intellij/util/CachedValuesManagerImpl.java index c1a816c1d6a2..7a6dce67541a 100644 --- a/platform/core-impl/src/com/intellij/util/CachedValuesManagerImpl.java +++ b/platform/core-impl/src/com/intellij/util/CachedValuesManagerImpl.java @@ -50,44 +50,58 @@ public class CachedValuesManagerImpl extends CachedValuesManager { @Override @Nullable - public T getCachedValue(@NotNull D dataHolder, - @NotNull Key> key, - @NotNull CachedValueProvider provider, - boolean trackValue) { + public T getCachedValue(@NotNull UserDataHolder dataHolder, + @NotNull Key> key, + @NotNull CachedValueProvider provider, + boolean trackValue) { + return dataHolder instanceof UserDataHolderEx + ? getCachedValueFromExHolder((UserDataHolderEx)dataHolder, key, provider, trackValue) + : getCachedValueFromHolder(dataHolder, key, provider, trackValue); + } + + private T getCachedValueFromExHolder(@NotNull UserDataHolderEx dataHolder, + @NotNull Key> key, + @NotNull CachedValueProvider provider, + boolean trackValue) { + CachedValue value = dataHolder.getUserData(key); + while (isOutdated(value)) { + if (dataHolder.replace(key, value, null)) { + value = null; + break; + } + value = dataHolder.getUserData(key); + } + if (value == null) { + value = dataHolder.putUserDataIfAbsent(key, freshCachedValue(dataHolder, key, provider, trackValue)); + } + return value.getValue(); + } + + private T getCachedValueFromHolder(@NotNull UserDataHolder dataHolder, + @NotNull Key> key, + @NotNull CachedValueProvider provider, boolean trackValue) { CachedValue value; - if (dataHolder instanceof UserDataHolderEx) { - UserDataHolderEx dh = (UserDataHolderEx)dataHolder; - value = dh.getUserData(key); - while (isOutdated(value)) { - if (dh.replace(key, value, null)) { - value = null; - break; - } - value = dh.getUserData(key); + //noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (dataHolder) { + value = dataHolder.getUserData(key); + if (isOutdated(value)) { + value = null; } if (value == null) { - CachedValueLeakChecker.checkProvider(provider, key, dataHolder); - value = createCachedValue(provider, trackValue); - assert ((CachedValueBase)value).isFromMyProject(myProject); - value = dh.putUserDataIfAbsent(key, value); - } - } - else { - synchronized (dataHolder) { - value = dataHolder.getUserData(key); - if (isOutdated(value)) { - value = null; - } - if (value == null) { - CachedValueLeakChecker.checkProvider(provider, key, dataHolder); - value = createCachedValue(provider, trackValue); - dataHolder.putUserData(key, value); - } + value = freshCachedValue(dataHolder, key, provider, trackValue); + dataHolder.putUserData(key, value); } } return value.getValue(); } + private CachedValue freshCachedValue(UserDataHolder dh, Key> key, CachedValueProvider provider, boolean trackValue) { + CachedValueLeakChecker.checkProvider(provider, key, dh); + CachedValue value = createCachedValue(provider, trackValue); + assert ((CachedValueBase)value).isFromMyProject(myProject); + return value; + } + private boolean isOutdated(CachedValue value) { return value instanceof CachedValueBase && (!((CachedValueBase)value).isFromMyProject(myProject) || hasOutdatedValue((CachedValueBase)value)); @@ -97,7 +111,4 @@ public class CachedValuesManagerImpl extends CachedValuesManager { return !base.hasUpToDateValue() && base.getRawData() != null; } - public Project getProject() { - return myProject; - } }