diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt index 4c4dc2790dd..0fe604bdfb5 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt @@ -116,7 +116,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImp return descriptor.valueParameters.isEmpty() && descriptor.typeParameters.isEmpty() - && descriptor.visibility == Visibilities.PUBLIC //TODO: what about protected and package-local? + && descriptor.visibility.isVisibleOutside() } private fun isGoodSetMethod(descriptor: FunctionDescriptor, getMethod: FunctionDescriptor): Boolean { @@ -133,7 +133,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImp return parameter.varargElementType == null && descriptor.typeParameters.isEmpty() && descriptor.returnType?.let { it.isUnit() } ?: false - && descriptor.visibility == Visibilities.PUBLIC + && descriptor.visibility.isVisibleOutside() } private fun FunctionDescriptor.findOverridden(condition: (FunctionDescriptor) -> Boolean): FunctionDescriptor? { @@ -251,15 +251,15 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImp name: Name, type: JetType ) : SyntheticJavaPropertyDescriptor, PropertyDescriptorImpl( - DescriptorUtils.getContainingModule(ownerClass)/* TODO:is it ok? */, + DescriptorUtils.getContainingModule(ownerClass), null, Annotations.EMPTY, Modality.FINAL, - Visibilities.PUBLIC, + syntheticExtensionVisibility(getMethod), setMethod != null, name, CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE/*TODO?*/ + SourceElement.NO_SOURCE ) { init { val classTypeParams = ownerClass.typeConstructor.parameters @@ -273,24 +273,24 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImp val getter = PropertyGetterDescriptorImpl(this, Annotations.EMPTY, Modality.FINAL, - Visibilities.PUBLIC, + visibility, false, false, CallableMemberDescriptor.Kind.SYNTHESIZED, null, - SourceElement.NO_SOURCE/*TODO*/) + SourceElement.NO_SOURCE) getter.initialize(null) val setter = if (setMethod != null) PropertySetterDescriptorImpl(this, Annotations.EMPTY, Modality.FINAL, - Visibilities.PUBLIC, + syntheticExtensionVisibility(setMethod), false, false, CallableMemberDescriptor.Kind.SYNTHESIZED, null, - SourceElement.NO_SOURCE/*TODO*/) + SourceElement.NO_SOURCE) else null setter?.initializeDefault() diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt index 76dd5a3fea7..5a835762b4a 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/SamAdapterFunctionsScope.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.DescriptorSubstitutor import org.jetbrains.kotlin.types.JetType @@ -46,7 +45,7 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet } private fun extensionForFunctionNotCached(function: FunctionDescriptor): FunctionDescriptor? { - if (function.visibility == Visibilities.PRIVATE || function.visibility == Visibilities.PRIVATE_TO_THIS || function.visibility == Visibilities.INVISIBLE_FAKE) return null + if (!function.visibility.isVisibleOutside()) return null if (!function.hasJavaOriginInHierarchy()) return null //TODO: should we go into base at all? if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null if (function.returnType == null) return null @@ -111,24 +110,7 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet val receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT) val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(originalFunction, this, typeSubstitutor) - val originalVisibility = originalFunction.visibility - val visibility = when (originalVisibility) { - Visibilities.PUBLIC -> Visibilities.PUBLIC - - else -> object : Visibility(originalVisibility.name, originalVisibility.isPublicAPI) { - override fun isVisible(receiver: ReceiverValue, what: DeclarationDescriptorWithVisibility, from: DeclarationDescriptor) - = originalVisibility.isVisible(receiver, originalFunction, from) - - override fun mustCheckInImports() - = throw UnsupportedOperationException("Should never be called for this visibility") - - override fun normalize() - = originalVisibility.normalize() - - override val displayName: String - get() = originalVisibility.displayName + " for synthetic extension" - } - } + val visibility = syntheticExtensionVisibility(originalFunction) initialize(receiverType, null, typeParameters, valueParameters, returnType, Modality.FINAL, visibility) } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt index 81781e781e7..eb859606ded 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/syntheticExtensionsUtils.kt @@ -16,8 +16,9 @@ package org.jetbrains.kotlin.synthetic -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean { return if (overriddenDescriptors.isEmpty()) @@ -25,3 +26,27 @@ fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean { else overriddenDescriptors.any { it.hasJavaOriginInHierarchy() } } + +fun Visibility.isVisibleOutside() = this != Visibilities.PRIVATE && this != Visibilities.PRIVATE_TO_THIS && this != Visibilities.INVISIBLE_FAKE + +fun syntheticExtensionVisibility(originalDescriptor: DeclarationDescriptorWithVisibility): Visibility { + val originalVisibility = originalDescriptor.visibility + return when (originalVisibility) { + Visibilities.PUBLIC -> Visibilities.PUBLIC + + else -> object : Visibility(originalVisibility.name, originalVisibility.isPublicAPI) { + override fun isVisible(receiver: ReceiverValue, what: DeclarationDescriptorWithVisibility, from: DeclarationDescriptor) + = originalVisibility.isVisible(receiver, originalDescriptor, from) + + override fun mustCheckInImports() + = throw UnsupportedOperationException("Should never be called for this visibility") + + override fun normalize() + = originalVisibility.normalize() + + override val displayName: String + get() = originalVisibility.displayName + " for synthetic extension" + } + } + +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.kt index 9bcc925eb27..6a5ac7818fb 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.kt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.kt @@ -1,10 +1,14 @@ // FILE: KotlinFile.kt +package k + +import JavaClass + fun foo(javaClass: JavaClass) { javaClass.somethingPublic - javaClass.somethingProtected + javaClass.somethingProtected javaClass.somethingPrivate - javaClass.somethingPackage - javaClass.somethingPublic = 1 + javaClass.somethingPackage + javaClass.somethingPublic = 1 } // FILE: JavaClass.java diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.txt b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.txt index cbb81bad348..62f2d1f13a4 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.txt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/OnlyPublic.txt @@ -1,7 +1,5 @@ package -internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit - public open class JavaClass { public constructor JavaClass() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean @@ -13,3 +11,7 @@ public open class JavaClass { protected/*protected and package*/ open fun setSomethingPublic(/*0*/ value: kotlin.Int): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +package k { + internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit +} diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterHasHigherAccess.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterHasHigherAccess.kt new file mode 100644 index 00000000000..ddb4ee89226 --- /dev/null +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterHasHigherAccess.kt @@ -0,0 +1,16 @@ +// FILE: KotlinFile.kt +package k + +import JavaClass + +fun foo(javaClass: JavaClass) { + val v = javaClass.something + javaClass.something = 1 + javaClass.something++ +} + +// FILE: JavaClass.java +public class JavaClass { + protected int getSomething() { return 1; } + public void setSomething(int value) {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterHasHigherAccess.txt b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterHasHigherAccess.txt new file mode 100644 index 00000000000..34af938b5e7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterHasHigherAccess.txt @@ -0,0 +1,14 @@ +package + +public open class JavaClass { + public constructor JavaClass() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ open fun getSomething(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open fun setSomething(/*0*/ value: kotlin.Int): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +package k { + internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index eeacd4450d6..ab441504050 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -14366,6 +14366,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("SetterHasHigherAccess.kt") + public void testSetterHasHigherAccess() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterHasHigherAccess.kt"); + doTest(fileName); + } + @TestMetadata("SetterOnly.kt") public void testSetterOnly() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterOnly.kt");