[FIR] Introduce FirResolvedArgumentList with argument-parameter mapping

#KT-36345 Fixed
This commit is contained in:
Mikhail Glukhikh
2020-03-11 13:46:09 +03:00
parent 6b0a3aa176
commit 3d17ce05b5
27 changed files with 49 additions and 37 deletions
@@ -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)
@@ -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
View File
@@ -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,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun Int.foo(a: Int = 1,
b: Int = 2,
c: Int = 3,
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun Int.foo(a: Int = 1, b: String): Int {
return a
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A {
fun Int.foo(a: Int = 1,
b: Int = 2,
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A() {
fun foo(a: Int = 1,
b: Int = 2,
@@ -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,
@@ -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,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: destructuringAssignmentWithNullabilityAssertionOnExtensionReceiver_lv12.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: test.kt
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: test.kt
// WITH_RUNTIME
@@ -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: 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)
}
@@ -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