diff --git a/compiler/testData/codegen/boxWithStdlib/callableReference/property/privateClassVal.kt b/compiler/testData/codegen/boxWithStdlib/callableReference/property/privateClassVal.kt new file mode 100644 index 00000000000..eaafec45535 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/callableReference/property/privateClassVal.kt @@ -0,0 +1,15 @@ +class Result { + private val value = "OK" + + fun ref(): KMemberProperty = ::value +} + +fun box(): String { + val p = Result().ref() + try { + p.get(Result()) + return "Fail: private property is accessible by default" + } catch(e: IllegalAccessException) { } + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 257d4fb5d7f..9080f40c293 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -454,6 +454,11 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/callableReference/property/overriddenInSubclass.kt"); } + @TestMetadata("privateClassVal.kt") + public void testPrivateClassVal() throws Exception { + doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/callableReference/property/privateClassVal.kt"); + } + @TestMetadata("simpleExtension.kt") public void testSimpleExtension() throws Exception { doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/callableReference/property/simpleExtension.kt"); diff --git a/core/runtime.jvm/src/kotlin/reflect/jvm/internal/KMemberPropertyImpl.kt b/core/runtime.jvm/src/kotlin/reflect/jvm/internal/KMemberPropertyImpl.kt index 2cee6e4e2c1..482a274f0c6 100644 --- a/core/runtime.jvm/src/kotlin/reflect/jvm/internal/KMemberPropertyImpl.kt +++ b/core/runtime.jvm/src/kotlin/reflect/jvm/internal/KMemberPropertyImpl.kt @@ -32,7 +32,7 @@ open class KMemberPropertyImpl( // TODO: extract, make lazy (weak?), use our descriptors knowledge protected val getter: Method? = if (owner.origin == KClassOrigin.KOTLIN) { - owner.jClass.getMethod(getterName(name)) + owner.jClass.getMaybeDeclaredMethod(getterName(name)) } else null @@ -51,7 +51,7 @@ class KMutableMemberPropertyImpl( ) : KMutableMemberProperty, KMemberPropertyImpl(name, owner) { private val setter: Method? = if (owner.origin == KClassOrigin.KOTLIN) { - owner.jClass.getMethod(setterName(name), getter!!.getReturnType()!!) + owner.jClass.getMaybeDeclaredMethod(setterName(name), getter!!.getReturnType()!!) } else null diff --git a/core/runtime.jvm/src/kotlin/reflect/jvm/internal/util.kt b/core/runtime.jvm/src/kotlin/reflect/jvm/internal/util.kt index b8a5c6368f5..b1ed0ac560a 100644 --- a/core/runtime.jvm/src/kotlin/reflect/jvm/internal/util.kt +++ b/core/runtime.jvm/src/kotlin/reflect/jvm/internal/util.kt @@ -16,6 +16,7 @@ package kotlin.reflect.jvm.internal +import java.lang.reflect.Method import java.util.concurrent.ConcurrentHashMap // TODO: use stdlib? @@ -34,6 +35,17 @@ private fun getterName(propertyName: String): String = "get" + propertyName.capi private fun setterName(propertyName: String): String = "set" + propertyName.capitalizeWithJavaBeanConvention() +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) + } +} + + // TODO: should use weak references private val foreignKClasses: MutableMap, KClassImpl<*>> = ConcurrentHashMap()