[FIR] Map Class to KClass in java annotations

This commit is contained in:
Dmitriy Novozhilov
2020-07-23 15:57:34 +03:00
committed by Mikhail Glukhikh
parent 282a295d43
commit b63257345b
10 changed files with 58 additions and 40 deletions
@@ -106,11 +106,12 @@ internal fun JavaClassifierType.toFirResolvedTypeRef(
internal fun JavaType?.toConeKotlinTypeWithoutEnhancement(
session: FirSession,
javaTypeParameterStack: JavaTypeParameterStack
javaTypeParameterStack: JavaTypeParameterStack,
forAnnotationValueParameter: Boolean = false
): ConeKotlinType {
return when (this) {
is JavaClassifierType -> {
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack)
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forAnnotationValueParameter = forAnnotationValueParameter)
}
is JavaPrimitiveType -> {
val primitiveType = type
@@ -123,7 +124,7 @@ internal fun JavaType?.toConeKotlinTypeWithoutEnhancement(
classId.toConeKotlinType(emptyArray(), isNullable = false)
}
is JavaArrayType -> {
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack)
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forAnnotationValueParameter)
}
is JavaWildcardType -> bound?.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack) ?: run {
StandardClassIds.Any.toConeFlexibleType(emptyArray())
@@ -137,12 +138,13 @@ internal fun JavaType?.toConeKotlinTypeWithoutEnhancement(
private fun JavaArrayType.toConeKotlinTypeWithoutEnhancement(
session: FirSession,
javaTypeParameterStack: JavaTypeParameterStack
javaTypeParameterStack: JavaTypeParameterStack,
forAnnotationValueParameter: Boolean = false
): ConeFlexibleType {
val componentType = componentType
return if (componentType !is JavaPrimitiveType) {
val classId = StandardClassIds.Array
val argumentType = componentType.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack)
val argumentType = componentType.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forAnnotationValueParameter)
classId.toConeFlexibleType(
arrayOf(argumentType),
typeArgumentsForUpper = arrayOf(ConeKotlinTypeProjectionOut(argumentType))
@@ -166,12 +168,24 @@ private fun ClassId.toConeFlexibleType(
private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement(
session: FirSession,
javaTypeParameterStack: JavaTypeParameterStack,
forTypeParameterBounds: Boolean = false
forTypeParameterBounds: Boolean = false,
forAnnotationValueParameter: Boolean = false
): ConeKotlinType {
val lowerBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, isLowerBound = true, forTypeParameterBounds)
val lowerBound = toConeKotlinTypeForFlexibleBound(
session,
javaTypeParameterStack,
isLowerBound = true,
forTypeParameterBounds,
forAnnotationValueParameter = forAnnotationValueParameter
)
val upperBound =
toConeKotlinTypeForFlexibleBound(
session, javaTypeParameterStack, isLowerBound = false, forTypeParameterBounds, lowerBound
session,
javaTypeParameterStack,
isLowerBound = false,
forTypeParameterBounds,
lowerBound,
forAnnotationValueParameter = forAnnotationValueParameter
)
return if (isRaw) ConeRawType(lowerBound, upperBound) else ConeFlexibleType(lowerBound, upperBound)
@@ -272,12 +286,17 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
javaTypeParameterStack: JavaTypeParameterStack,
isLowerBound: Boolean,
forTypeParameterBounds: Boolean,
lowerBound: ConeLookupTagBasedType? = null
lowerBound: ConeLookupTagBasedType? = null,
forAnnotationValueParameter: Boolean = false
): ConeLookupTagBasedType {
return when (val classifier = classifier) {
is JavaClass -> {
//val classId = classifier.classId!!
var classId = JavaToKotlinClassMap.mapJavaToKotlin(classifier.fqName!!) ?: classifier.classId!!
var classId = if (forAnnotationValueParameter) {
JavaToKotlinClassMap.mapJavaToKotlinIncludingClassMapping(classifier.fqName!!)
} else {
JavaToKotlinClassMap.mapJavaToKotlin(classifier.fqName!!)
} ?: classifier.classId!!
if (isLowerBound) {
classId = classId.readOnlyToMutable() ?: classId
@@ -47,7 +47,8 @@ internal class EnhancementSignatureParts(
internal fun enhance(
session: FirSession,
jsr305State: Jsr305State,
predefined: TypeEnhancementInfo? = null
predefined: TypeEnhancementInfo? = null,
forAnnotationValueParameter: Boolean = false
): PartEnhancementResult {
val qualifiers = computeIndexedQualifiersForOverride(session, jsr305State)
@@ -57,7 +58,11 @@ internal class EnhancementSignatureParts(
}
}
val typeWithoutEnhancement = current.type.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack)
val typeWithoutEnhancement = current.type.toConeKotlinTypeWithoutEnhancement(
session,
javaTypeParameterStack,
forAnnotationValueParameter
)
val containsFunctionN = typeWithoutEnhancement.contains {
if (it is ConeClassErrorType) false
else {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.java.enhancement
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
@@ -289,7 +290,12 @@ class FirSignatureEnhancement(
parameterContainer = ownerParameter,
methodContext = memberContext,
typeInSignature = TypeInSignature.ValueParameter(hasReceiver, index)
).enhance(session, jsr305State, predefinedEnhancementInfo?.parametersInfo?.getOrNull(index))
).enhance(
session,
jsr305State,
predefinedEnhancementInfo?.parametersInfo?.getOrNull(index),
forAnnotationValueParameter = owner.classKind == ClassKind.ANNOTATION_CLASS
)
val firResolvedTypeRef = signatureParts.type
val defaultValueExpression = when (val defaultValue = ownerParameter.getDefaultValueFromAnnotation()) {
NullDefaultValue -> buildConstExpression(null, FirConstKind.Null, null)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_REFLECT
// TARGET_BACKEND: JVM
// FILE: Anno.java
@@ -2,9 +2,9 @@
import java.lang.annotation.Repeatable
<!INAPPLICABLE_CANDIDATE!>@java.lang.annotation.Repeatable(Annotations::class)<!> annotation class RepAnn
@java.lang.annotation.Repeatable(Annotations::class) annotation class RepAnn
<!INAPPLICABLE_CANDIDATE!>@Repeatable(OtherAnnotations::class)<!> annotation class OtherAnn
@Repeatable(OtherAnnotations::class) annotation class OtherAnn
annotation class Annotations(vararg val value: RepAnn)
@@ -12,11 +12,11 @@ public @interface A {
@A(*arrayOf("5", "6"), "7", y = 3) fun test3() {}
<!INAPPLICABLE_CANDIDATE!>@A("1", "2", "3", x = String::class, y = 4)<!> fun test4() {}
@A("1", "2", "3", x = String::class, y = 4) fun test4() {}
@A("4", y = 5) fun test5() {}
<!INAPPLICABLE_CANDIDATE!>@A(*arrayOf("5", "6"), "7", x = Any::class, y = 6)<!> fun test6() {}
@A(*arrayOf("5", "6"), "7", x = Any::class, y = 6) fun test6() {}
@A(y = 7) fun test7() {}
@@ -15,11 +15,11 @@ public @interface A {
@A(*arrayOf("5", "6"), "7") fun test3() {}
<!INAPPLICABLE_CANDIDATE!>@A("1", "2", "3", x = String::class)<!> fun test4() {}
@A("1", "2", "3", x = String::class) fun test4() {}
@A("4", y = 2) fun test5() {}
<!INAPPLICABLE_CANDIDATE!>@A(*arrayOf("5", "6"), "7", x = Any::class, y = 3)<!> fun test6() {}
@A(*arrayOf("5", "6"), "7", x = Any::class, y = 3) fun test6() {}
@A() fun test7() {}
@@ -27,4 +27,4 @@ public @interface A {
<!INAPPLICABLE_CANDIDATE!>@A(x = Any::class, *arrayOf("5", "6"), "7", y = 3)<!> fun test9() {}
<!INAPPLICABLE_CANDIDATE!>@A(x = Any::class, value = ["5", "6"], "7", y = 3)<!> fun test10() {}
<!INAPPLICABLE_CANDIDATE!>@A(x = Any::class, value = ["5", "6", "7"], y = 3)<!> fun test11() {}
@A(x = Any::class, value = ["5", "6", "7"], y = 3) fun test11() {}
@@ -1,19 +0,0 @@
// FILE: A.java
public @interface A {
Class<?> arg() default Integer.class;
int x() default 1;
B b();
}
// FILE: B.java
public @interface B {
Class<?> arg() default String.class;
int y() default 2;
}
// FILE: c.kt
@A(arg = String::class, b = B(y = 1)) class MyClass1
@A(b = B(y = 3)) class MyClass2
@A(arg = String::class, b = <!INAPPLICABLE_CANDIDATE!>B<!>(arg = Boolean::class)) class MyClass3
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: A.java
public @interface A {
Class<?> arg() default Integer.class;
@@ -34,6 +34,8 @@ object JavaToKotlinClassMap : PlatformToKotlinClassMap {
private val FUNCTION_N_CLASS_ID = ClassId.topLevel(FqName("kotlin.jvm.functions.FunctionN"))
val FUNCTION_N_FQ_NAME = FUNCTION_N_CLASS_ID.asSingleFqName()
private val K_FUNCTION_CLASS_ID = ClassId.topLevel(FqName("kotlin.reflect.KFunction"))
private val K_CLASS_CLASS_ID = ClassId.topLevel(FqName("kotlin.reflect.KClass"))
private val CLASS_CLASS_ID = classId(java.lang.Class::class.java)
private val javaToKotlin = HashMap<FqNameUnsafe, ClassId>()
private val kotlinToJava = HashMap<FqNameUnsafe, ClassId>()
@@ -123,6 +125,11 @@ object JavaToKotlinClassMap : PlatformToKotlinClassMap {
return javaToKotlin[fqName.toUnsafe()]
}
fun mapJavaToKotlinIncludingClassMapping(fqName: FqName): ClassId? {
if (fqName == CLASS_CLASS_ID.asSingleFqName()) return K_CLASS_CLASS_ID
return mapJavaToKotlin(fqName)
}
fun mapJavaToKotlin(fqName: FqName, builtIns: KotlinBuiltIns, functionTypeArity: Int? = null): ClassDescriptor? {
val kotlinClassId =
if (functionTypeArity != null && fqName == FUNCTION_N_FQ_NAME) KotlinBuiltIns.getFunctionClassId(functionTypeArity)