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,
|
KtSymbolsMixIn,
|
||||||
KtReferenceResolveMixIn,
|
KtReferenceResolveMixIn,
|
||||||
KtReferenceShortenerMixIn,
|
KtReferenceShortenerMixIn,
|
||||||
KtSymbolDeclarationRendererMixIn {
|
KtSymbolDeclarationRendererMixIn,
|
||||||
|
KtVisibilityCheckerMixIn {
|
||||||
|
|
||||||
override val analysisSession: KtAnalysisSession get() = this
|
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
|
internal val expressionInfoProvider: KtExpressionInfoProvider get() = expressionInfoProviderImpl
|
||||||
protected abstract val expressionInfoProviderImpl: KtExpressionInfoProvider
|
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.fir.low.level.api.api.getFirFile
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
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.tokens.ValidityToken
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtSymbolDeclarationRendererProvider
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtSymbolDeclarationRendererProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
||||||
@@ -61,6 +62,8 @@ private constructor(
|
|||||||
|
|
||||||
override val expressionInfoProviderImpl = KtFirExpressionInfoProvider(this, token)
|
override val expressionInfoProviderImpl = KtFirExpressionInfoProvider(this, token)
|
||||||
|
|
||||||
|
override val visibilityCheckerImpl: KtVisibilityChecker = KtFirVisibilityChecker(this, token)
|
||||||
|
|
||||||
override val typeProviderImpl = KtFirTypeProvider(this, token)
|
override val typeProviderImpl = KtFirTypeProvider(this, token)
|
||||||
|
|
||||||
override val typeInfoProviderImpl = KtFirTypeInfoProvider(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