blob: e686e693f250eae4b30a2e44ecce78fe32b62fa7 [file]
// TARGET_BACKEND: JVM
// WITH_REFLECT
// FILE: test/J.java
package test;
public class J {
public String memberField = "";
public static String staticField = "";
public static final String staticFinalField = "";
public J(String value) {}
public void memberFun() {}
public static void staticFun() {}
}
// FILE: test/JOverride.java
package test;
public class JOverride extends KBase {
private String storage;
@Override
public String getOverriddenVal() {
return storage;
}
@Override
public String getOverriddenVar() {
return storage;
}
@Override
public void setOverriddenVar(String value) {
storage = value;
}
}
// FILE: test/JEnum.java
package test;
public enum JEnum {
ENTRY
}
// FILE: test/JAnno.java
package test;
public @interface JAnno {
String value();
}
// FILE: test.kt
package test
import kotlin.reflect.KCallable
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
class K(val constructorVal: Int) {
val memberVal: String = ""
var memberVar: String = ""
fun memberFun() {}
}
abstract class KBase {
abstract val overriddenVal: String?
abstract var overriddenVar: String?
}
val topLevelVal = ""
var topLevelVar = ""
fun topLevelFun() {}
private val useK1 = Class.forName("kotlin.reflect.jvm.internal.SystemPropertiesKt").getMethod("getUseK1Implementation").invoke(null) == true
private val errors = StringBuilder()
private fun implementationClassName(callable: KCallable<*>): String {
var result: Any = callable
if (result is kotlin.jvm.internal.CallableReference) {
result = result.compute()
}
// Property references are wrapped in kotlin.reflect.jvm.internal.LazyKPropertyN/LazyKMutablePropertyN.
while (result.javaClass.simpleName.startsWith("LazyK")) {
val getDelegate = result.javaClass.methods.single { method ->
method.name == "getDelegate" && method.parameterTypes.isEmpty() && KProperty::class.java.isAssignableFrom(method.returnType)
}
result = getDelegate.invoke(result)!!
}
return result.javaClass.simpleName
}
private fun check(description: String, callable: KCallable<*>, new: String, k1: String) {
val expected = if (useK1) k1 else new
val actual = implementationClassName(callable)
if (expected != actual) {
errors.append("$description: expected $expected, actual $actual\n")
}
}
private fun member(klass: KClass<*>, name: String): KCallable<*> = klass.members.single { it.name == name }
fun box(): String {
// Kotlin member properties and functions.
check("K::memberVal", K::memberVal, new = "KotlinKProperty1", k1 = "DescriptorKProperty1")
check("K::memberVar", K::memberVar, new = "KotlinKMutableProperty1", k1 = "DescriptorKMutableProperty1")
check("K::memberFun", K::memberFun, new = "KotlinKNamedFunction", k1 = "DescriptorKFunction")
check("K::class.members['memberVal']", member(K::class, "memberVal"), new = "KotlinKProperty1", k1 = "DescriptorKProperty1")
check("K::class.members['memberVar']", member(K::class, "memberVar"), new = "KotlinKMutableProperty1", k1 = "DescriptorKMutableProperty1")
check("K::class.members['memberFun']", member(K::class, "memberFun"), new = "KotlinKNamedFunction", k1 = "DescriptorKFunction")
// Kotlin constructors.
check("::K", ::K, new = "KotlinKConstructor", k1 = "DescriptorKFunction")
check("K::class.constructors", K::class.constructors.single(), new = "KotlinKConstructor", k1 = "DescriptorKFunction")
// Kotlin top-level properties and functions.
check("::topLevelVal", ::topLevelVal, new = "KotlinKProperty0", k1 = "DescriptorKProperty0")
check("::topLevelVar", ::topLevelVar, new = "KotlinKMutableProperty0", k1 = "DescriptorKMutableProperty0")
check("::topLevelFun", ::topLevelFun, new = "KotlinKNamedFunction", k1 = "DescriptorKFunction")
// Java member properties and functions.
check("J::memberField", J::memberField, new = "JavaFieldKMutableProperty1", k1 = "DescriptorKMutableProperty1")
check("J::memberFun", J::memberFun, new = "JavaKNamedFunction", k1 = "DescriptorKFunction")
check("J::class.members['memberField']", member(J::class, "memberField"), new = "JavaFieldKMutableProperty1", k1 = "DescriptorKMutableProperty1")
check("J::class.members['memberFun']", member(J::class, "memberFun"), new = "JavaKNamedFunction", k1 = "DescriptorKFunction")
// Java constructors.
check("::J", ::J, new = "JavaKConstructor", k1 = "DescriptorKFunction")
check("J::class.constructors", J::class.constructors.single(), new = "JavaKConstructor", k1 = "DescriptorKFunction")
// Java static properties and functions.
check("J::staticField", J::staticField, new = "JavaFieldKMutableProperty0", k1 = "DescriptorKMutableProperty0")
check("J::staticFinalField", J::staticFinalField, new = "JavaFieldKProperty0", k1 = "DescriptorKProperty0")
check("J::staticFun", J::staticFun, new = "JavaKNamedFunction", k1 = "DescriptorKFunction")
check(
"J::class.members['staticField']", member(J::class, "staticField"),
new = "JavaFieldKMutableProperty0", k1 = "DescriptorKMutableProperty0",
)
check(
"J::class.members['staticFinalField']", member(J::class, "staticFinalField"),
new = "JavaFieldKProperty0", k1 = "DescriptorKProperty0",
)
check("J::class.members['staticFun']", member(J::class, "staticFun"), new = "JavaKNamedFunction", k1 = "DescriptorKFunction")
// Properties declared in Kotlin and overridden by methods in Java.
// Note that callable references to such properties are not supported yet, see KT-87863.
check(
"JOverride::class.members['overriddenVal']", member(JOverride::class, "overriddenVal"),
new = "JavaForKotlinOverrideKProperty1", k1 = "DescriptorKProperty1",
)
check(
"JOverride::class.members['overriddenVar']", member(JOverride::class, "overriddenVar"),
new = "JavaForKotlinOverrideKMutableProperty1", k1 = "DescriptorKMutableProperty1",
)
// Java annotation methods, represented as properties.
// Note that `JAnno::value` is a reference to a synthetic Java property, which does not use kotlin-reflect at all, see KT-55980.
check(
"JAnno::class.members['value']", member(JAnno::class, "value"),
new = "JavaAnnotationMethodKProperty1", k1 = "DescriptorKProperty1",
)
// The synthetic `entries` property of a Java enum class.
check("JEnum::entries", JEnum::entries, new = "JavaEnumEntriesKProperty", k1 = "DescriptorKProperty0")
check(
"JEnum::class.members['entries']", member(JEnum::class, "entries"),
new = "JavaEnumEntriesKProperty", k1 = "DescriptorKProperty0",
)
return if (errors.isEmpty()) "OK" else "Fail:\n$errors"
}