Skip to content

Commit 06a9f0c

Browse files
authored
Merge pull request github#86 from github/igfoo/vararg
Kotlin: Add support for varargs
2 parents b61f3b4 + d4e80f9 commit 06a9f0c

File tree

8 files changed

+85
-0
lines changed

8 files changed

+85
-0
lines changed

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,15 @@ open class KotlinFileExtractor(
16951695
val exprParent = parent.expr(e, callable)
16961696
extractTypeOperatorCall(e, callable, exprParent.parent, exprParent.idx)
16971697
}
1698+
is IrVararg -> {
1699+
val exprParent = parent.expr(e, callable)
1700+
val id = tw.getFreshIdLabel<DbVarargexpr>()
1701+
val locId = tw.getLocation(e)
1702+
val type = useType(e.type)
1703+
tw.writeExprs_varargexpr(id, type.javaResult.id, type.kotlinResult.id, exprParent.parent, exprParent.idx)
1704+
tw.writeHasLocation(id, locId)
1705+
e.elements.forEachIndexed { i, arg -> extractVarargElement(arg, callable, id, i) }
1706+
}
16981707
is IrGetObjectValue -> {
16991708
// For `object MyObject { ... }`, the .class has an
17001709
// automatically-generated `public static final MyObject INSTANCE`
@@ -1719,6 +1728,17 @@ open class KotlinFileExtractor(
17191728
}
17201729
}
17211730

1731+
fun extractVarargElement(e: IrVarargElement, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int) {
1732+
when(e) {
1733+
is IrExpression -> {
1734+
extractExpressionExpr(e, callable, parent, idx)
1735+
}
1736+
else -> {
1737+
logger.warnElement(Severity.ErrorSevere, "Unrecognised IrVarargElement: " + e.javaClass, e)
1738+
}
1739+
}
1740+
}
1741+
17221742
fun extractModifier(m: String): Label<DbModifier> {
17231743
val modifierLabel = "@\"modifier;$m\""
17241744
val id: Label<DbModifier> = tw.getLabelFor(modifierLabel, {

java/ql/lib/config/semmlecode.dbscheme

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ case @expr.kind of
692692
| 77 = @notinstanceofexpr
693693
| 78 = @stmtexpr
694694
| 79 = @stringtemplateexpr
695+
| 80 = @varargexpr
695696
;
696697

697698
/** Holds if this `when` expression was written as an `if` expression. */

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2225,3 +2225,26 @@ class StringTemplateExpr extends Expr, @stringtemplateexpr {
22252225

22262226
override string getAPrimaryQlClass() { result = "StringTemplateExpr" }
22272227
}
2228+
2229+
/**
2230+
* A Kotlin(TODO: Should Java make these too?) vararg expression.
2231+
* This is the argument to a function that corresponds to a `vararg`
2232+
* parameter.
2233+
*/
2234+
class VarArgExpr extends Expr, @varargexpr {
2235+
/**
2236+
* Gets the `i`th component of this vararg. TODO: Is this always Expr?
2237+
*
2238+
* For example, in the string template `"foo${bar}baz"`, the 0th
2239+
* component is the string literal `"foo"`, the 1st component is
2240+
* the variable access `bar`, and the 2nd component is the string
2241+
* literal `"bar"`.
2242+
*/
2243+
Expr getComponent(int i) { result.isNthChildOf(this, i) }
2244+
2245+
override string toString() { result = "..." }
2246+
2247+
override string getHalsteadID() { result = "VarArgExpr" }
2248+
2249+
override string getAPrimaryQlClass() { result = "VarArgExpr" }
2250+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
| test.kt:13:5:13:34 | funWithOnlyVarArgs(...) | 0 | test.kt:13:24:13:33 | ... |
2+
| test.kt:14:5:14:50 | funWithArgsAndVarArgs(...) | 0 | test.kt:14:28:14:30 | foo |
3+
| test.kt:14:5:14:50 | funWithArgsAndVarArgs(...) | 1 | test.kt:14:34:14:37 | true |
4+
| test.kt:14:5:14:50 | funWithArgsAndVarArgs(...) | 2 | test.kt:14:40:14:49 | ... |
5+
| test.kt:15:5:15:53 | funWithMiddleVarArgs(...) | 0 | test.kt:15:27:15:29 | foo |
6+
| test.kt:15:5:15:53 | funWithMiddleVarArgs(...) | 1 | test.kt:15:33:15:42 | ... |
7+
| test.kt:15:5:15:53 | funWithMiddleVarArgs(...) | 2 | test.kt:15:49:15:52 | true |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import java
2+
3+
from Call c, int i
4+
select c, i, c.getArgument(i)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
fun funWithOnlyVarArgs(vararg xs: Int) {
3+
}
4+
5+
fun funWithArgsAndVarArgs(x: String, y: Boolean, vararg xs: Int) {
6+
}
7+
8+
fun funWithMiddleVarArgs(x: String, vararg xs: Int, y: Boolean) {
9+
}
10+
11+
fun myFun() {
12+
// TODO val xs = listOf(10, 11, 12)
13+
funWithOnlyVarArgs(20, 21, 22)
14+
funWithArgsAndVarArgs("foo", true, 30, 31, 32)
15+
funWithMiddleVarArgs("foo", 41, 42, 43, y = true)
16+
}
17+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
| test.kt:13:24:13:33 | ... | 0 | test.kt:13:24:13:25 | 20 |
2+
| test.kt:13:24:13:33 | ... | 1 | test.kt:13:28:13:29 | 21 |
3+
| test.kt:13:24:13:33 | ... | 2 | test.kt:13:32:13:33 | 22 |
4+
| test.kt:14:40:14:49 | ... | 0 | test.kt:14:40:14:41 | 30 |
5+
| test.kt:14:40:14:49 | ... | 1 | test.kt:14:44:14:45 | 31 |
6+
| test.kt:14:40:14:49 | ... | 2 | test.kt:14:48:14:49 | 32 |
7+
| test.kt:15:33:15:42 | ... | 0 | test.kt:15:33:15:34 | 41 |
8+
| test.kt:15:33:15:42 | ... | 1 | test.kt:15:37:15:38 | 42 |
9+
| test.kt:15:33:15:42 | ... | 2 | test.kt:15:41:15:42 | 43 |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import java
2+
3+
from VarArgExpr vae, int i
4+
select vae, i, vae.getComponent(i)

0 commit comments

Comments
 (0)