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 package org.jetbrains.kotlin.idea.references
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.ControlFlowException import com.intellij.openapi.diagnostic.ControlFlowException
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementResolveResult import com.intellij.psi.PsiElementResolveResult
import com.intellij.psi.ResolveResult import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache 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.analyze
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.runInPossiblyEdtThread
import org.jetbrains.kotlin.idea.util.getElementTextInContext import org.jetbrains.kotlin.idea.util.getElementTextInContext
object KtFirReferenceResolver : ResolveCache.PolyVariantResolver<KtReference> { object KtFirReferenceResolver : ResolveCache.PolyVariantResolver<KtReference> {
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element) class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
override fun resolve(ref: KtReference, incompleteCode: Boolean): Array<ResolveResult> { override fun resolve(ref: KtReference, incompleteCode: Boolean): Array<ResolveResult> {
check(ref is KtFirReference) { "reference should be FirKtReference, but was ${ref::class}" } check(ref is KtFirReference) { "reference should be FirKtReference, but was ${ref::class}" }
check(ref is AbstractKtReference<*>) { "reference should be AbstractKtReference, but was ${ref::class}" } check(ref is AbstractKtReference<*>) { "reference should be AbstractKtReference, but was ${ref::class}" }
if (ApplicationManager.getApplication().isDispatchThread) { return runInPossiblyEdtThread {
throw ProcessCanceledException() 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()
} }
} }