[FIR] Support effective visibility with @PublishedApi

#KT-46270 Fixed
This commit is contained in:
Dmitriy Novozhilov
2021-04-23 17:35:39 +03:00
committed by TeamCityServer
parent 32c3f85679
commit 07b15f9de6
8 changed files with 37 additions and 14 deletions
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
import org.jetbrains.kotlin.fir.resolve.inference.isFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isFunctionalType
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.publishedApiEffectiveVisibility
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -196,7 +197,8 @@ object FirInlineDeclarationChecker : FirMemberDeclarationChecker() {
context: CheckerContext context: CheckerContext
) { ) {
if (calledDeclaration == null) return if (calledDeclaration == null) return
val calledFunEffectiveVisibility = calledDeclaration.effectiveVisibility.let { val recordedEffectiveVisibility = calledDeclaration.publishedApiEffectiveVisibility ?: calledDeclaration.effectiveVisibility
val calledFunEffectiveVisibility = recordedEffectiveVisibility.let {
if (it == EffectiveVisibility.Local) { if (it == EffectiveVisibility.Local) {
EffectiveVisibility.Public EffectiveVisibility.Public
} else { } else {
@@ -22,16 +22,16 @@ fun Visibility.toEffectiveVisibility(
fun Visibility.toEffectiveVisibility( fun Visibility.toEffectiveVisibility(
owner: ConeClassLikeLookupTag?, owner: ConeClassLikeLookupTag?,
forClass: Boolean = false, forClass: Boolean = false,
checkPublishedApi: Boolean = false ownerIsPublishedApi: Boolean = false
): EffectiveVisibility { ): EffectiveVisibility {
customEffectiveVisibility()?.let { return it } customEffectiveVisibility()?.let { return it }
return when (this.normalize()) { return when (this.normalize()) {
Visibilities.PrivateToThis, Visibilities.InvisibleFake -> EffectiveVisibility.PrivateInClass Visibilities.PrivateToThis, Visibilities.InvisibleFake -> EffectiveVisibility.PrivateInClass
Visibilities.Private -> if (owner == null && forClass) EffectiveVisibility.PrivateInFile else EffectiveVisibility.PrivateInClass Visibilities.Private -> if (owner == null && forClass) EffectiveVisibility.PrivateInFile else EffectiveVisibility.PrivateInClass
Visibilities.Protected -> EffectiveVisibility.Protected(owner) Visibilities.Protected -> EffectiveVisibility.Protected(owner)
Visibilities.Internal -> when (!checkPublishedApi /*|| !owner.isPublishedApi()*/) { // TODO Visibilities.Internal -> when (ownerIsPublishedApi) {
true -> EffectiveVisibility.Internal true -> EffectiveVisibility.Public
false -> EffectiveVisibility.Public false -> EffectiveVisibility.Internal
} }
Visibilities.Public -> EffectiveVisibility.Public Visibilities.Public -> EffectiveVisibility.Public
Visibilities.Local -> EffectiveVisibility.Local Visibilities.Local -> EffectiveVisibility.Local
@@ -16,6 +16,9 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.toEffectiveVisibility import org.jetbrains.kotlin.fir.toEffectiveVisibility
import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.StandardClassIds
class FirStatusResolver( class FirStatusResolver(
val session: FirSession, val session: FirSession,
@@ -172,6 +175,22 @@ class FirStatusResolver(
containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*> containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*>
) )
val effectiveVisibility = parentEffectiveVisibility.lowerBound(selfEffectiveVisibility, session.typeContext) val effectiveVisibility = parentEffectiveVisibility.lowerBound(selfEffectiveVisibility, session.typeContext)
val annotations = ((containingProperty ?: declaration) as? FirAnnotatedDeclaration)?.annotations ?: emptyList()
if (annotations.any { it.typeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId == StandardClassIds.PublishedApi }) {
val publishedApiSelfEffectiveVisibility = visibility.toEffectiveVisibility(
containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*>, ownerIsPublishedApi = true
)
val parentPublishedEffectiveVisibility = when {
containingProperty != null -> containingProperty.publishedApiEffectiveVisibility
containingClass is FirRegularClass -> containingClass.publishedApiEffectiveVisibility
else -> null
} ?: parentEffectiveVisibility
declaration.publishedApiEffectiveVisibility = parentPublishedEffectiveVisibility.lowerBound(
publishedApiSelfEffectiveVisibility,
session.typeContext
)
}
return status.resolved(visibility, modality, effectiveVisibility) return status.resolved(visibility, modality, effectiveVisibility)
} }
@@ -243,3 +262,6 @@ private fun FirDeclaration.hasOwnBodyOrAccessorBody(): Boolean {
else -> true else -> true
} }
} }
private object PublishedApiEffectiveVisibilityKey : FirDeclarationDataKey()
var FirDeclaration.publishedApiEffectiveVisibility: EffectiveVisibility? by FirDeclarationDataRegistry.data(PublishedApiEffectiveVisibilityKey)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
//WITH_REFLECT //WITH_REFLECT
class A { class A {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// MODULE: lib // MODULE: lib
// FILE: lib.kt // FILE: lib.kt
class A { class A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// MODULE: lib // MODULE: lib
// FILE: lib.kt // FILE: lib.kt
@PublishedApi @PublishedApi
@@ -1,13 +1,13 @@
// !DIAGNOSTICS: -EXPOSED_PARAMETER_TYPE -NOTHING_TO_INLINE // !DIAGNOSTICS: -EXPOSED_PARAMETER_TYPE -NOTHING_TO_INLINE
inline fun call(a: A) { inline fun call(a: A) {
a.<!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>test<!>() a.test()
<!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>publishedTopLevel<!>() publishedTopLevel()
a.<!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>publishedVar<!> a.publishedVar
a.publishedVar <!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>=<!> 1 a.publishedVar = 1
<!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>publishedVarTopLevel<!> publishedVarTopLevel
publishedVarTopLevel <!NON_PUBLIC_CALL_FROM_PUBLIC_INLINE!>=<!> 1 publishedVarTopLevel = 1
} }
inline var inlineVar: Int inline var inlineVar: Int
@@ -110,6 +110,8 @@ object StandardClassIds {
val FlexibleNullability = ClassId(FqName("kotlin.internal.ir"), Name.identifier("FlexibleNullability")) val FlexibleNullability = ClassId(FqName("kotlin.internal.ir"), Name.identifier("FlexibleNullability"))
val EnhancedNullability = ClassId(FqName("kotlin.jvm.internal"), Name.identifier("EnhancedNullability")) val EnhancedNullability = ClassId(FqName("kotlin.jvm.internal"), Name.identifier("EnhancedNullability"))
val PublishedApi = "PublishedApi".baseId()
} }
private fun <K, V> Map<K, V>.inverseMap() = entries.associate { (k, v) -> v to k } private fun <K, V> Map<K, V>.inverseMap() = entries.associate { (k, v) -> v to k }