diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java index ea083d93f34..b187ebdc619 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java @@ -70,6 +70,7 @@ public class AsmUtil { .put(Visibilities.PRIVATE, ACC_PRIVATE) .put(Visibilities.PROTECTED, ACC_PROTECTED) .put(JavaDescriptorResolver.PROTECTED_STATIC_VISIBILITY, ACC_PROTECTED) + .put(JavaDescriptorResolver.PROTECTED_AND_PACKAGE, ACC_PROTECTED) .put(Visibilities.PUBLIC, ACC_PUBLIC) .put(Visibilities.INTERNAL, ACC_PUBLIC) .put(Visibilities.LOCAL, NO_FLAG_LOCAL) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java index b16c7cda7bf..eb7a79acdf3 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java @@ -95,7 +95,7 @@ public final class DescriptorResolverUtils { if (modifierListOwner.hasModifierProperty(PsiModifier.STATIC)) { return JavaDescriptorResolver.PROTECTED_STATIC_VISIBILITY; } - return Visibilities.PROTECTED; + return JavaDescriptorResolver.PROTECTED_AND_PACKAGE; } return JavaDescriptorResolver.PACKAGE_VISIBILITY; } @@ -121,7 +121,7 @@ public final class DescriptorResolverUtils { public static Visibility getConstructorVisibility(ClassDescriptor classDescriptor) { Visibility containingClassVisibility = classDescriptor.getVisibility(); if (containingClassVisibility == JavaDescriptorResolver.PROTECTED_STATIC_VISIBILITY) { - return Visibilities.PROTECTED; + return JavaDescriptorResolver.PROTECTED_AND_PACKAGE; } return containingClassVisibility; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 9aab7fc16d7..4ed129c8d78 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -41,10 +41,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes public static Visibility PACKAGE_VISIBILITY = new Visibility("package", false) { @Override protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) { - NamespaceDescriptor parentPackage = DescriptorUtils.getParentOfType(what, NamespaceDescriptor.class); - NamespaceDescriptor fromPackage = DescriptorUtils.getParentOfType(from, NamespaceDescriptor.class, false); - assert parentPackage != null; - return parentPackage.equals(fromPackage); + return DescriptorUtils.isInSameNamespace(what, from); } @Override @@ -84,6 +81,34 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes } }; + public static final Visibility PROTECTED_AND_PACKAGE = new Visibility("protected_and_package", false) { + @Override + protected boolean isVisible(@NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) { + if (DescriptorUtils.isInSameNamespace(what, from)) { + return true; + } + + ClassDescriptor whatClass = DescriptorUtils.getParentOfType(what, ClassDescriptor.class, false); + if (whatClass == null) return false; + + ClassDescriptor fromClass = DescriptorUtils.getParentOfType(from, ClassDescriptor.class, false); + if (fromClass == null) return false; + + if (DescriptorUtils.isSubclass(fromClass, whatClass)) { + return true; + } + return isVisible(what, fromClass.getContainingDeclaration()); + } + + @Override + protected Integer compareTo(@NotNull Visibility visibility) { + if (this == visibility) return 0; + if (visibility == Visibilities.INTERNAL) return null; + if (visibility == Visibilities.PRIVATE) return 1; + return -1; + } + }; + private JavaPropertyResolver propertiesResolver; private JavaClassResolver classResolver; private JavaConstructorResolver constructorResolver; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 632d2cda915..ac2b5c01680 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -135,6 +135,12 @@ public class DescriptorUtils { return descriptor.getContainingDeclaration() instanceof NamespaceDescriptor; } + public static boolean isInSameNamespace(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) { + NamespaceDescriptor whatPackage = DescriptorUtils.getParentOfType(first, NamespaceDescriptor.class, false); + NamespaceDescriptor fromPackage = DescriptorUtils.getParentOfType(second, NamespaceDescriptor.class, false); + return fromPackage != null && whatPackage != null && whatPackage.equals(fromPackage); + } + @Nullable public static DeclarationDescriptor findTopLevelParent(@NotNull DeclarationDescriptor declarationDescriptor) { DeclarationDescriptor descriptor = declarationDescriptor; diff --git a/compiler/frontend/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java b/compiler/frontend/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java index 42350fe59ab..662a6f9df91 100644 --- a/compiler/frontend/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java @@ -317,6 +317,10 @@ public class DescriptorRendererImpl implements DescriptorRenderer { else if ("protected_static".equals(visibility.toString())) { builder.append("protected/*protected static*/ "); } + else if ("protected_and_package".equals(visibility.toString())) { + builder.append("protected/*protected and package*/ "); + } + else{ builder.append(renderKeyword(visibility.toString())).append(" "); } diff --git a/compiler/testData/codegen/visibility/protected_and_package/overrideProtectedFunInPackage.java b/compiler/testData/codegen/visibility/protected_and_package/overrideProtectedFunInPackage.java new file mode 100644 index 00000000000..40b91da9818 --- /dev/null +++ b/compiler/testData/codegen/visibility/protected_and_package/overrideProtectedFunInPackage.java @@ -0,0 +1,9 @@ +package protectedPack; + +import java.lang.String; + +public class overrideProtectedFunInPackage { + protected String foo() { + return "fail"; + } +} diff --git a/compiler/testData/codegen/visibility/protected_and_package/overrideProtectedFunInPackage.kt b/compiler/testData/codegen/visibility/protected_and_package/overrideProtectedFunInPackage.kt new file mode 100644 index 00000000000..c372f368c72 --- /dev/null +++ b/compiler/testData/codegen/visibility/protected_and_package/overrideProtectedFunInPackage.kt @@ -0,0 +1,17 @@ +package protectedPackKotlin + +import protectedPack.overrideProtectedFunInPackage + +class Derived: overrideProtectedFunInPackage() { + protected override fun foo(): String? { + return "OK" + } + + fun test(): String { + return foo()!! + } +} + +fun box(): String { + return Derived().test() +} diff --git a/compiler/testData/codegen/visibility/protected_and_package/protectedFunInPackage.java b/compiler/testData/codegen/visibility/protected_and_package/protectedFunInPackage.java new file mode 100644 index 00000000000..4ded638d775 --- /dev/null +++ b/compiler/testData/codegen/visibility/protected_and_package/protectedFunInPackage.java @@ -0,0 +1,9 @@ +package protectedPack; + +import java.lang.String; + +public class protectedFunInPackage { + protected String foo() { + return "OK"; + } +} diff --git a/compiler/testData/codegen/visibility/protected_and_package/protectedFunInPackage.kt b/compiler/testData/codegen/visibility/protected_and_package/protectedFunInPackage.kt new file mode 100644 index 00000000000..e7180155bd8 --- /dev/null +++ b/compiler/testData/codegen/visibility/protected_and_package/protectedFunInPackage.kt @@ -0,0 +1,5 @@ +package protectedPack + +fun box(): String { + return protectedFunInPackage().foo()!! +} diff --git a/compiler/testData/codegen/visibility/protected_and_package/protectedPropertyInPackage.java b/compiler/testData/codegen/visibility/protected_and_package/protectedPropertyInPackage.java new file mode 100644 index 00000000000..52f8393d12c --- /dev/null +++ b/compiler/testData/codegen/visibility/protected_and_package/protectedPropertyInPackage.java @@ -0,0 +1,7 @@ +package protectedPack; + +import java.lang.String; + +public class protectedPropertyInPackage { + protected String foo = "OK"; +} diff --git a/compiler/testData/codegen/visibility/protected_and_package/protectedPropertyInPackage.kt b/compiler/testData/codegen/visibility/protected_and_package/protectedPropertyInPackage.kt new file mode 100644 index 00000000000..93bef23ffba --- /dev/null +++ b/compiler/testData/codegen/visibility/protected_and_package/protectedPropertyInPackage.kt @@ -0,0 +1,5 @@ +package protectedPack + +fun box(): String { + return protectedPropertyInPackage().foo!! +} diff --git a/compiler/testData/codegen/visibility/protected_and_package/protectedStaticClass.java b/compiler/testData/codegen/visibility/protected_and_package/protectedStaticClass.java new file mode 100644 index 00000000000..c07f6404b1d --- /dev/null +++ b/compiler/testData/codegen/visibility/protected_and_package/protectedStaticClass.java @@ -0,0 +1,11 @@ +package protectedPack; + +import java.lang.String; + +public class protectedStaticClass { + protected static class Inner { + public String foo() { + return "OK"; + } + } +} diff --git a/compiler/testData/codegen/visibility/protected_and_package/protectedStaticClass.kt b/compiler/testData/codegen/visibility/protected_and_package/protectedStaticClass.kt new file mode 100644 index 00000000000..728a19cdd9e --- /dev/null +++ b/compiler/testData/codegen/visibility/protected_and_package/protectedStaticClass.kt @@ -0,0 +1,11 @@ +package protectedPack + +class Derived(): protectedStaticClass() { + fun test(): String { + return protectedStaticClass.Inner().foo()!! + } +} + +fun box(): String { + return Derived().test() +} diff --git a/compiler/testData/loadJavaCustom/packageLocalVisibility/expected.txt b/compiler/testData/loadJavaCustom/packageLocalVisibility/expected.txt index fe42572302a..0a59bfbc728 100644 --- a/compiler/testData/loadJavaCustom/packageLocalVisibility/expected.txt +++ b/compiler/testData/loadJavaCustom/packageLocalVisibility/expected.txt @@ -2,5 +2,5 @@ package test public open class JFrame : awt.Frame { public constructor JFrame() - protected final var accessibleContext : jet.String? + protected/*protected and package*/ final var accessibleContext : jet.String? } diff --git a/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageConstructor.java b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageConstructor.java new file mode 100644 index 00000000000..6f4e06a7459 --- /dev/null +++ b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageConstructor.java @@ -0,0 +1,5 @@ +package test; + +public class ProtectedPackageConstructor { + protected static class Foo { } +} \ No newline at end of file diff --git a/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageConstructor.txt b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageConstructor.txt new file mode 100644 index 00000000000..77c1c029b16 --- /dev/null +++ b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageConstructor.txt @@ -0,0 +1,9 @@ +package test + +public open class ProtectedPackageConstructor : java.lang.Object { + public constructor ProtectedPackageConstructor() + + protected/*protected static*/ open class Foo : java.lang.Object { + protected/*protected and package*/ constructor Foo() + } +} diff --git a/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageFun.java b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageFun.java new file mode 100644 index 00000000000..a1e0fdf9d96 --- /dev/null +++ b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageFun.java @@ -0,0 +1,5 @@ +package test; + +public class ProtectedPackageFun { + protected void foo() {} +} \ No newline at end of file diff --git a/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageFun.txt b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageFun.txt new file mode 100644 index 00000000000..331b8349667 --- /dev/null +++ b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageFun.txt @@ -0,0 +1,6 @@ +package test + +public open class ProtectedPackageFun : java.lang.Object { + public constructor ProtectedPackageFun() + protected/*protected and package*/ open fun foo() : Unit +} diff --git a/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageProperty.java b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageProperty.java new file mode 100644 index 00000000000..6fd7a675dd8 --- /dev/null +++ b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageProperty.java @@ -0,0 +1,5 @@ +package test; + +public class ProtectedPackageProperty { + protected int foo = 1; +} \ No newline at end of file diff --git a/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageProperty.txt b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageProperty.txt new file mode 100644 index 00000000000..884a0d99f50 --- /dev/null +++ b/compiler/testData/loadJavaCustom/protectedPackageVisibility/ProtectedPackageProperty.txt @@ -0,0 +1,6 @@ +package test + +public open class ProtectedPackageProperty : java.lang.Object { + public constructor ProtectedPackageProperty() + protected/*protected and package*/ final var foo : jet.Int +} diff --git a/compiler/testData/loadJavaCustom/protectedStaticVisibility/constructor/ConstructorInProtectedStaticNestedClass.txt b/compiler/testData/loadJavaCustom/protectedStaticVisibility/constructor/ConstructorInProtectedStaticNestedClass.txt index eae227d3105..20b0a080ccc 100644 --- a/compiler/testData/loadJavaCustom/protectedStaticVisibility/constructor/ConstructorInProtectedStaticNestedClass.txt +++ b/compiler/testData/loadJavaCustom/protectedStaticVisibility/constructor/ConstructorInProtectedStaticNestedClass.txt @@ -4,6 +4,6 @@ public open class ConstructorInProtectedStaticNestedClass : java.lang.Object { public constructor ConstructorInProtectedStaticNestedClass() protected/*protected static*/ open class Inner : java.lang.Object { - protected constructor Inner() + protected/*protected and package*/ constructor Inner() } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/JavaVisibilityTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/JavaVisibilityTestGenerated.java index a724845e585..3236029c716 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/JavaVisibilityTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/JavaVisibilityTestGenerated.java @@ -30,7 +30,7 @@ import org.jetbrains.jet.codegen.AbstractJavaVisibilityTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/visibility") -@InnerTestClasses({JavaVisibilityTestGenerated.Package.class}) +@InnerTestClasses({JavaVisibilityTestGenerated.Package.class, JavaVisibilityTestGenerated.Protected_and_package.class}) public class JavaVisibilityTestGenerated extends AbstractJavaVisibilityTest { public void testAllFilesPresentInVisibility() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/visibility"), "kt", true); @@ -59,10 +59,39 @@ public class JavaVisibilityTestGenerated extends AbstractJavaVisibilityTest { } + @TestMetadata("compiler/testData/codegen/visibility/protected_and_package") + public static class Protected_and_package extends AbstractJavaVisibilityTest { + public void testAllFilesPresentInProtected_and_package() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/visibility/protected_and_package"), "kt", true); + } + + @TestMetadata("overrideProtectedFunInPackage.kt") + public void testOverrideProtectedFunInPackage() throws Exception { + blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/protected_and_package/overrideProtectedFunInPackage.kt"); + } + + @TestMetadata("protectedFunInPackage.kt") + public void testProtectedFunInPackage() throws Exception { + blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/protected_and_package/protectedFunInPackage.kt"); + } + + @TestMetadata("protectedPropertyInPackage.kt") + public void testProtectedPropertyInPackage() throws Exception { + blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/protected_and_package/protectedPropertyInPackage.kt"); + } + + @TestMetadata("protectedStaticClass.kt") + public void testProtectedStaticClass() throws Exception { + blackBoxFileWithJavaByFullPath("compiler/testData/codegen/visibility/protected_and_package/protectedStaticClass.kt"); + } + + } + public static Test suite() { TestSuite suite = new TestSuite("JavaVisibilityTestGenerated"); suite.addTestSuite(JavaVisibilityTestGenerated.class); suite.addTestSuite(Package.class); + suite.addTestSuite(Protected_and_package.class); return suite; } } diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java index 4b50ad153ed..15c1371d4c5 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java @@ -100,6 +100,24 @@ public final class LoadJavaCustomTest extends KotlinTestWithEnvironment { dir + "ConstructorInProtectedStaticNestedClass.java"); } + public void testProtectedPackageFun() throws Exception { + String dir = PATH + "/protectedPackageVisibility/"; + doTest(dir + "ProtectedPackageFun.txt", + dir + "ProtectedPackageFun.java"); + } + + public void testProtectedPackageConstructor() throws Exception { + String dir = PATH + "/protectedPackageVisibility/"; + doTest(dir + "ProtectedPackageConstructor.txt", + dir + "ProtectedPackageConstructor.java"); + } + + public void testProtectedPackageProperty() throws Exception { + String dir = PATH + "/protectedPackageVisibility/"; + doTest(dir + "ProtectedPackageProperty.txt", + dir + "ProtectedPackageProperty.java"); + } + public void testStaticFinal() throws Exception { String dir = "/staticFinal/"; doTest(PATH + dir + "expected.txt",