diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt index e247ca1dbd4..aecb99ec4a1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt @@ -643,7 +643,7 @@ internal fun isVisible( val visibility = descriptor.visibility if (position == QualifierPosition.IMPORT) { - if (Visibilities.isPrivate(visibility)) return false + if (Visibilities.isPrivate(visibility)) return Visibilities.inSameFile(descriptor, shouldBeVisibleFrom) if (!visibility.mustCheckInImports()) return true } return Visibilities.isVisibleIgnoringReceiver(descriptor, shouldBeVisibleFrom) diff --git a/compiler/testData/codegen/box/package/privateMembersInImportList.kt b/compiler/testData/codegen/box/package/privateMembersInImportList.kt new file mode 100644 index 00000000000..e7009753efa --- /dev/null +++ b/compiler/testData/codegen/box/package/privateMembersInImportList.kt @@ -0,0 +1,40 @@ +package test + +import test.C.E1 +import test.A.B.* +import test.Obj.CInObj.Tt +import test.Obj.foo + +private enum class C { + E1 +} + +class A { + private class B { + object C + class D + } + + fun test() { + C + D() + } +} + +private object Obj { + private class CInObj { + class Tt + } + + fun foo() { + Tt() + } +} + +fun box(): String { + E1 + A().test() + foo() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportPrivateMember.kt b/compiler/testData/diagnostics/tests/imports/ImportPrivateMember.kt new file mode 100644 index 00000000000..568b1a01e0c --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportPrivateMember.kt @@ -0,0 +1,37 @@ +package test + +import test.TopLevelClass.NestedClass +import test.TopLevelClass.NestedClass.InNested +import test.TopLevelEnum.NestedEnum.NestedEntry +import test.TopLevelObject.inObject +import test.TopLevelEnum.E1 + +private class TopLevelClass { + private class NestedClass { + class InNested + } + + fun test() { + InNested() + } +} + +private enum class TopLevelEnum(private val e: NestedEnum) { + E1(NestedEntry); + + private enum class NestedEnum { + NestedEntry; + } +} + +private object TopLevelObject { + fun inObject() {} +} + +fun testAccess() { + NestedClass() + E1 + InNested() + NestedEntry + inObject() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportPrivateMember.txt b/compiler/testData/diagnostics/tests/imports/ImportPrivateMember.txt new file mode 100644 index 00000000000..3b837d4e57e --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportPrivateMember.txt @@ -0,0 +1,74 @@ +package + +package test { + public fun testAccess(): kotlin.Unit + + private final class TopLevelClass { + public constructor TopLevelClass() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + private final class NestedClass { + public constructor NestedClass() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class InNested { + public constructor InNested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } + } + + private final enum class TopLevelEnum : kotlin.Enum { + enum entry E1 + + private constructor TopLevelEnum(/*0*/ e: test.TopLevelEnum.NestedEnum) + private final val e: test.TopLevelEnum.NestedEnum + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.TopLevelEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + private final enum class NestedEnum : kotlin.Enum { + enum entry NestedEntry + + private constructor NestedEnum() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.TopLevelEnum.NestedEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.TopLevelEnum.NestedEnum + public final /*synthesized*/ fun values(): kotlin.Array + } + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.TopLevelEnum + public final /*synthesized*/ fun values(): kotlin.Array + } + + private object TopLevelObject { + private constructor TopLevelObject() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun inObject(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/imports/ImportPrivateMemberFromOtherFile.kt b/compiler/testData/diagnostics/tests/imports/ImportPrivateMemberFromOtherFile.kt new file mode 100644 index 00000000000..525c8dd5774 --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportPrivateMemberFromOtherFile.kt @@ -0,0 +1,26 @@ +// FILE: A.kt + +class A { + private class Nested { + object O1 + } +} + +// FILE: B.java + +public class B { + private static class JC { + public static class JC1 { + } + } +} + +// FILE: C.kt + +import A.Nested.* +import B.JC.JC1 + +fun test() { + O1 + JC1() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportPrivateMemberFromOtherFile.txt b/compiler/testData/diagnostics/tests/imports/ImportPrivateMemberFromOtherFile.txt new file mode 100644 index 00000000000..39d8a0666e8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportPrivateMemberFromOtherFile.txt @@ -0,0 +1,45 @@ +package + +public fun test(): kotlin.Unit + +public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + private final class Nested { + public constructor Nested() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public object O1 { + private constructor O1() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } +} + +public open class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + private open class JC { + private constructor JC() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public open class JC1 { + public constructor JC1() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } +} diff --git a/compiler/testData/diagnostics/tests/imports/ImportPrivateMembersWithStar.kt b/compiler/testData/diagnostics/tests/imports/ImportPrivateMembersWithStar.kt new file mode 100644 index 00000000000..e93a7515d4c --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportPrivateMembersWithStar.kt @@ -0,0 +1,32 @@ +package test + +import test.TopLevelClass.NestedClass.* +import test.TopLevelEnum.NestedEnum.* +import test.TopLevelEnum.* + +private class TopLevelClass { + private class NestedClass { + class A1 + object A2 + } + + fun test() { + A1() + A2 + } +} + +private enum class TopLevelEnum(private val e: NestedEnum) { + E1(NestedEntry); + + private enum class NestedEnum { + NestedEntry; + } +} + +fun testAccess() { + E1 + NestedEntry + A1() + A2 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportPrivateMembersWithStar.txt b/compiler/testData/diagnostics/tests/imports/ImportPrivateMembersWithStar.txt new file mode 100644 index 00000000000..b94209cd4a1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportPrivateMembersWithStar.txt @@ -0,0 +1,73 @@ +package + +package test { + public fun testAccess(): kotlin.Unit + + private final class TopLevelClass { + public constructor TopLevelClass() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final fun test(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + private final class NestedClass { + public constructor NestedClass() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final class A1 { + public constructor A1() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public object A2 { + private constructor A2() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + } + } + + private final enum class TopLevelEnum : kotlin.Enum { + enum entry E1 + + private constructor TopLevelEnum(/*0*/ e: test.TopLevelEnum.NestedEnum) + private final val e: test.TopLevelEnum.NestedEnum + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.TopLevelEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + private final enum class NestedEnum : kotlin.Enum { + enum entry NestedEntry + + private constructor NestedEnum() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.TopLevelEnum.NestedEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.TopLevelEnum.NestedEnum + public final /*synthesized*/ fun values(): kotlin.Array + } + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.TopLevelEnum + public final /*synthesized*/ fun values(): kotlin.Array + } +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 2a330a33db6..bc788706ef4 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -11651,6 +11651,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("privateMembersInImportList.kt") + public void testPrivateMembersInImportList() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/package/privateMembersInImportList.kt"); + doTest(fileName); + } + @TestMetadata("privateTopLevelPropAndVarInInner.kt") public void testPrivateTopLevelPropAndVarInInner() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/package/privateTopLevelPropAndVarInInner.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index a9c332e8e7f..7890769ddb4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -9487,6 +9487,24 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("ImportPrivateMember.kt") + public void testImportPrivateMember() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportPrivateMember.kt"); + doTest(fileName); + } + + @TestMetadata("ImportPrivateMemberFromOtherFile.kt") + public void testImportPrivateMemberFromOtherFile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportPrivateMemberFromOtherFile.kt"); + doTest(fileName); + } + + @TestMetadata("ImportPrivateMembersWithStar.kt") + public void testImportPrivateMembersWithStar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportPrivateMembersWithStar.kt"); + doTest(fileName); + } + @TestMetadata("ImportProtectedClass.kt") public void testImportProtectedClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportProtectedClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index fd16f61b991..944bbd21db0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11651,6 +11651,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("privateMembersInImportList.kt") + public void testPrivateMembersInImportList() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/package/privateMembersInImportList.kt"); + doTest(fileName); + } + @TestMetadata("privateTopLevelPropAndVarInInner.kt") public void testPrivateTopLevelPropAndVarInInner() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/package/privateTopLevelPropAndVarInInner.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index d8f89276e3d..70bb224b775 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11651,6 +11651,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("privateMembersInImportList.kt") + public void testPrivateMembersInImportList() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/package/privateMembersInImportList.kt"); + doTest(fileName); + } + @TestMetadata("privateTopLevelPropAndVarInInner.kt") public void testPrivateTopLevelPropAndVarInInner() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/package/privateTopLevelPropAndVarInInner.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibilities.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibilities.java index 4c77faff58c..9493b65544d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibilities.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/Visibilities.java @@ -39,16 +39,6 @@ public class Visibilities { return true; } - // Note that this method returns false if `from` declaration is `init` initializer - // because initializer does not have source element - private boolean inSameFile(@NotNull DeclarationDescriptor what, @NotNull DeclarationDescriptor from) { - SourceFile fromContainingFile = DescriptorUtils.getContainingSourceFile(from); - if (fromContainingFile != SourceFile.NO_SOURCE_FILE) { - return fromContainingFile.equals(DescriptorUtils.getContainingSourceFile(what)); - } - return false; - } - private boolean hasContainingSourceFile(@NotNull DeclarationDescriptor descriptor) { return DescriptorUtils.getContainingSourceFile(descriptor) != SourceFile.NO_SOURCE_FILE; } @@ -318,6 +308,16 @@ public class Visibilities { return findInvisibleMember(IRRELEVANT_RECEIVER, what, from) == null; } + // Note that this method returns false if `from` declaration is `init` initializer + // because initializer does not have source element + public static boolean inSameFile(@NotNull DeclarationDescriptor what, @NotNull DeclarationDescriptor from) { + SourceFile fromContainingFile = DescriptorUtils.getContainingSourceFile(from); + if (fromContainingFile != SourceFile.NO_SOURCE_FILE) { + return fromContainingFile.equals(DescriptorUtils.getContainingSourceFile(what)); + } + return false; + } + @Nullable public static DeclarationDescriptorWithVisibility findInvisibleMember( @Nullable ReceiverValue receiver, diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index df354e50432..ed65b8c0df8 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13123,6 +13123,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("privateMembersInImportList.kt") + public void testPrivateMembersInImportList() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/package/privateMembersInImportList.kt"); + doTest(fileName); + } + @TestMetadata("privateTopLevelPropAndVarInInner.kt") public void testPrivateTopLevelPropAndVarInInner() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/package/privateTopLevelPropAndVarInInner.kt");