[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(
|
internal fun JavaType?.toConeKotlinTypeWithoutEnhancement(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
javaTypeParameterStack: JavaTypeParameterStack
|
javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
|
forAnnotationValueParameter: Boolean = false
|
||||||
): ConeKotlinType {
|
): ConeKotlinType {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is JavaClassifierType -> {
|
is JavaClassifierType -> {
|
||||||
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack)
|
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forAnnotationValueParameter = forAnnotationValueParameter)
|
||||||
}
|
}
|
||||||
is JavaPrimitiveType -> {
|
is JavaPrimitiveType -> {
|
||||||
val primitiveType = type
|
val primitiveType = type
|
||||||
@@ -123,7 +124,7 @@ internal fun JavaType?.toConeKotlinTypeWithoutEnhancement(
|
|||||||
classId.toConeKotlinType(emptyArray(), isNullable = false)
|
classId.toConeKotlinType(emptyArray(), isNullable = false)
|
||||||
}
|
}
|
||||||
is JavaArrayType -> {
|
is JavaArrayType -> {
|
||||||
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack)
|
toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forAnnotationValueParameter)
|
||||||
}
|
}
|
||||||
is JavaWildcardType -> bound?.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack) ?: run {
|
is JavaWildcardType -> bound?.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack) ?: run {
|
||||||
StandardClassIds.Any.toConeFlexibleType(emptyArray())
|
StandardClassIds.Any.toConeFlexibleType(emptyArray())
|
||||||
@@ -137,12 +138,13 @@ internal fun JavaType?.toConeKotlinTypeWithoutEnhancement(
|
|||||||
|
|
||||||
private fun JavaArrayType.toConeKotlinTypeWithoutEnhancement(
|
private fun JavaArrayType.toConeKotlinTypeWithoutEnhancement(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
javaTypeParameterStack: JavaTypeParameterStack
|
javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
|
forAnnotationValueParameter: Boolean = false
|
||||||
): ConeFlexibleType {
|
): ConeFlexibleType {
|
||||||
val componentType = componentType
|
val componentType = componentType
|
||||||
return if (componentType !is JavaPrimitiveType) {
|
return if (componentType !is JavaPrimitiveType) {
|
||||||
val classId = StandardClassIds.Array
|
val classId = StandardClassIds.Array
|
||||||
val argumentType = componentType.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack)
|
val argumentType = componentType.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forAnnotationValueParameter)
|
||||||
classId.toConeFlexibleType(
|
classId.toConeFlexibleType(
|
||||||
arrayOf(argumentType),
|
arrayOf(argumentType),
|
||||||
typeArgumentsForUpper = arrayOf(ConeKotlinTypeProjectionOut(argumentType))
|
typeArgumentsForUpper = arrayOf(ConeKotlinTypeProjectionOut(argumentType))
|
||||||
@@ -166,12 +168,24 @@ private fun ClassId.toConeFlexibleType(
|
|||||||
private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement(
|
private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
javaTypeParameterStack: JavaTypeParameterStack,
|
javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
forTypeParameterBounds: Boolean = false
|
forTypeParameterBounds: Boolean = false,
|
||||||
|
forAnnotationValueParameter: Boolean = false
|
||||||
): ConeKotlinType {
|
): ConeKotlinType {
|
||||||
val lowerBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, isLowerBound = true, forTypeParameterBounds)
|
val lowerBound = toConeKotlinTypeForFlexibleBound(
|
||||||
|
session,
|
||||||
|
javaTypeParameterStack,
|
||||||
|
isLowerBound = true,
|
||||||
|
forTypeParameterBounds,
|
||||||
|
forAnnotationValueParameter = forAnnotationValueParameter
|
||||||
|
)
|
||||||
val upperBound =
|
val upperBound =
|
||||||
toConeKotlinTypeForFlexibleBound(
|
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)
|
return if (isRaw) ConeRawType(lowerBound, upperBound) else ConeFlexibleType(lowerBound, upperBound)
|
||||||
@@ -272,12 +286,17 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
|
|||||||
javaTypeParameterStack: JavaTypeParameterStack,
|
javaTypeParameterStack: JavaTypeParameterStack,
|
||||||
isLowerBound: Boolean,
|
isLowerBound: Boolean,
|
||||||
forTypeParameterBounds: Boolean,
|
forTypeParameterBounds: Boolean,
|
||||||
lowerBound: ConeLookupTagBasedType? = null
|
lowerBound: ConeLookupTagBasedType? = null,
|
||||||
|
forAnnotationValueParameter: Boolean = false
|
||||||
): ConeLookupTagBasedType {
|
): ConeLookupTagBasedType {
|
||||||
return when (val classifier = classifier) {
|
return when (val classifier = classifier) {
|
||||||
is JavaClass -> {
|
is JavaClass -> {
|
||||||
//val classId = classifier.classId!!
|
//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) {
|
if (isLowerBound) {
|
||||||
classId = classId.readOnlyToMutable() ?: classId
|
classId = classId.readOnlyToMutable() ?: classId
|
||||||
|
|||||||
+7
-2
@@ -47,7 +47,8 @@ internal class EnhancementSignatureParts(
|
|||||||
internal fun enhance(
|
internal fun enhance(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
jsr305State: Jsr305State,
|
jsr305State: Jsr305State,
|
||||||
predefined: TypeEnhancementInfo? = null
|
predefined: TypeEnhancementInfo? = null,
|
||||||
|
forAnnotationValueParameter: Boolean = false
|
||||||
): PartEnhancementResult {
|
): PartEnhancementResult {
|
||||||
val qualifiers = computeIndexedQualifiersForOverride(session, jsr305State)
|
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 {
|
val containsFunctionN = typeWithoutEnhancement.contains {
|
||||||
if (it is ConeClassErrorType) false
|
if (it is ConeClassErrorType) false
|
||||||
else {
|
else {
|
||||||
|
|||||||
+7
-1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.java.enhancement
|
package org.jetbrains.kotlin.fir.java.enhancement
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
@@ -289,7 +290,12 @@ class FirSignatureEnhancement(
|
|||||||
parameterContainer = ownerParameter,
|
parameterContainer = ownerParameter,
|
||||||
methodContext = memberContext,
|
methodContext = memberContext,
|
||||||
typeInSignature = TypeInSignature.ValueParameter(hasReceiver, index)
|
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 firResolvedTypeRef = signatureParts.type
|
||||||
val defaultValueExpression = when (val defaultValue = ownerParameter.getDefaultValueFromAnnotation()) {
|
val defaultValueExpression = when (val defaultValue = ownerParameter.getDefaultValueFromAnnotation()) {
|
||||||
NullDefaultValue -> buildConstExpression(null, FirConstKind.Null, null)
|
NullDefaultValue -> buildConstExpression(null, FirConstKind.Null, null)
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// FILE: Anno.java
|
// FILE: Anno.java
|
||||||
|
|||||||
+2
-2
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
import java.lang.annotation.Repeatable
|
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)
|
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() {}
|
@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() {}
|
@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() {}
|
@A(y = 7) fun test7() {}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -15,11 +15,11 @@ public @interface A {
|
|||||||
|
|
||||||
@A(*arrayOf("5", "6"), "7") fun test3() {}
|
@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() {}
|
@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() {}
|
@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, *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 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
|
// FILE: A.java
|
||||||
public @interface A {
|
public @interface A {
|
||||||
Class<?> arg() default Integer.class;
|
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"))
|
private val FUNCTION_N_CLASS_ID = ClassId.topLevel(FqName("kotlin.jvm.functions.FunctionN"))
|
||||||
val FUNCTION_N_FQ_NAME = FUNCTION_N_CLASS_ID.asSingleFqName()
|
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_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 javaToKotlin = HashMap<FqNameUnsafe, ClassId>()
|
||||||
private val kotlinToJava = HashMap<FqNameUnsafe, ClassId>()
|
private val kotlinToJava = HashMap<FqNameUnsafe, ClassId>()
|
||||||
@@ -123,6 +125,11 @@ object JavaToKotlinClassMap : PlatformToKotlinClassMap {
|
|||||||
return javaToKotlin[fqName.toUnsafe()]
|
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? {
|
fun mapJavaToKotlin(fqName: FqName, builtIns: KotlinBuiltIns, functionTypeArity: Int? = null): ClassDescriptor? {
|
||||||
val kotlinClassId =
|
val kotlinClassId =
|
||||||
if (functionTypeArity != null && fqName == FUNCTION_N_FQ_NAME) KotlinBuiltIns.getFunctionClassId(functionTypeArity)
|
if (functionTypeArity != null && fqName == FUNCTION_N_FQ_NAME) KotlinBuiltIns.getFunctionClassId(functionTypeArity)
|
||||||
|
|||||||
Reference in New Issue
Block a user