FIR IDE: allow reference resolving from EDT

It may be called from some other subsystems like Find usages.
Throwing PCE every time we try to resolve some reference from EDT
may result endless try to resolving
This commit is contained in:
Ilya Kirillov
2020-10-29 23:05:40 +03:00
parent b742a475ff
commit 171157ff78
2 changed files with 27 additions and 11 deletions
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.fir.utils
import com.intellij.openapi.application.ApplicationManager
import org.jetbrains.kotlin.idea.frontend.api.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.hackyAllowRunningOnEdt
@HackToForceAllowRunningAnalyzeOnEDT
internal inline fun <R> runInPossiblyEdtThread(action: () -> R): R = when {
!ApplicationManager.getApplication().isDispatchThread -> action()
else -> hackyAllowRunningOnEdt(action)
}
@@ -5,32 +5,32 @@
package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.ControlFlowException
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementResolveResult
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import org.jetbrains.kotlin.idea.frontend.api.HackToForceAllowRunningAnalyzeOnEDT
import org.jetbrains.kotlin.idea.frontend.api.analyze
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.runInPossiblyEdtThread
import org.jetbrains.kotlin.idea.util.getElementTextInContext
object KtFirReferenceResolver : ResolveCache.PolyVariantResolver<KtReference> {
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
override fun resolve(ref: KtReference, incompleteCode: Boolean): Array<ResolveResult> {
check(ref is KtFirReference) { "reference should be FirKtReference, but was ${ref::class}" }
check(ref is AbstractKtReference<*>) { "reference should be AbstractKtReference, but was ${ref::class}" }
if (ApplicationManager.getApplication().isDispatchThread) {
throw ProcessCanceledException()
return runInPossiblyEdtThread {
val resolveToPsiElements = try {
analyze(ref.expression) { ref.getResolvedToPsi(this) }
} catch (e: Throwable) {
if (e is ControlFlowException) throw e
throw KtReferenceResolveException(ref, e)
}
resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray()
}
val resolveToPsiElements = try {
analyze(ref.expression) { ref.getResolvedToPsi(this) }
} catch (e: Throwable) {
if (e is ControlFlowException) throw e
throw KtReferenceResolveException(ref, e)
}
return resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray()
}
}