FIR: introduce & resolve spread named arguments #KT-31575 Fixed
This commit is contained in:
@@ -1212,8 +1212,16 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
|
||||
is FirNamedArgumentExpression -> {
|
||||
simpleName(expression.name)
|
||||
+" = "
|
||||
if (expression.isSpread) {
|
||||
+"*"
|
||||
}
|
||||
generate(expression.expression)
|
||||
}
|
||||
is FirSpreadArgumentExpression -> {
|
||||
+"*"
|
||||
generate(expression.expression)
|
||||
|
||||
}
|
||||
is FirLambdaArgumentExpression -> {
|
||||
keyword("lambda")
|
||||
+" = "
|
||||
|
||||
+1
-1
@@ -288,7 +288,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
result += FirAnnotationCallImpl(session, null, null, symbol.toDefaultResolvedTypeRef(annotationClassId)).apply {
|
||||
for ((name, expression) in argumentMap) {
|
||||
arguments += FirNamedArgumentExpressionImpl(
|
||||
this@KotlinDeserializedJvmSymbolsProvider.session, null, name, expression
|
||||
this@KotlinDeserializedJvmSymbolsProvider.session, null, name, false, expression
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,12 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
|
||||
{ expression }.toFirExpression("Argument is absent")
|
||||
}
|
||||
}
|
||||
return if (name != null) FirNamedArgumentExpressionImpl(session, expression, name, firExpression) else firExpression
|
||||
val isSpread = getSpreadElement() != null
|
||||
return when {
|
||||
name != null -> FirNamedArgumentExpressionImpl(session, expression, name, isSpread, firExpression)
|
||||
isSpread -> FirSpreadArgumentExpressionImpl(session, expression, firExpression)
|
||||
else -> firExpression
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtPropertyAccessor?.toFirPropertyAccessor(
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ abstract class AbstractAnnotationDeserializer(
|
||||
val parameter = parameterByName[name] ?: return@mapNotNull null
|
||||
val value = resolveValue(parameter.returnTypeRef, it.value, nameResolver) ?: return@mapNotNull null
|
||||
FirNamedArgumentExpressionImpl(
|
||||
session, null, name, value
|
||||
session, null, name, false, value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,18 +54,7 @@ fun resolveArgumentExpression(
|
||||
is FirCallableReferenceAccess -> Unit
|
||||
// TODO:!
|
||||
//TODO: Collection literal
|
||||
is FirLambdaArgumentExpression -> resolveArgumentExpression(
|
||||
csBuilder,
|
||||
argument.expression,
|
||||
expectedType,
|
||||
expectedTypeRef,
|
||||
sink,
|
||||
isReceiver,
|
||||
isSafeCall,
|
||||
acceptLambdaAtoms,
|
||||
typeProvider
|
||||
)
|
||||
is FirNamedArgumentExpression -> resolveArgumentExpression(
|
||||
is FirWrappedArgumentExpression -> resolveArgumentExpression(
|
||||
csBuilder,
|
||||
argument.expression,
|
||||
expectedType,
|
||||
@@ -180,7 +169,7 @@ internal fun FirExpression.getExpectedType(
|
||||
// if (this.isSpread || this.isArrayAssignedAsNamedArgumentInAnnotation(parameter, languageVersionSettings)) {
|
||||
// parameter.type.unwrap()
|
||||
// } else {
|
||||
if (parameter.isVararg) {
|
||||
if (parameter.isVararg && (this !is FirWrappedArgumentExpression || !isSpread)) {
|
||||
parameter.returnTypeRef.coneTypeUnsafe<ConeKotlinType>().varargElementType(session)
|
||||
} else {
|
||||
parameter.returnTypeRef.coneTypeUnsafe()
|
||||
|
||||
+8
-13
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
@@ -13,8 +12,6 @@ import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
|
||||
class FirCallArgumentsProcessor(
|
||||
private val function: FirFunction,
|
||||
@@ -25,7 +22,7 @@ class FirCallArgumentsProcessor(
|
||||
fun process(): Result {
|
||||
var currentState: State = State.PositionalOnly(function.valueParameters)
|
||||
for (argument in arguments) {
|
||||
if (argument is FirWrappedArgumentExpression) {
|
||||
if (argument is FirNamedArgumentExpression || argument is FirLambdaArgumentExpression) {
|
||||
currentState = State.PositionalThenNamed(
|
||||
function.valueParameters,
|
||||
currentState.argumentMap,
|
||||
@@ -65,21 +62,19 @@ class FirCallArgumentsProcessor(
|
||||
|
||||
val currentParameter get() = valueParameters.getOrNull(currentParameterIndex)
|
||||
|
||||
fun nextParameter() {
|
||||
val currentParameter = currentParameter ?: return
|
||||
if (currentParameter.isVararg) return
|
||||
usedParameters += currentParameter
|
||||
currentParameterIndex++
|
||||
}
|
||||
|
||||
override fun processArgument(argument: FirExpression): MappingStatus {
|
||||
require(argument !is FirNamedArgumentExpression) {
|
||||
"Positional-only argument processor state should not receiver ${argument.render()}"
|
||||
"Positional-only argument processor state should not receive ${argument.render()}"
|
||||
}
|
||||
|
||||
val currentParameter = currentParameter ?: return MappingStatus.ERROR
|
||||
argumentMap[argument] = currentParameter
|
||||
nextParameter()
|
||||
if (!currentParameter.isVararg ||
|
||||
argument is FirWrappedArgumentExpression && argument.isSpread
|
||||
) {
|
||||
usedParameters += currentParameter
|
||||
currentParameterIndex++
|
||||
}
|
||||
|
||||
return MappingStatus.SUCCESS
|
||||
}
|
||||
|
||||
+3
-10
@@ -1166,17 +1166,10 @@ private object ReplaceInArguments : FirTransformer<Map<FirElement, FirElement>>(
|
||||
return (functionCall.transformChildren(this, data) as FirStatement).compose()
|
||||
}
|
||||
|
||||
override fun transformNamedArgumentExpression(
|
||||
namedArgumentExpression: FirNamedArgumentExpression,
|
||||
override fun transformWrappedArgumentExpression(
|
||||
wrappedArgumentExpression: FirWrappedArgumentExpression,
|
||||
data: Map<FirElement, FirElement>
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return (namedArgumentExpression.transformChildren(this, data) as FirStatement).compose()
|
||||
}
|
||||
|
||||
override fun transformLambdaArgumentExpression(
|
||||
lambdaArgumentExpression: FirLambdaArgumentExpression,
|
||||
data: Map<FirElement, FirElement>
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return (lambdaArgumentExpression.transformChildren(this, data) as FirStatement).compose()
|
||||
return (wrappedArgumentExpression.transformChildren(this, data) as FirStatement).compose()
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ fun test() {
|
||||
foo(1)
|
||||
foo(1, "")
|
||||
foo(1, "my", "yours")
|
||||
foo(1, *arrayOf("my", "yours"))
|
||||
|
||||
foo("")
|
||||
foo(1, 2)
|
||||
|
||||
@@ -7,9 +7,10 @@ FILE: vararg.kt
|
||||
R|/foo|(Int(1))
|
||||
R|/foo|(Int(1), String())
|
||||
R|/foo|(Int(1), String(my), String(yours))
|
||||
R|/foo|(Int(1), *R|kotlin/arrayOf|<R|kotlin/String|>(String(my), String(yours)))
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(String())
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(Int(1), Int(2))
|
||||
R|/bar|(Int(1), z = Boolean(true), y = R|kotlin/arrayOf|<R|TypeVariable(T)|>(String(my), String(yours)))
|
||||
R|/bar|(Int(1), z = Boolean(true), y = *R|kotlin/arrayOf|<R|kotlin/String|>(String(my), String(yours)))
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/bar]>#(Int(0), z = Boolean(false), y = String(), y = String(other))
|
||||
<Inapplicable(PARAMETER_MAPPING_ERROR): [/bar]>#(Int(0), String(), Boolean(true))
|
||||
}
|
||||
|
||||
@@ -627,9 +627,19 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
|
||||
override fun visitNamedArgumentExpression(namedArgumentExpression: FirNamedArgumentExpression) {
|
||||
print(namedArgumentExpression.name)
|
||||
print(" = ")
|
||||
if (namedArgumentExpression.isSpread) {
|
||||
print("*")
|
||||
}
|
||||
namedArgumentExpression.expression.accept(this)
|
||||
}
|
||||
|
||||
override fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression) {
|
||||
if (spreadArgumentExpression.isSpread) {
|
||||
print("*")
|
||||
}
|
||||
spreadArgumentExpression.expression.accept(this)
|
||||
}
|
||||
|
||||
override fun visitLambdaArgumentExpression(lambdaArgumentExpression: FirLambdaArgumentExpression) {
|
||||
print("<L> = ")
|
||||
lambdaArgumentExpression.expression.accept(this)
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
interface FirSpreadArgumentExpression : FirWrappedArgumentExpression {
|
||||
override val isSpread: Boolean
|
||||
get() = true
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||
visitor.visitSpreadArgumentExpression(this, data)
|
||||
}
|
||||
+3
@@ -11,6 +11,9 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
interface FirWrappedArgumentExpression : FirExpression {
|
||||
val expression: FirExpression
|
||||
|
||||
val isSpread: Boolean
|
||||
get() = false
|
||||
|
||||
override val typeRef: FirTypeRef
|
||||
get() = expression.typeRef
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,6 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirLambdaArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.transformSingle
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
@@ -20,6 +19,7 @@ class FirNamedArgumentExpressionImpl(
|
||||
session: FirSession,
|
||||
psi: PsiElement?,
|
||||
override val name: Name,
|
||||
override val isSpread: Boolean,
|
||||
override var expression: FirExpression
|
||||
) : FirNamedArgumentExpression, FirAbstractExpression(session, psi) {
|
||||
override var typeRef: FirTypeRef
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSpreadArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.transformSingle
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
|
||||
class FirSpreadArgumentExpressionImpl(
|
||||
session: FirSession,
|
||||
psi: PsiElement?,
|
||||
override var expression: FirExpression
|
||||
) : FirSpreadArgumentExpression, FirAbstractExpression(session, psi) {
|
||||
override var typeRef: FirTypeRef
|
||||
get() = super<FirSpreadArgumentExpression>.typeRef
|
||||
set(_) {}
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
|
||||
expression = expression.transformSingle(transformer, data)
|
||||
return super<FirAbstractExpression>.transformChildren(transformer, data)
|
||||
}
|
||||
}
|
||||
+8
@@ -300,6 +300,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformWrappedArgumentExpression(namedArgumentExpression, data)
|
||||
}
|
||||
|
||||
open fun transformSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression, data: D): CompositeTransformResult<FirStatement> {
|
||||
return transformWrappedArgumentExpression(spreadArgumentExpression, data)
|
||||
}
|
||||
|
||||
open fun transformLoop(loop: FirLoop, data: D): CompositeTransformResult<FirStatement> {
|
||||
return transformStatement(loop, data)
|
||||
}
|
||||
@@ -680,6 +684,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
|
||||
return transformReturnExpression(returnExpression, data)
|
||||
}
|
||||
|
||||
final override fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformSpreadArgumentExpression(spreadArgumentExpression, data)
|
||||
}
|
||||
|
||||
final override fun visitStarProjection(starProjection: FirStarProjection, data: D): CompositeTransformResult<FirElement> {
|
||||
return transformStarProjection(starProjection, data)
|
||||
}
|
||||
|
||||
@@ -300,6 +300,10 @@ abstract class FirVisitor<out R, in D> {
|
||||
return visitWrappedArgumentExpression(namedArgumentExpression, data)
|
||||
}
|
||||
|
||||
open fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression, data: D): R {
|
||||
return visitWrappedArgumentExpression(spreadArgumentExpression, data)
|
||||
}
|
||||
|
||||
open fun visitLoop(loop: FirLoop, data: D): R {
|
||||
return visitStatement(loop, data)
|
||||
}
|
||||
|
||||
+8
@@ -300,6 +300,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitWrappedArgumentExpression(namedArgumentExpression, null)
|
||||
}
|
||||
|
||||
open fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression) {
|
||||
visitWrappedArgumentExpression(spreadArgumentExpression, null)
|
||||
}
|
||||
|
||||
open fun visitLoop(loop: FirLoop) {
|
||||
visitStatement(loop, null)
|
||||
}
|
||||
@@ -680,6 +684,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitReturnExpression(returnExpression)
|
||||
}
|
||||
|
||||
final override fun visitSpreadArgumentExpression(spreadArgumentExpression: FirSpreadArgumentExpression, data: Nothing?) {
|
||||
visitSpreadArgumentExpression(spreadArgumentExpression)
|
||||
}
|
||||
|
||||
final override fun visitStarProjection(starProjection: FirStarProjection, data: Nothing?) {
|
||||
visitStarProjection(starProjection)
|
||||
}
|
||||
|
||||
+5
-6
@@ -21,16 +21,15 @@ FILE fqName:<root> fileName:/vararg.kt
|
||||
RETURN type=kotlin.Nothing from='public final fun <get-test2> (): kotlin.Array<kotlin.String> declared in <root>'
|
||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test2 type:kotlin.Array<kotlin.String> visibility:public [final,static] ' type=kotlin.Array<kotlin.String> origin=null
|
||||
PROPERTY name:test3 visibility:public modality:FINAL [val]
|
||||
FIELD PROPERTY_BACKING_FIELD name:test3 type:kotlin.Array<kotlin.String> visibility:public [final,static]
|
||||
FIELD PROPERTY_BACKING_FIELD name:test3 type:IrErrorType visibility:public [final,static]
|
||||
EXPRESSION_BODY
|
||||
ERROR_CALL 'Cannot bind 4 arguments to arrayOf call with 1 parameters' type=kotlin.Array<kotlin.String>
|
||||
ERROR_CALL 'Unresolved reference: <Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/arrayOf]>#' type=IrErrorType
|
||||
CONST String type=kotlin.String value="0"
|
||||
CALL 'public final fun <get-test2> (): kotlin.Array<kotlin.String> declared in <root>' type=kotlin.Array<kotlin.String> origin=null
|
||||
CALL 'public final fun <get-test1> (): kotlin.Array<kotlin.String> declared in <root>' type=kotlin.Array<kotlin.String> origin=null
|
||||
CONST String type=kotlin.String value="4"
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test3> visibility:public modality:FINAL <> () returnType:kotlin.Array<kotlin.String>
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-test3> visibility:public modality:FINAL <> () returnType:IrErrorType
|
||||
correspondingProperty: PROPERTY name:test3 visibility:public modality:FINAL [val]
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun <get-test3> (): kotlin.Array<kotlin.String> declared in <root>'
|
||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test3 type:kotlin.Array<kotlin.String> visibility:public [final,static] ' type=kotlin.Array<kotlin.String> origin=null
|
||||
|
||||
RETURN type=kotlin.Nothing from='public final fun <get-test3> (): IrErrorType declared in <root>'
|
||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test3 type:IrErrorType visibility:public [final,static] ' type=IrErrorType origin=null
|
||||
|
||||
Reference in New Issue
Block a user