[FIR2IR] Re-use applyCallArguments for IrDelegatedConstructorCall
This commit is contained in:
@@ -62,10 +62,10 @@ class Fir2IrVisitor(
|
|||||||
|
|
||||||
private val conversionScope = Fir2IrConversionScope()
|
private val conversionScope = Fir2IrConversionScope()
|
||||||
|
|
||||||
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope, fakeOverrideMode)
|
|
||||||
|
|
||||||
private val callGenerator = CallAndReferenceGenerator(components, this, conversionScope)
|
private val callGenerator = CallAndReferenceGenerator(components, this, conversionScope)
|
||||||
|
|
||||||
|
private val memberGenerator = ClassMemberGenerator(components, this, conversionScope, callGenerator, fakeOverrideMode)
|
||||||
|
|
||||||
private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
|
private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() }
|
||||||
|
|
||||||
private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration)
|
private fun <T : IrDeclaration> applyParentFromStackTo(declaration: T): T = conversionScope.applyParentFromStackTo(declaration)
|
||||||
|
|||||||
+53
-54
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrNull
|
|||||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||||
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
||||||
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
|
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
|
|
||||||
internal class CallAndReferenceGenerator(
|
internal class CallAndReferenceGenerator(
|
||||||
private val components: Fir2IrComponents,
|
private val components: Fir2IrComponents,
|
||||||
@@ -292,7 +293,7 @@ internal class CallAndReferenceGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrExpression.applyCallArguments(call: FirCall?): IrExpression {
|
internal fun IrExpression.applyCallArguments(call: FirCall?): IrExpression {
|
||||||
if (call == null) return this
|
if (call == null) return this
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is IrCallWithIndexedArgumentsBase -> {
|
is IrCallWithIndexedArgumentsBase -> {
|
||||||
@@ -301,15 +302,16 @@ internal class CallAndReferenceGenerator(
|
|||||||
apply {
|
apply {
|
||||||
val argumentMapping = call.argumentMapping
|
val argumentMapping = call.argumentMapping
|
||||||
if (argumentMapping != null && argumentMapping.isNotEmpty()) {
|
if (argumentMapping != null && argumentMapping.isNotEmpty()) {
|
||||||
require(call is FirFunctionCall)
|
val calleeReference = when (call) {
|
||||||
val function =
|
is FirFunctionCall -> call.calleeReference
|
||||||
((call.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir
|
is FirDelegatedConstructorCall -> call.calleeReference
|
||||||
|
else -> throw IllegalArgumentException("Unsupported call: ${call.render()}")
|
||||||
|
} as? FirResolvedNamedReference
|
||||||
|
val function = (calleeReference?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir
|
||||||
val valueParameters = function?.valueParameters
|
val valueParameters = function?.valueParameters
|
||||||
|
|
||||||
if (valueParameters != null) {
|
if (valueParameters != null) {
|
||||||
return applyArgumentsWithReordering(
|
return applyArgumentsWithReorderingIfNeeded(argumentMapping, valueParameters)
|
||||||
argumentMapping, valueParameters, visitor, conversionScope, declarationStorage
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ((index, argument) in call.arguments.withIndex()) {
|
for ((index, argument) in call.arguments.withIndex()) {
|
||||||
@@ -338,6 +340,50 @@ internal class CallAndReferenceGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrCallWithIndexedArgumentsBase.applyArgumentsWithReorderingIfNeeded(
|
||||||
|
argumentMapping: Map<FirExpression, FirValueParameter>,
|
||||||
|
valueParameters: List<FirValueParameter>,
|
||||||
|
): IrExpressionBase {
|
||||||
|
if (needArgumentReordering(argumentMapping.values, valueParameters)) {
|
||||||
|
return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply {
|
||||||
|
for ((argument, parameter) in argumentMapping) {
|
||||||
|
val parameterIndex = valueParameters.indexOf(parameter)
|
||||||
|
val irArgument = visitor.convertToIrExpression(argument)
|
||||||
|
if (irArgument.hasNoSideEffects()) {
|
||||||
|
putValueArgument(parameterIndex, irArgument)
|
||||||
|
} else {
|
||||||
|
val tempVar = declarationStorage.declareTemporaryVariable(irArgument, parameter.name.asString()).apply {
|
||||||
|
parent = conversionScope.parentFromStack()
|
||||||
|
}
|
||||||
|
this.statements.add(tempVar)
|
||||||
|
putValueArgument(parameterIndex, IrGetValueImpl(startOffset, endOffset, tempVar.symbol, null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.statements.add(this@applyArgumentsWithReorderingIfNeeded)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for ((argument, parameter) in argumentMapping) {
|
||||||
|
val argumentExpression = visitor.convertToIrExpression(argument)
|
||||||
|
putValueArgument(valueParameters.indexOf(parameter), argumentExpression)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun needArgumentReordering(
|
||||||
|
parametersInActualOrder: Collection<FirValueParameter>,
|
||||||
|
valueParameters: List<FirValueParameter>
|
||||||
|
): Boolean {
|
||||||
|
var lastValueParameterIndex = -1
|
||||||
|
for (parameter in parametersInActualOrder) {
|
||||||
|
val index = valueParameters.indexOf(parameter)
|
||||||
|
if (index < lastValueParameterIndex) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
lastValueParameterIndex = index
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrExpression.applyTypeArguments(access: FirQualifiedAccess): IrExpression {
|
private fun IrExpression.applyTypeArguments(access: FirQualifiedAccess): IrExpression {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
@@ -469,50 +515,3 @@ internal class CallAndReferenceGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun IrCallWithIndexedArgumentsBase.applyArgumentsWithReordering(
|
|
||||||
argumentMapping: Map<FirExpression, FirValueParameter>,
|
|
||||||
valueParameters: List<FirValueParameter>,
|
|
||||||
visitor: Fir2IrVisitor,
|
|
||||||
conversionScope: Fir2IrConversionScope,
|
|
||||||
declarationStorage: Fir2IrDeclarationStorage
|
|
||||||
): IrExpressionBase {
|
|
||||||
if (needArgumentReordering(argumentMapping.values, valueParameters)) {
|
|
||||||
return IrBlockImpl(startOffset, endOffset, type, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL).apply {
|
|
||||||
for ((argument, parameter) in argumentMapping) {
|
|
||||||
val parameterIndex = valueParameters.indexOf(parameter)
|
|
||||||
val irArgument = visitor.convertToIrExpression(argument)
|
|
||||||
if (irArgument.hasNoSideEffects()) {
|
|
||||||
putValueArgument(parameterIndex, irArgument)
|
|
||||||
} else {
|
|
||||||
val tempVar = declarationStorage.declareTemporaryVariable(irArgument, parameter.name.asString()).apply {
|
|
||||||
parent = conversionScope.parentFromStack()
|
|
||||||
}
|
|
||||||
this.statements.add(tempVar)
|
|
||||||
putValueArgument(parameterIndex, IrGetValueImpl(startOffset, endOffset, tempVar.symbol, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.statements.add(this@applyArgumentsWithReordering)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for ((argument, parameter) in argumentMapping) {
|
|
||||||
val argumentExpression = visitor.convertToIrExpression(argument)
|
|
||||||
putValueArgument(valueParameters.indexOf(parameter), argumentExpression)
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun needArgumentReordering(
|
|
||||||
parametersInActualOrder: Collection<FirValueParameter>,
|
|
||||||
valueParameters: List<FirValueParameter>
|
|
||||||
): Boolean {
|
|
||||||
var lastValueParameterIndex = -1
|
|
||||||
for (parameter in parametersInActualOrder) {
|
|
||||||
val index = valueParameters.indexOf(parameter)
|
|
||||||
if (index < lastValueParameterIndex) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
lastValueParameterIndex = index
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|||||||
+5
-18
@@ -12,13 +12,12 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
|
|||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.arguments
|
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
@@ -29,6 +28,7 @@ internal class ClassMemberGenerator(
|
|||||||
private val components: Fir2IrComponents,
|
private val components: Fir2IrComponents,
|
||||||
private val visitor: Fir2IrVisitor,
|
private val visitor: Fir2IrVisitor,
|
||||||
private val conversionScope: Fir2IrConversionScope,
|
private val conversionScope: Fir2IrConversionScope,
|
||||||
|
private val callGenerator: CallAndReferenceGenerator,
|
||||||
fakeOverrideMode: FakeOverrideMode
|
fakeOverrideMode: FakeOverrideMode
|
||||||
) : Fir2IrComponents by components {
|
) : Fir2IrComponents by components {
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ internal class ClassMemberGenerator(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrExpressionBase {
|
private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrExpression {
|
||||||
val constructedIrType = constructedTypeRef.toIrType()
|
val constructedIrType = constructedTypeRef.toIrType()
|
||||||
val constructorSymbol = (this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol
|
val constructorSymbol = (this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol
|
||||||
?: return convertWithOffsets { startOffset, endOffset ->
|
?: return convertWithOffsets { startOffset, endOffset ->
|
||||||
@@ -240,21 +240,8 @@ internal class ClassMemberGenerator(
|
|||||||
irConstructorSymbol
|
irConstructorSymbol
|
||||||
)
|
)
|
||||||
}.let {
|
}.let {
|
||||||
val argumentMapping = mutableMapOf<FirExpression, FirValueParameter>()
|
with(callGenerator) {
|
||||||
val valueParameters = constructorSymbol.fir.valueParameters
|
it.applyCallArguments(this@toIrDelegatingConstructorCall)
|
||||||
for (argument in arguments) {
|
|
||||||
if (argument is FirNamedArgumentExpression) {
|
|
||||||
valueParameters.firstOrNull { it.name == argument.name }?.let { argumentMapping[argument] = it }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (argumentMapping.size == valueParameters.size) {
|
|
||||||
it.applyArgumentsWithReordering(argumentMapping, valueParameters, visitor, conversionScope, declarationStorage)
|
|
||||||
} else {
|
|
||||||
for ((index, argument) in arguments.withIndex()) {
|
|
||||||
val argumentExpression = visitor.convertToIrExpression(argument)
|
|
||||||
it.putValueArgument(index, argumentExpression)
|
|
||||||
}
|
|
||||||
it
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class Foo(val a: Int = 1, val b: String) {
|
enum class Foo(val a: Int = 1, val b: String) {
|
||||||
B(2, "b"),
|
B(2, "b"),
|
||||||
C(b = "b")
|
C(b = "b")
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class Foo(val a: Int = 1, val b: String = "a") {
|
enum class Foo(val a: Int = 1, val b: String = "a") {
|
||||||
A(),
|
A(),
|
||||||
B(2, "b"),
|
B(2, "b"),
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
enum class Foo(val a: Double = 1.0, val b: Double = 1.0) {
|
enum class Foo(val a: Double = 1.0, val b: Double = 1.0) {
|
||||||
A(),
|
A(),
|
||||||
B(2.0, 2.0),
|
B(2.0, 2.0),
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
open class A(val result: String) {
|
open class A(val result: String) {
|
||||||
constructor(x: Int = 11, y: Int = 22, z: Int = 33) : this("$x$y$z")
|
constructor(x: Int = 11, y: Int = 22, z: Int = 33) : this("$x$y$z")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user