Don't over-cache own methods list in KtUltraLightClass
The might be code that stores light class references (for example ChangeMethodSignatureFromUsageFix) and tries to find methods after invalidating. Internal class caches has an additional assert that methods obtained are valid and this assert can be violated if the list of methods was cached before some method invalidation. This a major problem of current light-classes implementation. Other places should be checked and fixed as well. Check test: QuickFixMultiFileTestGenerated$ChangeSignature$Jk.testJkKeepValOnAddingParameter1 Caused by: java.lang.AssertionError: Element: class org.jetbrains.kotlin.asJava.classes.KtUltraLightMethodForSourceDeclaration #kotlin because: File language:Language: JAVA != Provider base language:Language: kotlin invalidated at: no info Attachments: at com.intellij.testFramework.LoggedErrorProcessor.processError(LoggedErrorProcessor.java:61) at org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase$setUp$1.processError(KotlinLightCodeInsightFixtureTestCase.kt:84) at com.intellij.testFramework.TestLogger.error(TestLogger.java:40) at com.intellij.openapi.diagnostic.Logger.error(Logger.java:170) at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$null$1(PassExecutorService.java:442) at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1166) at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$2(PassExecutorService.java:423) at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:586) at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:532) at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:86) at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.doRun(PassExecutorService.java:422) at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$run$0(PassExecutorService.java:398) at com.intellij.openapi.application.impl.ReadMostlyRWLock.executeByImpatientReader(ReadMostlyRWLock.java:164) at com.intellij.openapi.application.impl.ApplicationImpl.executeByImpatientReader(ApplicationImpl.java:218) at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.run(PassExecutorService.java:396) at com.intellij.concurrency.JobLauncherImpl$VoidForkJoinTask$1.exec(JobLauncherImpl.java:174) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157) Caused by: com.intellij.psi.PsiInvalidElementAccessException: Element: class org.jetbrains.kotlin.asJava.classes.KtUltraLightMethodForSourceDeclaration #kotlin because: File language:Language: JAVA != Provider base language:Language: kotlin invalidated at: no info at com.intellij.psi.util.PsiUtilCore.ensureValid(PsiUtilCore.java:482) at com.intellij.psi.impl.PsiClassImplUtil$1.add(PsiClassImplUtil.java:380) at com.intellij.psi.scope.processor.FilterScopeProcessor.execute(FilterScopeProcessor.java:59) at com.intellij.psi.impl.PsiClassImplUtil.processDeclarationsInClassNotCached(PsiClassImplUtil.java:684) at com.intellij.psi.impl.PsiClassImplUtil.lambda$createMembersMap$2(PsiClassImplUtil.java:395) at com.intellij.util.containers.ConcurrentFactoryMap$2.create(ConcurrentFactoryMap.java:181) at com.intellij.util.containers.ConcurrentFactoryMap.get(ConcurrentFactoryMap.java:45) at com.intellij.psi.impl.PsiClassImplUtil$MembersMap.get(PsiClassImplUtil.java:357) at com.intellij.psi.impl.PsiClassImplUtil$MembersMap.access$000(PsiClassImplUtil.java:349) at com.intellij.psi.impl.PsiClassImplUtil.getMap(PsiClassImplUtil.java:207) at com.intellij.psi.impl.PsiClassImplUtil.findByMap(PsiClassImplUtil.java:153) at com.intellij.psi.impl.PsiClassImplUtil.findMethodsByName(PsiClassImplUtil.java:96) at com.intellij.psi.impl.source.ClassInnerStuffCache.findMethodsByName(ClassInnerStuffCache.java:67) at org.jetbrains.kotlin.asJava.classes.KtLightClassBase.findMethodsByName(KtLightClassBase.kt:52) at com.intellij.codeInsight.daemon.impl.quickfix.ChangeMethodSignatureFromUsageFix.getShortText(ChangeMethodSignatureFromUsageFix.java:94) at com.intellij.codeInsight.daemon.impl.quickfix.ChangeMethodSignatureFromUsageFix.isAvailable(ChangeMethodSignatureFromUsageFix.java:152) at com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler.availableFor(ShowIntentionActionsHandler.java:127) at com.intellij.codeInsight.intention.impl.CachedIntentions.wrapActionsTo(CachedIntentions.java:183) at com.intellij.codeInsight.intention.impl.CachedIntentions.wrapAndUpdateActions(CachedIntentions.java:135) at com.intellij.codeInsight.daemon.impl.ShowIntentionsPass.doCollectInformation(ShowIntentionsPass.java:222) at com.intellij.codeHighlighting.TextEditorHighlightingPass.collectInformation(TextEditorHighlightingPass.java:69) at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$null$1(PassExecutorService.java:430) ... 15 more
This commit is contained in:
@@ -11,6 +11,10 @@ import com.intellij.psi.impl.InheritanceImplUtil
|
||||
import com.intellij.psi.impl.PsiClassImplUtil
|
||||
import com.intellij.psi.impl.PsiSuperMethodImplUtil
|
||||
import com.intellij.psi.impl.light.LightMethodBuilder
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassData
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
@@ -242,8 +246,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
|
||||
private fun propertyParameters() = classOrObject.primaryConstructorParameters.filter { it.hasValOrVar() }
|
||||
|
||||
private val _ownMethods: List<KtLightMethod> by lazyPub {
|
||||
|
||||
private fun ownMethods(): List<KtLightMethod> {
|
||||
val result = arrayListOf<KtLightMethod>()
|
||||
|
||||
for (declaration in this.classOrObject.declarations.filterNot { it.isHiddenByDeprecation(support) }) {
|
||||
@@ -292,9 +295,18 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
addMethodsFromDataClass(result)
|
||||
addDelegatesToInterfaceMethods(result)
|
||||
|
||||
result
|
||||
return result
|
||||
}
|
||||
|
||||
private val _ownMethods: CachedValue<List<KtLightMethod>> = CachedValuesManager.getManager(project).createCachedValue(
|
||||
{
|
||||
CachedValueProvider.Result.create(
|
||||
ownMethods(),
|
||||
KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
|
||||
)
|
||||
}, false
|
||||
)
|
||||
|
||||
private fun addMethodsFromDataClass(result: MutableList<KtLightMethod>) {
|
||||
if (!classOrObject.hasModifier(DATA_KEYWORD)) return
|
||||
val descriptor = classOrObject.resolve() as? ClassDescriptor ?: return
|
||||
@@ -409,7 +421,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
|
||||
private fun isJvmStatic(declaration: KtAnnotated): Boolean = declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME)
|
||||
|
||||
override fun getOwnMethods(): List<KtLightMethod> = if (tooComplex) super.getOwnMethods() else _ownMethods
|
||||
override fun getOwnMethods(): List<KtLightMethod> = if (tooComplex) super.getOwnMethods() else _ownMethods.value
|
||||
|
||||
private fun KtAnnotated.hasAnnotation(name: FqName) = support.findAnnotation(this, name) != null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user