[Analysis API FIR] add check for public api

This commit is contained in:
aleksandrina-streltsova
2022-10-07 11:22:24 +03:00
committed by Space Team
parent 34d695cc72
commit 29502ba126
3 changed files with 32 additions and 0 deletions
@@ -23,7 +23,9 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
@@ -72,6 +74,11 @@ internal class KtFe10VisibilityChecker(
return false
}
override fun isPublicApi(symbol: KtSymbolWithVisibility): Boolean {
val descriptor = getSymbolDescriptor(symbol) as? DeclarationDescriptorWithVisibility ?: return false
return descriptor.isEffectivelyPublicApi || descriptor.isPublishedApi()
}
}
private fun findContainingNonLocalDeclaration(element: PsiElement): KtCallableDeclaration? {
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.api.components.KtVisibilityChecker
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.KtFirSymbol
import org.jetbrains.kotlin.analysis.api.fir.utils.firSymbol
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
@@ -19,8 +20,12 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
import org.jetbrains.kotlin.fir.resolve.transformers.publishedApiEffectiveVisibility
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.visibilityChecker
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
@@ -61,6 +66,15 @@ internal class KtFirVisibilityChecker(
)
}
override fun isPublicApi(symbol: KtSymbolWithVisibility): Boolean {
require(symbol is KtFirSymbol<*>)
val declaration = symbol.firSymbol.fir as? FirMemberDeclaration ?: return false
// Inspecting visibility requires resolving to status
declaration.lazyResolveToPhase(FirResolvePhase.STATUS)
return declaration.effectiveVisibility.publicApi || declaration.publishedApiEffectiveVisibility?.publicApi == true
}
private fun collectContainingDeclarations(position: PsiElement): List<FirDeclaration> {
val nonLocalContainer = findContainingNonLocalDeclaration(position)
val nonLocalContainerFir = nonLocalContainer?.getOrBuildFirSafe<FirDeclaration>(analysisSession.firResolveSession)
@@ -18,6 +18,8 @@ public abstract class KtVisibilityChecker : KtAnalysisSessionComponent() {
position: PsiElement,
receiverExpression: KtExpression?
): Boolean
public abstract fun isPublicApi(symbol: KtSymbolWithVisibility): Boolean
}
public interface KtVisibilityCheckerMixIn : KtAnalysisSessionMixIn {
@@ -29,4 +31,13 @@ public interface KtVisibilityCheckerMixIn : KtAnalysisSessionMixIn {
): Boolean = withValidityAssertion {
analysisSession.visibilityChecker.isVisible(candidateSymbol, useSiteFile, position, receiverExpression)
}
/**
* Returns true for effectively public symbols, including internal declarations with @PublishedApi annotation.
* In 'Explicit API' mode explicit visibility modifier and explicit return types are required for such symbols.
* See FirExplicitApiDeclarationChecker.kt
*/
public fun isPublicApi(symbol: KtSymbolWithVisibility): Boolean = withValidityAssertion {
analysisSession.visibilityChecker.isPublicApi(symbol)
}
}