FIR: support private-in-file effective visibility

This commit is contained in:
Mikhail Glukhikh
2021-04-07 14:43:14 +03:00
parent 6ee169c01e
commit 9af1de272e
9 changed files with 31 additions and 26 deletions
@@ -63,7 +63,7 @@ fun deserializeClassToSymbol(
val status = FirResolvedDeclarationStatusImpl(
visibility,
modality,
visibility.toEffectiveVisibility(parentContext?.outerClassSymbol)
visibility.toEffectiveVisibility(parentContext?.outerClassSymbol, forClass = true)
).apply {
isExpect = Flags.IS_EXPECT_CLASS.get(flags)
isActual = false
@@ -248,7 +248,7 @@ class JavaSymbolProvider(
existingNestedClassifierNames += javaClass.innerClassNames
scopeProvider = this@JavaSymbolProvider.scopeProvider
val selfEffectiveVisibility = visibility.toEffectiveVisibility(parentClassSymbol?.toLookupTag())
val selfEffectiveVisibility = visibility.toEffectiveVisibility(parentClassSymbol?.toLookupTag(), forClass = true)
val parentEffectiveVisibility = parentClassSymbol?.let {
parentClassEffectiveVisibilityCache[it] ?: it.fir.effectiveVisibility
} ?: EffectiveVisibility.Public
@@ -13,18 +13,21 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
fun Visibility.toEffectiveVisibility(
ownerSymbol: FirClassLikeSymbol<*>?,
forClass: Boolean = false,
checkPublishedApi: Boolean = false
): EffectiveVisibility {
return toEffectiveVisibility(ownerSymbol?.toLookupTag(), checkPublishedApi)
return toEffectiveVisibility(ownerSymbol?.toLookupTag(), forClass, checkPublishedApi)
}
fun Visibility.toEffectiveVisibility(
owner: ConeClassLikeLookupTag?,
forClass: Boolean = false,
checkPublishedApi: Boolean = false
): EffectiveVisibility {
customEffectiveVisibility()?.let { return it }
return when (this.normalize()) {
Visibilities.Private, Visibilities.PrivateToThis, Visibilities.InvisibleFake -> EffectiveVisibility.PrivateInClass
Visibilities.PrivateToThis, Visibilities.InvisibleFake -> EffectiveVisibility.PrivateInClass
Visibilities.Private -> if (owner == null && forClass) EffectiveVisibility.PrivateInFile else EffectiveVisibility.PrivateInClass
Visibilities.Protected -> EffectiveVisibility.Protected(owner)
Visibilities.Internal -> when (!checkPublishedApi /*|| !owner.isPublishedApi()*/) { // TODO
true -> EffectiveVisibility.Internal
@@ -168,7 +168,9 @@ class FirStatusResolver(
containingClass is FirAnonymousObject -> EffectiveVisibility.Local
else -> EffectiveVisibility.Public
}
val selfEffectiveVisibility = visibility.toEffectiveVisibility(containingClass?.symbol?.toLookupTag())
val selfEffectiveVisibility = visibility.toEffectiveVisibility(
containingClass?.symbol?.toLookupTag(), forClass = declaration is FirClass<*>
)
val effectiveVisibility = parentEffectiveVisibility.lowerBound(selfEffectiveVisibility, session.typeContext)
return status.resolved(visibility, modality, effectiveVisibility)
}
+2 -2
View File
@@ -1,13 +1,13 @@
compiler/testData/cli/jvm/firError.kt:5:13: error: x must be initialized before access
println(x)
^
compiler/testData/cli/jvm/firError.kt:10:16: error: public subclass exposes its private supertype 'Private'
compiler/testData/cli/jvm/firError.kt:10:16: error: public subclass exposes its private-in-file supertype 'Private'
class Public : Private() {
^
compiler/testData/cli/jvm/firError.kt:11:5: error: property must be initialized or be abstract
val x: Private
^
compiler/testData/cli/jvm/firError.kt:11:9: error: public property exposes its private type 'Private'
compiler/testData/cli/jvm/firError.kt:11:9: error: public property exposes its private-in-file type 'Private'
val x: Private
^
COMPILATION_ERROR
@@ -13,17 +13,17 @@ class Public {
private class PrivateInFileClass {
private open class NestedPrivate
fun test1() = NestedPrivate()
fun test2(p: NestedPrivate) {}
fun NestedPrivate.test3() {}
val test4 = NestedPrivate()
class Test5 : NestedPrivate()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>test1<!>() = NestedPrivate()
fun test2(<!EXPOSED_PARAMETER_TYPE!>p: NestedPrivate<!>) {}
fun <!EXPOSED_RECEIVER_TYPE!>NestedPrivate<!>.test3() {}
val <!EXPOSED_PROPERTY_TYPE!>test4<!> = NestedPrivate()
class Test5 : <!EXPOSED_SUPER_CLASS!>NestedPrivate<!>()
}
private interface PrivateInFile {
private class Private
fun expose() = Private()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>expose<!>() = Private()
}
// Exposes 'PrivateInFile$Private' via 'expose'
@@ -13,17 +13,17 @@ class Public {
private class PrivateInFileClass {
private open class NestedPrivate
fun test1() = NestedPrivate()
fun test2(p: NestedPrivate) {}
fun NestedPrivate.test3() {}
val test4 = NestedPrivate()
class Test5 : NestedPrivate()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>test1<!>() = NestedPrivate()
fun test2(<!EXPOSED_PARAMETER_TYPE!>p: NestedPrivate<!>) {}
fun <!EXPOSED_RECEIVER_TYPE!>NestedPrivate<!>.test3() {}
val <!EXPOSED_PROPERTY_TYPE!>test4<!> = NestedPrivate()
class Test5 : <!EXPOSED_SUPER_CLASS!>NestedPrivate<!>()
}
private interface PrivateInFile {
private class Private
fun expose() = Private()
fun <!EXPOSED_FUNCTION_RETURN_TYPE!>expose<!>() = Private()
}
// Exposes 'PrivateInFile$Private' via 'expose'
@@ -11,4 +11,4 @@ package a
import pack1.SomeClass.*
private class X : <!HIDDEN!>N<!>()
private class X : <!EXPOSED_SUPER_CLASS, HIDDEN!>N<!>()
+6 -6
View File
@@ -2,18 +2,18 @@ private class A
open class B<T>(val x: T)
class C(<error descr="[EXPOSED_PARAMETER_TYPE] public function exposes its private parameter type 'A'">x: A</error>): <error descr="[EXPOSED_SUPER_CLASS] public subclass exposes its private supertype 'A'">B<A></error>(x)
class C(<error descr="[EXPOSED_PARAMETER_TYPE] public function exposes its private-in-file parameter type 'A'">x: A</error>): <error descr="[EXPOSED_SUPER_CLASS] public subclass exposes its private-in-file supertype 'A'">B<A></error>(x)
private class D {
class E
}
fun <error descr="[EXPOSED_FUNCTION_RETURN_TYPE] public function exposes its private return type 'A'">create</error>() = A()
fun <error descr="[EXPOSED_FUNCTION_RETURN_TYPE] public function exposes its private-in-file return type 'A'">create</error>() = A()
fun <error descr="[EXPOSED_FUNCTION_RETURN_TYPE] public function exposes its private return type 'A'">create</error>(<error descr="[EXPOSED_PARAMETER_TYPE] public function exposes its private parameter type 'A'">a: A</error>) = B(a)
fun <error descr="[EXPOSED_FUNCTION_RETURN_TYPE] public function exposes its private-in-file return type 'A'">create</error>(<error descr="[EXPOSED_PARAMETER_TYPE] public function exposes its private-in-file parameter type 'A'">a: A</error>) = B(a)
val <error descr="[EXPOSED_PROPERTY_TYPE] public property exposes its private type 'A'">x</error> = create()
val <error descr="[EXPOSED_PROPERTY_TYPE] public property exposes its private-in-file type 'A'">x</error> = create()
val <error descr="[EXPOSED_PROPERTY_TYPE] public property exposes its private type 'A'">y</error> = create(x)
val <error descr="[EXPOSED_PROPERTY_TYPE] public property exposes its private-in-file type 'A'">y</error> = create(x)
val <error descr="[EXPOSED_PROPERTY_TYPE] public property exposes its private type 'E'">z</error>: B<D.E>? = null
val <error descr="[EXPOSED_PROPERTY_TYPE] public property exposes its private-in-file type 'E'">z</error>: B<D.E>? = null