Kotlin: Extract missing arguments of enum constructor calls

This commit is contained in:
Tamas Vajk
2022-11-02 17:04:39 +01:00
parent b8e1aa67d8
commit 44e70afa85
7 changed files with 67 additions and 16 deletions

View File

@@ -1868,12 +1868,13 @@ open class KotlinFileExtractor(
extractStaticTypeAccessQualifierUnchecked(overriddenCallTarget.parent, id, locId, enclosingCallable, enclosingStmt)
}
extractDefaultsCallArguments(id, overriddenCallTarget, enclosingCallable, enclosingStmt, valueArguments, dispatchReceiver, extensionReceiver)
extractDefaultsCallArguments(id, overriddenCallTarget, locId, enclosingCallable, enclosingStmt, valueArguments, dispatchReceiver, extensionReceiver)
}
private fun extractDefaultsCallArguments(
id: Label<out DbExprparent>,
callTarget: IrFunction,
locId: Label<DbLocation>,
enclosingCallable: Label<out DbCallable>,
enclosingStmt: Label<out DbStmt>,
valueArguments: List<IrExpression?>,
@@ -1900,7 +1901,7 @@ open class KotlinFileExtractor(
IrConstImpl.defaultValueForType(0, 0, getDefaultsMethodLastArgType(callTarget))
)
extractCallValueArguments(id, valueArgsWithDummies + extraArgs, enclosingStmt, enclosingCallable, nextIdx, extractVarargAsArray = true)
extractCallValueArguments(id, valueArgsWithDummies + extraArgs, callTarget, locId, enclosingStmt, enclosingCallable, nextIdx, extractVarargAsArray = true)
}
private fun getFunctionInvokeMethod(typeArgs: List<IrTypeArgument>): IrFunction? {
@@ -2022,7 +2023,7 @@ open class KotlinFileExtractor(
childIdx,
enclosingStmt,
valueArguments.size,
{ argParent, idxOffset -> extractCallValueArguments(argParent, valueArguments, enclosingStmt, enclosingCallable, idxOffset) },
{ argParent, idxOffset -> extractCallValueArguments(argParent, valueArguments, syntacticCallTarget, locId, enclosingStmt, enclosingCallable, idxOffset) },
dispatchReceiver?.type,
dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } },
extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } },
@@ -2116,19 +2117,38 @@ open class KotlinFileExtractor(
this is IrEnumEntry
private fun extractCallValueArguments(callId: Label<out DbExprparent>, call: IrFunctionAccessExpression, enclosingStmt: Label<out DbStmt>, enclosingCallable: Label<out DbCallable>, idxOffset: Int) =
extractCallValueArguments(callId, (0 until call.valueArgumentsCount).map { call.getValueArgument(it) }, enclosingStmt, enclosingCallable, idxOffset)
private fun extractCallValueArguments(callId: Label<out DbExprparent>, call: IrFunctionAccessExpression, callTarget: IrFunction, fallbackLocation: Label<DbLocation>, enclosingStmt: Label<out DbStmt>, enclosingCallable: Label<out DbCallable>, idxOffset: Int) =
extractCallValueArguments(callId, (0 until call.valueArgumentsCount).map { call.getValueArgument(it) }, callTarget, fallbackLocation, enclosingStmt, enclosingCallable, idxOffset)
private fun extractCallValueArguments(callId: Label<out DbExprparent>, valueArguments: List<IrExpression?>, enclosingStmt: Label<out DbStmt>, enclosingCallable: Label<out DbCallable>, idxOffset: Int, extractVarargAsArray: Boolean = false) {
private fun extractCallValueArguments(callId: Label<out DbExprparent>, valueArguments: List<IrExpression?>, callTarget: IrFunction, fallbackLocation: Label<DbLocation>, enclosingStmt: Label<out DbStmt>, enclosingCallable: Label<out DbCallable>, idxOffset: Int, extractVarargAsArray: Boolean = false) {
var i = 0
valueArguments.forEach { arg ->
if(arg != null) {
if (arg != null) {
if (arg is IrVararg && !extractVarargAsArray) {
arg.elements.forEachIndexed { varargNo, vararg -> extractVarargElement(vararg, enclosingCallable, callId, i + idxOffset + varargNo, enclosingStmt) }
i += arg.elements.size
} else {
extractExpressionExpr(arg, enclosingCallable, callId, (i++) + idxOffset, enclosingStmt)
}
} else {
val realCallTarget = callTarget.target.realOverrideTarget
// Generated constructor calls to kotlin.Enum have no arguments in IR, but the constructor takes two parameters.
if (realCallTarget is IrConstructor &&
realCallTarget.parentClassOrNull?.symbol == pluginContext.irBuiltIns.enumClass &&
realCallTarget.valueParameters.size == 2 &&
i < realCallTarget.valueParameters.size) {
if (i == 0 && realCallTarget.valueParameters[i].type == pluginContext.irBuiltIns.stringType) {
val id = extractNull(pluginContext.irBuiltIns.stringType, fallbackLocation, callId, (i++) + idxOffset, enclosingCallable, enclosingStmt)
tw.writeCompiler_generated(id, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
} else if (i == 1 && realCallTarget.valueParameters[i].type == pluginContext.irBuiltIns.intType) {
val id = extractConstantInteger(0, fallbackLocation, callId, (i++) + idxOffset, enclosingCallable, enclosingStmt)
tw.writeCompiler_generated(id, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
}
}
}
}
}
@@ -3067,11 +3087,11 @@ open class KotlinFileExtractor(
// which have null arguments even though the parameters don't give default values.
val id = if (e !is IrEnumConstructorCall && callUsesDefaultArguments(e.symbol.owner, valueArgs)) {
extractNewExpr(getDefaultsMethodLabel(e.symbol.owner).cast(), type, locId, parent, idx, callable, enclosingStmt).also {
extractDefaultsCallArguments(it, e.symbol.owner, callable, enclosingStmt, valueArgs, null, null)
extractDefaultsCallArguments(it, e.symbol.owner, locId, callable, enclosingStmt, valueArgs, null, null)
}
} else {
extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt).also {
extractCallValueArguments(it, e, enclosingStmt, callable, 0)
extractCallValueArguments(it, e, e.symbol.owner, locId, enclosingStmt, callable, 0)
}
}
@@ -3396,6 +3416,14 @@ open class KotlinFileExtractor(
extractExprContext(it, locId, callable, enclosingStmt)
}
private fun extractNull(t: IrType, locId: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, callable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) =
tw.getFreshIdLabel<DbNullliteral>().also {
val type = useType(t)
tw.writeExprs_nullliteral(it, type.javaResult.id, parent, idx)
tw.writeExprsKotlinType(it, type.kotlinResult.id)
extractExprContext(it, locId, callable, enclosingStmt)
}
private fun extractAssignExpr(type: IrType, locId: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, callable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) =
tw.getFreshIdLabel<DbAssignexpr>().also {
val typeResults = useType(type)
@@ -3436,7 +3464,7 @@ open class KotlinFileExtractor(
tw.writeHasLocation(id, locId)
tw.writeCallableBinding(id.cast<DbCaller>(), methodId)
extractCallValueArguments(id, e, id, callable, 0)
extractCallValueArguments(id, e, e.symbol.owner, locId, id, callable, 0)
val dr = e.dispatchReceiver
if (dr != null) {
extractExpressionExpr(dr, callable, id, -1, id)
@@ -3614,12 +3642,7 @@ open class KotlinFileExtractor(
tw.writeNamestrings(v.toString(), v.toString(), id)
}
v == null -> {
val id = tw.getFreshIdLabel<DbNullliteral>()
val type = useType(e.type) // class;kotlin.Nothing
val locId = tw.getLocation(e)
tw.writeExprs_nullliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx)
tw.writeExprsKotlinType(id, type.kotlinResult.id)
extractExprContext(id, locId, callable, exprParent.enclosingStmt)
extractNull(e.type, tw.getLocation(e), exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt)
}
else -> {
logger.errorElement("Unrecognised IrConst: " + v.javaClass, e)
@@ -5516,5 +5539,6 @@ open class KotlinFileExtractor(
JVMOVERLOADS_METHOD(9),
DEFAULT_ARGUMENTS_METHOD(10),
INTERFACE_FORWARDER(11),
ENUM_CONSTRUCTOR_ARGUMENT(12),
}
}