From 9af1de272e50883123e5e14e9f923e5713f71b1b Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 7 Apr 2021 14:43:14 +0300 Subject: [PATCH] FIR: support private-in-file effective visibility --- .../fir/deserialization/ClassDeserialization.kt | 2 +- .../jetbrains/kotlin/fir/java/JavaSymbolProvider.kt | 2 +- .../jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt | 7 +++++-- .../fir/resolve/transformers/FirStatusResolver.kt | 4 +++- compiler/testData/cli/jvm/firError.out | 4 ++-- .../diagnostics/tests/exposed/privateInFile.fir.kt | 12 ++++++------ .../tests/exposed/privateInFileDisabled.fir.kt | 12 ++++++------ .../tests/imports/PrivateClassReferencedError.fir.kt | 2 +- idea/testData/checker/ExposedInferredType.fir.kt | 12 ++++++------ 9 files changed, 31 insertions(+), 26 deletions(-) diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt index 8ca2e4023d7..58313500876 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt @@ -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 diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt index 95ddef966f1..217d746e28d 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -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 diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt index 10abd0c4b43..70d5e42c777 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/EffectiveVisibilityUtils.kt @@ -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 diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt index dbe5bf15687..96feef467bd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirStatusResolver.kt @@ -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) } diff --git a/compiler/testData/cli/jvm/firError.out b/compiler/testData/cli/jvm/firError.out index 21922f3d7fc..4b19f47a1fc 100644 --- a/compiler/testData/cli/jvm/firError.out +++ b/compiler/testData/cli/jvm/firError.out @@ -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 diff --git a/compiler/testData/diagnostics/tests/exposed/privateInFile.fir.kt b/compiler/testData/diagnostics/tests/exposed/privateInFile.fir.kt index 173e381c646..93174eccaba 100644 --- a/compiler/testData/diagnostics/tests/exposed/privateInFile.fir.kt +++ b/compiler/testData/diagnostics/tests/exposed/privateInFile.fir.kt @@ -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 test1() = NestedPrivate() + fun test2(p: NestedPrivate) {} + fun NestedPrivate.test3() {} + val test4 = NestedPrivate() + class Test5 : NestedPrivate() } private interface PrivateInFile { private class Private - fun expose() = Private() + fun expose() = Private() } // Exposes 'PrivateInFile$Private' via 'expose' diff --git a/compiler/testData/diagnostics/tests/exposed/privateInFileDisabled.fir.kt b/compiler/testData/diagnostics/tests/exposed/privateInFileDisabled.fir.kt index 025a5faaf20..fd3859693e2 100644 --- a/compiler/testData/diagnostics/tests/exposed/privateInFileDisabled.fir.kt +++ b/compiler/testData/diagnostics/tests/exposed/privateInFileDisabled.fir.kt @@ -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 test1() = NestedPrivate() + fun test2(p: NestedPrivate) {} + fun NestedPrivate.test3() {} + val test4 = NestedPrivate() + class Test5 : NestedPrivate() } private interface PrivateInFile { private class Private - fun expose() = Private() + fun expose() = Private() } // Exposes 'PrivateInFile$Private' via 'expose' diff --git a/compiler/testData/diagnostics/tests/imports/PrivateClassReferencedError.fir.kt b/compiler/testData/diagnostics/tests/imports/PrivateClassReferencedError.fir.kt index ffd7e80ca90..53b743de2c4 100644 --- a/compiler/testData/diagnostics/tests/imports/PrivateClassReferencedError.fir.kt +++ b/compiler/testData/diagnostics/tests/imports/PrivateClassReferencedError.fir.kt @@ -11,4 +11,4 @@ package a import pack1.SomeClass.* -private class X : N() +private class X : N() diff --git a/idea/testData/checker/ExposedInferredType.fir.kt b/idea/testData/checker/ExposedInferredType.fir.kt index 1609795fe2b..f45f426d5bf 100644 --- a/idea/testData/checker/ExposedInferredType.fir.kt +++ b/idea/testData/checker/ExposedInferredType.fir.kt @@ -2,18 +2,18 @@ private class A open class B(val x: T) -class C(x: A): B(x) +class C(x: A): B(x) private class D { class E } -fun create() = A() +fun create() = A() -fun create(a: A) = B(a) +fun create(a: A) = B(a) -val x = create() +val x = create() -val y = create(x) +val y = create(x) -val z: B? = null +val z: B? = null