[FIR] Introduce FirResolvedArgumentList with argument-parameter mapping
#KT-36345 Fixed
This commit is contained in:
@@ -542,6 +542,20 @@ class Fir2IrVisitor(
|
||||
val argumentsCount = call.arguments.size
|
||||
if (argumentsCount <= valueArgumentsCount) {
|
||||
apply {
|
||||
val argumentMapping = call.argumentMapping
|
||||
if (argumentMapping != null && argumentMapping.isNotEmpty()) {
|
||||
require(call is FirFunctionCall)
|
||||
val function =
|
||||
((call.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir
|
||||
val valueParameters = function?.valueParameters
|
||||
if (valueParameters != null) {
|
||||
for ((argument, parameter) in argumentMapping) {
|
||||
val argumentExpression = argument.toIrExpression()
|
||||
putValueArgument(valueParameters.indexOf(parameter), argumentExpression)
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
for ((index, argument) in call.arguments.withIndex()) {
|
||||
val argumentExpression = argument.toIrExpression()
|
||||
putValueArgument(index, argumentExpression)
|
||||
|
||||
+11
-12
@@ -181,15 +181,16 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
else -> {
|
||||
resultType = typeRef.substituteTypeRef(subCandidate)
|
||||
val argumentMapping = subCandidate.argumentMapping
|
||||
val vararg = argumentMapping?.values?.firstOrNull { it.isVararg }
|
||||
val varargParameter = argumentMapping?.values?.firstOrNull { it.isVararg }
|
||||
result.argumentList.transformArguments(this, subCandidate.createArgumentsMapping())
|
||||
with(result.argumentList) call@{
|
||||
if (vararg != null) {
|
||||
if (varargParameter != null) {
|
||||
// Create a FirVarargArgumentExpression for the vararg arguments
|
||||
val varargParameterTypeRef = vararg.returnTypeRef
|
||||
val varargParameterTypeRef = varargParameter.returnTypeRef
|
||||
val resolvedArrayType = varargParameterTypeRef.substitute(subCandidate)
|
||||
val resolvedElementType = resolvedArrayType.arrayElementType(session)
|
||||
var firstIndex = this@call.arguments.size
|
||||
val newArgumentMapping = mutableMapOf<FirExpression, FirValueParameter>()
|
||||
val varargArgument = buildVarargArgumentsExpression {
|
||||
varargElementType = varargParameterTypeRef.withReplacedConeType(resolvedElementType)
|
||||
this.typeRef = varargParameterTypeRef.withReplacedConeType(resolvedArrayType)
|
||||
@@ -198,20 +199,18 @@ class FirCallCompletionResultsWriterTransformer(
|
||||
if (valueParameter.isVararg) {
|
||||
firstIndex = min(firstIndex, i)
|
||||
arguments += arg
|
||||
} else {
|
||||
newArgumentMapping[arg] = valueParameter
|
||||
}
|
||||
}
|
||||
}
|
||||
result.replaceArgumentList(
|
||||
buildArgumentList {
|
||||
arguments += result.arguments
|
||||
for (arg in varargArgument.arguments) {
|
||||
arguments.remove(arg)
|
||||
}
|
||||
arguments.add(firstIndex, varargArgument)
|
||||
}
|
||||
)
|
||||
newArgumentMapping[varargArgument] = varargParameter
|
||||
subCandidate.argumentMapping = newArgumentMapping
|
||||
}
|
||||
}
|
||||
subCandidate.argumentMapping?.let {
|
||||
result.replaceArgumentList(FirResolvedArgumentList(it))
|
||||
}
|
||||
result.transformExplicitReceiver(integerApproximator, null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
@@ -48,4 +49,17 @@ class FirArraySetArgumentList(
|
||||
) : FirAbstractArgumentList() {
|
||||
override val arguments: List<FirExpression>
|
||||
get() = indexes + rValue
|
||||
}
|
||||
|
||||
class FirResolvedArgumentList(
|
||||
val mapping: Map<FirExpression, FirValueParameter>
|
||||
) : FirAbstractArgumentList() {
|
||||
override val arguments: List<FirExpression>
|
||||
get() = mapping.keys.toList()
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
for (argument in mapping.keys) {
|
||||
argument.accept(visitor, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression
|
||||
@@ -38,6 +39,9 @@ inline val FirCall.arguments: List<FirExpression> get() = argumentList.arguments
|
||||
|
||||
inline val FirCall.argument: FirExpression get() = argumentList.arguments.first()
|
||||
|
||||
inline val FirCall.argumentMapping: Map<FirExpression, FirValueParameter>?
|
||||
get() = (argumentList as? FirResolvedArgumentList)?.mapping
|
||||
|
||||
fun FirExpression.toResolvedCallableReference(): FirResolvedNamedReference? {
|
||||
return (this as? FirQualifiedAccess)?.calleeReference as? FirResolvedNamedReference
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// KT-9277 Unexpected NullPointerException in an invocaton with named arguments
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var res = "";
|
||||
var call = test(a = {res += "K"; "K"}(), b = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun box(): String {
|
||||
var res = "";
|
||||
var call = Z("Z").test(a = {res += "K"; "K"}(), b = {res+="O"; "O"}(), c = {res += "L"; "L"})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class A(val a: Int = 0, val b: String = "a")
|
||||
|
||||
fun box(): String {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun Int.foo(a: Int = 1,
|
||||
b: Int = 2,
|
||||
c: Int = 3,
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun Int.foo(a: Int = 1, b: String): Int {
|
||||
return a
|
||||
}
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class A {
|
||||
fun Int.foo(a: Int = 1,
|
||||
b: Int = 2,
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
class A() {
|
||||
fun foo(a: Int = 1,
|
||||
b: Int = 2,
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(a: String = "Companion", b: Int = 1, c: Long = 2): String {
|
||||
return "$a $b $c"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(a: Int = 1,
|
||||
b: Int = 2,
|
||||
c: Int = 3,
|
||||
|
||||
Vendored
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +ProperComputationOrderOfTailrecDefaultParameters
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// DONT_RUN_GENERATED_CODE: JS
|
||||
|
||||
var counter = 0
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun <T> T.toPrefixedString(prefix: String = "", suffix: String="") = prefix + this.toString() + suffix
|
||||
|
||||
fun box() : String {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: destructuringAssignmentWithNullabilityAssertionOnExtensionReceiver_lv12.kt
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: test.kt
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: test.kt
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: equalsNull.kt
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
val global = "OK"
|
||||
class A {
|
||||
val prop: String
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun foo(a: Int, vararg b: Int, f: (IntArray) -> String): String {
|
||||
return "test" + a + " " + f(b)
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ FILE fqName:<root> fileName:/useNextParamInLambda.kt
|
||||
RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
|
||||
CALL 'public final fun plus (other: kotlin.Any?): kotlin.String [operator] declared in kotlin.String' type=kotlin.String origin=PLUS
|
||||
$this: CALL 'public final fun f (f1: kotlin.Function0<kotlin.String>, f2: kotlin.Function0<kotlin.String>): kotlin.String declared in <root>' type=kotlin.String origin=null
|
||||
f1: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=LAMBDA
|
||||
f2: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String declared in <root>.box'
|
||||
|
||||
@@ -25,8 +25,8 @@ FILE fqName:<root> fileName:/callWithReorderedArguments.kt
|
||||
a: CALL 'public final fun noReorder1 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
b: CALL 'public final fun noReorder2 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
CALL 'public final fun foo (a: kotlin.Int, b: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||
a: CALL 'public final fun reordered1 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
b: CALL 'public final fun reordered2 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
a: CALL 'public final fun reordered2 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
b: CALL 'public final fun reordered1 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
CALL 'public final fun foo (a: kotlin.Int, b: kotlin.Int): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
|
||||
a: CONST Int type=kotlin.Int value=1
|
||||
b: CALL 'public final fun reordered2 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
a: CALL 'public final fun reordered2 (): kotlin.Int declared in <root>' type=kotlin.Int origin=null
|
||||
b: CONST Int type=kotlin.Int value=1
|
||||
|
||||
Reference in New Issue
Block a user