[FIR IDE] Correctly collect containing declarations in init { ... }
`init` is not a callable declaration, and is considered local, so you cannot build a designation starting from it. In that we case we traverse parents until we find the first non-local class, and use it as a container KTIJ-21910
This commit is contained in:
+23
-18
@@ -11,20 +11,17 @@ import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
|||||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirFileSymbol
|
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirFileSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
|
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
|
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
|
||||||
|
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility
|
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility
|
||||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
|
||||||
import org.jetbrains.kotlin.psi.KtProperty
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
|
|
||||||
internal class KtFirVisibilityChecker(
|
internal class KtFirVisibilityChecker(
|
||||||
@@ -41,13 +38,8 @@ internal class KtFirVisibilityChecker(
|
|||||||
require(candidateSymbol is KtFirSymbol<*>)
|
require(candidateSymbol is KtFirSymbol<*>)
|
||||||
require(useSiteFile is KtFirFileSymbol)
|
require(useSiteFile is KtFirFileSymbol)
|
||||||
|
|
||||||
val nonLocalContainingDeclaration = findContainingNonLocalDeclaration(position)
|
|
||||||
val useSiteFirFile = useSiteFile.firSymbol.fir
|
val useSiteFirFile = useSiteFile.firSymbol.fir
|
||||||
val containers = nonLocalContainingDeclaration
|
val containers = collectContainingDeclarations(position)
|
||||||
?.getOrBuildFirSafe<FirCallableDeclaration>(analysisSession.firResolveSession)
|
|
||||||
?.collectDesignation()
|
|
||||||
?.path
|
|
||||||
.orEmpty()
|
|
||||||
|
|
||||||
val explicitDispatchReceiver = receiverExpression
|
val explicitDispatchReceiver = receiverExpression
|
||||||
?.getOrBuildFirSafe<FirExpression>(analysisSession.firResolveSession)
|
?.getOrBuildFirSafe<FirExpression>(analysisSession.firResolveSession)
|
||||||
@@ -64,13 +56,26 @@ internal class KtFirVisibilityChecker(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findContainingNonLocalDeclaration(element: PsiElement): KtCallableDeclaration? {
|
private fun collectContainingDeclarations(position: PsiElement): List<FirDeclaration> {
|
||||||
return element
|
val nonLocalContainer = findContainingNonLocalDeclaration(position)
|
||||||
.parentsOfType<KtCallableDeclaration>()
|
val nonLocalContainerFir = nonLocalContainer?.getOrBuildFirSafe<FirDeclaration>(analysisSession.firResolveSession)
|
||||||
.firstOrNull { it.isNotFromLocalClass }
|
?: return emptyList()
|
||||||
|
|
||||||
|
val designation = nonLocalContainerFir.collectDesignation()
|
||||||
|
|
||||||
|
return designation
|
||||||
|
.toSequence(includeTarget = true) // we include the starting declaration in case it is a class or an object
|
||||||
|
.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val KtCallableDeclaration.isNotFromLocalClass
|
private fun findContainingNonLocalDeclaration(element: PsiElement): KtDeclaration? {
|
||||||
|
return element
|
||||||
|
.parentsOfType<KtDeclaration>()
|
||||||
|
.firstOrNull { it.isNotLocal }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val KtDeclaration.isNotLocal
|
||||||
get() = this is KtNamedFunction && (isTopLevel || containingClassOrObject?.isLocal == false) ||
|
get() = this is KtNamedFunction && (isTopLevel || containingClassOrObject?.isLocal == false) ||
|
||||||
this is KtProperty && (isTopLevel || containingClassOrObject?.isLocal == false)
|
this is KtProperty && (isTopLevel || containingClassOrObject?.isLocal == false) ||
|
||||||
|
this is KtClassOrObject && (isTopLevel() || !isLocal)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user