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