Fix loading class literal value void.class in reflection

#KT-27878 Fixed
This commit is contained in:
Alexander Udalov
2018-10-30 17:44:41 +01:00
parent 902d414d39
commit 2f72f68e1a
7 changed files with 61 additions and 2 deletions
@@ -0,0 +1,29 @@
// WITH_REFLECT
// TARGET_BACKEND: JVM
// FILE: Anno.java
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Anno {
Class<?> value() default void.class;
}
// FILE: test.kt
import kotlin.test.assertEquals
class C {
@Anno
fun f1() {}
@Anno(Void::class)
fun f2() {}
}
fun box(): String {
assertEquals("[@Anno(value=void)]", C::f1.annotations.toString())
assertEquals("[@Anno(value=class java.lang.Void)]", C::f2.annotations.toString())
return "OK"
}
@@ -5,6 +5,14 @@ public class ClassObjectArrayInParam {
Class<?>[] value();
}
@Anno({ClassObjectArrayInParam.class, Nested.class, String.class, java.util.List.class, String[][].class, int[][].class})
@Anno({
ClassObjectArrayInParam.class,
Nested.class,
String.class,
java.util.List.class,
String[][].class,
int[][].class,
void.class
})
public static class Nested {}
}
@@ -8,7 +8,7 @@ public open class ClassObjectArrayInParam {
public final val value: kotlin.Array<kotlin.reflect.KClass<*>>
}
@test.ClassObjectArrayInParam.Anno(value = {test.ClassObjectArrayInParam::class, test.ClassObjectArrayInParam.Nested::class, kotlin.String::class, kotlin.collections.MutableList::class, kotlin.Array<kotlin.Array<kotlin.String>>::class, kotlin.Array<kotlin.IntArray>::class}) public open class Nested {
@test.ClassObjectArrayInParam.Anno(value = {test.ClassObjectArrayInParam::class, test.ClassObjectArrayInParam.Nested::class, kotlin.String::class, kotlin.collections.MutableList::class, kotlin.Array<kotlin.Array<kotlin.String>>::class, kotlin.Array<kotlin.IntArray>::class, kotlin.Unit::class}) public open class Nested {
public constructor Nested()
}
}
@@ -18914,6 +18914,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/annotations/annotationsOnJavaMembers.kt");
}
@TestMetadata("classLiteralWithVoidDefault.kt")
public void testClassLiteralWithVoidDefault() throws Exception {
runTest("compiler/testData/codegen/box/reflection/annotations/classLiteralWithVoidDefault.kt");
}
@TestMetadata("findAnnotation.kt")
public void testFindAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/reflection/annotations/findAnnotation.kt");
@@ -18914,6 +18914,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/annotations/annotationsOnJavaMembers.kt");
}
@TestMetadata("classLiteralWithVoidDefault.kt")
public void testClassLiteralWithVoidDefault() throws Exception {
runTest("compiler/testData/codegen/box/reflection/annotations/classLiteralWithVoidDefault.kt");
}
@TestMetadata("findAnnotation.kt")
public void testFindAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/reflection/annotations/findAnnotation.kt");
@@ -18919,6 +18919,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/annotations/annotationsOnJavaMembers.kt");
}
@TestMetadata("classLiteralWithVoidDefault.kt")
public void testClassLiteralWithVoidDefault() throws Exception {
runTest("compiler/testData/codegen/box/reflection/annotations/classLiteralWithVoidDefault.kt");
}
@TestMetadata("findAnnotation.kt")
public void testFindAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/reflection/annotations/findAnnotation.kt");
@@ -16,11 +16,13 @@
package kotlin.reflect.jvm.internal.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.load.kotlin.header.ReadKotlinClassHeaderAnnotationVisitor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
@@ -195,6 +197,11 @@ private object ReflectClassStructure {
currentClass = currentClass.componentType
}
if (currentClass.isPrimitive) {
if (currentClass == Void.TYPE) {
// void.class is not representable in Kotlin, we approximate it by Unit::class
return ClassLiteralValue(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.unit.toSafe()), dimensions)
}
val primitiveType = JvmPrimitiveType.get(currentClass.name).primitiveType
if (dimensions > 0) {
return ClassLiteralValue(ClassId.topLevel(primitiveType.arrayTypeFqName), dimensions - 1)