[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
This commit is contained in:
Kirill Rakhman
2024-03-01 16:00:11 +01:00
committed by Space Team
parent 03fc0fd381
commit 8443daf78d
54 changed files with 249 additions and 117 deletions
@@ -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,
@@ -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<R|A|>(x = Int(1), b = R|<local>/i|.R|kotlin/Int.toString|())
this<R|A|>(Int(1), R|<local>/i|.R|kotlin/Int.toString|())
}
}
@@ -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<R|IJProject|>(init = [ResolvedTo(RAW_FIR)] fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
super<R|IJProject|>([ResolvedTo(RAW_FIR)] fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
local final [ResolvedTo(RAW_FIR)] fun foo(): R|kotlin/Unit| {
<Unresolved name: anySymbols>#
}
@@ -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|<local>/LocalClass| {
super<R|kotlin/Any|>()
}
@@ -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|<local>/LocalClass| {
super<R|kotlin/Any|>()
}
@@ -173,7 +173,7 @@ FILE: [ResolvedTo(IMPORTS)] compilerRequiredAnnotationOnLocalClassScript.kts
[ResolvedTo(TYPES)] lval args: R|kotlin/Array<kotlin/String>|
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|<local>/LocalClass| {
super<R|kotlin/Any|>()
}
@@ -197,7 +197,7 @@ FILE: [ResolvedTo(BODY_RESOLVE)] compilerRequiredAnnotationOnLocalClassScript.kt
[ResolvedTo(BODY_RESOLVE)] lval args: R|kotlin/Array<kotlin/String>|
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|<local>/LocalClass| {
super<R|kotlin/Any|>()
}
@@ -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 = <implicitArrayOf>(<getClass>(Q|kotlin/String|), <getClass>(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 = <implicitArrayOf>(<getClass>(Q|kotlin/String|), <getClass>(R|/constString|)), annotation = R|/MyOtherAnnotation.MyOtherAnnotation|(R|/constInt|, String(hello))) public final fun foo(): R|kotlin/Unit| {
}
@@ -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<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|()
R|/foo<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /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<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /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<Inapplicable(INAPPLICABLE): /baz>#|(Int(0), String(), Boolean(false))
}
@@ -24,6 +24,6 @@ FILE: defaultFromOverrides.kt
R|<local>/a|.R|/A.foo|(Int(1))
R|<local>/a|.R|/A.bar<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /A.bar>#|()
R|<local>/a|.R|/A.bar<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /A.bar>#|(String())
R|<local>/a|.R|/A.bar|(y = Int(1))
R|<local>/a|.R|/A.bar|(Int(1))
R|<local>/a|.R|/A.bar|(String(), Int(2))
}
@@ -22,7 +22,7 @@ FILE: lambda.kt
^@foo Unit
}
)
R|/foo<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|(f = foo@fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
R|/foo<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|(foo@fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
^@foo Unit
}
, <L> = foo@fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
@@ -33,7 +33,7 @@ FILE: lambda.kt
^@bar Unit
}
)
R|/bar|(x = Int(1), <L> = bar@fun <anonymous>(): R|kotlin/Unit| <inline=NoInline> {
R|/bar|(Int(1), <L> = bar@fun <anonymous>(): R|kotlin/Unit| <inline=NoInline> {
^@bar Unit
}
)
@@ -41,7 +41,7 @@ FILE: lambda.kt
^@bar Unit
}
)
R|/bar|(x = Int(1), f = bar@fun <anonymous>(): R|kotlin/Unit| <inline=NoInline> {
R|/bar|(Int(1), bar@fun <anonymous>(): R|kotlin/Unit| <inline=NoInline> {
^@bar Unit
}
)
@@ -53,7 +53,7 @@ FILE: lambda.kt
^@bar Unit
}
)
R|/baz|(other = Boolean(false), f = baz@fun <anonymous>(): R|kotlin/Unit| <inline=NoInline> {
R|/baz|(Boolean(false), baz@fun <anonymous>(): R|kotlin/Unit| <inline=NoInline> {
^@baz Unit
}
)
@@ -69,7 +69,7 @@ FILE: lambda.kt
^@baz Unit
}
)
R|/baz<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /baz>#|(other = Boolean(false), <L> = baz@fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
R|/baz<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /baz>#|(Boolean(false), <L> = baz@fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
^@baz Unit
}
)
@@ -8,7 +8,7 @@ FILE: namedArrayInAnnotation.kt
public get(): R|kotlin/Array<out kotlin/String>|
}
@R|Ann|(strings = vararg(strings = <implicitArrayOf>(String(hello)))) public final class A : R|kotlin/Any| {
@R|Ann|(strings = vararg(*<implicitArrayOf>(String(hello)))) public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
@@ -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<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|(y = Int(1))
R|/foo<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|(Int(1))
}
@@ -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<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|()
R|/foo<Inapplicable(INAPPLICABLE): /foo>#|(Double(0.0), Boolean(false), Int(0), String())
R|/foo|(Int(1), Double(2.0), third = Boolean(true), String())
R|/foo<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|(second = Double(0.0), first = Int(0), fourth = String())
R|/foo<Inapplicable(INAPPLICABLE): /foo>#|(first = Double(0.0), second = Int(0), third = String(), fourth = Boolean(false))
R|/foo<Inapplicable(INAPPLICABLE): /foo>#|(first = Int(0), second = Double(0.0), third = Boolean(false), fourth = String(), first = Int(1))
R|/foo<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|(Int(0), Double(0.0), Boolean(false), foth = String())
R|/foo|(Int(1), Double(2.0), Boolean(true), String())
R|/foo<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|(Double(0.0), Int(0), String())
R|/foo<Inapplicable(INAPPLICABLE): /foo>#|(Double(0.0), Int(0), String(), Boolean(false))
R|/foo<Inapplicable(INAPPLICABLE): /foo>#|(Int(0), Double(0.0), Boolean(false), String(), Int(1))
R|/foo<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /foo>#|(Int(0), Double(0.0), Boolean(false), String())
}
@@ -10,8 +10,8 @@ FILE: vararg.kt
R|/foo|(Int(1), vararg(*R|kotlin/arrayOf|<R|kotlin/String|>(vararg(String(my), String(yours)))))
R|/foo<Inapplicable(INAPPLICABLE): /foo>#|(String())
R|/foo<Inapplicable(INAPPLICABLE): /foo>#|(Int(1), Int(2))
R|/bar|(Int(1), z = Boolean(true), vararg(y = *R|kotlin/arrayOf|<R|kotlin/String|>(vararg(String(my), String(yours)))))
R|/bar<Inapplicable(INAPPLICABLE): /bar>#|(Int(0), z = Boolean(false), y = String(), y = String(other))
R|/bar|(Int(1), Boolean(true), vararg(*R|kotlin/arrayOf|<R|kotlin/String|>(vararg(String(my), String(yours)))))
R|/bar<Inapplicable(INAPPLICABLE): /bar>#|(Int(0), Boolean(false), *String(), String(other))
R|/bar<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): /bar>#|(Int(0), String(), Boolean(true))
R|/bar<Inapplicable(INAPPLICABLE): /bar>#|(Int(0), z = Boolean(false), y = String(), y = String(other), y = String(yet other))
R|/bar<Inapplicable(INAPPLICABLE): /bar>#|(Int(0), Boolean(false), *String(), String(other), String(yet other))
}
@@ -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|<local>/a|)
Q|Case2|.R|/Case2.Companion.invoke|(a = R|<local>/a|)
Q|Case2|.R|/Case2.Companion.invoke|(R|<local>/a|)
}
public final class Case2 : R|kotlin/Any| {
public constructor(): R|Case2| {
@@ -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 <anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
106 [label="Jump: ^test_4 R|/getInt|(getInt@fun <anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
^test_4 Int(1)
}
)"];
@@ -35,7 +35,7 @@ FILE: lambdas.kt
)
}
public final fun test_4(): R|kotlin/Int| {
^test_4 R|/getInt|(block = getInt@fun <anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
^test_4 R|/getInt|(getInt@fun <anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
^test_4 Int(1)
}
)
@@ -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|<local>/a|)
Q|Case2|.R|/Case2.Companion.invoke|(a = R|<local>/a|)
Q|Case2|.R|/Case2.Companion.invoke|(R|<local>/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|<local>/a|)
Q|Case3.Companion|.R|/Case3.Companion.invoke|(parameterA = R|<local>/a|)
Q|Case3.Companion|.R|/Case3.Companion.invoke|(R|<local>/a|)
}
public final class Case3 : R|kotlin/Any| {
public constructor(): R|Case3| {
+2 -2
View File
@@ -18,8 +18,8 @@ FILE: copy.kt
}
public final fun test(some: R|Some|): R|kotlin/Unit| {
lval other: R|Some| = R|<local>/some|.R|/Some.copy|(y = String(123))
lval another: R|Some| = R|<local>/some|.R|/Some.copy|(x = Int(123))
lval other: R|Some| = R|<local>/some|.R|/Some.copy|(String(123))
lval another: R|Some| = R|<local>/some|.R|/Some.copy|(Int(123))
lval same: R|Some| = R|<local>/some|.R|/Some.copy|()
lval different: R|Some| = R|<local>/some|.R|/Some.copy|(Int(456), String(456))
}
@@ -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<R|kotlin/Any|>()
}
@@ -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<R|kotlin/Any|>()
}
@@ -14,10 +14,10 @@ FILE: callsInPlace.kt
)
}
public final fun test_3(): R|kotlin/Unit| {
R|kotlin/repeat|(action = repeat@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
R|kotlin/repeat|(repeat@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
String(test_3)
}
, times = Int(10))
, Int(10))
}
public final fun test_4(): R|kotlin/Unit| {
Int(1).R|kotlin/takeUnless|<R|kotlin/Int|>(<L> = takeUnless@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Boolean| <inline=Inline, kind=EXACTLY_ONCE> {
@@ -27,7 +27,7 @@ FILE: callsInPlace.kt
)
}
public final fun test_5(): R|kotlin/Unit| {
Int(1).R|kotlin/takeUnless|<R|kotlin/Int|>(predicate = takeUnless@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Boolean| <inline=Inline, kind=EXACTLY_ONCE> {
Int(1).R|kotlin/takeUnless|<R|kotlin/Int|>(takeUnless@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Boolean| <inline=Inline, kind=EXACTLY_ONCE> {
String(test_5)
^ CMP(>, R|<local>/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 <anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
R|/myRun|(myRun@fun <anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
String(test_7_2)
}
, block1 = myRun@fun <anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
, myRun@fun <anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
String(test_7_1)
}
)
@@ -27,7 +27,7 @@ FILE: namedArgument.kt
)
}
R|/myRun|(f = R|<local>/g|)
R|/myRun|(R|<local>/g|)
}
@R|kotlin/OptIn|(markerClass = vararg(<getClass>(Q|kotlin/contracts/ExperimentalContracts|))) public final inline fun test_2(g: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
@@ -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|<local>/x|, y = R|<local>/y|)
R|/foo|(R|<local>/x|, R|<local>/y|)
R|<local>/x|.R|kotlin/Int.inc|()
R|<local>/y|.R|kotlin/String.length|
}
public final fun test_2(x: R|kotlin/Any|, y: R|kotlin/Any|): R|kotlin/Unit| {
R|/foo|(R|<local>/x|, y = R|<local>/y|)
R|/foo|(R|<local>/x|, R|<local>/y|)
R|<local>/x|.R|kotlin/Int.inc|()
R|<local>/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|<local>/y|, x = R|<local>/x|)
R|/foo|(R|<local>/y|, R|<local>/x|)
R|<local>/x|.R|kotlin/Int.inc|()
R|<local>/y|.R|kotlin/String.length|
}
@@ -9,7 +9,7 @@ FILE: builderInferenceAndCoercionToUnit.kt
}
public final fun test(strings: R|kotlin/collections/List<kotlin/String>|): R|kotlin/Unit| {
lval dropDown: R|DropDownComponent<kotlin/Any>| = R|/DropDownComponent.DropDownComponent|<R|kotlin/Any|>(initialValues = R|kotlin/collections/buildList|<R|kotlin/Any|>(<L> = buildList@fun R|kotlin/collections/MutableList<kotlin/Any>|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=EXACTLY_ONCE> {
lval dropDown: R|DropDownComponent<kotlin/Any>| = R|/DropDownComponent.DropDownComponent|<R|kotlin/Any|>(R|kotlin/collections/buildList|<R|kotlin/Any|>(<L> = buildList@fun R|kotlin/collections/MutableList<kotlin/Any>|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=EXACTLY_ONCE> {
this@R|special/anonymous|.R|SubstitutionOverride<kotlin/collections/MutableList.addAll: R|kotlin/Boolean|>|(R|<local>/strings|)
}
))
@@ -1,5 +1,5 @@
FILE: arrayOfImports.kt
@R|kotlin/Deprecated|(message = String(Use ...), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(String(bar), vararg(imports = <implicitArrayOf>(String(my.package.bar))))) @R|Third|(first = R|/First.First|(<implicitArrayOf>(<getClass>(Q|kotlin/String|))), second = R|/Second.Second|(<implicitArrayOf>(R|/First.First|(<implicitArrayOf>(<getClass>(Q|kotlin/Int|))), R|/First.First|(<implicitArrayOf>(<getClass>(Q|kotlin/Double|)))))) @R|Second|(value = <implicitArrayOf>(<implicitArrayOf>(String()), <implicitArrayOf>(R|/First.First|(<implicitArrayOf>())))) public final fun foo(): R|kotlin/Unit| {
@R|kotlin/Deprecated|(message = String(Use ...), replaceWith = R|kotlin/ReplaceWith.ReplaceWith|(String(bar), vararg(*<implicitArrayOf>(String(my.package.bar))))) @R|Third|(first = R|/First.First|(<implicitArrayOf>(<getClass>(Q|kotlin/String|))), second = R|/Second.Second|(<implicitArrayOf>(R|/First.First|(<implicitArrayOf>(<getClass>(Q|kotlin/Int|))), R|/First.First|(<implicitArrayOf>(<getClass>(Q|kotlin/Double|)))))) @R|Second|(value = <implicitArrayOf>(<implicitArrayOf>(String()), <implicitArrayOf>(R|/First.First|(<implicitArrayOf>())))) public final fun foo(): R|kotlin/Unit| {
}
public final annotation class First : R|kotlin/Annotation| {
public constructor(value: R|kotlin/Array<kotlin/reflect/KClass<*>>|): R|First| {
@@ -14,7 +14,7 @@ FILE: FieldAnnotationWithClasses.kt
super<R|kotlin/Any|>()
}
field:@FIELD:R|Ann|(allowedTypes = vararg(allowedTypes = <implicitArrayOf>(<getClass>(Q|Some|), <getClass>(Q|Other|)))) public final val x: R|kotlin/Int| = Int(42)
field:@FIELD:R|Ann|(allowedTypes = vararg(*<implicitArrayOf>(<getClass>(Q|Some|), <getClass>(Q|Other|)))) public final val x: R|kotlin/Int| = Int(42)
public get(): R|kotlin/Int|
}
@@ -1,5 +1,5 @@
FILE: NamedParameterInConcurrentMap.kt
public final fun main(): R|kotlin/Unit| {
lval map: R|java/util/concurrent/ConcurrentHashMap<kotlin/String, kotlin/String>| = R|java/util/concurrent/ConcurrentHashMap.ConcurrentHashMap|<R|kotlin/String|, R|kotlin/String|>()
R|<local>/map|.R|SubstitutionOverride<java/util/concurrent/ConcurrentHashMap.put: R|@EnhancedNullability kotlin/String?|>|(key = String(key), value = String(value))
R|<local>/map|.R|SubstitutionOverride<java/util/concurrent/ConcurrentHashMap.put: R|@EnhancedNullability kotlin/String?|>|(String(key), String(value))
}
@@ -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)
}
}
@@ -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
}
@@ -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)
@@ -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
}
}
@@ -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)
}
}
@@ -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
@@ -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)
@@ -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<Unit, Any?>() {
}
override fun visitArgumentList(argumentList: FirArgumentList, data: Any?) {
require(argumentList is FirResolvedArgumentList)
require(argumentList is FirResolvedArgumentList || argumentList is FirEmptyArgumentList)
argumentList.acceptChildren(this, null)
}
@@ -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<FirExpression> 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<FirExpression> get() = (argumentList as? FirResolvedArgumentList)?.originalArgumentList?.arguments ?: argumentList.arguments
val argumentCount get() = arguments.size
fun replaceWithVariableAccess(): CallInfo =
@@ -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<Nothing?>() {
private fun FirCall.transformArgumentList(expectedArgumentsTypeMapping: ExpectedArgumentType.ArgumentsMap?) {
val mapping = (argumentList as? FirResolvedArgumentList)?.mapping
class ArgumentTransformer : FirTransformer<Nothing?>() {
override fun <E : FirElement> 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())
@@ -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
@@ -24,6 +24,8 @@ abstract class FirSpreadArgumentExpression : FirWrappedArgumentExpression() {
abstract override val annotations: List<FirAnnotation>
abstract override val expression: FirExpression
abstract override val isSpread: Boolean
abstract val isNamed: Boolean
abstract val isFakeSpread: Boolean
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitSpreadArgumentExpression(this, data)
@@ -26,12 +26,16 @@ class FirSpreadArgumentExpressionBuilder : FirAnnotationContainerBuilder, FirExp
override var source: KtSourceElement? = null
override val annotations: MutableList<FirAnnotation> = 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,
)
}
@@ -26,6 +26,8 @@ internal class FirSpreadArgumentExpressionImpl(
override val source: KtSourceElement?,
override var annotations: MutableOrEmptyList<FirAnnotation>,
override var expression: FirExpression,
override val isNamed: Boolean,
override val isFakeSpread: Boolean,
) : FirSpreadArgumentExpression() {
@OptIn(UnresolvedExpressionTypeAccess::class)
override val coneTypeOrNull: ConeKotlinType?
@@ -22,18 +22,19 @@ fun buildBinaryArgumentList(left: FirExpression, right: FirExpression): FirArgum
}
fun buildResolvedArgumentList(
mapping: LinkedHashMap<FirExpression, FirValueParameter>,
source: KtSourceElement? = null
): FirResolvedArgumentList =
FirResolvedArgumentListImpl(source, mapping)
original: FirArgumentList?,
mapping: LinkedHashMap<FirExpression, FirValueParameter>
): FirResolvedArgumentList {
return FirResolvedArgumentListImpl(original, mapping)
}
fun buildArgumentListForErrorCall(
original: FirArgumentList,
mapping: Map<FirExpression, FirValueParameter?>
mapping: LinkedHashMap<FirExpression, FirValueParameter>
): FirArgumentList {
return FirResolvedArgumentListForErrorCall(
original.source,
original.arguments.map { key -> key to mapping[key] }.toMap(LinkedHashMap())
original,
original.arguments.associateWithTo(LinkedHashMap()) { key -> mapping[key] },
)
}
@@ -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<FirExpression, FirValueParameter>
final override val source: KtSourceElement?
get() = originalArgumentList?.source
override val arguments: List<FirExpression>
get() = mapping.keys.toList()
@@ -38,10 +46,9 @@ abstract class FirResolvedArgumentList : FirAbstractArgumentList() {
internal class FirResolvedArgumentListImpl(
override val source: KtSourceElement?,
mapping: LinkedHashMap<FirExpression, FirValueParameter>
override val originalArgumentList: FirArgumentList?,
mapping: LinkedHashMap<FirExpression, FirValueParameter>,
) : FirResolvedArgumentList() {
override var mapping: LinkedHashMap<FirExpression, FirValueParameter> = mapping
private set
@@ -52,8 +59,8 @@ internal class FirResolvedArgumentListImpl(
}
internal class FirResolvedArgumentListForErrorCall(
override var source: KtSourceElement?,
private var _mapping: LinkedHashMap<FirExpression, FirValueParameter?>
override val originalArgumentList: FirArgumentList?,
private var _mapping: LinkedHashMap<FirExpression, FirValueParameter?>,
) : FirResolvedArgumentList() {
override var mapping: LinkedHashMap<FirExpression, FirValueParameter> = computeMapping()
@@ -377,6 +377,10 @@ object BuilderConfigurator : AbstractFirBuilderConfigurator<FirTreeBuilder>(FirT
default("symbol", "FirAnonymousInitializerSymbol()")
}
builder(spreadArgumentExpression) {
defaultFalse("isNamed", "isFakeSpread")
}
val abstractResolvedQualifierBuilder by builder {
fields from resolvedQualifier
}
@@ -610,6 +610,11 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+booleanField("isSpread")
}
spreadArgumentExpression.configure {
+booleanField("isNamed")
+booleanField("isFakeSpread")
}
namedArgumentExpression.configure {
+name
}
@@ -11,19 +11,19 @@ FILE: targetOnPrimaryCtorParameter.kt
}
}
@R|kotlin/annotation/Target|(allowedTargets = vararg(allowedTargets = <implicitArrayOf>(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY|))) public final annotation class PropertyOnly : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(allowedTargets = vararg(*<implicitArrayOf>(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.PROPERTY|))) public final annotation class PropertyOnly : R|kotlin/Annotation| {
public constructor(): R|PropertyOnly| {
super<R|kotlin/Any|>()
}
}
@R|kotlin/annotation/Target|(allowedTargets = vararg(allowedTargets = <implicitArrayOf>(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.VALUE_PARAMETER|))) public final annotation class ParameterOnly : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(allowedTargets = vararg(*<implicitArrayOf>(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/Any|>()
}
}
@R|kotlin/annotation/Target|(allowedTargets = vararg(allowedTargets = *<implicitArrayOf>(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FIELD|))) public final annotation class FieldOnly : R|kotlin/Annotation| {
@R|kotlin/annotation/Target|(allowedTargets = vararg(*<implicitArrayOf>(Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.FIELD|))) public final annotation class FieldOnly : R|kotlin/Annotation| {
public constructor(): R|FieldOnly| {
super<R|kotlin/Any|>()
}
@@ -37,7 +37,7 @@ FILE: kt57960.kt
}
private final fun buildSchemaNodes1(): R|kotlin/Unit| {
R|/jso|<R|dynamic|>(<L> = jso@fun R|dynamic|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
Q|Foo|.R|/Foo.create2|(toDOM = create2@fun <anonymous>(domNode: R|Baz|): R|kotlin/Any| <inline=NoInline> {
Q|Foo|.R|/Foo.create2|(create2@fun <anonymous>(domNode: R|Baz|): R|kotlin/Any| <inline=NoInline> {
^ R|<local>/domNode|.R|/Baz.text|
}
)
@@ -0,0 +1,23 @@
// FILE: a.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>""<!>)
// FILE: b.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"a..b"<!>)
// FILE: c.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"a."<!>)
// FILE: d.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>".a"<!>)
// FILE: e.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"%^&"<!>)
// FILE: f.kt
@file:JsQualifier("a.bc.d23._$")
// FILE: g.kt
typealias JsQ = JsQualifier
// FILE: h.kt
@file:JsQ(value = <!WRONG_JS_QUALIFIER!>"%^&"<!>)
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FILE: a.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>""<!>)
@@ -0,0 +1,23 @@
// FILE: a.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>""<!>)
// FILE: b.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"a..b"<!>)
// FILE: c.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"a."<!>)
// FILE: d.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>".a"<!>)
// FILE: e.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>"%^&"<!>)
// FILE: f.kt
@file:JsQualifier("a.bc.d23._$")
// FILE: g.kt
typealias JsQ = JsQualifier
// FILE: h.kt
@file:JsQ(value = <!WRONG_JS_QUALIFIER!>"%^&"<!>)
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FILE: a.kt
@file:JsQualifier(<!WRONG_JS_QUALIFIER!>""<!>)
@@ -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
@@ -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 <anonymous>(): R|kotlin/Unit| <inline=NoInline> {
R|p3/Foo|(Foo@fun <anonymous>(): R|kotlin/Unit| <inline=NoInline> {
^@Foo Unit
}
)
@@ -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|<local>/onClick|, trailing = R|<local>/onClick|?.{ $subj$.R|kotlin/let|<R|() -> kotlin/Unit|, R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0<kotlin/Unit>?|>(<L> = let@fun <anonymous>(it: R|() -> kotlin/Unit|): R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0<kotlin/Unit>?| <inline=Inline, kind=EXACTLY_ONCE> {
R|/RMenuItem|(R|<local>/onClick|, R|<local>/onClick|?.{ $subj$.R|kotlin/let|<R|() -> kotlin/Unit|, R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0<kotlin/Unit>?|>(<L> = let@fun <anonymous>(it: R|() -> kotlin/Unit|): R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0<kotlin/Unit>?| <inline=Inline, kind=EXACTLY_ONCE> {
^ let@fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
^@let Unit
}
@@ -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<FirConstructorSymbol>() ?: return
val jsExportIgnoreAnnotationCall = buildAnnotationCall {
argumentList = buildResolvedArgumentList(linkedMapOf())
argumentList = FirEmptyArgumentList
annotationTypeRef = buildResolvedTypeRef {
type = jsExportIgnoreAnnotation.defaultType()
}