[FIR] Map Class to KClass in java annotations
This commit is contained in:
committed by
Mikhail Glukhikh
parent
282a295d43
commit
b63257345b
@@ -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
|
||||
|
||||
+7
-2
@@ -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 {
|
||||
|
||||
+7
-1
@@ -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
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_REFLECT
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: Anno.java
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -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() {}
|
||||
|
||||
|
||||
+3
-3
@@ -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() {}
|
||||
|
||||
-19
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user