K2 Java: fix 'value' annotation constructor parameter type to Array<out>

#KT-61100 Fixed
This commit is contained in:
Mikhail Glukhikh
2023-10-11 14:55:54 +02:00
committed by Space Team
parent 8e4a6759a4
commit af58b30e5f
7 changed files with 33 additions and 21 deletions
@@ -16,13 +16,11 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.fir.types.jvm.buildJavaTypeRef
import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
private fun ClassId.toConeFlexibleType(
@@ -37,8 +35,10 @@ private fun ClassId.toConeFlexibleType(
}
enum class FirJavaTypeConversionMode {
DEFAULT, ANNOTATION_MEMBER, SUPERTYPE,
TYPE_PARAMETER_BOUND_FIRST_ROUND, TYPE_PARAMETER_BOUND_AFTER_FIRST_ROUND
DEFAULT, ANNOTATION_MEMBER, ANNOTATION_CONSTRUCTOR_PARAMETER, SUPERTYPE,
TYPE_PARAMETER_BOUND_FIRST_ROUND, TYPE_PARAMETER_BOUND_AFTER_FIRST_ROUND;
val insideAnnotation: Boolean get() = this == ANNOTATION_MEMBER || this == ANNOTATION_CONSTRUCTOR_PARAMETER
}
fun FirTypeRef.resolveIfJavaType(
@@ -105,7 +105,7 @@ private fun JavaType?.toConeTypeProjection(
return when (this) {
is JavaClassifierType -> {
val lowerBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes)
if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) {
if (mode.insideAnnotation) {
return lowerBound
}
val upperBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, mode, attributes, lowerBound)
@@ -133,11 +133,14 @@ private fun JavaType?.toConeTypeProjection(
else ->
StandardClassIds.Array to arrayOf(componentType.toConeKotlinType(session, javaTypeParameterStack, mode))
}
if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) {
classId.constructClassLikeType(arguments, isNullable = false, attributes)
} else {
val argumentsForUpper = Array(arguments.size) { ConeKotlinTypeProjectionOut(arguments[it]) }
classId.toConeFlexibleType(arguments, argumentsForUpper, attributes)
val argumentsWithOutProjection = Array(arguments.size) { ConeKotlinTypeProjectionOut(arguments[it]) }
when (mode) {
FirJavaTypeConversionMode.ANNOTATION_CONSTRUCTOR_PARAMETER ->
classId.constructClassLikeType(argumentsWithOutProjection, isNullable = false, attributes)
FirJavaTypeConversionMode.ANNOTATION_MEMBER ->
classId.constructClassLikeType(arguments, isNullable = false, attributes)
else ->
classId.toConeFlexibleType(arguments, typeArgumentsForUpper = argumentsWithOutProjection, attributes)
}
}
@@ -175,7 +178,7 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
): ConeLookupTagBasedType {
return when (val classifier = classifier) {
is JavaClass -> {
var classId = if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) {
var classId = if (mode.insideAnnotation) {
JavaToKotlinClassMap.mapJavaToKotlinIncludingClassMapping(classifier.fqName!!)
} else {
JavaToKotlinClassMap.mapJavaToKotlin(classifier.fqName!!)
@@ -195,8 +198,8 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
lookupTag.takeIf { lowerBound == null && mode != FirJavaTypeConversionMode.TYPE_PARAMETER_BOUND_FIRST_ROUND }
?.toFirRegularClassSymbol(session)?.typeParameterSymbols
// Given `C<T : X>`, `C` -> `C<X>..C<*>?`.
when (mode) {
FirJavaTypeConversionMode.ANNOTATION_MEMBER -> Array(classifier.allTypeParametersNumber()) { ConeStarProjection }
when {
mode.insideAnnotation -> Array(classifier.allTypeParametersNumber()) { ConeStarProjection }
else -> typeParameterSymbols?.getProjectionsForRawType(session)
?: Array(classifier.allTypeParametersNumber()) { ConeStarProjection }
}
@@ -208,7 +211,7 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound(
?.toFirRegularClassSymbol(session)?.typeParameterSymbols
Array(typeArguments.size) { index ->
// TODO: check this
val newMode = if (mode == FirJavaTypeConversionMode.ANNOTATION_MEMBER) FirJavaTypeConversionMode.DEFAULT else mode
val newMode = if (mode.insideAnnotation) FirJavaTypeConversionMode.DEFAULT else mode
val argument = typeArguments[index]
val variance = typeParameterSymbols?.getOrNull(index)?.fir?.variance ?: Variance.INVARIANT
argument.toConeTypeProjection(session, javaTypeParameterStack, variance, newMode)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.java.enhancement
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.builtins.StandardNames.DEFAULT_VALUE_PARAMETER
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fakeElement
@@ -43,6 +44,7 @@ import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType.VALUE_PARAMETER
import org.jetbrains.kotlin.load.java.FakePureImplementationsProvider
import org.jetbrains.kotlin.load.java.JavaTypeQualifiersByElementType
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
@@ -647,7 +649,7 @@ class FirSignatureEnhancement(
parameterContainer?.let {
typeQualifierResolver.extractAndMergeDefaultQualifiers(defaultQualifiers, it.annotations)
} ?: defaultQualifiers,
AnnotationQualifierApplicabilityType.VALUE_PARAMETER,
VALUE_PARAMETER,
typeInSignature,
predefined,
forAnnotationMember
@@ -665,7 +667,14 @@ class FirSignatureEnhancement(
): FirResolvedTypeRef {
val typeRef = typeInSignature.getTypeRef(this)
val typeRefsFromOverridden = overriddenMembers.map { typeInSignature.getTypeRef(it) }
val mode = if (forAnnotationMember) FirJavaTypeConversionMode.ANNOTATION_MEMBER else FirJavaTypeConversionMode.DEFAULT
val mode = when {
!forAnnotationMember ->
FirJavaTypeConversionMode.DEFAULT
containerApplicabilityType == VALUE_PARAMETER && (typeContainer as? FirValueParameter)?.name == DEFAULT_VALUE_PARAMETER ->
FirJavaTypeConversionMode.ANNOTATION_CONSTRUCTOR_PARAMETER
else ->
FirJavaTypeConversionMode.ANNOTATION_MEMBER
}
return EnhancementSignatureParts(
session, typeQualifierResolver, typeContainer, isCovariant, forceOnlyHeadTypeConstructor = false,
containerApplicabilityType, containerQualifiers
@@ -16,7 +16,7 @@ public abstract interface AnnotationInParam : R|kotlin/Any| {
}
public final annotation class MyAnnotation2 : R|kotlin/Annotation| {
public constructor(vararg value: R|kotlin/Array<kotlin/String>|): R|test/AnnotationInParam.MyAnnotation2|
public constructor(vararg value: R|kotlin/Array<out kotlin/String>|): R|test/AnnotationInParam.MyAnnotation2|
}
public final annotation class MyAnnotation3 : R|kotlin/Annotation| {
@@ -4,7 +4,7 @@ public abstract interface ArrayOfStringInParam : R|kotlin/Any| {
}
public final annotation class MyAnnotation : R|kotlin/Annotation| {
public constructor(vararg value: R|kotlin/Array<kotlin/String>|): R|test/ArrayOfStringInParam.MyAnnotation|
public constructor(vararg value: R|kotlin/Array<out kotlin/String>|): R|test/ArrayOfStringInParam.MyAnnotation|
}
}
@@ -2,7 +2,7 @@ public open class ClassObjectArrayInParam : R|kotlin/Any| {
public constructor(): R|test/ClassObjectArrayInParam|
public final annotation class Anno : R|kotlin/Annotation| {
public constructor(vararg value: R|kotlin/Array<kotlin/reflect/KClass<*>>|): R|test/ClassObjectArrayInParam.Anno|
public constructor(vararg value: R|kotlin/Array<out kotlin/reflect/KClass<*>>|): R|test/ClassObjectArrayInParam.Anno|
}
@R|test/ClassObjectArrayInParam.Anno|(value = <implicitArrayOf>(<getClass>(<getClass>(R|test/ClassObjectArrayInParam!|)), <getClass>(<getClass>(R|test/ClassObjectArrayInParam.Nested!|)), <getClass>(<getClass>(R|kotlin/String!|)), <getClass>(<getClass>(R|ft<Raw type kotlin/collections/MutableList<kotlin/Any?>, kotlin/collections/List<*>?>|)), <getClass>(<getClass>(R|ft<kotlin/Array<ft<kotlin/Array<kotlin/String!>, kotlin/Array<out kotlin/String!>?>>, kotlin/Array<out ft<kotlin/Array<kotlin/String!>, kotlin/Array<out kotlin/String!>?>>?>|)), <getClass>(<getClass>(R|ft<kotlin/Array<kotlin/IntArray!>, kotlin/Array<out kotlin/IntArray!>?>|)), <getClass>(<getClass>(R|kotlin/Unit|)))) public open class Nested : R|kotlin/Any| {
@@ -4,7 +4,7 @@ public abstract interface EmptyArrayInParam : R|kotlin/Any| {
}
public final annotation class MyAnnotation : R|kotlin/Annotation| {
public constructor(vararg value: R|kotlin/Array<kotlin/String>|): R|test/EmptyArrayInParam.MyAnnotation|
public constructor(vararg value: R|kotlin/Array<out kotlin/String>|): R|test/EmptyArrayInParam.MyAnnotation|
}
}
@@ -20,7 +20,7 @@ public open class EnumArgumentWithCustomToString : R|kotlin/Any| {
}
public final annotation class EnumArrayAnno : R|kotlin/Annotation| {
public constructor(vararg value: R|kotlin/Array<test/EnumArgumentWithCustomToString.E>|): R|test/EnumArgumentWithCustomToString.EnumArrayAnno|
public constructor(vararg value: R|kotlin/Array<out test/EnumArgumentWithCustomToString.E>|): R|test/EnumArgumentWithCustomToString.EnumArrayAnno|
}
}