mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-28 15:51:42 +00:00
FIR IDE: split ValidityToken.isValid into isValid & isAccessible
This commit is contained in:
@@ -13,21 +13,30 @@ class ReadActionConfinementValidityToken(project: Project) : ValidityToken() {
|
||||
private val modificationTracker = project.createProjectWideOutOfBlockModificationTracker()
|
||||
private val onCreatedTimeStamp = modificationTracker.modificationCount
|
||||
|
||||
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
|
||||
override fun isValid(): Boolean {
|
||||
val application = ApplicationManager.getApplication()
|
||||
if (application.isDispatchThread && !allowOnEdt.get()) return false
|
||||
if (!application.isReadAccessAllowed) return false
|
||||
return onCreatedTimeStamp == modificationTracker.modificationCount
|
||||
}
|
||||
|
||||
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
|
||||
override fun getInvalidationReason(): String {
|
||||
if (onCreatedTimeStamp != modificationTracker.modificationCount) return "PSI has changed since creation"
|
||||
error("Getting invalidation reason for valid validity token")
|
||||
}
|
||||
|
||||
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
|
||||
override fun isAccessible(): Boolean {
|
||||
val application = ApplicationManager.getApplication()
|
||||
if (application.isDispatchThread && !allowOnEdt.get()) return false
|
||||
if (!application.isReadAccessAllowed) return false
|
||||
return true
|
||||
}
|
||||
|
||||
@OptIn(HackToForceAllowRunningAnalyzeOnEDT::class)
|
||||
override fun getInaccessibilityReason(): String {
|
||||
val application = ApplicationManager.getApplication()
|
||||
if (application.isDispatchThread && !allowOnEdt.get()) return "Called in EDT thread"
|
||||
if (!application.isReadAccessAllowed) return "Called outside read action"
|
||||
if (onCreatedTimeStamp != modificationTracker.modificationCount) return "PSI has changed since creation"
|
||||
error("Getting invalidation reason for valid validity token")
|
||||
error("Getting inaccessibility reason for validity token when it is accessible")
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -8,14 +8,23 @@ package org.jetbrains.kotlin.idea.frontend.api
|
||||
abstract class ValidityToken {
|
||||
abstract fun isValid(): Boolean
|
||||
abstract fun getInvalidationReason(): String
|
||||
|
||||
abstract fun isAccessible(): Boolean
|
||||
abstract fun getInaccessibilityReason(): String
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun ValidityToken.assertIsValid() {
|
||||
inline fun ValidityToken.assertIsValidAndAccessible() {
|
||||
if (!isValid()) {
|
||||
throw InvalidEntityAccessException("Access to invalid $this, invalidation reason is ${getInvalidationReason()}")
|
||||
throw InvalidEntityAccessException("Access to invalid $this: ${getInvalidationReason()}")
|
||||
}
|
||||
if (!isAccessible()) {
|
||||
throw InaccessibleEntityAccessException("$this is inaccessible: ${getInaccessibilityReason()}")
|
||||
}
|
||||
}
|
||||
|
||||
class InvalidEntityAccessException(override val message: String): IllegalStateException()
|
||||
abstract class BadEntityAccessException(): IllegalStateException()
|
||||
|
||||
class InvalidEntityAccessException(override val message: String) : BadEntityAccessException()
|
||||
class InaccessibleEntityAccessException(override val message: String): BadEntityAccessException()
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@ interface ValidityTokenOwner {
|
||||
val token: ValidityToken
|
||||
}
|
||||
|
||||
fun ValidityTokenOwner.isValid(): Boolean = token.isValid()
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun ValidityTokenOwner.assertIsValid() {
|
||||
token.assertIsValid()
|
||||
inline fun ValidityTokenOwner.assertIsValidAndAccessible() {
|
||||
token.assertIsValidAndAccessible()
|
||||
}
|
||||
|
||||
inline fun <R> ValidityTokenOwner.withValidityAssertion(action: () -> R): R {
|
||||
assertIsValid()
|
||||
assertIsValidAndAccessible()
|
||||
return action()
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.api.getResolveState
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ReadActionConfinementValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValidAndAccessible
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider
|
||||
@@ -35,7 +35,7 @@ private constructor(
|
||||
val context: KtFirAnalysisSessionContext,
|
||||
) : KtAnalysisSession(token) {
|
||||
init {
|
||||
assertIsValid()
|
||||
assertIsValidAndAccessible()
|
||||
}
|
||||
|
||||
internal val towerDataContextProvider: TowerDataContextProvider = TowerDataContextProvider(this)
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValidAndAccessible
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@@ -37,7 +37,7 @@ class KtFirAnalysisSessionProvider(project: Project) : KtAnalysisSessionProvider
|
||||
@Suppress("DEPRECATION")
|
||||
KtFirAnalysisSession.createForElement(contextElement)
|
||||
}.apply {
|
||||
assertIsValid()
|
||||
assertIsValidAndAccessible()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,10 +89,11 @@ internal class KtFirCallResolver(
|
||||
val target = when (val calleeReference = calleeReference) {
|
||||
is FirResolvedNamedReference -> calleeReference.getKtFunctionOrConstructorSymbol()?.let { KtSuccessCallTarget(it) }
|
||||
is FirErrorNamedReference -> calleeReference.createErrorCallTarget()
|
||||
is FirSimpleNamedReference -> error(
|
||||
"Looks like FirFunctionCall was not resolved to BODY_RESOLVE phase, " +
|
||||
"consider resolving it containing declaration before starting resolve calls"
|
||||
)
|
||||
is FirSimpleNamedReference ->
|
||||
error(
|
||||
"Looks like FirFunctionCall was not resolved to BODY_RESOLVE phase, " +
|
||||
"consider resolving it containing declaration before starting resolve calls"
|
||||
)
|
||||
else -> error("Unexpected call reference ${calleeReference::class.simpleName}")
|
||||
} ?: return null
|
||||
return KtFunctionCall(target)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
package org.jetbrains.kotlin.idea.frontend.api.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValidAndAccessible
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtSubtypingComponent
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
|
||||
@@ -20,7 +20,7 @@ internal class KtFirSubtypingComponent(
|
||||
override val token: ValidityToken,
|
||||
) : KtSubtypingComponent(), KtFirAnalysisSessionComponent {
|
||||
override fun isEqualTo(first: KtType, second: KtType): Boolean = withValidityAssertion {
|
||||
second.assertIsValid()
|
||||
second.assertIsValidAndAccessible()
|
||||
check(first is KtFirType)
|
||||
check(second is KtFirType)
|
||||
return AbstractTypeChecker.equalTypes(
|
||||
@@ -31,7 +31,7 @@ internal class KtFirSubtypingComponent(
|
||||
}
|
||||
|
||||
override fun isSubTypeOf(subType: KtType, superType: KtType): Boolean = withValidityAssertion {
|
||||
superType.assertIsValid()
|
||||
superType.assertIsValidAndAccessible()
|
||||
check(subType is KtFirType)
|
||||
check(superType is KtFirType)
|
||||
return AbstractTypeChecker.isSubtypeOf(
|
||||
|
||||
@@ -9,11 +9,10 @@ import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.resolvedFirToPhase
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValidAndAccessible
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveState: FirModuleResolveState, val token: ValidityToken) {
|
||||
@@ -25,7 +24,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
|
||||
firWeakRef.get() == null && resolveStateWeakRef.get() == null
|
||||
|
||||
inline fun <R> withFir(phase: FirResolvePhase = FirResolvePhase.RAW_FIR, crossinline action: (fir: D) -> R): R {
|
||||
token.assertIsValid()
|
||||
token.assertIsValidAndAccessible()
|
||||
val fir = firWeakRef.get()
|
||||
?: throw EntityWasGarbageCollectedException("FirElement")
|
||||
val resolveState = resolveStateWeakRef.get()
|
||||
|
||||
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.utils
|
||||
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.assertIsValidAndAccessible
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
@@ -22,7 +22,7 @@ class ValidityAwareCachedValue<T>(
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun getValue(thisRef: Any, property: KProperty<*>): T {
|
||||
token.assertIsValid()
|
||||
token.assertIsValidAndAccessible()
|
||||
return lazyValue.value
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user