Skip to content

Commit 11807e3

Browse files
authored
Merge pull request github#105 from github/igfoo/this
Kotlin: Add tests for `this`
2 parents 6ca2a97 + 106c485 commit 11807e3

File tree

7 files changed

+167
-25
lines changed

7 files changed

+167
-25
lines changed

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

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,26 +1175,6 @@ open class KotlinFileExtractor(
11751175
return FieldResult(instanceId, instanceName)
11761176
}
11771177

1178-
private fun isQualifiedThis(vp: IrValueParameter): Boolean {
1179-
return isQualifiedThisFunction(vp) ||
1180-
isQualifiedThisClass(vp)
1181-
}
1182-
1183-
private fun isQualifiedThisFunction(vp: IrValueParameter): Boolean {
1184-
val parent = vp.parent
1185-
return vp.index == -1 &&
1186-
parent is IrFunction &&
1187-
parent.dispatchReceiverParameter == vp &&
1188-
parent.extensionReceiverParameter != null
1189-
}
1190-
1191-
private fun isQualifiedThisClass(vp: IrValueParameter): Boolean {
1192-
val parent = vp.parent
1193-
return vp.index == -1 &&
1194-
parent is IrClass &&
1195-
parent.thisReceiver == vp
1196-
}
1197-
11981178
fun extractValueParameter(vp: IrValueParameter, parent: Label<out DbCallable>, idx: Int) {
11991179
val id = useValueParameter(vp)
12001180
val type = useType(vp.type)
@@ -1896,12 +1876,31 @@ open class KotlinFileExtractor(
18961876
val type = useType(e.type)
18971877
val locId = tw.getLocation(e)
18981878
tw.writeExprs_thisaccess(id, type.javaResult.id, type.kotlinResult.id, exprParent.parent, exprParent.idx)
1899-
if (isQualifiedThis(owner)) {
1900-
// todo: add type access as child of 'id' at index 0
1901-
logger.warnElement(Severity.ErrorSevere, "TODO: Qualified this access found.", e)
1902-
}
19031879
tw.writeHasLocation(id, locId)
19041880
tw.writeCallableEnclosingExpr(id, callable)
1881+
1882+
val ownerParent = owner.parent
1883+
when(ownerParent) {
1884+
is IrFunction -> {
1885+
if (ownerParent.dispatchReceiverParameter == owner &&
1886+
ownerParent.extensionReceiverParameter != null) {
1887+
logger.warnElement(Severity.ErrorSevere, "Function-qualifier for this", e)
1888+
}
1889+
}
1890+
is IrClass -> {
1891+
if (ownerParent.thisReceiver == owner) {
1892+
val qualId = tw.getFreshIdLabel<DbUnannotatedtypeaccess>()
1893+
// TODO: Type arguments
1894+
val qualType = useSimpleTypeClass(ownerParent, listOf(), false)
1895+
tw.writeExprs_unannotatedtypeaccess(qualId, qualType.javaResult.id, qualType.kotlinResult.id, id, 0)
1896+
tw.writeHasLocation(qualId, locId)
1897+
tw.writeCallableEnclosingExpr(qualId, callable)
1898+
}
1899+
}
1900+
else -> {
1901+
logger.warnElement(Severity.ErrorSevere, "Unexpected owner parent for this access: " + ownerParent.javaClass, e)
1902+
}
1903+
}
19051904
} else {
19061905
val id = tw.getFreshIdLabel<DbVaraccess>()
19071906
val type = useType(e.type)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
| this.kt:2:1:58:1 | <obinit>(...) | this.kt:2:1:58:1 | <obinit> |
2+
| this.kt:2:1:58:1 | super(...) | file://:0:0:0:0 | Any |
3+
| this.kt:3:5:53:5 | <obinit>(...) | this.kt:3:5:53:5 | <obinit> |
4+
| this.kt:3:5:53:5 | super(...) | file://:0:0:0:0 | Any |
5+
| this.kt:36:13:36:25 | topLevelFun(...) | this.kt:59:1:59:20 | topLevelFun |
6+
| this.kt:37:13:37:22 | outerFun(...) | this.kt:54:5:54:21 | outerFun |
7+
| this.kt:38:13:38:22 | innerFun(...) | this.kt:49:9:49:25 | innerFun |
8+
| this.kt:39:13:39:30 | topLevelOuterFun(...) | this.kt:55:5:55:29 | topLevelOuterFun |
9+
| this.kt:40:13:40:30 | topLevelInnerFun(...) | this.kt:50:9:50:33 | topLevelInnerFun |
10+
| this.kt:41:13:41:27 | outerInnerFun(...) | this.kt:51:9:51:30 | outerInnerFun |
11+
| this.kt:42:13:42:35 | topLevelOuterInnerFun(...) | this.kt:52:9:52:38 | topLevelOuterInnerFun |
12+
| this.kt:43:18:43:27 | innerFun(...) | this.kt:49:9:49:25 | innerFun |
13+
| this.kt:44:18:44:35 | topLevelInnerFun(...) | this.kt:50:9:50:33 | topLevelInnerFun |
14+
| this.kt:45:18:45:32 | outerInnerFun(...) | this.kt:51:9:51:30 | outerInnerFun |
15+
| this.kt:46:18:46:40 | topLevelOuterInnerFun(...) | this.kt:52:9:52:38 | topLevelOuterInnerFun |
16+
| this.kt:64:1:65:1 | <obinit>(...) | this.kt:64:1:65:1 | <obinit> |
17+
| this.kt:64:1:65:1 | super(...) | file://:0:0:0:0 | Any |
18+
| this.kt:67:1:68:1 | <obinit>(...) | this.kt:67:1:68:1 | <obinit> |
19+
| this.kt:67:1:68:1 | super(...) | file://:0:0:0:0 | Any |
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
4+
select c, c.getCallee()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
| this.kt:5:29:5:32 | this | file://:0:0:0:0 | <none> |
2+
| this.kt:6:29:6:38 | this | file://:0:0:0:0 | <none> |
3+
| this.kt:7:29:7:38 | Outer.this | this.kt:7:29:7:38 | Outer |
4+
| this.kt:29:38:29:41 | this | file://:0:0:0:0 | <none> |
5+
| this.kt:30:29:30:38 | this | file://:0:0:0:0 | <none> |
6+
| this.kt:31:29:31:38 | Outer.this | this.kt:31:29:31:38 | Outer |
7+
| this.kt:32:38:32:54 | this | file://:0:0:0:0 | <none> |
8+
| this.kt:37:13:37:22 | Outer.this | this.kt:37:13:37:22 | Outer |
9+
| this.kt:38:13:38:22 | this | file://:0:0:0:0 | <none> |
10+
| this.kt:39:13:39:30 | Outer.this | this.kt:39:13:39:30 | Outer |
11+
| this.kt:40:13:40:30 | this | file://:0:0:0:0 | <none> |
12+
| this.kt:41:13:41:27 | this | file://:0:0:0:0 | <none> |
13+
| this.kt:42:13:42:35 | this | file://:0:0:0:0 | <none> |
14+
| this.kt:43:13:43:16 | this | file://:0:0:0:0 | <none> |
15+
| this.kt:44:13:44:16 | this | file://:0:0:0:0 | <none> |
16+
| this.kt:45:13:45:16 | this | file://:0:0:0:0 | <none> |
17+
| this.kt:46:13:46:16 | this | file://:0:0:0:0 | <none> |
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
2+
class Outer {
3+
inner class Inner {
4+
fun someFun() {
5+
val x1: Inner = this
6+
val x2: Inner = this@Inner
7+
val x3: Outer = this@Outer
8+
9+
val labelledExtensionFun = someLabelledExtensionFun@ fun ExtensionClass.() {
10+
val x4: ExtensionClass = this
11+
val x5: ExtensionClass = this@someLabelledExtensionFun
12+
val nestedLabelledExtensionFun = someNestedLabelledExtensionFun@ fun AnotherExtensionClass.() {
13+
val x6: AnotherExtensionClass = this
14+
val x7: ExtensionClass = this@someLabelledExtensionFun
15+
val x8: AnotherExtensionClass = this@someNestedLabelledExtensionFun
16+
}
17+
}
18+
19+
val unLabelledExtensionFun = fun ExtensionClass.() {
20+
val x9: ExtensionClass = this
21+
}
22+
23+
val someLambda = { i: Int ->
24+
val x10: Inner = this
25+
}
26+
}
27+
28+
fun ExtensionClass.extensionFun() {
29+
val x1: ExtensionClass = this
30+
val x2: Inner = this@Inner
31+
val x3: Outer = this@Outer
32+
val x4: ExtensionClass = this@extensionFun
33+
}
34+
35+
fun innerCaller() {
36+
topLevelFun()
37+
outerFun()
38+
innerFun()
39+
topLevelOuterFun()
40+
topLevelInnerFun()
41+
outerInnerFun()
42+
topLevelOuterInnerFun()
43+
this.innerFun()
44+
this.topLevelInnerFun()
45+
this.outerInnerFun()
46+
this.topLevelOuterInnerFun()
47+
}
48+
49+
fun innerFun() {}
50+
fun topLevelInnerFun() {}
51+
fun outerInnerFun() {}
52+
fun topLevelOuterInnerFun() {}
53+
}
54+
fun outerFun() {}
55+
fun topLevelOuterFun() {}
56+
fun outerInnerFun() {}
57+
fun topLevelOuterInnerFun() {}
58+
}
59+
fun topLevelFun() {}
60+
fun topLevelOuterFun() {}
61+
fun topLevelInnerFun() {}
62+
fun topLevelOuterInnerFun() {}
63+
64+
class ExtensionClass {
65+
}
66+
67+
class AnotherExtensionClass {
68+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import java
2+
3+
newtype TMaybeElement =
4+
TElement(Element e) or
5+
TNoElement()
6+
7+
class MaybeElement extends TMaybeElement {
8+
abstract string toString();
9+
abstract Location getLocation();
10+
}
11+
12+
class YesMaybeElement extends MaybeElement {
13+
Element e;
14+
15+
YesMaybeElement() { this = TElement(e) }
16+
override string toString() { result = e.toString() }
17+
override Location getLocation() { result = e.getLocation() }
18+
}
19+
20+
class NoMaybeElement extends MaybeElement {
21+
NoMaybeElement() { this = TNoElement() }
22+
23+
override string toString() { result = "<none>" }
24+
override Location getLocation() { none() }
25+
}
26+
27+
MaybeElement qualifier(ThisAccess t) {
28+
if exists(t.getQualifier())
29+
then result = TElement(t.getQualifier())
30+
else result = TNoElement()
31+
}
32+
33+
from ThisAccess t
34+
select t, qualifier(t)

java/ql/test/kotlin/library-tests/variables/variableAccesses.expected

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ instAcc
1212
| variables.kt:31:9:31:15 | this |
1313
| variables.kt:32:9:32:15 | this |
1414
| variables.kt:41:13:41:16 | this |
15-
| variables.kt:42:13:42:19 | this |
15+
| variables.kt:42:13:42:19 | C3.this |
1616
instAccQualifier
17+
| variables.kt:42:13:42:19 | C3.this | variables.kt:42:13:42:19 | C3 |

0 commit comments

Comments
 (0)