FIR IDE: encapsulate isInsideAnalysisContext check into ReadActionConfinementValidityTokenFactory

This commit is contained in:
Ilya Kirillov
2021-02-20 16:47:53 +01:00
parent 0d12110112
commit 9eb6b785c6
3 changed files with 24 additions and 18 deletions
@@ -35,33 +35,24 @@ abstract class KtAnalysisSessionProvider {
inline fun <R> analyseInFakeAnalysisSession(originalFile: KtFile, fakeExpresion: KtElement, action: KtAnalysisSession.() -> R): R { inline fun <R> analyseInFakeAnalysisSession(originalFile: KtFile, fakeExpresion: KtElement, action: KtAnalysisSession.() -> R): R {
val fakeAnalysisSession = getAnalysisSession(originalFile, ReadActionConfinementValidityTokenFactory) val fakeAnalysisSession = getAnalysisSession(originalFile, ReadActionConfinementValidityTokenFactory)
.createContextDependentCopy(originalFile, fakeExpresion) .createContextDependentCopy(originalFile, fakeExpresion)
return analyse(fakeAnalysisSession, action) return analyse(fakeAnalysisSession, ReadActionConfinementValidityTokenFactory, action)
} }
@InvalidWayOfUsingAnalysisSession @InvalidWayOfUsingAnalysisSession
inline fun <R> analyse(contextElement: KtElement, tokenFactory: ValidityTokenFactory, action: KtAnalysisSession.() -> R): R = inline fun <R> analyse(contextElement: KtElement, tokenFactory: ValidityTokenFactory, action: KtAnalysisSession.() -> R): R =
analyse(getAnalysisSession(contextElement, tokenFactory), action) analyse(getAnalysisSession(contextElement, tokenFactory), tokenFactory, action)
@OptIn(KtAnalysisSessionProviderInternals::class) @OptIn(KtAnalysisSessionProviderInternals::class)
@InvalidWayOfUsingAnalysisSession @InvalidWayOfUsingAnalysisSession
inline fun <R> analyse(analysisSession: KtAnalysisSession, action: KtAnalysisSession.() -> R): R { inline fun <R> analyse(analysisSession: KtAnalysisSession, factory: ValidityTokenFactory, action: KtAnalysisSession.() -> R): R {
currentAnalysisContextEnteringCount.set(currentAnalysisContextEnteringCount.get() + 1) factory.beforeEnteringAnalysisContext()
return try { return try {
analysisSession.action() analysisSession.action()
} finally { } finally {
currentAnalysisContextEnteringCount.set(currentAnalysisContextEnteringCount.get() - 1) factory.afterLeavingAnalysisContext()
} }
} }
companion object {
@KtAnalysisSessionProviderInternals
val currentAnalysisContextEnteringCount = object : ThreadLocal<Int>() {
override fun initialValue() = 0
}
@OptIn(KtAnalysisSessionProviderInternals::class)
fun isInsideAnalysisContext() = currentAnalysisContextEnteringCount.get() > 0
}
} }
/** /**
@@ -31,7 +31,7 @@ class ReadActionConfinementValidityToken(project: Project) : ValidityToken() {
if (application.isDispatchThread && !allowOnEdt.get()) return false if (application.isDispatchThread && !allowOnEdt.get()) return false
if (ForbidKtResolve.resovleIsForbidenInActionWithName.get() != null) return false if (ForbidKtResolve.resovleIsForbidenInActionWithName.get() != null) return false
if (!application.isReadAccessAllowed) return false if (!application.isReadAccessAllowed) return false
if (!KtAnalysisSessionProvider.isInsideAnalysisContext()) return false if (!ReadActionConfinementValidityTokenFactory.isInsideAnalysisContext()) return false
return true return true
} }
@@ -43,7 +43,7 @@ class ReadActionConfinementValidityToken(project: Project) : ValidityToken() {
ForbidKtResolve.resovleIsForbidenInActionWithName.get()?.let { actionName -> ForbidKtResolve.resovleIsForbidenInActionWithName.get()?.let { actionName ->
return "Resolve is forbidden in $actionName" return "Resolve is forbidden in $actionName"
} }
if (!KtAnalysisSessionProvider.isInsideAnalysisContext()) return "Called outside analyse method" if (!ReadActionConfinementValidityTokenFactory.isInsideAnalysisContext()) return "Called outside analyse method"
error("Getting inaccessibility reason for validity token when it is accessible") error("Getting inaccessibility reason for validity token when it is accessible")
} }
@@ -58,6 +58,18 @@ object ReadActionConfinementValidityTokenFactory : ValidityTokenFactory() {
override val identifier: KClass<out ValidityToken> = ReadActionConfinementValidityToken::class override val identifier: KClass<out ValidityToken> = ReadActionConfinementValidityToken::class
override fun create(project: Project): ValidityToken = ReadActionConfinementValidityToken(project) override fun create(project: Project): ValidityToken = ReadActionConfinementValidityToken(project)
override fun beforeEnteringAnalysisContext() {
currentAnalysisContextEnteringCount.set(currentAnalysisContextEnteringCount.get() + 1)
}
override fun afterLeavingAnalysisContext() {
currentAnalysisContextEnteringCount.set(currentAnalysisContextEnteringCount.get() - 1)
}
private val currentAnalysisContextEnteringCount = ThreadLocal.withInitial { 0 }
internal fun isInsideAnalysisContext() = currentAnalysisContextEnteringCount.get() > 0
} }
@RequiresOptIn("All frontend related work should not be allowed to be ran from EDT thread. Only use it as a temporary solution") @RequiresOptIn("All frontend related work should not be allowed to be ran from EDT thread. Only use it as a temporary solution")
@@ -19,6 +19,9 @@ abstract class ValidityToken {
abstract class ValidityTokenFactory { abstract class ValidityTokenFactory {
abstract val identifier: KClass<out ValidityToken> abstract val identifier: KClass<out ValidityToken>
abstract fun create(project: Project): ValidityToken abstract fun create(project: Project): ValidityToken
open fun beforeEnteringAnalysisContext() {}
open fun afterLeavingAnalysisContext() {}
} }
@@ -32,8 +35,8 @@ inline fun ValidityToken.assertIsValidAndAccessible() {
} }
} }
abstract class BadEntityAccessException(): IllegalStateException() abstract class BadEntityAccessException() : IllegalStateException()
class InvalidEntityAccessException(override val message: String) : BadEntityAccessException() class InvalidEntityAccessException(override val message: String) : BadEntityAccessException()
class InaccessibleEntityAccessException(override val message: String): BadEntityAccessException() class InaccessibleEntityAccessException(override val message: String) : BadEntityAccessException()