diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirVisibilityChecker.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirVisibilityChecker.kt index e79054a9857..22769002e4e 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirVisibilityChecker.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirVisibilityChecker.kt @@ -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(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 ) } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt index 225f94fcee4..0c6f39bf8d9 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt @@ -90,11 +90,11 @@ internal fun KtDeclaration.findSourceNonLocalFirDeclaration(firFile: FirFile, pr } @KtAnalysisApiInternals -fun PsiElement.collectContainingDeclarationsIfNonLocal(session: LLFirResolveSession): List? { - 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? { + 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(