[LL FIR] LLFirTargetResolver: introduce resolveDependencyTarget step
This entry point is required to be able to pre-resolve dependency declarations. E.g., fake override declaration shares annotation instances between the original and the fake one, so we should resolve the original firstly to avoid concurrent modification and correct context. This will be done later. This commit effectively only drops body resolution for a file annotation container if the target element is not a file because this is not required for correct resolution ^KT-63042
This commit is contained in:
committed by
Space Team
parent
0b07b86ec9
commit
bc1e9fd2ea
+14
-9
@@ -16,11 +16,8 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.LLFirDecla
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDelegatedConstructorIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.*
|
||||
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDelegatedConstructorIsResolved
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
@@ -40,19 +37,22 @@ import org.jetbrains.kotlin.fir.references.builder.buildExplicitThisReference
|
||||
import org.jetbrains.kotlin.fir.resolve.FirCodeFragmentContext
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.codeFragmentContext
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.RealVariable
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForClass
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForFile
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractsDslNames
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForClass
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isUsedInControlFlowGraphBuilderForFile
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.isResolved
|
||||
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
|
||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||
import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment
|
||||
import org.jetbrains.kotlin.utils.exceptions.withPsiEntry
|
||||
import org.jetbrains.kotlin.utils.findIsInstanceAnd
|
||||
@@ -107,6 +107,11 @@ private class LLFirBodyTargetResolver(
|
||||
override val buildCfgForFiles: Boolean get() = false
|
||||
}
|
||||
|
||||
/**
|
||||
* No one should depend on body resolution of another declaration
|
||||
*/
|
||||
override val skipDependencyTargetResolutionStep: Boolean get() = true
|
||||
|
||||
override fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean {
|
||||
when (target) {
|
||||
is FirRegularClass -> {
|
||||
@@ -123,7 +128,7 @@ private class LLFirBodyTargetResolver(
|
||||
is FirFile -> {
|
||||
if (target.resolvePhase >= resolverPhase) return true
|
||||
|
||||
resolveFileAnnotationContainerIfNeeded(target)
|
||||
target.annotationsContainer?.lazyResolveToPhase(resolverPhase)
|
||||
|
||||
// resolve file CFG graph here, to do this we need to have property blocks resoled
|
||||
resolveMembersForControlFlowGraph(target)
|
||||
@@ -143,7 +148,7 @@ private class LLFirBodyTargetResolver(
|
||||
}
|
||||
}
|
||||
|
||||
return super.doResolveWithoutLock(target)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun calculateControlFlowGraph(target: FirRegularClass) {
|
||||
|
||||
+5
-9
@@ -13,14 +13,16 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockPro
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDeprecationProviderIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.forEachDependentDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptDependentDeclaration
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.util.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCallCopy
|
||||
@@ -31,9 +33,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredA
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.forEachDependentDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isScriptDependentDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.annotationPlatformSupport
|
||||
import org.jetbrains.kotlin.util.PrivateForInline
|
||||
|
||||
internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) {
|
||||
override fun resolve(
|
||||
@@ -103,12 +103,8 @@ private class LLFirCompilerRequiredAnnotationsTargetResolver(
|
||||
}
|
||||
|
||||
override fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean {
|
||||
if (target is FirFile) {
|
||||
resolveFileAnnotationContainerIfNeeded(target)
|
||||
return false
|
||||
}
|
||||
|
||||
when (target) {
|
||||
is FirFile -> return false
|
||||
is FirRegularClass, is FirScript, is FirCodeFragment -> {}
|
||||
else -> {
|
||||
if (!target.isRegularDeclarationWithAnnotation) {
|
||||
|
||||
+1
-1
@@ -148,7 +148,7 @@ private class LLFirStatusTargetResolver(
|
||||
true
|
||||
}
|
||||
|
||||
else -> super.doResolveWithoutLock(target)
|
||||
else -> false
|
||||
}
|
||||
|
||||
private inline fun <T : FirCallableDeclaration> performResolveWithOverriddenCallables(
|
||||
|
||||
-1
@@ -120,7 +120,6 @@ private class LLFirSuperTypeTargetResolver(
|
||||
superTypeUpdater = { target.replaceExpandedTypeRef(it.single()) },
|
||||
)
|
||||
else -> {
|
||||
resolveFileAnnotationContainerIfNeeded(target)
|
||||
performCustomResolveUnderLock(target) {
|
||||
// just update the phase
|
||||
}
|
||||
|
||||
+21
-5
@@ -27,7 +27,7 @@ internal abstract class LLFirTargetResolver(
|
||||
/**
|
||||
* Must be executed without a lock
|
||||
*/
|
||||
protected fun resolveFileAnnotationContainerIfNeeded(elementWithResolveState: FirElementWithResolveState) {
|
||||
private fun resolveFileAnnotationContainerIfNeeded(elementWithResolveState: FirElementWithResolveState) {
|
||||
if (elementWithResolveState !is FirFile) return
|
||||
val annotationContainer = elementWithResolveState.annotationsContainer ?: return
|
||||
withFile(elementWithResolveState) {
|
||||
@@ -35,6 +35,23 @@ internal abstract class LLFirTargetResolver(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see resolveDependencyTarget
|
||||
*/
|
||||
open val skipDependencyTargetResolutionStep: Boolean get() = false
|
||||
|
||||
/**
|
||||
* Requests the resolution for dependency targets to avoid race in the case of FIR instance sharing.
|
||||
* Will be executed before resolution without a lock.
|
||||
*
|
||||
* @see skipDependencyTargetResolutionStep
|
||||
*/
|
||||
private fun resolveDependencyTarget(target: FirElementWithResolveState) {
|
||||
if (skipDependencyTargetResolutionStep) return
|
||||
|
||||
resolveFileAnnotationContainerIfNeeded(target)
|
||||
}
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
@@ -57,10 +74,7 @@ internal abstract class LLFirTargetResolver(
|
||||
|
||||
protected open fun checkResolveConsistency() {}
|
||||
|
||||
protected open fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean {
|
||||
resolveFileAnnotationContainerIfNeeded(target)
|
||||
return false
|
||||
}
|
||||
protected open fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean = false
|
||||
|
||||
protected abstract fun doLazyResolveUnderLock(target: FirElementWithResolveState)
|
||||
|
||||
@@ -74,6 +88,8 @@ internal abstract class LLFirTargetResolver(
|
||||
}
|
||||
|
||||
protected fun performResolve(target: FirElementWithResolveState) {
|
||||
resolveDependencyTarget(target)
|
||||
|
||||
if (doResolveWithoutLock(target)) return
|
||||
performCustomResolveUnderLock(target) {
|
||||
doLazyResolveUnderLock(target)
|
||||
|
||||
@@ -70,7 +70,7 @@ FILE: [ResolvedTo(IMPORTS)] annotations.kt
|
||||
BODY_RESOLVE:
|
||||
FILE: [ResolvedTo(IMPORTS)] annotations.kt
|
||||
@FILE:R|kotlin/Suppress|[Types](names = vararg(String(1)))
|
||||
[ResolvedTo(BODY_RESOLVE)] annotations container
|
||||
[ResolvedTo(ANNOTATION_ARGUMENTS)] annotations container
|
||||
@R|kotlin/Suppress|[Types](names = vararg(String(2))) public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ FILE: [ResolvedTo(IMPORTS)] annotationsScript.kts
|
||||
BODY_RESOLVE:
|
||||
FILE: [ResolvedTo(IMPORTS)] annotationsScript.kts
|
||||
@FILE:R|kotlin/Suppress|[Types](names = vararg(String(1)))
|
||||
[ResolvedTo(BODY_RESOLVE)] annotations container
|
||||
[ResolvedTo(ANNOTATION_ARGUMENTS)] annotations container
|
||||
context(<script>@R|kotlin/script/templates/standard/ScriptTemplateWithArgs|)
|
||||
SCRIPT: [ResolvedTo(TYPES)] <script-annotationsScript.kts>
|
||||
[ResolvedTo(RAW_FIR)] lval args: R|kotlin/Array<kotlin/String>|
|
||||
@@ -144,3 +144,4 @@ FILE: [ResolvedTo(BODY_RESOLVE)] annotationsScript.kts
|
||||
|
||||
@R|kotlin/Suppress|[Types](names = vararg(String(2))) public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user