Call getMethod/getDeclaredMethod depending on visibility

This commit is contained in:
Alexander Udalov
2015-04-01 19:09:22 +03:00
parent 0202217135
commit 715641fb0d
4 changed files with 31 additions and 14 deletions
@@ -0,0 +1,16 @@
import kotlin.reflect.jvm.*
class K<in T : String> {
private var t: T
get() = "OK" as T
set(value) {}
fun run(): String {
val p = ::t
p.accessible = true
p.set(this, "" as T)
return p.get(this)
}
}
fun box() = K<String>().run()
@@ -3038,6 +3038,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("privateToThisAccessors.kt")
public void testPrivateToThisAccessors() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/properties/privateToThisAccessors.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("propertyOfNestedClassAndArrayType.kt")
public void testPropertyOfNestedClassAndArrayType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/properties/propertyOfNestedClassAndArrayType.kt");
@@ -17,6 +17,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
@@ -60,13 +61,15 @@ abstract class DescriptorBasedProperty(computeDescriptor: () -> PropertyDescript
open val getter: Method? by ReflectProperties.lazySoft {
val proto = protoData
if (proto == null || !proto.signature.hasGetter()) null
else container.findMethodBySignature(proto.signature.getGetter(), proto.nameResolver)
else container.findMethodBySignature(proto.signature.getGetter(), proto.nameResolver,
descriptor.getGetter()?.getVisibility()?.let { Visibilities.isPrivate(it) } ?: false)
}
open val setter: Method? by ReflectProperties.lazySoft {
val proto = protoData
if (proto == null || !proto.signature.hasSetter()) null
else container.findMethodBySignature(proto.signature.getSetter(), proto.nameResolver)
else container.findMethodBySignature(proto.signature.getSetter(), proto.nameResolver,
descriptor.getSetter()?.getVisibility()?.let { Visibilities.isPrivate(it) } ?: false)
}
override fun equals(other: Any?): Boolean =
@@ -68,14 +68,16 @@ abstract class KCallableContainerImpl {
}
// TODO: check resulting method's return type
fun findMethodBySignature(signature: JvmProtoBuf.JvmMethodSignature, nameResolver: NameResolver): Method? {
fun findMethodBySignature(signature: JvmProtoBuf.JvmMethodSignature, nameResolver: NameResolver, declared: Boolean): Method? {
val name = nameResolver.getString(signature.getName())
val classLoader = jClass.classLoader
val parameterTypes = signature.getParameterTypeList().map { jvmType ->
loadJvmType(jvmType, nameResolver, classLoader)
}.copyToArray()
return try {
jClass.getMaybeDeclaredMethod(name, *parameterTypes)
if (declared) jClass.getDeclaredMethod(name, *parameterTypes)
else jClass.getMethod(name, *parameterTypes)
}
catch (e: NoSuchMethodException) {
null
@@ -112,16 +114,6 @@ abstract class KCallableContainerImpl {
}
}
private fun Class<*>.getMaybeDeclaredMethod(name: String, vararg parameterTypes: Class<*>): Method {
try {
return getMethod(name, *parameterTypes)
}
catch (e: NoSuchMethodException) {
// This is needed to support private methods
return getDeclaredMethod(name, *parameterTypes)
}
}
/* private // KT-5786 */ fun loadJvmType(
type: JvmProtoBuf.JvmType,
nameResolver: NameResolver,