FIR IDE: Add KtVisibilityChecker component
This commit is contained in:
+5
-1
@@ -40,7 +40,8 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
|
||||
KtSymbolsMixIn,
|
||||
KtReferenceResolveMixIn,
|
||||
KtReferenceShortenerMixIn,
|
||||
KtSymbolDeclarationRendererMixIn {
|
||||
KtSymbolDeclarationRendererMixIn,
|
||||
KtVisibilityCheckerMixIn {
|
||||
|
||||
override val analysisSession: KtAnalysisSession get() = this
|
||||
|
||||
@@ -90,4 +91,7 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
|
||||
|
||||
internal val expressionInfoProvider: KtExpressionInfoProvider get() = expressionInfoProviderImpl
|
||||
protected abstract val expressionInfoProviderImpl: KtExpressionInfoProvider
|
||||
|
||||
internal val visibilityChecker: KtVisibilityChecker get() = visibilityCheckerImpl
|
||||
protected abstract val visibilityCheckerImpl: KtVisibilityChecker
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.frontend.api.components
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFileSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
|
||||
abstract class KtVisibilityChecker : KtAnalysisSessionComponent() {
|
||||
abstract fun isVisible(
|
||||
candidateSymbol: KtSymbolWithVisibility,
|
||||
useSiteFile: KtFileSymbol,
|
||||
position: PsiElement,
|
||||
receiverExpression: KtExpression?
|
||||
): Boolean
|
||||
}
|
||||
|
||||
interface KtVisibilityCheckerMixIn : KtAnalysisSessionMixIn {
|
||||
fun isVisible(
|
||||
candidateSymbol: KtSymbolWithVisibility,
|
||||
useSiteFile: KtFileSymbol,
|
||||
receiverExpression: KtExpression? = null,
|
||||
position: PsiElement
|
||||
): Boolean =
|
||||
analysisSession.visibilityChecker.isVisible(candidateSymbol, useSiteFile, position, receiverExpression)
|
||||
}
|
||||
+3
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForCo
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile
|
||||
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtVisibilityChecker
|
||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtSymbolDeclarationRendererProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
||||
@@ -61,6 +62,8 @@ private constructor(
|
||||
|
||||
override val expressionInfoProviderImpl = KtFirExpressionInfoProvider(this, token)
|
||||
|
||||
override val visibilityCheckerImpl: KtVisibilityChecker = KtFirVisibilityChecker(this, token)
|
||||
|
||||
override val typeProviderImpl = KtFirTypeProvider(this, token)
|
||||
|
||||
override val typeInfoProviderImpl = KtFirTypeInfoProvider(this, token)
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.frontend.api.fir.components
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.parentsOfType
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDesignation
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtVisibilityChecker
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirFileSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFileSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
|
||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
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
|
||||
|
||||
internal class KtFirVisibilityChecker(
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
override val token: ValidityToken
|
||||
) : KtVisibilityChecker(), KtFirAnalysisSessionComponent {
|
||||
|
||||
override fun isVisible(
|
||||
candidateSymbol: KtSymbolWithVisibility,
|
||||
useSiteFile: KtFileSymbol,
|
||||
position: PsiElement,
|
||||
receiverExpression: KtExpression?
|
||||
): Boolean {
|
||||
require(candidateSymbol is KtFirSymbol<*>)
|
||||
require(useSiteFile is KtFirFileSymbol)
|
||||
|
||||
val nonLocalContainingDeclaration = findContainingNonLocalDeclaration(position)
|
||||
|
||||
return useSiteFile.firRef.withFir { useSiteFirFile ->
|
||||
val containers = nonLocalContainingDeclaration
|
||||
?.getOrBuildFirSafe<FirCallableDeclaration<*>>(analysisSession.firResolveState)
|
||||
?.collectDesignation()
|
||||
?.path
|
||||
.orEmpty()
|
||||
|
||||
val explicitDispatchReceiver = receiverExpression
|
||||
?.getOrBuildFirSafe<FirExpression>(analysisSession.firResolveState)
|
||||
?.let { ExpressionReceiverValue(it) }
|
||||
|
||||
candidateSymbol.firRef.withFir { candidateFirSymbol ->
|
||||
require(candidateFirSymbol is FirMemberDeclaration && candidateFirSymbol is FirSymbolOwner<*>) {
|
||||
"$candidateFirSymbol must be a FirMemberDeclaration and FirSymbolOwner; it were ${candidateFirSymbol::class} instead"
|
||||
}
|
||||
|
||||
rootModuleSession.visibilityChecker.isVisible(
|
||||
candidateFirSymbol,
|
||||
rootModuleSession,
|
||||
useSiteFirFile,
|
||||
containers,
|
||||
explicitDispatchReceiver
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findContainingNonLocalDeclaration(element: PsiElement): KtCallableDeclaration? {
|
||||
return element
|
||||
.parentsOfType<KtCallableDeclaration>()
|
||||
.firstOrNull { it.isNotFromLocalClass }
|
||||
}
|
||||
|
||||
private val KtCallableDeclaration.isNotFromLocalClass
|
||||
get() = this is KtNamedFunction && (isTopLevel || containingClassOrObject?.isLocal == false) ||
|
||||
this is KtProperty && (isTopLevel || containingClassOrObject?.isLocal == false)
|
||||
}
|
||||
Reference in New Issue
Block a user