[SLC] invalidate local class members cache on any file changes
We should track the containing file modifications to avoid PIEAE by changes in members ^KTIJ-26661 Fixed
This commit is contained in:
committed by
Space Team
parent
765a8bdd7c
commit
e05cb49671
+1
-1
@@ -44,7 +44,7 @@ open class KtLightClassForDecompiledDeclaration(
|
|||||||
ClassInnerStuffCache(
|
ClassInnerStuffCache(
|
||||||
/* aClass = */ this,
|
/* aClass = */ this,
|
||||||
/* generateEnumMethods = */ true,
|
/* generateEnumMethods = */ true,
|
||||||
/* modificationTracker = */ project.createAllLibrariesModificationTracker(),
|
/* modificationTrackers = */ listOf(project.createAllLibrariesModificationTracker()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+26
-22
@@ -50,27 +50,27 @@ public final class ClassInnerStuffCache {
|
|||||||
public static final String NOT_NULL_ANNOTATION_QUALIFIER = "@" + NotNull.class.getName();
|
public static final String NOT_NULL_ANNOTATION_QUALIFIER = "@" + NotNull.class.getName();
|
||||||
|
|
||||||
private final @NotNull KtExtensibleLightClass myClass;
|
private final @NotNull KtExtensibleLightClass myClass;
|
||||||
private final @NotNull ModificationTracker myModificationTracker;
|
private final @NotNull List<ModificationTracker> myModificationTrackers;
|
||||||
private final @NotNull Ref<Pair<Long, Interner<PsiMember>>> myInterner = Ref.create();
|
private final @NotNull Ref<Pair<Long, Interner<PsiMember>>> myInterner = Ref.create();
|
||||||
private final boolean myGenerateEnumMethods;
|
private final boolean myGenerateEnumMethods;
|
||||||
|
|
||||||
public ClassInnerStuffCache(
|
public ClassInnerStuffCache(
|
||||||
@NotNull KtExtensibleLightClass aClass,
|
@NotNull KtExtensibleLightClass aClass,
|
||||||
boolean generateEnumMethods,
|
boolean generateEnumMethods,
|
||||||
@NotNull ModificationTracker modificationTracker
|
@NotNull List<ModificationTracker> modificationTrackers
|
||||||
) {
|
) {
|
||||||
myGenerateEnumMethods = generateEnumMethods;
|
myGenerateEnumMethods = generateEnumMethods;
|
||||||
myClass = aClass;
|
myClass = aClass;
|
||||||
myModificationTracker = modificationTracker;
|
myModificationTrackers = modificationTrackers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public PsiMethod[] getConstructors() {
|
public PsiMethod[] getConstructors() {
|
||||||
return copy(CachedValuesManager.getCachedValue(
|
return copy(CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
PsiImplUtil.getConstructors(myClass),
|
PsiImplUtil.getConstructors(myClass),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -79,9 +79,9 @@ public final class ClassInnerStuffCache {
|
|||||||
public PsiField[] getFields() {
|
public PsiField[] getFields() {
|
||||||
return copy(CachedValuesManager.getCachedValue(
|
return copy(CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
calcFields(),
|
calcFields(),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -90,9 +90,9 @@ public final class ClassInnerStuffCache {
|
|||||||
public PsiMethod[] getMethods() {
|
public PsiMethod[] getMethods() {
|
||||||
return copy(CachedValuesManager.getCachedValue(
|
return copy(CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
calcMethods(),
|
calcMethods(),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -101,9 +101,9 @@ public final class ClassInnerStuffCache {
|
|||||||
public PsiClass[] getInnerClasses() {
|
public PsiClass[] getInnerClasses() {
|
||||||
return copy(CachedValuesManager.getCachedValue(
|
return copy(CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
calcInnerClasses(),
|
calcInnerClasses(),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -116,9 +116,9 @@ public final class ClassInnerStuffCache {
|
|||||||
else {
|
else {
|
||||||
return CachedValuesManager.getCachedValue(
|
return CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
getFieldsMap(),
|
getFieldsMap(),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
).get(name);
|
).get(name);
|
||||||
}
|
}
|
||||||
@@ -132,9 +132,9 @@ public final class ClassInnerStuffCache {
|
|||||||
else {
|
else {
|
||||||
return copy(notNull(CachedValuesManager.getCachedValue(
|
return copy(notNull(CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
getMethodsMap(),
|
getMethodsMap(),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
).get(name), PsiMethod.EMPTY_ARRAY));
|
).get(name), PsiMethod.EMPTY_ARRAY));
|
||||||
}
|
}
|
||||||
@@ -148,9 +148,9 @@ public final class ClassInnerStuffCache {
|
|||||||
else {
|
else {
|
||||||
return CachedValuesManager.getCachedValue(
|
return CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
getInnerClassesMap(),
|
getInnerClassesMap(),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
).get(name);
|
).get(name);
|
||||||
}
|
}
|
||||||
@@ -160,9 +160,9 @@ public final class ClassInnerStuffCache {
|
|||||||
private PsiMethod getValuesMethod() {
|
private PsiMethod getValuesMethod() {
|
||||||
return isEnum() ? internMember(CachedValuesManager.getCachedValue(
|
return isEnum() ? internMember(CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
makeValuesMethod(myClass),
|
makeValuesMethod(myClass),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
)) : null;
|
)) : null;
|
||||||
}
|
}
|
||||||
@@ -171,9 +171,9 @@ public final class ClassInnerStuffCache {
|
|||||||
private PsiMethod getValueOfMethod() {
|
private PsiMethod getValueOfMethod() {
|
||||||
return isEnum() ? internMember(CachedValuesManager.getCachedValue(
|
return isEnum() ? internMember(CachedValuesManager.getCachedValue(
|
||||||
myClass,
|
myClass,
|
||||||
() -> CachedValueProvider.Result.createSingleDependency(
|
() -> CachedValueProvider.Result.create(
|
||||||
makeValueOfMethod(myClass),
|
makeValueOfMethod(myClass),
|
||||||
myModificationTracker
|
myModificationTrackers
|
||||||
)
|
)
|
||||||
)) : null;
|
)) : null;
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,11 @@ public final class ClassInnerStuffCache {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T extends PsiMember> T internMember(T m) {
|
private <T extends PsiMember> T internMember(T m) {
|
||||||
if (m == null) return null;
|
if (m == null) return null;
|
||||||
long modCount = myModificationTracker.getModificationCount();
|
long modCount = 0;
|
||||||
|
for (ModificationTracker tracker : myModificationTrackers) {
|
||||||
|
modCount += tracker.getModificationCount();
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (myInterner) {
|
synchronized (myInterner) {
|
||||||
Pair<Long, Interner<PsiMember>> pair = myInterner.get();
|
Pair<Long, Interner<PsiMember>> pair = myInterner.get();
|
||||||
if (pair == null || pair.first.longValue() != modCount) {
|
if (pair == null || pair.first.longValue() != modCount) {
|
||||||
|
|||||||
+6
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.light.classes.symbol.classes
|
|||||||
|
|
||||||
import com.intellij.navigation.ItemPresentation
|
import com.intellij.navigation.ItemPresentation
|
||||||
import com.intellij.navigation.ItemPresentationProviders
|
import com.intellij.navigation.ItemPresentationProviders
|
||||||
|
import com.intellij.openapi.util.ModificationTracker
|
||||||
import com.intellij.openapi.util.Pair
|
import com.intellij.openapi.util.Pair
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
@@ -37,10 +38,14 @@ abstract class SymbolLightClassBase protected constructor(val ktModule: KtModule
|
|||||||
ClassInnerStuffCache(
|
ClassInnerStuffCache(
|
||||||
/* aClass = */ this,
|
/* aClass = */ this,
|
||||||
/* generateEnumMethods = */ false,
|
/* generateEnumMethods = */ false,
|
||||||
/* modificationTracker = */ project.createProjectWideOutOfBlockModificationTracker(),
|
/* modificationTrackers = */ modificationTrackerForClassInnerStuff(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun modificationTrackerForClassInnerStuff(): List<ModificationTracker> {
|
||||||
|
return listOf(project.createProjectWideOutOfBlockModificationTracker())
|
||||||
|
}
|
||||||
|
|
||||||
override fun getFields(): Array<PsiField> = myInnersCache.fields
|
override fun getFields(): Array<PsiField> = myInnersCache.fields
|
||||||
|
|
||||||
override fun getMethods(): Array<PsiMethod> = myInnersCache.methods
|
override fun getMethods(): Array<PsiMethod> = myInnersCache.methods
|
||||||
|
|||||||
+5
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.light.classes.symbol.classes
|
package org.jetbrains.kotlin.light.classes.symbol.classes
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.ModificationTracker
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.InheritanceImplUtil
|
import com.intellij.psi.impl.InheritanceImplUtil
|
||||||
import com.intellij.psi.impl.PsiClassImplUtil
|
import com.intellij.psi.impl.PsiClassImplUtil
|
||||||
@@ -56,6 +57,10 @@ abstract class SymbolLightClassForClassLike<SType : KtClassOrObjectSymbol> prote
|
|||||||
manager = manager,
|
manager = manager,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override fun modificationTrackerForClassInnerStuff(): List<ModificationTracker> {
|
||||||
|
return classOrObjectDeclaration?.modificationTrackerForClassInnerStuff() ?: super.modificationTrackerForClassInnerStuff()
|
||||||
|
}
|
||||||
|
|
||||||
override val kotlinOrigin: KtClassOrObject? get() = classOrObjectDeclaration
|
override val kotlinOrigin: KtClassOrObject? get() = classOrObjectDeclaration
|
||||||
|
|
||||||
internal inline fun <T> withClassOrObjectSymbol(crossinline action: KtAnalysisSession.(SType) -> T): T =
|
internal inline fun <T> withClassOrObjectSymbol(crossinline action: KtAnalysisSession.(SType) -> T): T =
|
||||||
|
|||||||
+12
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.light.classes.symbol.classes
|
package org.jetbrains.kotlin.light.classes.symbol.classes
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.ModificationTracker
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.PsiModifier
|
import com.intellij.psi.PsiModifier
|
||||||
@@ -22,6 +23,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtType
|
|||||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
|
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||||
|
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
|
||||||
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
|
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
|
||||||
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
|
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||||
@@ -68,6 +70,16 @@ internal fun createLightClassNoCache(ktClassOrObject: KtClassOrObject, ktModule:
|
|||||||
else -> SymbolLightClassForClassOrObject(ktClassOrObject, ktModule)
|
else -> SymbolLightClassForClassOrObject(ktClassOrObject, ktModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun KtClassOrObject.modificationTrackerForClassInnerStuff(): List<ModificationTracker> {
|
||||||
|
val outOfBlockTracker = project.createProjectWideOutOfBlockModificationTracker()
|
||||||
|
return if (isLocal) {
|
||||||
|
val file = containingKtFile
|
||||||
|
listOf(outOfBlockTracker, ModificationTracker { file.modificationStamp })
|
||||||
|
} else {
|
||||||
|
listOf(outOfBlockTracker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context(KtAnalysisSession)
|
context(KtAnalysisSession)
|
||||||
internal fun createLightClassNoCache(
|
internal fun createLightClassNoCache(
|
||||||
ktClassOrObjectSymbol: KtNamedClassOrObjectSymbol,
|
ktClassOrObjectSymbol: KtNamedClassOrObjectSymbol,
|
||||||
|
|||||||
+9
-1
@@ -32,8 +32,10 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.light.classes.symbol.annotations.*
|
import org.jetbrains.kotlin.light.classes.symbol.annotations.*
|
||||||
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
|
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
|
||||||
|
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForClassLike
|
||||||
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForInterface
|
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForInterface
|
||||||
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForInterfaceDefaultImpls
|
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForInterfaceDefaultImpls
|
||||||
|
import org.jetbrains.kotlin.light.classes.symbol.classes.modificationTrackerForClassInnerStuff
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
|
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
|
||||||
@@ -324,5 +326,11 @@ internal inline fun <reified T> Collection<T>.toArrayIfNotEmptyOrDefault(default
|
|||||||
internal inline fun <R : PsiElement, T> R.cachedValue(
|
internal inline fun <R : PsiElement, T> R.cachedValue(
|
||||||
crossinline computer: () -> T,
|
crossinline computer: () -> T,
|
||||||
): T = CachedValuesManager.getCachedValue(this) {
|
): T = CachedValuesManager.getCachedValue(this) {
|
||||||
CachedValueProvider.Result.createSingleDependency(computer(), project.createProjectWideOutOfBlockModificationTracker())
|
val value = computer()
|
||||||
|
val specialClassTrackers = (this as? SymbolLightClassForClassLike<*>)?.classOrObjectDeclaration?.modificationTrackerForClassInnerStuff()
|
||||||
|
if (specialClassTrackers != null) {
|
||||||
|
CachedValueProvider.Result.create(value, specialClassTrackers)
|
||||||
|
} else {
|
||||||
|
CachedValueProvider.Result.createSingleDependency(value, project.createProjectWideOutOfBlockModificationTracker())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user