diff --git a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt index 1f2476c869d..9d1c29cbbfd 100644 --- a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt +++ b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt @@ -1212,8 +1212,16 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver is FirNamedArgumentExpression -> { simpleName(expression.name) +" = " + if (expression.isSpread) { + +"*" + } generate(expression.expression) } + is FirSpreadArgumentExpression -> { + +"*" + generate(expression.expression) + + } is FirLambdaArgumentExpression -> { keyword("lambda") +" = " diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt index 86a09977903..8a9230e2fef 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt @@ -288,7 +288,7 @@ class KotlinDeserializedJvmSymbolsProvider( result += FirAnnotationCallImpl(session, null, null, symbol.toDefaultResolvedTypeRef(annotationClassId)).apply { for ((name, expression) in argumentMap) { arguments += FirNamedArgumentExpressionImpl( - this@KotlinDeserializedJvmSymbolsProvider.session, null, name, expression + this@KotlinDeserializedJvmSymbolsProvider.session, null, name, false, expression ) } } diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 73c6ef5f973..3a9f5ba53d8 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -199,7 +199,12 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) { { expression }.toFirExpression("Argument is absent") } } - return if (name != null) FirNamedArgumentExpressionImpl(session, expression, name, firExpression) else firExpression + val isSpread = getSpreadElement() != null + return when { + name != null -> FirNamedArgumentExpressionImpl(session, expression, name, isSpread, firExpression) + isSpread -> FirSpreadArgumentExpressionImpl(session, expression, firExpression) + else -> firExpression + } } private fun KtPropertyAccessor?.toFirPropertyAccessor( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt index bc9f372868a..c7c6af35dbf 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt @@ -83,7 +83,7 @@ abstract class AbstractAnnotationDeserializer( val parameter = parameterByName[name] ?: return@mapNotNull null val value = resolveValue(parameter.returnTypeRef, it.value, nameResolver) ?: return@mapNotNull null FirNamedArgumentExpressionImpl( - session, null, name, value + session, null, name, false, value ) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index 146c46de40c..dcfd2da3a98 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -54,18 +54,7 @@ fun resolveArgumentExpression( is FirCallableReferenceAccess -> Unit // TODO:! //TODO: Collection literal - is FirLambdaArgumentExpression -> resolveArgumentExpression( - csBuilder, - argument.expression, - expectedType, - expectedTypeRef, - sink, - isReceiver, - isSafeCall, - acceptLambdaAtoms, - typeProvider - ) - is FirNamedArgumentExpression -> resolveArgumentExpression( + is FirWrappedArgumentExpression -> resolveArgumentExpression( csBuilder, argument.expression, expectedType, @@ -180,7 +169,7 @@ internal fun FirExpression.getExpectedType( // if (this.isSpread || this.isArrayAssignedAsNamedArgumentInAnnotation(parameter, languageVersionSettings)) { // parameter.type.unwrap() // } else { - if (parameter.isVararg) { + if (parameter.isVararg && (this !is FirWrappedArgumentExpression || !isSpread)) { parameter.returnTypeRef.coneTypeUnsafe().varargElementType(session) } else { parameter.returnTypeRef.coneTypeUnsafe() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirCallArgumentsProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirCallArgumentsProcessor.kt index c5b7c14894c..81d6cf195ca 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirCallArgumentsProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/FirCallArgumentsProcessor.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.resolve.calls -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.FirExpression @@ -13,8 +12,6 @@ import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression import org.jetbrains.kotlin.fir.render -import org.jetbrains.kotlin.fir.types.ConeClassType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef class FirCallArgumentsProcessor( private val function: FirFunction, @@ -25,7 +22,7 @@ class FirCallArgumentsProcessor( fun process(): Result { var currentState: State = State.PositionalOnly(function.valueParameters) for (argument in arguments) { - if (argument is FirWrappedArgumentExpression) { + if (argument is FirNamedArgumentExpression || argument is FirLambdaArgumentExpression) { currentState = State.PositionalThenNamed( function.valueParameters, currentState.argumentMap, @@ -65,21 +62,19 @@ class FirCallArgumentsProcessor( val currentParameter get() = valueParameters.getOrNull(currentParameterIndex) - fun nextParameter() { - val currentParameter = currentParameter ?: return - if (currentParameter.isVararg) return - usedParameters += currentParameter - currentParameterIndex++ - } - override fun processArgument(argument: FirExpression): MappingStatus { require(argument !is FirNamedArgumentExpression) { - "Positional-only argument processor state should not receiver ${argument.render()}" + "Positional-only argument processor state should not receive ${argument.render()}" } val currentParameter = currentParameter ?: return MappingStatus.ERROR argumentMap[argument] = currentParameter - nextParameter() + if (!currentParameter.isVararg || + argument is FirWrappedArgumentExpression && argument.isSpread + ) { + usedParameters += currentParameter + currentParameterIndex++ + } return MappingStatus.SUCCESS } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt index f83db517cc0..8c11e455e9b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt @@ -1166,17 +1166,10 @@ private object ReplaceInArguments : FirTransformer>( return (functionCall.transformChildren(this, data) as FirStatement).compose() } - override fun transformNamedArgumentExpression( - namedArgumentExpression: FirNamedArgumentExpression, + override fun transformWrappedArgumentExpression( + wrappedArgumentExpression: FirWrappedArgumentExpression, data: Map ): CompositeTransformResult { - return (namedArgumentExpression.transformChildren(this, data) as FirStatement).compose() - } - - override fun transformLambdaArgumentExpression( - lambdaArgumentExpression: FirLambdaArgumentExpression, - data: Map - ): CompositeTransformResult { - return (lambdaArgumentExpression.transformChildren(this, data) as FirStatement).compose() + return (wrappedArgumentExpression.transformChildren(this, data) as FirStatement).compose() } } \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/arguments/vararg.kt b/compiler/fir/resolve/testData/resolve/arguments/vararg.kt index 35fdf26963a..4702d5958cd 100644 --- a/compiler/fir/resolve/testData/resolve/arguments/vararg.kt +++ b/compiler/fir/resolve/testData/resolve/arguments/vararg.kt @@ -5,6 +5,7 @@ fun test() { foo(1) foo(1, "") foo(1, "my", "yours") + foo(1, *arrayOf("my", "yours")) foo("") foo(1, 2) diff --git a/compiler/fir/resolve/testData/resolve/arguments/vararg.txt b/compiler/fir/resolve/testData/resolve/arguments/vararg.txt index 26a6bb89e5e..25fee9b4118 100644 --- a/compiler/fir/resolve/testData/resolve/arguments/vararg.txt +++ b/compiler/fir/resolve/testData/resolve/arguments/vararg.txt @@ -7,9 +7,10 @@ FILE: vararg.kt R|/foo|(Int(1)) R|/foo|(Int(1), String()) R|/foo|(Int(1), String(my), String(yours)) + R|/foo|(Int(1), *R|kotlin/arrayOf|(String(my), String(yours))) #(String()) #(Int(1), Int(2)) - R|/bar|(Int(1), z = Boolean(true), y = R|kotlin/arrayOf|(String(my), String(yours))) + R|/bar|(Int(1), z = Boolean(true), y = *R|kotlin/arrayOf|(String(my), String(yours))) #(Int(0), z = Boolean(false), y = String(), y = String(other)) #(Int(0), String(), Boolean(true)) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index cece9915d06..ed97bb44f4f 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -627,9 +627,19 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() { override fun visitNamedArgumentExpression(namedArgumentExpression: FirNamedArgumentExpression) { print(namedArgumentExpression.name) print(" = ") + if (namedArgumentExpression.isSpread) { + print("*") + } namedArgumentExpression.expression.accept(this) } + override fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression) { + if (spreadArgumentExpression.isSpread) { + print("*") + } + spreadArgumentExpression.expression.accept(this) + } + override fun visitLambdaArgumentExpression(lambdaArgumentExpression: FirLambdaArgumentExpression) { print(" = ") lambdaArgumentExpression.expression.accept(this) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt new file mode 100644 index 00000000000..0de02a2d19c --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.expressions + +import org.jetbrains.kotlin.fir.visitors.FirVisitor + +interface FirSpreadArgumentExpression : FirWrappedArgumentExpression { + override val isSpread: Boolean + get() = true + + override fun accept(visitor: FirVisitor, data: D): R = + visitor.visitSpreadArgumentExpression(this, data) +} \ No newline at end of file diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirWrappedArgumentExpression.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirWrappedArgumentExpression.kt index ae8ead40573..6407c23fda2 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirWrappedArgumentExpression.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirWrappedArgumentExpression.kt @@ -11,6 +11,9 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitor interface FirWrappedArgumentExpression : FirExpression { val expression: FirExpression + val isSpread: Boolean + get() = false + override val typeRef: FirTypeRef get() = expression.typeRef diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirNamedArgumentExpressionImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirNamedArgumentExpressionImpl.kt index 0c96870aee9..0eb1b19f873 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirNamedArgumentExpressionImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirNamedArgumentExpressionImpl.kt @@ -9,7 +9,6 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression import org.jetbrains.kotlin.fir.transformSingle import org.jetbrains.kotlin.fir.types.FirTypeRef @@ -20,6 +19,7 @@ class FirNamedArgumentExpressionImpl( session: FirSession, psi: PsiElement?, override val name: Name, + override val isSpread: Boolean, override var expression: FirExpression ) : FirNamedArgumentExpression, FirAbstractExpression(session, psi) { override var typeRef: FirTypeRef diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt new file mode 100644 index 00000000000..35d009f9d51 --- /dev/null +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.expressions.impl + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirSpreadArgumentExpression +import org.jetbrains.kotlin.fir.transformSingle +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.FirTransformer + +class FirSpreadArgumentExpressionImpl( + session: FirSession, + psi: PsiElement?, + override var expression: FirExpression +) : FirSpreadArgumentExpression, FirAbstractExpression(session, psi) { + override var typeRef: FirTypeRef + get() = super.typeRef + set(_) {} + + override fun transformChildren(transformer: FirTransformer, data: D): FirElement { + expression = expression.transformSingle(transformer, data) + return super.transformChildren(transformer, data) + } +} \ No newline at end of file diff --git a/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirTransformerGenerated.kt b/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirTransformerGenerated.kt index 07ad55a1fe6..b64e9cf9854 100644 --- a/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirTransformerGenerated.kt +++ b/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirTransformerGenerated.kt @@ -300,6 +300,10 @@ abstract class FirTransformer : FirVisitor { + return transformWrappedArgumentExpression(spreadArgumentExpression, data) + } + open fun transformLoop(loop: FirLoop, data: D): CompositeTransformResult { return transformStatement(loop, data) } @@ -680,6 +684,10 @@ abstract class FirTransformer : FirVisitor { + return transformSpreadArgumentExpression(spreadArgumentExpression, data) + } + final override fun visitStarProjection(starProjection: FirStarProjection, data: D): CompositeTransformResult { return transformStarProjection(starProjection, data) } diff --git a/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirVisitorGenerated.kt b/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirVisitorGenerated.kt index ddbb6ca1113..5db73e1b37b 100644 --- a/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirVisitorGenerated.kt +++ b/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirVisitorGenerated.kt @@ -300,6 +300,10 @@ abstract class FirVisitor { return visitWrappedArgumentExpression(namedArgumentExpression, data) } + open fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression, data: D): R { + return visitWrappedArgumentExpression(spreadArgumentExpression, data) + } + open fun visitLoop(loop: FirLoop, data: D): R { return visitStatement(loop, data) } diff --git a/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirVisitorVoidGenerated.kt b/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirVisitorVoidGenerated.kt index 355451e2926..795d2e79f21 100644 --- a/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirVisitorVoidGenerated.kt +++ b/compiler/fir/tree/visitors/org/jetbrains/kotlin/fir/visitors/FirVisitorVoidGenerated.kt @@ -300,6 +300,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitWrappedArgumentExpression(namedArgumentExpression, null) } + open fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression) { + visitWrappedArgumentExpression(spreadArgumentExpression, null) + } + open fun visitLoop(loop: FirLoop) { visitStatement(loop, null) } @@ -680,6 +684,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitReturnExpression(returnExpression) } + final override fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression, data: Nothing?) { + visitSpreadArgumentExpression(spreadArgumentExpression) + } + final override fun visitStarProjection(starProjection: FirStarProjection, data: Nothing?) { visitStarProjection(starProjection) } diff --git a/compiler/testData/ir/irText/expressions/vararg.fir.txt b/compiler/testData/ir/irText/expressions/vararg.fir.txt index 50663712338..bafc3ab0e2d 100644 --- a/compiler/testData/ir/irText/expressions/vararg.fir.txt +++ b/compiler/testData/ir/irText/expressions/vararg.fir.txt @@ -21,16 +21,15 @@ FILE fqName: fileName:/vararg.kt RETURN type=kotlin.Nothing from='public final fun (): kotlin.Array declared in ' GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Array visibility:public [final,static] ' type=kotlin.Array origin=null PROPERTY name:test3 visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:test3 type:kotlin.Array visibility:public [final,static] + FIELD PROPERTY_BACKING_FIELD name:test3 type:IrErrorType visibility:public [final,static] EXPRESSION_BODY - ERROR_CALL 'Cannot bind 4 arguments to arrayOf call with 1 parameters' type=kotlin.Array + ERROR_CALL 'Unresolved reference: #' type=IrErrorType CONST String type=kotlin.String value="0" CALL 'public final fun (): kotlin.Array declared in ' type=kotlin.Array origin=null CALL 'public final fun (): kotlin.Array declared in ' type=kotlin.Array origin=null CONST String type=kotlin.String value="4" - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Array + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:IrErrorType correspondingProperty: PROPERTY name:test3 visibility:public modality:FINAL [val] BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.Array declared in ' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test3 type:kotlin.Array visibility:public [final,static] ' type=kotlin.Array origin=null - + RETURN type=kotlin.Nothing from='public final fun (): IrErrorType declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test3 type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null