Synthetic extensions for non-public get/set java methods

This commit is contained in:
Valentin Kipyatkov
2015-07-29 18:15:27 +03:00
parent d5f95cf126
commit c3064e2b0f
8 changed files with 84 additions and 35 deletions
@@ -116,7 +116,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImp
return descriptor.valueParameters.isEmpty() return descriptor.valueParameters.isEmpty()
&& descriptor.typeParameters.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 { private fun isGoodSetMethod(descriptor: FunctionDescriptor, getMethod: FunctionDescriptor): Boolean {
@@ -133,7 +133,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImp
return parameter.varargElementType == null return parameter.varargElementType == null
&& descriptor.typeParameters.isEmpty() && descriptor.typeParameters.isEmpty()
&& descriptor.returnType?.let { it.isUnit() } ?: false && descriptor.returnType?.let { it.isUnit() } ?: false
&& descriptor.visibility == Visibilities.PUBLIC && descriptor.visibility.isVisibleOutside()
} }
private fun FunctionDescriptor.findOverridden(condition: (FunctionDescriptor) -> Boolean): FunctionDescriptor? { private fun FunctionDescriptor.findOverridden(condition: (FunctionDescriptor) -> Boolean): FunctionDescriptor? {
@@ -251,15 +251,15 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImp
name: Name, name: Name,
type: JetType type: JetType
) : SyntheticJavaPropertyDescriptor, PropertyDescriptorImpl( ) : SyntheticJavaPropertyDescriptor, PropertyDescriptorImpl(
DescriptorUtils.getContainingModule(ownerClass)/* TODO:is it ok? */, DescriptorUtils.getContainingModule(ownerClass),
null, null,
Annotations.EMPTY, Annotations.EMPTY,
Modality.FINAL, Modality.FINAL,
Visibilities.PUBLIC, syntheticExtensionVisibility(getMethod),
setMethod != null, setMethod != null,
name, name,
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE/*TODO?*/ SourceElement.NO_SOURCE
) { ) {
init { init {
val classTypeParams = ownerClass.typeConstructor.parameters val classTypeParams = ownerClass.typeConstructor.parameters
@@ -273,24 +273,24 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : JetScopeImp
val getter = PropertyGetterDescriptorImpl(this, val getter = PropertyGetterDescriptorImpl(this,
Annotations.EMPTY, Annotations.EMPTY,
Modality.FINAL, Modality.FINAL,
Visibilities.PUBLIC, visibility,
false, false,
false, false,
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
null, null,
SourceElement.NO_SOURCE/*TODO*/) SourceElement.NO_SOURCE)
getter.initialize(null) getter.initialize(null)
val setter = if (setMethod != null) val setter = if (setMethod != null)
PropertySetterDescriptorImpl(this, PropertySetterDescriptorImpl(this,
Annotations.EMPTY, Annotations.EMPTY,
Modality.FINAL, Modality.FINAL,
Visibilities.PUBLIC, syntheticExtensionVisibility(setMethod),
false, false,
false, false,
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
null, null,
SourceElement.NO_SOURCE/*TODO*/) SourceElement.NO_SOURCE)
else else
null null
setter?.initializeDefault() setter?.initializeDefault()
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.JetScope 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.storage.StorageManager
import org.jetbrains.kotlin.types.DescriptorSubstitutor import org.jetbrains.kotlin.types.DescriptorSubstitutor
import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.JetType
@@ -46,7 +45,7 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : JetScope by Jet
} }
private fun extensionForFunctionNotCached(function: FunctionDescriptor): FunctionDescriptor? { 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 (!function.hasJavaOriginInHierarchy()) return null //TODO: should we go into base at all?
if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null
if (function.returnType == null) 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 receiverType = typeSubstitutor.safeSubstitute(ownerClass.defaultType, Variance.INVARIANT)
val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(originalFunction, this, typeSubstitutor) val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(originalFunction, this, typeSubstitutor)
val originalVisibility = originalFunction.visibility val visibility = syntheticExtensionVisibility(originalFunction)
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"
}
}
initialize(receiverType, null, typeParameters, valueParameters, returnType, Modality.FINAL, visibility) initialize(receiverType, null, typeParameters, valueParameters, returnType, Modality.FINAL, visibility)
} }
@@ -16,8 +16,9 @@
package org.jetbrains.kotlin.synthetic 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.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean { fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean {
return if (overriddenDescriptors.isEmpty()) return if (overriddenDescriptors.isEmpty())
@@ -25,3 +26,27 @@ fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean {
else else
overriddenDescriptors.any { it.hasJavaOriginInHierarchy() } 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"
}
}
}
@@ -1,10 +1,14 @@
// FILE: KotlinFile.kt // FILE: KotlinFile.kt
package k
import JavaClass
fun foo(javaClass: JavaClass) { fun foo(javaClass: JavaClass) {
javaClass.somethingPublic javaClass.somethingPublic
javaClass.<!UNRESOLVED_REFERENCE!>somethingProtected<!> javaClass.<!INVISIBLE_MEMBER!>somethingProtected<!>
javaClass.<!UNRESOLVED_REFERENCE!>somethingPrivate<!> javaClass.<!UNRESOLVED_REFERENCE!>somethingPrivate<!>
javaClass.<!UNRESOLVED_REFERENCE!>somethingPackage<!> javaClass.<!INVISIBLE_MEMBER!>somethingPackage<!>
<!VAL_REASSIGNMENT!>javaClass.somethingPublic<!> = 1 <!INVISIBLE_SETTER!>javaClass.somethingPublic<!> = 1
} }
// FILE: JavaClass.java // FILE: JavaClass.java
@@ -1,7 +1,5 @@
package package
internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit
public open class JavaClass { public open class JavaClass {
public constructor JavaClass() public constructor JavaClass()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean 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 protected/*protected and package*/ open fun setSomethingPublic(/*0*/ value: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
package k {
internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit
}
@@ -0,0 +1,16 @@
// FILE: KotlinFile.kt
package k
import JavaClass
fun foo(javaClass: JavaClass) {
val <!UNUSED_VARIABLE!>v<!> = javaClass.<!INVISIBLE_MEMBER!>something<!>
javaClass.<!INVISIBLE_MEMBER!>something<!> = 1
javaClass.<!INVISIBLE_MEMBER!>something<!>++
}
// FILE: JavaClass.java
public class JavaClass {
protected int getSomething() { return 1; }
public void setSomething(int value) {}
}
@@ -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
}
@@ -14366,6 +14366,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName); 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") @TestMetadata("SetterOnly.kt")
public void testSetterOnly() throws Exception { public void testSetterOnly() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterOnly.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/syntheticExtensions/javaProperties/SetterOnly.kt");