From af58b30e5f4fca29445f2ef50bc21a16cba11a17 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 11 Oct 2023 14:55:54 +0200 Subject: [PATCH] K2 Java: fix 'value' annotation constructor parameter type to Array #KT-61100 Fixed --- .../kotlin/fir/java/JavaTypeConversion.kt | 31 ++++++++++--------- .../java/enhancement/SignatureEnhancement.kt | 13 ++++++-- .../annotations/AnnotationInParam.fir.txt | 2 +- .../annotations/ArrayOfStringInParam.fir.txt | 2 +- .../ClassObjectArrayInParam.fir.txt | 2 +- .../annotations/EmptyArrayInParam.fir.txt | 2 +- .../EnumArgumentWithCustomToString.fir.txt | 2 +- 7 files changed, 33 insertions(+), 21 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt index b574138e03b..d0a9ac23c51 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt @@ -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`, `C` -> `C..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) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt index 032ecc21204..b4602a4f104 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt @@ -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 diff --git a/compiler/testData/loadJava/compiledJava/annotations/AnnotationInParam.fir.txt b/compiler/testData/loadJava/compiledJava/annotations/AnnotationInParam.fir.txt index 4f286c4cf30..6f34a8823d2 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/AnnotationInParam.fir.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/AnnotationInParam.fir.txt @@ -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|): R|test/AnnotationInParam.MyAnnotation2| + public constructor(vararg value: R|kotlin/Array|): R|test/AnnotationInParam.MyAnnotation2| } public final annotation class MyAnnotation3 : R|kotlin/Annotation| { diff --git a/compiler/testData/loadJava/compiledJava/annotations/ArrayOfStringInParam.fir.txt b/compiler/testData/loadJava/compiledJava/annotations/ArrayOfStringInParam.fir.txt index 4474504ff89..056170d8afb 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/ArrayOfStringInParam.fir.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/ArrayOfStringInParam.fir.txt @@ -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|): R|test/ArrayOfStringInParam.MyAnnotation| + public constructor(vararg value: R|kotlin/Array|): R|test/ArrayOfStringInParam.MyAnnotation| } } diff --git a/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.fir.txt b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.fir.txt index 2cf07431c75..b15059cb8ff 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.fir.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.fir.txt @@ -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>|): R|test/ClassObjectArrayInParam.Anno| + public constructor(vararg value: R|kotlin/Array>|): R|test/ClassObjectArrayInParam.Anno| } @R|test/ClassObjectArrayInParam.Anno|(value = (((R|test/ClassObjectArrayInParam!|)), ((R|test/ClassObjectArrayInParam.Nested!|)), ((R|kotlin/String!|)), ((R|ft, kotlin/collections/List<*>?>|)), ((R|ft, kotlin/Array?>>, kotlin/Array, kotlin/Array?>>?>|)), ((R|ft, kotlin/Array?>|)), ((R|kotlin/Unit|)))) public open class Nested : R|kotlin/Any| { diff --git a/compiler/testData/loadJava/compiledJava/annotations/EmptyArrayInParam.fir.txt b/compiler/testData/loadJava/compiledJava/annotations/EmptyArrayInParam.fir.txt index a3969db3883..11c91858ebb 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/EmptyArrayInParam.fir.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/EmptyArrayInParam.fir.txt @@ -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|): R|test/EmptyArrayInParam.MyAnnotation| + public constructor(vararg value: R|kotlin/Array|): R|test/EmptyArrayInParam.MyAnnotation| } } diff --git a/compiler/testData/loadJava/compiledJava/annotations/EnumArgumentWithCustomToString.fir.txt b/compiler/testData/loadJava/compiledJava/annotations/EnumArgumentWithCustomToString.fir.txt index a604e8adbc7..06a0d7fd35d 100644 --- a/compiler/testData/loadJava/compiledJava/annotations/EnumArgumentWithCustomToString.fir.txt +++ b/compiler/testData/loadJava/compiledJava/annotations/EnumArgumentWithCustomToString.fir.txt @@ -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|): R|test/EnumArgumentWithCustomToString.EnumArrayAnno| + public constructor(vararg value: R|kotlin/Array|): R|test/EnumArgumentWithCustomToString.EnumArrayAnno| } }