Skip to content

Commit 830be92

Browse files
authored
Merge pull request github#11089 from tamasvajk/kotlin-enum-ctor-call
Kotlin: Extract missing arguments of enum constructor calls
2 parents f8e80f9 + 4e8d8a4 commit 830be92

File tree

8 files changed

+59
-10
lines changed

8 files changed

+59
-10
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,7 +2089,7 @@ open class KotlinFileExtractor(
20892089
private fun extractCallValueArguments(callId: Label<out DbExprparent>, valueArguments: List<IrExpression?>, enclosingStmt: Label<out DbStmt>, enclosingCallable: Label<out DbCallable>, idxOffset: Int, extractVarargAsArray: Boolean = false) {
20902090
var i = 0
20912091
valueArguments.forEach { arg ->
2092-
if(arg != null) {
2092+
if (arg != null) {
20932093
if (arg is IrVararg && !extractVarargAsArray) {
20942094
arg.elements.forEachIndexed { varargNo, vararg -> extractVarargElement(vararg, enclosingCallable, callId, i + idxOffset + varargNo, enclosingStmt) }
20952095
i += arg.elements.size
@@ -3030,15 +3030,31 @@ open class KotlinFileExtractor(
30303030
val isAnonymous = eType.isAnonymous
30313031
val locId = tw.getLocation(e)
30323032
val valueArgs = (0 until e.valueArgumentsCount).map { e.getValueArgument(it) }
3033-
// For now, don't try to use default methods for enum constructor calls,
3034-
// which have null arguments even though the parameters don't give default values.
3033+
30353034
val id = if (e !is IrEnumConstructorCall && callUsesDefaultArguments(e.symbol.owner, valueArgs)) {
30363035
extractNewExpr(getDefaultsMethodLabel(e.symbol.owner).cast(), type, locId, parent, idx, callable, enclosingStmt).also {
30373036
extractDefaultsCallArguments(it, e.symbol.owner, callable, enclosingStmt, valueArgs, null, null)
30383037
}
30393038
} else {
30403039
extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt).also {
3041-
extractCallValueArguments(it, e, enclosingStmt, callable, 0)
3040+
3041+
val realCallTarget = e.symbol.owner.realOverrideTarget
3042+
// Generated constructor calls to kotlin.Enum have no arguments in IR, but the constructor takes two parameters.
3043+
if (e is IrEnumConstructorCall &&
3044+
realCallTarget is IrConstructor &&
3045+
realCallTarget.parentClassOrNull?.fqNameWhenAvailable?.asString() == "kotlin.Enum" &&
3046+
realCallTarget.valueParameters.size == 2 &&
3047+
realCallTarget.valueParameters[0].type == pluginContext.irBuiltIns.stringType &&
3048+
realCallTarget.valueParameters[1].type == pluginContext.irBuiltIns.intType) {
3049+
3050+
val id0 = extractNull(pluginContext.irBuiltIns.stringType, locId, it, 0, callable, enclosingStmt)
3051+
tw.writeCompiler_generated(id0, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
3052+
3053+
val id1 = extractConstantInteger(0, locId, it, 1, callable, enclosingStmt)
3054+
tw.writeCompiler_generated(id1, CompilerGeneratedKinds.ENUM_CONSTRUCTOR_ARGUMENT.kind)
3055+
} else {
3056+
extractCallValueArguments(it, e, enclosingStmt, callable, 0)
3057+
}
30423058
}
30433059
}
30443060

@@ -3363,6 +3379,14 @@ open class KotlinFileExtractor(
33633379
extractExprContext(it, locId, callable, enclosingStmt)
33643380
}
33653381

3382+
private fun extractNull(t: IrType, locId: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, callable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) =
3383+
tw.getFreshIdLabel<DbNullliteral>().also {
3384+
val type = useType(t)
3385+
tw.writeExprs_nullliteral(it, type.javaResult.id, parent, idx)
3386+
tw.writeExprsKotlinType(it, type.kotlinResult.id)
3387+
extractExprContext(it, locId, callable, enclosingStmt)
3388+
}
3389+
33663390
private fun extractAssignExpr(type: IrType, locId: Label<DbLocation>, parent: Label<out DbExprparent>, idx: Int, callable: Label<out DbCallable>, enclosingStmt: Label<out DbStmt>) =
33673391
tw.getFreshIdLabel<DbAssignexpr>().also {
33683392
val typeResults = useType(type)
@@ -3581,12 +3605,7 @@ open class KotlinFileExtractor(
35813605
tw.writeNamestrings(v.toString(), v.toString(), id)
35823606
}
35833607
v == null -> {
3584-
val id = tw.getFreshIdLabel<DbNullliteral>()
3585-
val type = useType(e.type) // class;kotlin.Nothing
3586-
val locId = tw.getLocation(e)
3587-
tw.writeExprs_nullliteral(id, type.javaResult.id, exprParent.parent, exprParent.idx)
3588-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3589-
extractExprContext(id, locId, callable, exprParent.enclosingStmt)
3608+
extractNull(e.type, tw.getLocation(e), exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt)
35903609
}
35913610
else -> {
35923611
logger.errorElement("Unrecognised IrConst: " + v.javaClass, e)
@@ -5483,5 +5502,6 @@ open class KotlinFileExtractor(
54835502
JVMOVERLOADS_METHOD(9),
54845503
DEFAULT_ARGUMENTS_METHOD(10),
54855504
INTERFACE_FORWARDER(11),
5505+
ENUM_CONSTRUCTOR_ARGUMENT(12),
54865506
}
54875507
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import java
2+
3+
from Call call, Callable c
4+
where
5+
count(call.getAnArgument()) != c.getNumberOfParameters() and
6+
call.getCallee() = c and
7+
not exists(Parameter p | c.getAParameter() = p and p.isVarargs()) and
8+
call.getFile().isKotlinSourceFile()
9+
select call, c, count(call.getAnArgument()), c.getNumberOfParameters()

java/ql/lib/semmle/code/java/Element.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class Element extends @element, Top {
6969
i = 10 and result = "Forwarder for Kotlin calls that need default arguments filling in"
7070
or
7171
i = 11 and result = "Forwarder for a Kotlin class inheriting an interface default method"
72+
or
73+
i = 12 and result = "Argument for enum constructor call"
7274
)
7375
}
7476
}

java/ql/test/kotlin/library-tests/classes/PrintAst.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ classes.kt:
174174
# 49| 0: [ClassInstanceExpr] new Enum(...)
175175
# 49| -3: [TypeAccess] Enum<Direction>
176176
# 49| 0: [TypeAccess] Direction
177+
# 49| 0: [NullLiteral] null
178+
# 49| 1: [IntegerLiteral] 0
177179
# 49| 1: [BlockStmt] { ... }
178180
# 50| 5: [FieldDeclaration] Direction NORTH;
179181
# 50| -1: [TypeAccess] Direction
@@ -209,6 +211,8 @@ classes.kt:
209211
# 53| 0: [ClassInstanceExpr] new Enum(...)
210212
# 53| -3: [TypeAccess] Enum<Color>
211213
# 53| 0: [TypeAccess] Color
214+
# 53| 0: [NullLiteral] null
215+
# 53| 1: [IntegerLiteral] 0
212216
# 53| 1: [BlockStmt] { ... }
213217
# 53| 0: [ExprStmt] <Expr>;
214218
# 53| 0: [KtInitializerAssignExpr] ...=...

java/ql/test/kotlin/library-tests/exprs/PrintAst.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3358,6 +3358,8 @@ exprs.kt:
33583358
# 174| 0: [ClassInstanceExpr] new Enum(...)
33593359
# 174| -3: [TypeAccess] Enum<Direction>
33603360
# 174| 0: [TypeAccess] Direction
3361+
# 174| 0: [NullLiteral] null
3362+
# 174| 1: [IntegerLiteral] 0
33613363
# 174| 1: [BlockStmt] { ... }
33623364
# 175| 5: [FieldDeclaration] Direction NORTH;
33633365
# 175| -1: [TypeAccess] Direction
@@ -3393,6 +3395,8 @@ exprs.kt:
33933395
# 178| 0: [ClassInstanceExpr] new Enum(...)
33943396
# 178| -3: [TypeAccess] Enum<Color>
33953397
# 178| 0: [TypeAccess] Color
3398+
# 178| 0: [NullLiteral] null
3399+
# 178| 1: [IntegerLiteral] 0
33963400
# 178| 1: [BlockStmt] { ... }
33973401
# 178| 0: [ExprStmt] <Expr>;
33983402
# 178| 0: [KtInitializerAssignExpr] ...=...

java/ql/test/kotlin/library-tests/exprs/exprs.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,9 +1470,11 @@
14701470
| exprs.kt:170:9:170:17 | r2.height | exprs.kt:165:1:172:1 | foo | VarAccess |
14711471
| exprs.kt:170:9:170:21 | ...=... | exprs.kt:165:1:172:1 | foo | AssignExpr |
14721472
| exprs.kt:170:21:170:21 | 3 | exprs.kt:165:1:172:1 | foo | IntegerLiteral |
1473+
| exprs.kt:174:1:176:1 | 0 | exprs.kt:174:6:176:1 | Direction | IntegerLiteral |
14731474
| exprs.kt:174:1:176:1 | Direction | exprs.kt:174:6:176:1 | Direction | TypeAccess |
14741475
| exprs.kt:174:1:176:1 | Enum<Direction> | exprs.kt:174:6:176:1 | Direction | TypeAccess |
14751476
| exprs.kt:174:1:176:1 | new Enum(...) | exprs.kt:174:6:176:1 | Direction | ClassInstanceExpr |
1477+
| exprs.kt:174:1:176:1 | null | exprs.kt:174:6:176:1 | Direction | NullLiteral |
14761478
| exprs.kt:175:5:175:10 | ...=... | exprs.kt:0:0:0:0 | <clinit> | KtInitializerAssignExpr |
14771479
| exprs.kt:175:5:175:10 | Direction | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
14781480
| exprs.kt:175:5:175:10 | Direction | exprs.kt:0:0:0:0 | <clinit> | TypeAccess |
@@ -1497,9 +1499,11 @@
14971499
| exprs.kt:175:25:175:28 | Direction | file://:0:0:0:0 | <none> | TypeAccess |
14981500
| exprs.kt:175:25:175:28 | Direction.EAST | exprs.kt:0:0:0:0 | <clinit> | VarAccess |
14991501
| exprs.kt:175:25:175:28 | new Direction(...) | exprs.kt:0:0:0:0 | <clinit> | ClassInstanceExpr |
1502+
| exprs.kt:178:1:182:1 | 0 | exprs.kt:178:6:182:1 | Color | IntegerLiteral |
15001503
| exprs.kt:178:1:182:1 | Color | exprs.kt:178:6:182:1 | Color | TypeAccess |
15011504
| exprs.kt:178:1:182:1 | Enum<Color> | exprs.kt:178:6:182:1 | Color | TypeAccess |
15021505
| exprs.kt:178:1:182:1 | new Enum(...) | exprs.kt:178:6:182:1 | Color | ClassInstanceExpr |
1506+
| exprs.kt:178:1:182:1 | null | exprs.kt:178:6:182:1 | Color | NullLiteral |
15031507
| exprs.kt:178:18:178:29 | ...=... | exprs.kt:178:6:182:1 | Color | KtInitializerAssignExpr |
15041508
| exprs.kt:178:18:178:29 | int | file://:0:0:0:0 | <none> | TypeAccess |
15051509
| exprs.kt:178:18:178:29 | int | file://:0:0:0:0 | <none> | TypeAccess |

java/ql/test/kotlin/library-tests/exprs_typeaccess/PrintAst.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ A.kt:
8888
# 23| 0: [ClassInstanceExpr] new Enum(...)
8989
# 23| -3: [TypeAccess] Enum<Enu>
9090
# 23| 0: [TypeAccess] Enu
91+
# 23| 0: [NullLiteral] null
92+
# 23| 1: [IntegerLiteral] 0
9193
# 23| 1: [BlockStmt] { ... }
9294
# 24| 5: [FieldDeclaration] Enu A;
9395
# 24| -1: [TypeAccess] Enu

java/ql/test/kotlin/library-tests/methods/exprs.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,11 @@
231231
| enumClass.kt:0:0:0:0 | EnumWithFunctions[] | TypeAccess |
232232
| enumClass.kt:0:0:0:0 | String | TypeAccess |
233233
| enumClass.kt:0:0:0:0 | String | TypeAccess |
234+
| enumClass.kt:1:1:4:1 | 0 | IntegerLiteral |
234235
| enumClass.kt:1:1:4:1 | Enum<EnumClass> | TypeAccess |
235236
| enumClass.kt:1:1:4:1 | EnumClass | TypeAccess |
236237
| enumClass.kt:1:1:4:1 | new Enum(...) | ClassInstanceExpr |
238+
| enumClass.kt:1:1:4:1 | null | NullLiteral |
237239
| enumClass.kt:1:22:1:31 | ...=... | KtInitializerAssignExpr |
238240
| enumClass.kt:1:22:1:31 | int | TypeAccess |
239241
| enumClass.kt:1:22:1:31 | int | TypeAccess |
@@ -256,9 +258,11 @@
256258
| enumClass.kt:3:5:3:12 | EnumClass.enum2 | VarAccess |
257259
| enumClass.kt:3:5:3:12 | new EnumClass(...) | ClassInstanceExpr |
258260
| enumClass.kt:3:11:3:11 | 1 | IntegerLiteral |
261+
| enumClass.kt:6:1:16:1 | 0 | IntegerLiteral |
259262
| enumClass.kt:6:1:16:1 | Enum<EnumWithFunctions> | TypeAccess |
260263
| enumClass.kt:6:1:16:1 | EnumWithFunctions | TypeAccess |
261264
| enumClass.kt:6:1:16:1 | new Enum(...) | ClassInstanceExpr |
265+
| enumClass.kt:6:1:16:1 | null | NullLiteral |
262266
| enumClass.kt:8:3:11:4 | ...=... | KtInitializerAssignExpr |
263267
| enumClass.kt:8:3:11:4 | <implicit coercion to unit> | ImplicitCoercionToUnitExpr |
264268
| enumClass.kt:8:3:11:4 | EnumWithFunctions | TypeAccess |

0 commit comments

Comments
 (0)