Support KClassValue in JavaActualAnnotationArgumentExtractor

#KT-22704 Fixed
This commit is contained in:
Alexander Udalov
2018-10-18 18:24:25 +02:00
parent 49d6a7a7cb
commit 3bfe138dbe
3 changed files with 44 additions and 8 deletions
@@ -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
}
@@ -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<String> = ["bu", "zz"],
// TODO: val ka: Array<KClass<*>> = [Double::class, String::class, LongArray::class, Array<Array<Array<Int>>>::class],
val ka: Array<KClass<*>> = [Double::class, String::class, LongArray::class, Array<Array<Array<Int>>>::class, Unit::class],
val ea: Array<E> = [E.E2, E.E3]
// TODO: val aa: Array<A> = [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")};
}
@@ -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<kotlin.String> = ..., /*21*/ ea: kotlin.Array<E> = ...)
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<kotlin.String> = ..., /*22*/ ka: kotlin.Array<kotlin.reflect.KClass<*>> = ..., /*23*/ ea: kotlin.Array<E> = ...)
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<kotlin.reflect.KClass<*>>
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<E> {
}
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<kotlin.String> = ..., /*21*/ ea: kotlin.Array<E> = ...)
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<kotlin.String> = ..., /*22*/ ka: kotlin.Array<kotlin.reflect.KClass<*>> = ..., /*23*/ ea: kotlin.Array<E> = ...)
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<kotlin.reflect.KClass<*>>
public final val s: kotlin.Short
public final val sa: kotlin.ShortArray
public final val str: kotlin.String