From 3bfe138dbec85a17d0c6801874a369563fda45b9 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 18 Oct 2018 18:24:25 +0200 Subject: [PATCH] Support KClassValue in JavaActualAnnotationArgumentExtractor #KT-22704 Fixed --- .../JavaActualAnnotationArgumentExtractor.kt | 36 +++++++++++++++++-- .../annotationsViaActualTypeAlias2.kt | 8 ++--- .../annotationsViaActualTypeAlias2.txt | 8 +++-- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt index a2ccdd73064..a0edf64e720 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/multiplatform/JavaActualAnnotationArgumentExtractor.kt @@ -7,13 +7,17 @@ package org.jetbrains.kotlin.resolve.jvm.multiplatform import com.intellij.psi.PsiAnnotationMethod import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluatorImpl import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.impl.JavaAnnotationArgumentImpl +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory import org.jetbrains.kotlin.resolve.constants.EnumValue +import org.jetbrains.kotlin.resolve.constants.KClassValue import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.builtIns @@ -47,8 +51,36 @@ class JavaActualAnnotationArgumentExtractor : ExpectedActualDeclarationChecker.A null } is JavaClassObjectAnnotationArgument -> { - // TODO: support class literals as annotation arguments - null + convertTypeToKClassValue(getReferencedType()) + } + else -> null + } + } + + // See FileBasedKotlinClass.resolveKotlinNameByType + private fun convertTypeToKClassValue(javaType: JavaType): KClassValue? { + var type = javaType + var arrayDimensions = 0 + while (type is JavaArrayType) { + type = type.componentType + arrayDimensions++ + } + return when (type) { + is JavaPrimitiveType -> { + val primitiveType = type.type + // void.class is not representable in Kotlin, we approximate it by Unit::class + ?: return KClassValue(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.unit.toSafe()), 0) + if (arrayDimensions > 0) { + KClassValue(ClassId.topLevel(primitiveType.arrayTypeFqName), arrayDimensions - 1) + } else { + KClassValue(ClassId.topLevel(primitiveType.typeFqName), arrayDimensions) + } + } + is JavaClassifierType -> { + val fqName = FqName(type.classifierQualifiedName) + // TODO: support nested classes somehow + val classId = JavaToKotlinClassMap.mapJavaToKotlin(fqName) ?: ClassId.topLevel(fqName) + KClassValue(classId, arrayDimensions) } else -> null } diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt index 4c49a8c0173..197680e2091 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.kt @@ -24,11 +24,11 @@ expect annotation class Anno( val sa: ShortArray = [(-43).toShort()], val za: BooleanArray = [false, true], val str: String = "fizz", - // TODO: val k: KClass<*> = Number::class, + val k: KClass<*> = Number::class, val e: E = E.E1, // TODO: val a: A = A("1"), val stra: Array = ["bu", "zz"], - // TODO: val ka: Array> = [Double::class, String::class, LongArray::class, Array>>::class], + val ka: Array> = [Double::class, String::class, LongArray::class, Array>>::class, Unit::class], val ea: Array = [E.E2, E.E3] // TODO: val aa: Array = [A("2"), A("3")] ) @@ -67,11 +67,11 @@ public @interface Jnno { short[] sa() default {-43}; boolean[] za() default {false, true}; String str() default "fi" + "zz"; - // TODO: Class k() default Number.class; + Class k() default Number.class; E e() default E.E1; // TODO: A a() default @A("1"); String[] stra() default {"bu", "zz"}; - // TODO: Class[] ka() default {double.class, String.class, long[].class, Integer[][][].class}; + Class[] ka() default {double.class, String.class, long[].class, Integer[][][].class, void.class}; E[] ea() default {E.E2, E.E3}; // TODO: A[] aa() default {@A("2"), @A("3")}; } diff --git a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.txt b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.txt index 8b5e19a7b74..1084752c636 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.txt +++ b/compiler/testData/diagnostics/tests/multiplatform/defaultArguments/annotationsViaActualTypeAlias2.txt @@ -12,7 +12,7 @@ public final annotation class A : kotlin.Annotation { } public final expect annotation class Anno : kotlin.Annotation { - public constructor Anno(/*0*/ b: kotlin.Byte = ..., /*1*/ c: kotlin.Char = ..., /*2*/ d: kotlin.Double = ..., /*3*/ f: kotlin.Float = ..., /*4*/ i: kotlin.Int = ..., /*5*/ i2: kotlin.Int = ..., /*6*/ j: kotlin.Long = ..., /*7*/ j2: kotlin.Long = ..., /*8*/ s: kotlin.Short = ..., /*9*/ z: kotlin.Boolean = ..., /*10*/ ba: kotlin.ByteArray = ..., /*11*/ ca: kotlin.CharArray = ..., /*12*/ da: kotlin.DoubleArray = ..., /*13*/ fa: kotlin.FloatArray = ..., /*14*/ ia: kotlin.IntArray = ..., /*15*/ ja: kotlin.LongArray = ..., /*16*/ sa: kotlin.ShortArray = ..., /*17*/ za: kotlin.BooleanArray = ..., /*18*/ str: kotlin.String = ..., /*19*/ e: E = ..., /*20*/ stra: kotlin.Array = ..., /*21*/ ea: kotlin.Array = ...) + public constructor Anno(/*0*/ b: kotlin.Byte = ..., /*1*/ c: kotlin.Char = ..., /*2*/ d: kotlin.Double = ..., /*3*/ f: kotlin.Float = ..., /*4*/ i: kotlin.Int = ..., /*5*/ i2: kotlin.Int = ..., /*6*/ j: kotlin.Long = ..., /*7*/ j2: kotlin.Long = ..., /*8*/ s: kotlin.Short = ..., /*9*/ z: kotlin.Boolean = ..., /*10*/ ba: kotlin.ByteArray = ..., /*11*/ ca: kotlin.CharArray = ..., /*12*/ da: kotlin.DoubleArray = ..., /*13*/ fa: kotlin.FloatArray = ..., /*14*/ ia: kotlin.IntArray = ..., /*15*/ ja: kotlin.LongArray = ..., /*16*/ sa: kotlin.ShortArray = ..., /*17*/ za: kotlin.BooleanArray = ..., /*18*/ str: kotlin.String = ..., /*19*/ k: kotlin.reflect.KClass<*> = ..., /*20*/ e: E = ..., /*21*/ stra: kotlin.Array = ..., /*22*/ ka: kotlin.Array> = ..., /*23*/ ea: kotlin.Array = ...) public expect final val b: kotlin.Byte public expect final val ba: kotlin.ByteArray public expect final val c: kotlin.Char @@ -29,6 +29,8 @@ public final expect annotation class Anno : kotlin.Annotation { public expect final val j: kotlin.Long public expect final val j2: kotlin.Long public expect final val ja: kotlin.LongArray + public expect final val k: kotlin.reflect.KClass<*> + public expect final val ka: kotlin.Array> public expect final val s: kotlin.Short public expect final val sa: kotlin.ShortArray public expect final val str: kotlin.String @@ -99,7 +101,7 @@ public final enum class E : kotlin.Enum { } public final annotation class Jnno : kotlin.Annotation { - public constructor Jnno(/*0*/ b: kotlin.Byte = ..., /*1*/ c: kotlin.Char = ..., /*2*/ d: kotlin.Double = ..., /*3*/ f: kotlin.Float = ..., /*4*/ i: kotlin.Int = ..., /*5*/ i2: kotlin.Int = ..., /*6*/ j: kotlin.Long = ..., /*7*/ j2: kotlin.Long = ..., /*8*/ s: kotlin.Short = ..., /*9*/ z: kotlin.Boolean = ..., /*10*/ ba: kotlin.ByteArray = ..., /*11*/ ca: kotlin.CharArray = ..., /*12*/ da: kotlin.DoubleArray = ..., /*13*/ fa: kotlin.FloatArray = ..., /*14*/ ia: kotlin.IntArray = ..., /*15*/ ja: kotlin.LongArray = ..., /*16*/ sa: kotlin.ShortArray = ..., /*17*/ za: kotlin.BooleanArray = ..., /*18*/ str: kotlin.String = ..., /*19*/ e: E = ..., /*20*/ stra: kotlin.Array = ..., /*21*/ ea: kotlin.Array = ...) + public constructor Jnno(/*0*/ b: kotlin.Byte = ..., /*1*/ c: kotlin.Char = ..., /*2*/ d: kotlin.Double = ..., /*3*/ f: kotlin.Float = ..., /*4*/ i: kotlin.Int = ..., /*5*/ i2: kotlin.Int = ..., /*6*/ j: kotlin.Long = ..., /*7*/ j2: kotlin.Long = ..., /*8*/ s: kotlin.Short = ..., /*9*/ z: kotlin.Boolean = ..., /*10*/ ba: kotlin.ByteArray = ..., /*11*/ ca: kotlin.CharArray = ..., /*12*/ da: kotlin.DoubleArray = ..., /*13*/ fa: kotlin.FloatArray = ..., /*14*/ ia: kotlin.IntArray = ..., /*15*/ ja: kotlin.LongArray = ..., /*16*/ sa: kotlin.ShortArray = ..., /*17*/ za: kotlin.BooleanArray = ..., /*18*/ str: kotlin.String = ..., /*19*/ k: kotlin.reflect.KClass<*> = ..., /*20*/ e: E = ..., /*21*/ stra: kotlin.Array = ..., /*22*/ ka: kotlin.Array> = ..., /*23*/ ea: kotlin.Array = ...) public final val b: kotlin.Byte public final val ba: kotlin.ByteArray public final val c: kotlin.Char @@ -116,6 +118,8 @@ public final annotation class Jnno : kotlin.Annotation { public final val j: kotlin.Long public final val j2: kotlin.Long public final val ja: kotlin.LongArray + public final val k: kotlin.reflect.KClass<*> + public final val ka: kotlin.Array> public final val s: kotlin.Short public final val sa: kotlin.ShortArray public final val str: kotlin.String