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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy