[Analysis API] Support dangling file copies in 'KtFirVisibilityChecker'
Dangling files are copies of files in the context module, or just depend on it. In any way, dangling file modules see all internals of the context module.
This commit is contained in:
+22
-11
@@ -16,7 +16,9 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.collectContainingDeclarationsIfNonLocal
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.collectUseSiteContainers
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
@@ -48,22 +50,31 @@ internal class KtFirVisibilityChecker(
|
||||
candidateSymbol.isVisibleByPsi(useSiteFile)?.let { return it }
|
||||
}
|
||||
|
||||
val useSiteFirFile = useSiteFile.firSymbol.fir
|
||||
val containers = position.collectContainingDeclarationsIfNonLocal(analysisSession.firResolveSession).orEmpty()
|
||||
|
||||
val dispatchReceiverCanBeExplicit = candidateSymbol is KtCallableSymbol && !candidateSymbol.isExtension
|
||||
val explicitDispatchReceiver = runIf(dispatchReceiverCanBeExplicit) {
|
||||
receiverExpression?.getOrBuildFirSafe<FirExpression>(analysisSession.firResolveSession)
|
||||
}
|
||||
|
||||
val candidateFirSymbol = candidateSymbol.firSymbol.fir as FirMemberDeclaration
|
||||
val candidateDeclaration = candidateSymbol.firSymbol.fir as FirMemberDeclaration
|
||||
|
||||
val rootModuleSession = rootModuleSession
|
||||
return rootModuleSession.visibilityChecker.isVisible(
|
||||
candidateFirSymbol,
|
||||
rootModuleSession,
|
||||
useSiteFirFile,
|
||||
containers,
|
||||
val positionModule = firResolveSession.moduleProvider.getModule(position)
|
||||
val candidateModule = candidateDeclaration.llFirModuleData.ktModule
|
||||
|
||||
val effectiveSession = if (positionModule is KtDanglingFileModule && candidateModule != positionModule) {
|
||||
@Suppress("USELESS_CAST") // Smart cast is only available in K2
|
||||
val contextModule = (positionModule as KtDanglingFileModule).contextModule
|
||||
firResolveSession.getSessionFor(contextModule)
|
||||
} else {
|
||||
firResolveSession.getSessionFor(positionModule)
|
||||
}
|
||||
|
||||
val effectiveContainers = collectUseSiteContainers(position, firResolveSession).orEmpty()
|
||||
|
||||
return effectiveSession.visibilityChecker.isVisible(
|
||||
candidateDeclaration,
|
||||
effectiveSession,
|
||||
useSiteFile.firSymbol.fir,
|
||||
effectiveContainers,
|
||||
explicitDispatchReceiver
|
||||
)
|
||||
}
|
||||
|
||||
+5
-5
@@ -90,11 +90,11 @@ internal fun KtDeclaration.findSourceNonLocalFirDeclaration(firFile: FirFile, pr
|
||||
}
|
||||
|
||||
@KtAnalysisApiInternals
|
||||
fun PsiElement.collectContainingDeclarationsIfNonLocal(session: LLFirResolveSession): List<FirDeclaration>? {
|
||||
val ktFile = containingFile as? KtFile ?: return null
|
||||
val ktDeclaration = getNonLocalContainingOrThisDeclaration { !it.canBePartOfParentDeclaration } ?: return null
|
||||
val firFile = session.getOrBuildFirFile(ktFile)
|
||||
return FirElementFinder.findPathToDeclarationWithTarget(firFile, ktDeclaration)
|
||||
fun collectUseSiteContainers(element: PsiElement, resolveSession: LLFirResolveSession): List<FirDeclaration>? {
|
||||
val containingDeclaration = element.getNonLocalContainingOrThisDeclaration { !it.canBePartOfParentDeclaration } ?: return null
|
||||
val containingFile = containingDeclaration.containingKtFile
|
||||
val firFile = resolveSession.getOrBuildFirFile(containingFile)
|
||||
return FirElementFinder.findPathToDeclarationWithTarget(firFile, containingDeclaration)
|
||||
}
|
||||
|
||||
internal fun KtElement.findSourceByTraversingWholeTree(
|
||||
|
||||
Reference in New Issue
Block a user