[FIR] Fix serialization of annotation vararg arguments
#KT-58937 Fixed
This commit is contained in:
committed by
Space Team
parent
fd4d4f516f
commit
8ff67218f5
+6
@@ -60,6 +60,12 @@ public class FirLoadK1CompiledJvmKotlinTestGenerated extends AbstractFirLoadK1Co
|
||||
runTest("compiler/testData/loadJava/compiledKotlin/annotations/AnnotationOnTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationWithVarargParam.kt")
|
||||
public void testAnnotationWithVarargParam() throws Exception {
|
||||
runTest("compiler/testData/loadJava/compiledKotlin/annotations/AnnotationWithVarargParam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassLiteralArguments.kt")
|
||||
public void testClassLiteralArguments() throws Exception {
|
||||
|
||||
+6
@@ -60,6 +60,12 @@ public class FirLoadK2CompiledJvmKotlinTestGenerated extends AbstractFirLoadK2Co
|
||||
runTest("compiler/testData/loadJava/compiledKotlin/annotations/AnnotationOnTypeParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationWithVarargParam.kt")
|
||||
public void testAnnotationWithVarargParam() throws Exception {
|
||||
runTest("compiler/testData/loadJava/compiledKotlin/annotations/AnnotationWithVarargParam.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ClassLiteralArguments.kt")
|
||||
public void testClassLiteralArguments() throws Exception {
|
||||
|
||||
+25
-13
@@ -14,14 +14,15 @@ import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isConst
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirArrayOfCallTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirArrayOfCallTransformer.Companion.isArrayOfCall
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||
|
||||
@@ -49,6 +50,11 @@ internal data class FirToConstantValueTransformerData(
|
||||
internal abstract class FirToConstantValueTransformer(
|
||||
private val failOnNonConst: Boolean,
|
||||
) : FirDefaultVisitor<ConstantValue<*>?, FirToConstantValueTransformerData>() {
|
||||
private fun FirExpression.toConstantValue(data: FirToConstantValueTransformerData): ConstantValue<*>? {
|
||||
return data.constValueProvider?.findConstantValueFor(this)
|
||||
?: accept(this@FirToConstantValueTransformer, data)
|
||||
}
|
||||
|
||||
override fun visitElement(
|
||||
element: FirElement,
|
||||
data: FirToConstantValueTransformerData
|
||||
@@ -87,7 +93,7 @@ internal abstract class FirToConstantValueTransformer(
|
||||
stringConcatenationCall: FirStringConcatenationCall,
|
||||
data: FirToConstantValueTransformerData
|
||||
): ConstantValue<*>? {
|
||||
val strings = stringConcatenationCall.argumentList.arguments.map { it.accept(this, data) }
|
||||
val strings = stringConcatenationCall.argumentList.arguments.map { it.toConstantValue(data) }
|
||||
if (strings.any { it == null || it !is StringValue }) return null
|
||||
return StringValue(strings.joinToString(separator = "") { (it as StringValue).value })
|
||||
}
|
||||
@@ -96,7 +102,7 @@ internal abstract class FirToConstantValueTransformer(
|
||||
arrayOfCall: FirArrayOfCall,
|
||||
data: FirToConstantValueTransformerData
|
||||
): ConstantValue<*> {
|
||||
return ArrayValue(arrayOfCall.argumentList.arguments.mapNotNull { it.accept(this, data) })
|
||||
return ArrayValue(arrayOfCall.argumentList.arguments.mapNotNull { it.toConstantValue(data) })
|
||||
}
|
||||
|
||||
override fun visitAnnotation(
|
||||
@@ -132,12 +138,12 @@ internal abstract class FirToConstantValueTransformer(
|
||||
}
|
||||
|
||||
symbol is FirPropertySymbol -> {
|
||||
if (symbol.fir.isConst) symbol.fir.initializer?.accept(this, data) else null
|
||||
if (symbol.fir.isConst) symbol.fir.initializer?.toConstantValue(data) else null
|
||||
}
|
||||
|
||||
fir is FirJavaField -> {
|
||||
if (fir.isFinal) {
|
||||
fir.initializer?.accept(this, data)
|
||||
fir.initializer?.toConstantValue(data)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -156,7 +162,7 @@ internal abstract class FirToConstantValueTransformer(
|
||||
|
||||
symbol.callableId.packageName.asString() == "kotlin" -> {
|
||||
val dispatchReceiver = qualifiedAccessExpression.dispatchReceiver
|
||||
val dispatchReceiverValue by lazy { dispatchReceiver.accept(this, data) }
|
||||
val dispatchReceiverValue by lazy { dispatchReceiver.toConstantValue(data) }
|
||||
when (symbol.callableId.callableName.asString()) {
|
||||
"toByte" -> ByteValue((dispatchReceiverValue!!.value as Number).toByte())
|
||||
"toLong" -> LongValue((dispatchReceiverValue!!.value as Number).toLong())
|
||||
@@ -201,16 +207,22 @@ internal abstract class FirToConstantValueTransformer(
|
||||
|
||||
override fun visitVarargArgumentsExpression(
|
||||
varargArgumentsExpression: FirVarargArgumentsExpression,
|
||||
data: FirToConstantValueTransformerData
|
||||
data: FirToConstantValueTransformerData,
|
||||
): ConstantValue<*> {
|
||||
return ArrayValue(varargArgumentsExpression.arguments.mapNotNull { it.accept(this, data) })
|
||||
val arguments = varargArgumentsExpression.arguments.let {
|
||||
// Named, spread or array literal arguments for vararg parameters have the form Vararg(Named/Spread?(ArrayOfCall(..))).
|
||||
// We need to extract the ArrayOfCall, otherwise we will get two nested ArrayValue as a result.
|
||||
(it.singleOrNull()?.unwrapArgument() as? FirArrayOfCall)?.arguments ?: it
|
||||
}
|
||||
|
||||
return ArrayValue(arguments.mapNotNull { it.toConstantValue(data) })
|
||||
}
|
||||
|
||||
override fun visitNamedArgumentExpression(
|
||||
namedArgumentExpression: FirNamedArgumentExpression,
|
||||
data: FirToConstantValueTransformerData
|
||||
override fun visitWrappedArgumentExpression(
|
||||
wrappedArgumentExpression: FirWrappedArgumentExpression,
|
||||
data: FirToConstantValueTransformerData,
|
||||
): ConstantValue<*>? {
|
||||
return namedArgumentExpression.expression.accept(this, data)
|
||||
return wrappedArgumentExpression.expression.toConstantValue(data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-5
@@ -5,8 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fakeElement
|
||||
import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
@@ -45,6 +44,10 @@ internal fun remapArgumentsWithVararg(
|
||||
//todo ideally we should use here a source from the use-site and not from the declaration-site
|
||||
this.varargElementType = varargParameterTypeRef.withReplacedConeType(varargElementType, KtFakeSourceElementKind.VarargArgument)
|
||||
this.typeRef = varargParameterTypeRef.withReplacedConeType(varargArrayType, KtFakeSourceElementKind.VarargArgument)
|
||||
var startOffset = Int.MAX_VALUE
|
||||
var endOffset = 0
|
||||
var firstVarargElementSource: KtSourceElement? = null
|
||||
|
||||
for ((i, arg) in argumentList.withIndex()) {
|
||||
val valueParameter = argumentMapping.getValue(arg)
|
||||
// Collect arguments if `arg` is a vararg argument of interest or other vararg arguments.
|
||||
@@ -53,9 +56,9 @@ internal fun remapArgumentsWithVararg(
|
||||
(valueParameter.isVararg && arg !is FirNamedArgumentExpression)
|
||||
) {
|
||||
arguments += arg
|
||||
if (this.source == null) {
|
||||
this.source = arg.source?.fakeElement(KtFakeSourceElementKind.VarargArgument)
|
||||
}
|
||||
startOffset = minOf(startOffset, arg.source?.startOffset ?: Int.MAX_VALUE)
|
||||
endOffset = maxOf(endOffset, arg.source?.endOffset ?: 0)
|
||||
if (firstVarargElementSource == null) firstVarargElementSource = arg.source
|
||||
} else if (arguments.isEmpty()) {
|
||||
// `arg` is BEFORE the vararg arguments.
|
||||
newArgumentMapping[arg] = valueParameter
|
||||
@@ -65,6 +68,8 @@ internal fun remapArgumentsWithVararg(
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
source = firstVarargElementSource?.fakeElement(KtFakeSourceElementKind.VarargArgument, startOffset, endOffset)
|
||||
}
|
||||
newArgumentMapping[varargArgument] = varargParameter
|
||||
|
||||
|
||||
Reference in New Issue
Block a user