From 8443daf78dd97510bf3ba2879e3d2dab2b58fff8 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Fri, 1 Mar 2024 16:00:11 +0100 Subject: [PATCH] [FIR] Remove FirNamedArgumentExpressions during completion They are mostly necessary for argument mapping during resolution. To support a couple checkers, we transform named args for varargs into "fake" spread expressions. Other than that, named arguments aren't needed for anything and often lead to bugs where we forget to unwrap them for something, so it's better to get rid of them. #KT-66124 --- .../references/FirReferenceResolveHelper.kt | 17 ++++--- .../secondaryConstructor.lazy.resolve.txt | 2 +- ...sideSuperCallInsideImplicitConstructor.txt | 2 +- ...compilerRequiredAnnotationOnLocalClass.txt | 4 +- ...erRequiredAnnotationOnLocalClassScript.txt | 4 +- ...nDeclarationWithDifferentArguments.fir.txt | 2 +- .../resolve/arguments/default.fir.txt | 6 +-- .../arguments/defaultFromOverrides.fir.txt | 2 +- .../testData/resolve/arguments/lambda.fir.txt | 10 ++-- .../arguments/namedArrayInAnnotation.fir.txt | 2 +- .../arguments/noParameterForName.fir.txt | 2 +- .../testData/resolve/arguments/simple.fir.txt | 18 ++++---- .../testData/resolve/arguments/vararg.fir.txt | 6 +-- .../resolve/callResolution/kt37056.fir.txt | 4 +- .../testData/resolve/cfg/lambdas.dot | 2 +- .../testData/resolve/cfg/lambdas.fir.txt | 2 +- .../resolve/companionObjectCall.fir.txt | 6 +-- .../testData/resolve/copy.fir.txt | 4 +- ...nestedAnnotationConstExprArguments.fir.txt | 4 +- .../fromLibrary/callsInPlace.fir.txt | 10 ++-- .../good/callsInPlace/namedArgument.fir.txt | 2 +- .../returnsImplies/namedArguments.fir.txt | 6 +-- .../builderInferenceAndCoercionToUnit.fir.txt | 2 +- .../intellij/arrayOfImports.fir.txt | 2 +- .../FieldAnnotationWithClasses.fir.txt | 2 +- .../NamedParameterInConcurrentMap.fir.txt | 2 +- .../expression/FirJavaAnnotationsChecker.kt | 5 +- .../fir/analysis/checkers/FirConstChecks.kt | 4 ++ .../FirAnnotationExpressionChecker.kt | 5 +- .../expression/FirNamedVarargChecker.kt | 20 ++++++-- .../expression/FirSpreadOfNullableChecker.kt | 2 +- .../generators/CallAndReferenceGenerator.kt | 2 +- .../fir/plugin/ConstructorBuildingContext.kt | 4 +- .../GeneratedDeclarationValidation.kt | 3 +- .../kotlin/fir/resolve/calls/CallInfo.kt | 21 ++++++--- ...rCallCompletionResultsWriterTransformer.kt | 46 +++++++++++++++---- .../body/resolve/BodyResolveUtils.kt | 12 ++++- .../FirSpreadArgumentExpression.kt | 2 + .../FirSpreadArgumentExpressionBuilder.kt | 4 ++ .../impl/FirSpreadArgumentExpressionImpl.kt | 2 + .../kotlin/fir/expressions/FirArgumentUtil.kt | 15 +++--- .../impl/FirResolvedArgumentList.kt | 19 +++++--- .../fir/tree/generator/BuilderConfigurator.kt | 4 ++ .../fir/tree/generator/NodeConfigurator.kt | 5 ++ .../targetOnPrimaryCtorParameter.fir.txt | 6 +-- .../dynamicTypes/kt57960.fir.txt | 2 +- .../qualifier/wrongQualifier.fir.kt | 23 ++++++++++ .../qualifier/wrongQualifier.kt | 1 - .../wasmTests/jsInterop/wrongQualifier.fir.kt | 23 ++++++++++ .../wasmTests/jsInterop/wrongQualifier.kt | 1 - .../DataFrameLikeCallsRefinementExtension.kt | 3 +- .../composableFunctionMultiModules.fir.txt | 2 +- ...leComposableParameterAcrossModules.fir.txt | 2 +- .../compiler/fir/SerializationFirUtils.kt | 3 +- 54 files changed, 249 insertions(+), 117 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/qualifier/wrongQualifier.fir.kt create mode 100644 compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.fir.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt index a8e3c7c309d..22dee1f739f 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/references/FirReferenceResolveHelper.kt @@ -48,6 +48,7 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* @@ -221,6 +222,11 @@ internal object FirReferenceResolveHelper { val expression = ref.expression if (expression.isSyntheticOperatorReference()) return emptyList() val symbolBuilder = analysisSession.firSymbolBuilder + + if (expression is KtNameReferenceExpression && expression.parent is KtValueArgumentName) { + return getSymbolsByNameArgumentExpression(expression, analysisSession, symbolBuilder) + } + val adjustedResolutionExpression = adjustResolutionExpression(expression) val fir = when (val baseFir = adjustedResolutionExpression.getOrBuildFir(analysisSession.firResolveSession)) { is FirSmartCastExpression -> baseFir.originalExpression @@ -246,7 +252,6 @@ internal object FirReferenceResolveHelper { is FirDelegatedConstructorCall -> getSymbolByDelegatedConstructorCall(expression, adjustedResolutionExpression, fir, session, symbolBuilder) is FirResolvable -> getSymbolsByResolvable(fir, expression, session, symbolBuilder) - is FirNamedArgumentExpression -> getSymbolsByNameArgumentExpression(expression, analysisSession, symbolBuilder) is FirEqualityOperatorCall -> getSymbolsByEqualsName(fir, session, analysisSession, symbolBuilder) is FirTypeParameter -> getSybmolsByTypeParameter(symbolBuilder, fir) is FirResolvedReifiedParameterReference -> getSymbolsByResolvedReifiedTypeParameterReference(symbolBuilder, fir) @@ -371,15 +376,13 @@ internal object FirReferenceResolveHelper { val ktCallExpression = ktValueArgumentList.parent as? KtCallElement ?: return emptyList() val firCall = ktCallExpression.getOrBuildFir(analysisSession.firResolveSession)?.unwrapSafeCall() as? FirCall ?: return emptyList() - val parameter = firCall.findCorrespondingParameter(ktValueArgument) ?: return emptyList() + val parameter = firCall.findCorrespondingParameter(ktValueArgumentName.asName) ?: return emptyList() return listOfNotNull(parameter.buildSymbol(symbolBuilder)) } - private fun FirCall.findCorrespondingParameter(ktValueArgument: KtValueArgument): FirValueParameter? = - resolvedArgumentMapping?.entries?.firstNotNullOfOrNull { (firArgument, firParameter) -> - if (firArgument.psi == ktValueArgument) firParameter - else null - } + private fun FirCall.findCorrespondingParameter(name: Name): FirValueParameter? { + return resolvedArgumentMapping?.values?.first { it.name == name } + } private fun handleUnknownFirElement( expression: KtSimpleNameExpression, diff --git a/analysis/low-level-api-fir/testData/fileStructure/secondaryConstructor.lazy.resolve.txt b/analysis/low-level-api-fir/testData/fileStructure/secondaryConstructor.lazy.resolve.txt index 0916a65a8b4..9e92a3827b5 100644 --- a/analysis/low-level-api-fir/testData/fileStructure/secondaryConstructor.lazy.resolve.txt +++ b/analysis/low-level-api-fir/testData/fileStructure/secondaryConstructor.lazy.resolve.txt @@ -11,7 +11,7 @@ FILE: [ResolvedTo(BODY_RESOLVE)] secondaryConstructor.kt public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/String| public [ResolvedTo(BODY_RESOLVE)] constructor([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/Int|): R|A| { - this(x = Int(1), b = R|/i|.R|kotlin/Int.toString|()) + this(Int(1), R|/i|.R|kotlin/Int.toString|()) } } diff --git a/analysis/low-level-api-fir/testData/getOrBuildFir/calls/callInsideLambdaInsideSuperCallInsideImplicitConstructor.txt b/analysis/low-level-api-fir/testData/getOrBuildFir/calls/callInsideLambdaInsideSuperCallInsideImplicitConstructor.txt index a373802b4bd..78025e17a58 100644 --- a/analysis/low-level-api-fir/testData/getOrBuildFir/calls/callInsideLambdaInsideSuperCallInsideImplicitConstructor.txt +++ b/analysis/low-level-api-fir/testData/getOrBuildFir/calls/callInsideLambdaInsideSuperCallInsideImplicitConstructor.txt @@ -18,7 +18,7 @@ FILE: [ResolvedTo(IMPORTS)] callInsideLambdaInsideSuperCallInsideImplicitConstru } public final [ResolvedTo(BODY_RESOLVE)] class KotlinIDE : R|IJProject| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=KotlinIDE] constructor(): R|KotlinIDE| { - super(init = [ResolvedTo(RAW_FIR)] fun (): R|kotlin/Unit| { + super([ResolvedTo(RAW_FIR)] fun (): R|kotlin/Unit| { local final [ResolvedTo(RAW_FIR)] fun foo(): R|kotlin/Unit| { # } diff --git a/analysis/low-level-api-fir/testData/lazyResolve/compilerRequiredAnnotationOnLocalClass.txt b/analysis/low-level-api-fir/testData/lazyResolve/compilerRequiredAnnotationOnLocalClass.txt index 2ecee0d133c..e791c65519f 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/compilerRequiredAnnotationOnLocalClass.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/compilerRequiredAnnotationOnLocalClass.txt @@ -109,7 +109,7 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationOnLocalClass.kt BODY_RESOLVE: FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationOnLocalClass.kt public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe(): R|kotlin/Unit| { - @R|kotlin/Deprecated|[Types](message = String(), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(expression = String(abc)), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.ERROR|) local final [ResolvedTo(BODY_RESOLVE)] class LocalClass : R|kotlin/Any| { + @R|kotlin/Deprecated|[Types](message = String(), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(String(abc)), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.ERROR|) local final [ResolvedTo(BODY_RESOLVE)] class LocalClass : R|kotlin/Any| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=LocalClass] constructor(): R|/LocalClass| { super() } @@ -128,7 +128,7 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationOnLocalClass.kt FILE RAW TO BODY: FILE: [ResolvedTo(BODY_RESOLVE)] compilerRequiredAnnotationOnLocalClass.kt public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe(): R|kotlin/Unit| { - @R|kotlin/Deprecated|[Types](message = String(), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(expression = String(abc)), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.ERROR|) local final [ResolvedTo(BODY_RESOLVE)] class LocalClass : R|kotlin/Any| { + @R|kotlin/Deprecated|[Types](message = String(), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(String(abc)), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.ERROR|) local final [ResolvedTo(BODY_RESOLVE)] class LocalClass : R|kotlin/Any| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=LocalClass] constructor(): R|/LocalClass| { super() } diff --git a/analysis/low-level-api-fir/testData/lazyResolve/compilerRequiredAnnotationOnLocalClassScript.txt b/analysis/low-level-api-fir/testData/lazyResolve/compilerRequiredAnnotationOnLocalClassScript.txt index 6ea9912a1db..15897dae528 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/compilerRequiredAnnotationOnLocalClassScript.txt +++ b/analysis/low-level-api-fir/testData/lazyResolve/compilerRequiredAnnotationOnLocalClassScript.txt @@ -173,7 +173,7 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationOnLocalClassScript.kts [ResolvedTo(TYPES)] lval args: R|kotlin/Array| public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe(): R|kotlin/Unit| { - @R|kotlin/Deprecated|[Types](message = String(), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(expression = String(abc)), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.ERROR|) local final [ResolvedTo(BODY_RESOLVE)] class LocalClass : R|kotlin/Any| { + @R|kotlin/Deprecated|[Types](message = String(), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(String(abc)), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.ERROR|) local final [ResolvedTo(BODY_RESOLVE)] class LocalClass : R|kotlin/Any| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=LocalClass] constructor(): R|/LocalClass| { super() } @@ -197,7 +197,7 @@ FILE: [ResolvedTo(BODY_RESOLVE)] compilerRequiredAnnotationOnLocalClassScript.kt [ResolvedTo(BODY_RESOLVE)] lval args: R|kotlin/Array| public final [ResolvedTo(BODY_RESOLVE)] fun resolveMe(): R|kotlin/Unit| { - @R|kotlin/Deprecated|[Types](message = String(), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(expression = String(abc)), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.ERROR|) local final [ResolvedTo(BODY_RESOLVE)] class LocalClass : R|kotlin/Any| { + @R|kotlin/Deprecated|[Types](message = String(), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(String(abc)), level = Q|kotlin/DeprecationLevel|.R|kotlin/DeprecationLevel.ERROR|) local final [ResolvedTo(BODY_RESOLVE)] class LocalClass : R|kotlin/Any| { public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=LocalClass] constructor(): R|/LocalClass| { super() } diff --git a/compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.fir.txt b/compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.fir.txt index 476947a19cf..bfb5b928e4f 100644 --- a/compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/annotationOnDeclarationWithDifferentArguments.fir.txt @@ -53,5 +53,5 @@ FILE: annotationOnDeclarationWithDifferentArguments.kt public get(): R|kotlin/Int| public final const val constString: R|kotlin/String| = String() public get(): R|kotlin/String| - @R|MyAnnotation|(intValue = Int(10), stringValue = R|/constString|, enumValue = Q|SomeEnum|.R|/SomeEnum.A|, kClasses = ((Q|kotlin/String|), (R|/constString|)), annotation = R|/MyOtherAnnotation.MyOtherAnnotation|(intValue = R|/constInt|, stringValue = String(hello))) public final fun foo(): R|kotlin/Unit| { + @R|MyAnnotation|(intValue = Int(10), stringValue = R|/constString|, enumValue = Q|SomeEnum|.R|/SomeEnum.A|, kClasses = ((Q|kotlin/String|), (R|/constString|)), annotation = R|/MyOtherAnnotation.MyOtherAnnotation|(R|/constInt|, String(hello))) public final fun foo(): R|kotlin/Unit| { } diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/default.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/default.fir.txt index 1071ef74cd6..7c6ee02544d 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/default.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/default.fir.txt @@ -9,15 +9,15 @@ FILE: default.kt R|/foo|(Int(1)) R|/foo|(Int(1), Double(2.0)) R|/foo|(Int(1), Double(2.0), Boolean(true)) - R|/foo|(Int(1), third = Boolean(true)) + R|/foo|(Int(1), Boolean(true)) R|/foo#|() R|/foo#|(Int(0), Double(0.0), Boolean(false), String()) - R|/bar|(Int(1), third = Boolean(true)) + R|/bar|(Int(1), Boolean(true)) R|/bar|(Int(1), Double(2.0), Boolean(true)) R|/bar|(Int(1), Double(2.0), Boolean(true), String(my)) R|/bar#|(Int(1), Boolean(true)) R|/baz|(Int(1)) R|/baz|(Int(1), vararg(String(my), String(yours))) - R|/baz|(Int(1), z = Boolean(true)) + R|/baz|(Int(1), Boolean(true)) R|/baz#|(Int(0), String(), Boolean(false)) } diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/defaultFromOverrides.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/defaultFromOverrides.fir.txt index 0b2a46219fa..881aff3acd5 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/defaultFromOverrides.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/defaultFromOverrides.fir.txt @@ -24,6 +24,6 @@ FILE: defaultFromOverrides.kt R|/a|.R|/A.foo|(Int(1)) R|/a|.R|/A.bar#|() R|/a|.R|/A.bar#|(String()) - R|/a|.R|/A.bar|(y = Int(1)) + R|/a|.R|/A.bar|(Int(1)) R|/a|.R|/A.bar|(String(), Int(2)) } diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/lambda.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/lambda.fir.txt index 7220b69c0a0..deda34c0459 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/lambda.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/lambda.fir.txt @@ -22,7 +22,7 @@ FILE: lambda.kt ^@foo Unit } ) - R|/foo#|(f = foo@fun (): R|kotlin/Unit| { + R|/foo#|(foo@fun (): R|kotlin/Unit| { ^@foo Unit } , = foo@fun (): R|kotlin/Unit| { @@ -33,7 +33,7 @@ FILE: lambda.kt ^@bar Unit } ) - R|/bar|(x = Int(1), = bar@fun (): R|kotlin/Unit| { + R|/bar|(Int(1), = bar@fun (): R|kotlin/Unit| { ^@bar Unit } ) @@ -41,7 +41,7 @@ FILE: lambda.kt ^@bar Unit } ) - R|/bar|(x = Int(1), f = bar@fun (): R|kotlin/Unit| { + R|/bar|(Int(1), bar@fun (): R|kotlin/Unit| { ^@bar Unit } ) @@ -53,7 +53,7 @@ FILE: lambda.kt ^@bar Unit } ) - R|/baz|(other = Boolean(false), f = baz@fun (): R|kotlin/Unit| { + R|/baz|(Boolean(false), baz@fun (): R|kotlin/Unit| { ^@baz Unit } ) @@ -69,7 +69,7 @@ FILE: lambda.kt ^@baz Unit } ) - R|/baz#|(other = Boolean(false), = baz@fun (): R|kotlin/Unit| { + R|/baz#|(Boolean(false), = baz@fun (): R|kotlin/Unit| { ^@baz Unit } ) diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/namedArrayInAnnotation.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/namedArrayInAnnotation.fir.txt index fb3c97f0695..71b1bdceb17 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/namedArrayInAnnotation.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/namedArrayInAnnotation.fir.txt @@ -8,7 +8,7 @@ FILE: namedArrayInAnnotation.kt public get(): R|kotlin/Array| } - @R|Ann|(strings = vararg(strings = (String(hello)))) public final class A : R|kotlin/Any| { + @R|Ann|(strings = vararg(*(String(hello)))) public final class A : R|kotlin/Any| { public constructor(): R|A| { super() } diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/noParameterForName.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/noParameterForName.fir.txt index a8e9fcc795e..04eb5b03c4b 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/noParameterForName.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/noParameterForName.fir.txt @@ -2,5 +2,5 @@ FILE: noParameterForName.kt public final fun foo(x: R|kotlin/Int|): R|kotlin/Unit| { } public final fun bar(): R|kotlin/Unit| { - R|/foo#|(y = Int(1)) + R|/foo#|(Int(1)) } diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/simple.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/simple.fir.txt index d5382ef2028..2a8e4b88db0 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/simple.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/simple.fir.txt @@ -3,15 +3,15 @@ FILE: simple.kt } public final fun test(): R|kotlin/Unit| { R|/foo|(Int(1), Double(2.0), Boolean(true), String()) - R|/foo|(Int(1), Double(2.0), Boolean(true), fourth = String(!)) - R|/foo|(Int(1), Double(2.0), fourth = String(???), third = Boolean(false)) - R|/foo|(Int(1), second = Double(3.14), third = Boolean(false), fourth = String(!?)) - R|/foo|(third = Boolean(false), second = Double(2.71), fourth = String(?!), first = Int(0)) + R|/foo|(Int(1), Double(2.0), Boolean(true), String(!)) + R|/foo|(Int(1), Double(2.0), String(???), Boolean(false)) + R|/foo|(Int(1), Double(3.14), Boolean(false), String(!?)) + R|/foo|(Boolean(false), Double(2.71), String(?!), Int(0)) R|/foo#|() R|/foo#|(Double(0.0), Boolean(false), Int(0), String()) - R|/foo|(Int(1), Double(2.0), third = Boolean(true), String()) - R|/foo#|(second = Double(0.0), first = Int(0), fourth = String()) - R|/foo#|(first = Double(0.0), second = Int(0), third = String(), fourth = Boolean(false)) - R|/foo#|(first = Int(0), second = Double(0.0), third = Boolean(false), fourth = String(), first = Int(1)) - R|/foo#|(Int(0), Double(0.0), Boolean(false), foth = String()) + R|/foo|(Int(1), Double(2.0), Boolean(true), String()) + R|/foo#|(Double(0.0), Int(0), String()) + R|/foo#|(Double(0.0), Int(0), String(), Boolean(false)) + R|/foo#|(Int(0), Double(0.0), Boolean(false), String(), Int(1)) + R|/foo#|(Int(0), Double(0.0), Boolean(false), String()) } diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/vararg.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/vararg.fir.txt index 242b4d5c7ae..5f96d3f8bd7 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/vararg.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/vararg.fir.txt @@ -10,8 +10,8 @@ FILE: vararg.kt R|/foo|(Int(1), vararg(*R|kotlin/arrayOf|(vararg(String(my), String(yours))))) R|/foo#|(String()) R|/foo#|(Int(1), Int(2)) - R|/bar|(Int(1), z = Boolean(true), vararg(y = *R|kotlin/arrayOf|(vararg(String(my), String(yours))))) - R|/bar#|(Int(0), z = Boolean(false), y = String(), y = String(other)) + R|/bar|(Int(1), Boolean(true), vararg(*R|kotlin/arrayOf|(vararg(String(my), String(yours))))) + R|/bar#|(Int(0), Boolean(false), *String(), String(other)) R|/bar#|(Int(0), String(), Boolean(true)) - R|/bar#|(Int(0), z = Boolean(false), y = String(), y = String(other), y = String(yet other)) + R|/bar#|(Int(0), Boolean(false), *String(), String(other), String(yet other)) } diff --git a/compiler/fir/analysis-tests/testData/resolve/callResolution/kt37056.fir.txt b/compiler/fir/analysis-tests/testData/resolve/callResolution/kt37056.fir.txt index aa9709e56f0..45116ca9d0d 100644 --- a/compiler/fir/analysis-tests/testData/resolve/callResolution/kt37056.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/callResolution/kt37056.fir.txt @@ -7,7 +7,7 @@ FILE: kt37056.kt } ) } Q|Case1|.R|/Case1.Companion.invoke|(R|/A.A|()) - Q|Case1|.R|/Case1.Companion.invoke|(a = R|/A.A|()) + Q|Case1|.R|/Case1.Companion.invoke|(R|/A.A|()) } public final class Case1 : R|kotlin/Any| { private constructor(a: R|A|): R|Case1| { @@ -31,7 +31,7 @@ FILE: kt37056.kt } public final fun case2(a: R|A|): R|kotlin/Unit| { Q|Case2|.R|/Case2.Companion.invoke|(R|/a|) - Q|Case2|.R|/Case2.Companion.invoke|(a = R|/a|) + Q|Case2|.R|/Case2.Companion.invoke|(R|/a|) } public final class Case2 : R|kotlin/Any| { public constructor(): R|Case2| { diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.dot index e517303099d..99e6daed421 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.dot @@ -311,7 +311,7 @@ digraph lambdas_kt { } 104 [label="Postponed exit from lambda"]; 105 [label="Function call: R|/getInt|(...)" style="filled" fillcolor=yellow]; - 106 [label="Jump: ^test_4 R|/getInt|(block = getInt@fun (): R|kotlin/Unit| { + 106 [label="Jump: ^test_4 R|/getInt|(getInt@fun (): R|kotlin/Unit| { ^test_4 Int(1) } )"]; diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.fir.txt index 270de8bea4c..d8509511d21 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/lambdas.fir.txt @@ -35,7 +35,7 @@ FILE: lambdas.kt ) } public final fun test_4(): R|kotlin/Int| { - ^test_4 R|/getInt|(block = getInt@fun (): R|kotlin/Unit| { + ^test_4 R|/getInt|(getInt@fun (): R|kotlin/Unit| { ^test_4 Int(1) } ) diff --git a/compiler/fir/analysis-tests/testData/resolve/companionObjectCall.fir.txt b/compiler/fir/analysis-tests/testData/resolve/companionObjectCall.fir.txt index 2bed6e77056..c3b91cddc13 100644 --- a/compiler/fir/analysis-tests/testData/resolve/companionObjectCall.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/companionObjectCall.fir.txt @@ -13,7 +13,7 @@ FILE: companionObjectCall.kt } ) } Q|Case1|.R|/Case1.Companion.invoke|(R|/A.A|()) - Q|Case1|.R|/Case1.Companion.invoke|(a = R|/A.A|()) + Q|Case1|.R|/Case1.Companion.invoke|(R|/A.A|()) } public final class Case1 : R|kotlin/Any| { private constructor(a: R|kotlin/String|): R|Case1| { @@ -37,7 +37,7 @@ FILE: companionObjectCall.kt } public final fun case2(a: R|A|): R|kotlin/Unit| { Q|Case2|.R|/Case2.Companion.invoke|(R|/a|) - Q|Case2|.R|/Case2.Companion.invoke|(a = R|/a|) + Q|Case2|.R|/Case2.Companion.invoke|(R|/a|) } public final class Case2 : R|kotlin/Any| { public constructor(): R|Case2| { @@ -58,7 +58,7 @@ FILE: companionObjectCall.kt } public final fun case3(a: R|A|): R|kotlin/Unit| { Q|Case3.Companion|.R|/Case3.Companion.invoke|(R|/a|) - Q|Case3.Companion|.R|/Case3.Companion.invoke|(parameterA = R|/a|) + Q|Case3.Companion|.R|/Case3.Companion.invoke|(R|/a|) } public final class Case3 : R|kotlin/Any| { public constructor(): R|Case3| { diff --git a/compiler/fir/analysis-tests/testData/resolve/copy.fir.txt b/compiler/fir/analysis-tests/testData/resolve/copy.fir.txt index a2fcf1d8146..64f15af2eba 100644 --- a/compiler/fir/analysis-tests/testData/resolve/copy.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/copy.fir.txt @@ -18,8 +18,8 @@ FILE: copy.kt } public final fun test(some: R|Some|): R|kotlin/Unit| { - lval other: R|Some| = R|/some|.R|/Some.copy|(y = String(123)) - lval another: R|Some| = R|/some|.R|/Some.copy|(x = Int(123)) + lval other: R|Some| = R|/some|.R|/Some.copy|(String(123)) + lval another: R|Some| = R|/some|.R|/Some.copy|(Int(123)) lval same: R|Some| = R|/some|.R|/Some.copy|() lval different: R|Some| = R|/some|.R|/Some.copy|(Int(456), String(456)) } diff --git a/compiler/fir/analysis-tests/testData/resolve/nestedAnnotationConstExprArguments.fir.txt b/compiler/fir/analysis-tests/testData/resolve/nestedAnnotationConstExprArguments.fir.txt index a7dda21c1dc..e71899d8126 100644 --- a/compiler/fir/analysis-tests/testData/resolve/nestedAnnotationConstExprArguments.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/nestedAnnotationConstExprArguments.fir.txt @@ -17,7 +17,7 @@ FILE: nestedAnnotationConstExprArguments.kt public get(): R|InnerAnnotation| } - @R|OuterAnnotation|(inner = R|/InnerAnnotation.InnerAnnotation|(text = String(x).R|kotlin/String.plus|(String(x)))) public final class Payload : R|kotlin/Any| { + @R|OuterAnnotation|(inner = R|/InnerAnnotation.InnerAnnotation|(String(x).R|kotlin/String.plus|(String(x)))) public final class Payload : R|kotlin/Any| { public constructor(): R|Payload| { super() } @@ -29,7 +29,7 @@ FILE: nestedAnnotationConstExprArguments.kt } } - @R|OuterAnnotation|(inner = R|/InnerAnnotation.InnerAnnotation|(text = String(x))) public final class Payload3 : R|kotlin/Any| { + @R|OuterAnnotation|(inner = R|/InnerAnnotation.InnerAnnotation|(String(x))) public final class Payload3 : R|kotlin/Any| { public constructor(): R|Payload3| { super() } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromLibrary/callsInPlace.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromLibrary/callsInPlace.fir.txt index a7774ef7f27..21b9448a2f8 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromLibrary/callsInPlace.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromLibrary/callsInPlace.fir.txt @@ -14,10 +14,10 @@ FILE: callsInPlace.kt ) } public final fun test_3(): R|kotlin/Unit| { - R|kotlin/repeat|(action = repeat@fun (it: R|kotlin/Int|): R|kotlin/Unit| { + R|kotlin/repeat|(repeat@fun (it: R|kotlin/Int|): R|kotlin/Unit| { String(test_3) } - , times = Int(10)) + , Int(10)) } public final fun test_4(): R|kotlin/Unit| { Int(1).R|kotlin/takeUnless|( = takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { @@ -27,7 +27,7 @@ FILE: callsInPlace.kt ) } public final fun test_5(): R|kotlin/Unit| { - Int(1).R|kotlin/takeUnless|(predicate = takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { + Int(1).R|kotlin/takeUnless|(takeUnless@fun (it: R|kotlin/Int|): R|kotlin/Boolean| { String(test_5) ^ CMP(>, R|/it|.R|kotlin/Int.compareTo|(Int(0))) } @@ -47,10 +47,10 @@ FILE: callsInPlace.kt ) } public final fun test_7(): R|kotlin/Unit| { - R|/myRun|(block2 = myRun@fun (): R|kotlin/Unit| { + R|/myRun|(myRun@fun (): R|kotlin/Unit| { String(test_7_2) } - , block1 = myRun@fun (): R|kotlin/Unit| { + , myRun@fun (): R|kotlin/Unit| { String(test_7_1) } ) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/namedArgument.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/namedArgument.fir.txt index 4710c2fa60c..cf39ef1a775 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/namedArgument.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/callsInPlace/namedArgument.fir.txt @@ -27,7 +27,7 @@ FILE: namedArgument.kt ) } - R|/myRun|(f = R|/g|) + R|/myRun|(R|/g|) } @R|kotlin/OptIn|(markerClass = vararg((Q|kotlin/contracts/ExperimentalContracts|))) public final inline fun test_2(g: R|() -> kotlin/Unit|): R|kotlin/Unit| [R|Contract description] diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.fir.txt index eddc3a95d16..55970fd2440 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/contracts/fromSource/good/returnsImplies/namedArguments.fir.txt @@ -20,17 +20,17 @@ FILE: namedArguments.kt } public final fun test_1(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { - R|/foo|(x = R|/x|, y = R|/y|) + R|/foo|(R|/x|, R|/y|) R|/x|.R|kotlin/Int.inc|() R|/y|.R|kotlin/String.length| } public final fun test_2(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { - R|/foo|(R|/x|, y = R|/y|) + R|/foo|(R|/x|, R|/y|) R|/x|.R|kotlin/Int.inc|() R|/y|.R|kotlin/String.length| } public final fun test_3(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| { - R|/foo|(y = R|/y|, x = R|/x|) + R|/foo|(R|/y|, R|/x|) R|/x|.R|kotlin/Int.inc|() R|/y|.R|kotlin/String.length| } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/builderInferenceAndCoercionToUnit.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/builderInferenceAndCoercionToUnit.fir.txt index 409bee0e8f3..4450b6194d8 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/builderInferenceAndCoercionToUnit.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/inference/builderInferenceAndCoercionToUnit.fir.txt @@ -9,7 +9,7 @@ FILE: builderInferenceAndCoercionToUnit.kt } public final fun test(strings: R|kotlin/collections/List|): R|kotlin/Unit| { - lval dropDown: R|DropDownComponent| = R|/DropDownComponent.DropDownComponent|(initialValues = R|kotlin/collections/buildList|( = buildList@fun R|kotlin/collections/MutableList|.(): R|kotlin/Unit| { + lval dropDown: R|DropDownComponent| = R|/DropDownComponent.DropDownComponent|(R|kotlin/collections/buildList|( = buildList@fun R|kotlin/collections/MutableList|.(): R|kotlin/Unit| { this@R|special/anonymous|.R|SubstitutionOverride|(R|/strings|) } )) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/arrayOfImports.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/arrayOfImports.fir.txt index fa0a0563d89..aebb68b61e2 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/arrayOfImports.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/arrayOfImports.fir.txt @@ -1,5 +1,5 @@ FILE: arrayOfImports.kt - @R|kotlin/Deprecated|(message = String(Use ...), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(String(bar), vararg(imports = (String(my.package.bar))))) @R|Third|(first = R|/First.First|(((Q|kotlin/String|))), second = R|/Second.Second|((R|/First.First|(((Q|kotlin/Int|))), R|/First.First|(((Q|kotlin/Double|)))))) @R|Second|(value = ((String()), (R|/First.First|(())))) public final fun foo(): R|kotlin/Unit| { + @R|kotlin/Deprecated|(message = String(Use ...), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(String(bar), vararg(*(String(my.package.bar))))) @R|Third|(first = R|/First.First|(((Q|kotlin/String|))), second = R|/Second.Second|((R|/First.First|(((Q|kotlin/Int|))), R|/First.First|(((Q|kotlin/Double|)))))) @R|Second|(value = ((String()), (R|/First.First|(())))) public final fun foo(): R|kotlin/Unit| { } public final annotation class First : R|kotlin/Annotation| { public constructor(value: R|kotlin/Array>|): R|First| { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/FieldAnnotationWithClasses.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/FieldAnnotationWithClasses.fir.txt index 3868219fefa..a2b51ce972f 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/FieldAnnotationWithClasses.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/FieldAnnotationWithClasses.fir.txt @@ -14,7 +14,7 @@ FILE: FieldAnnotationWithClasses.kt super() } - field:@FIELD:R|Ann|(allowedTypes = vararg(allowedTypes = ((Q|Some|), (Q|Other|)))) public final val x: R|kotlin/Int| = Int(42) + field:@FIELD:R|Ann|(allowedTypes = vararg(*((Q|Some|), (Q|Other|)))) public final val x: R|kotlin/Int| = Int(42) public get(): R|kotlin/Int| } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/NamedParameterInConcurrentMap.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/NamedParameterInConcurrentMap.fir.txt index 5a8588c350c..c4b4446f10e 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/NamedParameterInConcurrentMap.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/NamedParameterInConcurrentMap.fir.txt @@ -1,5 +1,5 @@ FILE: NamedParameterInConcurrentMap.kt public final fun main(): R|kotlin/Unit| { lval map: R|java/util/concurrent/ConcurrentHashMap| = R|java/util/concurrent/ConcurrentHashMap.ConcurrentHashMap|() - R|/map|.R|SubstitutionOverride|(key = String(key), value = String(value)) + R|/map|.R|SubstitutionOverride|(String(key), String(value)) } diff --git a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJavaAnnotationsChecker.kt b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJavaAnnotationsChecker.kt index 0fee8eb2819..b71732a09ce 100644 --- a/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJavaAnnotationsChecker.kt +++ b/compiler/fir/checkers/checkers.jvm/src/org/jetbrains/kotlin/fir/analysis/jvm/checkers/expression/FirJavaAnnotationsChecker.kt @@ -48,8 +48,9 @@ object FirJavaAnnotationsChecker : FirAnnotationChecker(MppCheckerKind.Common) { if (expression is FirAnnotationCall) { val argumentList = expression.argumentList if (argumentList is FirResolvedArgumentList) { - for ((key, value) in argumentList.mapping) { - if (value.name != Annotations.ParameterNames.value && key !is FirWrappedArgumentExpression) { + val arguments = argumentList.originalArgumentList?.arguments ?: return + for (key in arguments) { + if (key !is FirWrappedArgumentExpression && argumentList.mapping[key]?.name.let { it != null && it != Annotations.ParameterNames.value}) { reporter.reportOn(key.source, FirJvmErrors.POSITIONED_VALUE_ARGUMENT_FOR_JAVA_ANNOTATION, context) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt index c4f03fd66ec..248a5f30125 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt @@ -92,6 +92,10 @@ private class FirConstCheckVisitor(private val session: FirSession) : FirVisitor return namedArgumentExpression.expression.accept(this, data) } + override fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression, data: Nothing?): ConstantArgumentKind { + return spreadArgumentExpression.expression.accept(this, data) + } + override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: Nothing?): ConstantArgumentKind { return if (typeOperatorCall.operation == FirOperation.AS) ConstantArgumentKind.NOT_CONST else ConstantArgumentKind.VALID_CONST } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationExpressionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationExpressionChecker.kt index 9f02c02b42d..59a0a6c6ebc 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationExpressionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAnnotationExpressionChecker.kt @@ -50,7 +50,7 @@ object FirAnnotationExpressionChecker : FirAnnotationCallChecker(MppCheckerKind. val annotationClassId = expression.toAnnotationClassId(context.session) val fqName = annotationClassId?.asSingleFqName() for (arg in argumentMapping.values) { - val argExpression = (arg as? FirNamedArgumentExpression)?.expression ?: (arg as? FirErrorExpression)?.expression ?: arg + val argExpression = (arg as? FirErrorExpression)?.expression ?: arg checkAnnotationArgumentWithSubElements(argExpression, context.session, reporter, context) ?.let { reporter.reportOn(argExpression.source, it, context) } } @@ -123,8 +123,7 @@ object FirAnnotationExpressionChecker : FirAnnotationCallChecker(MppCheckerKind. context: CheckerContext, reporter: DiagnosticReporter ): ApiVersion? { - val constantExpression = (expression as? FirLiteralExpression<*>) - ?: ((expression as? FirNamedArgumentExpression)?.expression as? FirLiteralExpression<*>) ?: return null + val constantExpression = (expression as? FirLiteralExpression<*>) ?: return null val stringValue = constantExpression.value as? String ?: return null if (!stringValue.matches(RequireKotlinConstants.VERSION_REGEX)) { reporter.reportOn(expression.source, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNamedVarargChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNamedVarargChecker.kt index 66b32f5f2d7..44da95ab085 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNamedVarargChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirNamedVarargChecker.kt @@ -20,6 +20,8 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.types.* +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract object FirNamedVarargChecker : FirCallChecker(MppCheckerKind.Common) { override fun check(expression: FirCall, context: CheckerContext, reporter: DiagnosticReporter) { @@ -38,8 +40,8 @@ object FirNamedVarargChecker : FirCallChecker(MppCheckerKind.Common) { ) fun checkArgument(argument: FirExpression, isVararg: Boolean, expectedArrayType: ConeKotlinType) { - if (argument !is FirNamedArgumentExpression) return - if (argument.isSpread) { + if (!isNamedSpread(argument)) return + if (!argument.isFakeSpread && argument.isNamed) { if (isVararg && (expression as? FirResolvable)?.calleeReference !is FirErrorNamedReference) { reporter.reportOn(argument.expression.source, redundantSpreadWarningFactory, context) } @@ -69,17 +71,25 @@ object FirNamedVarargChecker : FirCallChecker(MppCheckerKind.Common) { if (expression is FirArrayLiteral) { // FirArrayLiteral has the `vararg` argument expression pre-flattened and doesn't have an argument mapping. - expression.arguments.forEach { checkArgument(it, it is FirNamedArgumentExpression, expression.resolvedType) } + expression.arguments.forEach { checkArgument(it, isVararg = isNamedSpread(it), expression.resolvedType) } } else { val argumentMap = expression.resolvedArgumentMapping ?: return for ((argument, parameter) in argumentMap) { if (!parameter.isVararg) continue if (argument is FirVarargArgumentsExpression) { - argument.arguments.forEach { checkArgument(it, true, parameter.returnTypeRef.coneType) } + argument.arguments.forEach { checkArgument(it, isVararg = true, parameter.returnTypeRef.coneType) } } else { - checkArgument(argument, false, parameter.returnTypeRef.coneType) + checkArgument(argument, isVararg = false, parameter.returnTypeRef.coneType) } } } } + + @OptIn(ExperimentalContracts::class) + private fun isNamedSpread(expression: FirExpression): Boolean { + contract { + returns(true) implies (expression is FirSpreadArgumentExpression) + } + return expression is FirSpreadArgumentExpression && expression.isNamed + } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSpreadOfNullableChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSpreadOfNullableChecker.kt index fa170e90cd3..f710e032fe2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSpreadOfNullableChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSpreadOfNullableChecker.kt @@ -23,7 +23,7 @@ object FirSpreadOfNullableChecker : FirFunctionCallChecker(MppCheckerKind.Common override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { fun checkAndReport(argument: FirExpression, source: KtSourceElement?) { val coneType = argument.resolvedType - if (argument is FirSpreadArgumentExpression && coneType !is ConeFlexibleType && coneType.canBeNull(context.session)) { + if (argument is FirSpreadArgumentExpression && !argument.isFakeSpread && coneType !is ConeFlexibleType && coneType.canBeNull(context.session)) { reporter.reportOn(source, FirErrors.SPREAD_OF_NULLABLE, context) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index c03335f5f9a..1a3d1618489 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -821,7 +821,7 @@ class CallAndReferenceGenerator( val argument = this@toAnnotationCall.argumentMapping.mapping[parameter.name] ?: return@mapNotNull null argument to parameter }.toMap(LinkedHashMap()) - argumentList = buildResolvedArgumentList(argumentToParameterToMapping) + argumentList = buildResolvedArgumentList(original = null, argumentToParameterToMapping) calleeReference = buildResolvedNamedReference { name = symbol.classId.shortClassName resolvedSymbol = constructorSymbol diff --git a/compiler/fir/plugin-utils/src/org/jetbrains/kotlin/fir/plugin/ConstructorBuildingContext.kt b/compiler/fir/plugin-utils/src/org/jetbrains/kotlin/fir/plugin/ConstructorBuildingContext.kt index cd0aa2a6764..e252703498d 100644 --- a/compiler/fir/plugin-utils/src/org/jetbrains/kotlin/fir/plugin/ConstructorBuildingContext.kt +++ b/compiler/fir/plugin-utils/src/org/jetbrains/kotlin/fir/plugin/ConstructorBuildingContext.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.declarations.origin import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.isInner -import org.jetbrains.kotlin.fir.expressions.buildResolvedArgumentList +import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList import org.jetbrains.kotlin.fir.expressions.builder.buildDelegatedConstructorCall import org.jetbrains.kotlin.fir.extensions.FirExtension import org.jetbrains.kotlin.fir.getContainingClassLookupTag @@ -174,7 +174,7 @@ private fun FirConstructor.generateNoArgDelegatingConstructorCall() { name = superConstructorSymbol.name resolvedSymbol = superConstructorSymbol } - argumentList = buildResolvedArgumentList(LinkedHashMap()) + argumentList = FirEmptyArgumentList isThis = false } replaceDelegatedConstructor(delegatingConstructorCall) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/GeneratedDeclarationValidation.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/GeneratedDeclarationValidation.kt index b96118d17a8..27bbd8f97cc 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/GeneratedDeclarationValidation.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/GeneratedDeclarationValidation.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirArgumentList +import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference @@ -43,7 +44,7 @@ object FirGeneratedElementsValidator : FirDefaultVisitor() { } override fun visitArgumentList(argumentList: FirArgumentList, data: Any?) { - require(argumentList is FirResolvedArgumentList) + require(argumentList is FirResolvedArgumentList || argumentList is FirEmptyArgumentList) argumentList.acceptChildren(this, null) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallInfo.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallInfo.kt index 8721f663f5b..4bd71fa3a7b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallInfo.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CallInfo.kt @@ -5,15 +5,14 @@ package org.jetbrains.kotlin.fir.resolve.calls +import org.jetbrains.kotlin.fir.FirCallResolver import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.expressions.FirArgumentList -import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList -import org.jetbrains.kotlin.fir.expressions.FirExpression -import org.jetbrains.kotlin.fir.expressions.FirFunctionCallOrigin +import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList +import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.types.ConeKotlinType @@ -47,8 +46,18 @@ data class CallInfo( val hasSyntheticOuterCall: Boolean = false, val origin: FirFunctionCallOrigin = FirFunctionCallOrigin.Regular, ) : AbstractCallInfo() { - val arguments: List get() = argumentList.arguments - + /** + * If [argumentList] is a [FirResolvedArgumentList], + * returns the [FirArgumentList.arguments] of the [FirResolvedArgumentList.originalArgumentList]. + * This means the result still contains [FirNamedArgumentExpression]s that are removed from the + * [FirResolvedArgumentList] during completion. + * + * This is important for Analysis API because it will trigger resolution on already resolved expressions, + * and we wouldn't otherwise have access to named arguments. + * + * @see FirCallResolver.collectAllCandidates + */ + val arguments: List get() = (argumentList as? FirResolvedArgumentList)?.originalArgumentList?.arguments ?: argumentList.arguments val argumentCount get() = arguments.size fun replaceWithVariableAccess(): CallInfo = diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index aa6cc6f4763..853589acdaa 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -17,6 +17,8 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.buildSamConversionExpression +import org.jetbrains.kotlin.fir.expressions.builder.buildSpreadArgumentExpression +import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedCallableReference @@ -345,16 +347,17 @@ class FirCallCompletionResultsWriterTransformer( val calleeReference = functionCall.calleeReference as? FirNamedReferenceWithCandidate ?: return functionCall val result = prepareQualifiedTransform(functionCall, calleeReference) + val originalArgumentList = result.argumentList val subCandidate = calleeReference.candidate val resultType = result.resolvedType.substituteType(subCandidate) if (calleeReference.isError) { subCandidate.argumentMapping?.let { - result.replaceArgumentList(buildArgumentListForErrorCall(result.argumentList, it)) + result.replaceArgumentList(buildArgumentListForErrorCall(originalArgumentList, it)) } } else { subCandidate.handleVarargs() subCandidate.argumentMapping?.let { - val newArgumentList = buildResolvedArgumentList(it, source = functionCall.argumentList.source) + val newArgumentList = buildResolvedArgumentList(originalArgumentList, it) val symbol = subCandidate.symbol val functionIsInline = (symbol as? FirNamedFunctionSymbol)?.fir?.isInline == true || symbol.isArrayConstructorWithLambda @@ -375,7 +378,7 @@ class FirCallCompletionResultsWriterTransformer( } val expectedArgumentsTypeMapping = runIf(!calleeReference.isError) { subCandidate.createArgumentsMapping() } - result.transformWithExpectedTypes(expectedArgumentsTypeMapping) + result.transformArgumentList(expectedArgumentsTypeMapping) result.replaceConeTypeOrNull(resultType) session.lookupTracker?.recordTypeResolveAsLookup(resultType, functionCall.source, context.file.source) @@ -398,8 +401,10 @@ class FirCallCompletionResultsWriterTransformer( } } - private fun FirCall.transformWithExpectedTypes(expectedArgumentsTypeMapping: ExpectedArgumentType.ArgumentsMap?) { - class SamConversionInsertionTransformer : FirTransformer() { + private fun FirCall.transformArgumentList(expectedArgumentsTypeMapping: ExpectedArgumentType.ArgumentsMap?) { + val mapping = (argumentList as? FirResolvedArgumentList)?.mapping + + class ArgumentTransformer : FirTransformer() { override fun transformElement(element: E, data: Nothing?): E { // We want to handle only the most top-level "real" expressions // We only recursively transform named, spread, lambda argument and vararg expressions. @@ -422,9 +427,27 @@ class FirCallCompletionResultsWriterTransformer( return transformed } + + override fun transformNamedArgumentExpression( + namedArgumentExpression: FirNamedArgumentExpression, + data: Nothing? + ): FirStatement { + val expression = transformElement(namedArgumentExpression.expression, data) + val parameter = mapping?.get(namedArgumentExpression) + return if (namedArgumentExpression.isSpread || parameter?.isVararg == true) { + buildSpreadArgumentExpression { + this.source = namedArgumentExpression.source + this.expression = expression + this.isNamed = true + this.isFakeSpread = !namedArgumentExpression.isSpread + } + } else { + expression + } + } } - argumentList.transformArguments(SamConversionInsertionTransformer(), null) + argumentList.transformArguments(ArgumentTransformer(), null) } private fun FirExpression.wrapInSamExpression(expectedArgumentType: ConeKotlinType): FirExpression { @@ -468,9 +491,11 @@ class FirCallCompletionResultsWriterTransformer( } else { subCandidate.handleVarargs() subCandidate.argumentMapping?.let { - annotationCall.replaceArgumentList(buildResolvedArgumentList(it, annotationCall.argumentList.source)) + annotationCall.replaceArgumentList(buildResolvedArgumentList(annotationCall.argumentList, it)) } } + + annotationCall.transformArgumentList(expectedArgumentsTypeMapping = null) return annotationCall } @@ -673,21 +698,22 @@ class FirCallCompletionResultsWriterTransformer( delegatedConstructorCall.calleeReference as? FirNamedReferenceWithCandidate ?: return delegatedConstructorCall val subCandidate = calleeReference.candidate + val originalArgumentList = delegatedConstructorCall.argumentList if (calleeReference.isError) { subCandidate.argumentMapping?.let { - delegatedConstructorCall.replaceArgumentList(buildArgumentListForErrorCall(delegatedConstructorCall.argumentList, it)) + delegatedConstructorCall.replaceArgumentList(buildArgumentListForErrorCall(originalArgumentList, it)) } } else { subCandidate.handleVarargs() subCandidate.argumentMapping?.let { - delegatedConstructorCall.replaceArgumentList(buildResolvedArgumentList(it, delegatedConstructorCall.argumentList.source)) + delegatedConstructorCall.replaceArgumentList(buildResolvedArgumentList(originalArgumentList, it)) } } runPCLARelatedTasksForCandidate(subCandidate) val argumentsMapping = runIf(!calleeReference.isError) { subCandidate.createArgumentsMapping() } - delegatedConstructorCall.transformWithExpectedTypes(argumentsMapping) + delegatedConstructorCall.transformArgumentList(argumentsMapping) return delegatedConstructorCall.apply { replaceCalleeReference(calleeReference.toResolvedReference()) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt index 48d6ee375aa..6613d05c98b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveUtils.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression import org.jetbrains.kotlin.fir.expressions.UnresolvedExpressionTypeAccess +import org.jetbrains.kotlin.fir.expressions.builder.buildSpreadArgumentExpression import org.jetbrains.kotlin.fir.expressions.builder.buildVarargArgumentsExpression import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.types.* @@ -57,7 +58,16 @@ internal fun remapArgumentsWithVararg( // NB: don't pull out of named arguments. (valueParameter.isVararg && arg !is FirNamedArgumentExpression) ) { - arguments += arg + arguments += if (arg is FirNamedArgumentExpression) { + buildSpreadArgumentExpression { + this.source = arg.source + this.expression = arg.expression + this.isNamed = true + this.isFakeSpread = !arg.isSpread + } + } else { + arg + } startOffset = minOf(startOffset, arg.source?.startOffset ?: Int.MAX_VALUE) endOffset = maxOf(endOffset, arg.source?.endOffset ?: 0) if (firstVarargElementSource == null) firstVarargElementSource = arg.source diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt index 835cc023314..8cab5544454 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirSpreadArgumentExpression.kt @@ -24,6 +24,8 @@ abstract class FirSpreadArgumentExpression : FirWrappedArgumentExpression() { abstract override val annotations: List abstract override val expression: FirExpression abstract override val isSpread: Boolean + abstract val isNamed: Boolean + abstract val isFakeSpread: Boolean override fun accept(visitor: FirVisitor, data: D): R = visitor.visitSpreadArgumentExpression(this, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirSpreadArgumentExpressionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirSpreadArgumentExpressionBuilder.kt index ba8f0806590..c42de198018 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirSpreadArgumentExpressionBuilder.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirSpreadArgumentExpressionBuilder.kt @@ -26,12 +26,16 @@ class FirSpreadArgumentExpressionBuilder : FirAnnotationContainerBuilder, FirExp override var source: KtSourceElement? = null override val annotations: MutableList = mutableListOf() lateinit var expression: FirExpression + var isNamed: Boolean = false + var isFakeSpread: Boolean = false override fun build(): FirSpreadArgumentExpression { return FirSpreadArgumentExpressionImpl( source, annotations.toMutableOrEmpty(), expression, + isNamed, + isFakeSpread, ) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt index 4b0b317c3d1..3dbe74dc9a6 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirSpreadArgumentExpressionImpl.kt @@ -26,6 +26,8 @@ internal class FirSpreadArgumentExpressionImpl( override val source: KtSourceElement?, override var annotations: MutableOrEmptyList, override var expression: FirExpression, + override val isNamed: Boolean, + override val isFakeSpread: Boolean, ) : FirSpreadArgumentExpression() { @OptIn(UnresolvedExpressionTypeAccess::class) override val coneTypeOrNull: ConeKotlinType? diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirArgumentUtil.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirArgumentUtil.kt index bd390be7c63..3d83094b9db 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirArgumentUtil.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/FirArgumentUtil.kt @@ -22,18 +22,19 @@ fun buildBinaryArgumentList(left: FirExpression, right: FirExpression): FirArgum } fun buildResolvedArgumentList( - mapping: LinkedHashMap, - source: KtSourceElement? = null -): FirResolvedArgumentList = - FirResolvedArgumentListImpl(source, mapping) + original: FirArgumentList?, + mapping: LinkedHashMap +): FirResolvedArgumentList { + return FirResolvedArgumentListImpl(original, mapping) +} fun buildArgumentListForErrorCall( original: FirArgumentList, - mapping: Map + mapping: LinkedHashMap ): FirArgumentList { return FirResolvedArgumentListForErrorCall( - original.source, - original.arguments.map { key -> key to mapping[key] }.toMap(LinkedHashMap()) + original, + original.arguments.associateWithTo(LinkedHashMap()) { key -> mapping[key] }, ) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirResolvedArgumentList.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirResolvedArgumentList.kt index c359cc69faa..76df95342ce 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirResolvedArgumentList.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/expressions/impl/FirResolvedArgumentList.kt @@ -11,14 +11,22 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.FirAbstractArgumentList import org.jetbrains.kotlin.fir.expressions.FirArgumentList import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirVisitor import org.jetbrains.kotlin.fir.visitors.transformSingle abstract class FirResolvedArgumentList : FirAbstractArgumentList() { - abstract override val source: KtSourceElement? + /** + * Contains the original, unresolved [FirArgumentList] which contains [FirNamedArgumentExpression]s, + * whereas [FirNamedArgumentExpression]s are removed from `this` resolved argument list. + */ + abstract val originalArgumentList: FirArgumentList? abstract val mapping: LinkedHashMap + final override val source: KtSourceElement? + get() = originalArgumentList?.source + override val arguments: List get() = mapping.keys.toList() @@ -38,10 +46,9 @@ abstract class FirResolvedArgumentList : FirAbstractArgumentList() { internal class FirResolvedArgumentListImpl( - override val source: KtSourceElement?, - mapping: LinkedHashMap + override val originalArgumentList: FirArgumentList?, + mapping: LinkedHashMap, ) : FirResolvedArgumentList() { - override var mapping: LinkedHashMap = mapping private set @@ -52,8 +59,8 @@ internal class FirResolvedArgumentListImpl( } internal class FirResolvedArgumentListForErrorCall( - override var source: KtSourceElement?, - private var _mapping: LinkedHashMap + override val originalArgumentList: FirArgumentList?, + private var _mapping: LinkedHashMap, ) : FirResolvedArgumentList() { override var mapping: LinkedHashMap = computeMapping() diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt index a1b9bd74d17..56b8a9f3b3e 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt @@ -377,6 +377,10 @@ object BuilderConfigurator : AbstractFirBuilderConfigurator(FirT default("symbol", "FirAnonymousInitializerSymbol()") } + builder(spreadArgumentExpression) { + defaultFalse("isNamed", "isFakeSpread") + } + val abstractResolvedQualifierBuilder by builder { fields from resolvedQualifier } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index eb474e172b6..2cba55d4201 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -610,6 +610,11 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +booleanField("isSpread") } + spreadArgumentExpression.configure { + +booleanField("isNamed") + +booleanField("isFakeSpread") + } + namedArgumentExpression.configure { +name } diff --git a/compiler/testData/codegen/box/annotations/targetOnPrimaryCtorParameter.fir.txt b/compiler/testData/codegen/box/annotations/targetOnPrimaryCtorParameter.fir.txt index bb6c12f1ed5..800bb6b0c5c 100644 --- a/compiler/testData/codegen/box/annotations/targetOnPrimaryCtorParameter.fir.txt +++ b/compiler/testData/codegen/box/annotations/targetOnPrimaryCtorParameter.fir.txt @@ -11,19 +11,19 @@ FILE: targetOnPrimaryCtorParameter.kt } } - @R|kotlin/annotation/Target|(allowedTargets = vararg(allowedTargets = (Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY|))) public final annotation class PropertyOnly : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|(allowedTargets = vararg(*(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY|))) public final annotation class PropertyOnly : R|kotlin/Annotation| { public constructor(): R|PropertyOnly| { super() } } - @R|kotlin/annotation/Target|(allowedTargets = vararg(allowedTargets = (Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|))) public final annotation class ParameterOnly : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|(allowedTargets = vararg(*(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|))) public final annotation class ParameterOnly : R|kotlin/Annotation| { public constructor(): R|ParameterOnly| { super() } } - @R|kotlin/annotation/Target|(allowedTargets = vararg(allowedTargets = *(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FIELD|))) public final annotation class FieldOnly : R|kotlin/Annotation| { + @R|kotlin/annotation/Target|(allowedTargets = vararg(*(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FIELD|))) public final annotation class FieldOnly : R|kotlin/Annotation| { public constructor(): R|FieldOnly| { super() } diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/kt57960.fir.txt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/kt57960.fir.txt index 8d96815b584..8f518bf00b3 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/kt57960.fir.txt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/kt57960.fir.txt @@ -37,7 +37,7 @@ FILE: kt57960.kt } private final fun buildSchemaNodes1(): R|kotlin/Unit| { R|/jso|( = jso@fun R|dynamic|.(): R|kotlin/Unit| { - Q|Foo|.R|/Foo.create2|(toDOM = create2@fun (domNode: R|Baz|): R|kotlin/Any| { + Q|Foo|.R|/Foo.create2|(create2@fun (domNode: R|Baz|): R|kotlin/Any| { ^ R|/domNode|.R|/Baz.text| } ) diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/qualifier/wrongQualifier.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/qualifier/wrongQualifier.fir.kt new file mode 100644 index 00000000000..c4bf6d39562 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/qualifier/wrongQualifier.fir.kt @@ -0,0 +1,23 @@ +// FILE: a.kt +@file:JsQualifier("") + +// FILE: b.kt +@file:JsQualifier("a..b") + +// FILE: c.kt +@file:JsQualifier("a.") + +// FILE: d.kt +@file:JsQualifier(".a") + +// FILE: e.kt +@file:JsQualifier("%^&") + +// FILE: f.kt +@file:JsQualifier("a.bc.d23._$") + +// FILE: g.kt +typealias JsQ = JsQualifier + +// FILE: h.kt +@file:JsQ(value = "%^&") diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/qualifier/wrongQualifier.kt b/compiler/testData/diagnostics/testsWithJsStdLib/qualifier/wrongQualifier.kt index a188aef0d30..b9da80848f6 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/qualifier/wrongQualifier.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/qualifier/wrongQualifier.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // FILE: a.kt @file:JsQualifier("") diff --git a/compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.fir.kt b/compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.fir.kt new file mode 100644 index 00000000000..c4bf6d39562 --- /dev/null +++ b/compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.fir.kt @@ -0,0 +1,23 @@ +// FILE: a.kt +@file:JsQualifier("") + +// FILE: b.kt +@file:JsQualifier("a..b") + +// FILE: c.kt +@file:JsQualifier("a.") + +// FILE: d.kt +@file:JsQualifier(".a") + +// FILE: e.kt +@file:JsQualifier("%^&") + +// FILE: f.kt +@file:JsQualifier("a.bc.d23._$") + +// FILE: g.kt +typealias JsQ = JsQualifier + +// FILE: h.kt +@file:JsQ(value = "%^&") diff --git a/compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.kt b/compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.kt index a188aef0d30..b9da80848f6 100644 --- a/compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.kt +++ b/compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // FILE: a.kt @file:JsQualifier("") diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/DataFrameLikeCallsRefinementExtension.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/DataFrameLikeCallsRefinementExtension.kt index 769eead29c8..26190646d47 100644 --- a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/DataFrameLikeCallsRefinementExtension.kt +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/DataFrameLikeCallsRefinementExtension.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl +import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.buildResolvedArgumentList import org.jetbrains.kotlin.fir.expressions.builder.buildAnonymousFunctionExpression @@ -225,7 +226,7 @@ class DataFrameLikeCallsRefinementExtension(session: FirSession) : FirFunctionCa dispatchReceiver = call.dispatchReceiver this.explicitReceiver = call.explicitReceiver extensionReceiver = call.extensionReceiver - argumentList = buildResolvedArgumentList(linkedMapOf(argument to parameter.fir)) + argumentList = buildResolvedArgumentList(original = null, linkedMapOf(argument to parameter.fir)) calleeReference = buildResolvedNamedReference { name = Name.identifier("let") resolvedSymbol = resolvedLet diff --git a/plugins/fir-plugin-prototype/testData/box/composableFunctionMultiModules.fir.txt b/plugins/fir-plugin-prototype/testData/box/composableFunctionMultiModules.fir.txt index 82bc03d844d..91bb4473212 100644 --- a/plugins/fir-plugin-prototype/testData/box/composableFunctionMultiModules.fir.txt +++ b/plugins/fir-plugin-prototype/testData/box/composableFunctionMultiModules.fir.txt @@ -7,7 +7,7 @@ FILE: foo.kt Module: main FILE: main.kt @R|org/jetbrains/kotlin/fir/plugin/MyComposable|() public final fun Bar(): R|kotlin/Unit| { - R|p3/Foo|(text = Foo@fun (): R|kotlin/Unit| { + R|p3/Foo|(Foo@fun (): R|kotlin/Unit| { ^@Foo Unit } ) diff --git a/plugins/fir-plugin-prototype/testData/box/nullableComposableParameterAcrossModules.fir.txt b/plugins/fir-plugin-prototype/testData/box/nullableComposableParameterAcrossModules.fir.txt index f471c68b9ad..536339fb668 100644 --- a/plugins/fir-plugin-prototype/testData/box/nullableComposableParameterAcrossModules.fir.txt +++ b/plugins/fir-plugin-prototype/testData/box/nullableComposableParameterAcrossModules.fir.txt @@ -5,7 +5,7 @@ FILE: a.kt Module: b FILE: b.kt public final fun bar(onClick: R|(() -> kotlin/Unit)?| = Null(null)): R|kotlin/Unit| { - R|/RMenuItem|(onClick = R|/onClick|, trailing = R|/onClick|?.{ $subj$.R|kotlin/let| kotlin/Unit|, R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0?|>( = let@fun (it: R|() -> kotlin/Unit|): R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0?| { + R|/RMenuItem|(R|/onClick|, R|/onClick|?.{ $subj$.R|kotlin/let| kotlin/Unit|, R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0?|>( = let@fun (it: R|() -> kotlin/Unit|): R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0?| { ^ let@fun (): R|kotlin/Unit| { ^@let Unit } diff --git a/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt b/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt index 0ed2b1c60c1..160585baea6 100644 --- a/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt +++ b/plugins/kotlinx-serialization/kotlinx-serialization.k2/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlinx.serialization.compiler.fir import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* @@ -267,7 +266,7 @@ fun FirDeclaration.excludeFromJsExport() { val jsExportIgnoreConstructor = jsExportIgnoreAnnotation.declarationSymbols.firstIsInstanceOrNull() ?: return val jsExportIgnoreAnnotationCall = buildAnnotationCall { - argumentList = buildResolvedArgumentList(linkedMapOf()) + argumentList = FirEmptyArgumentList annotationTypeRef = buildResolvedTypeRef { type = jsExportIgnoreAnnotation.defaultType() }