[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
@@ -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
}