Skip to content

Commit ce3a531

Browse files
authored
QL: Merge pull request #73 from github/tausbn/add-implicit-this-query
Add "implicit `this`" query
2 parents 823c24a + d0cb138 commit ce3a531

6 files changed

Lines changed: 81 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @name Using implicit `this`
3+
* @description Writing member predicate calls with an implicit `this` can be confusing
4+
* @kind problem
5+
* @problem.severity warning
6+
* @precision very-high
7+
* @id ql/implicit-this
8+
* @tags maintainability
9+
*/
10+
11+
import ql
12+
13+
MemberCall explicitThisCallInFile(File f) {
14+
result.getLocation().getFile() = f and
15+
result.getBase() instanceof ThisAccess and
16+
// Exclude `this.(Type).whatever(...)`, as some files have that as their only instance of `this`.
17+
not result = any(InlineCast c).getBase()
18+
}
19+
20+
PredicateCall implicitThisCallInFile(File f) {
21+
result.getLocation().getFile() = f and
22+
exists(result.getTarget().getDeclaringType().getASuperType()) and
23+
// Exclude `SomeModule::whatever(...)`
24+
not exists(result.getQualifier())
25+
}
26+
27+
PredicateCall confusingImplicitThisCall(File f) {
28+
result = implicitThisCallInFile(f) and
29+
exists(explicitThisCallInFile(f))
30+
}
31+
32+
from PredicateCall c
33+
where c = confusingImplicitThisCall(_)
34+
select c, "Use of implicit `this`."
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import ql
2+
3+
class Foo extends string {
4+
Foo() { this = "hello" }
5+
6+
string getBar() { result = "bar" }
7+
8+
string getBarWithThis() { result = this.getBar() }
9+
10+
string getBarWithoutThis() { result = getBar() }
11+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import ql
2+
3+
class Foo extends string {
4+
Foo() { this = "hello" }
5+
6+
string getBar() { result = "bar" }
7+
8+
string getBarWithThis() { result = this.getBar() }
9+
10+
/* Okay because not a member predicate. */
11+
string getBaz() { result = Baz::baz() }
12+
13+
/* Okay because not a member predicate. */
14+
string getOuterQuux() { result = getQuux() }
15+
}
16+
17+
string getQuux() { result = "quux" }
18+
19+
module Baz {
20+
string baz() { result = "baz" }
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| Bad.qll:10:41:10:48 | PredicateCall | Use of implicit `this`. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
queries/style/ImplicitThis.ql
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import ql
2+
3+
class Foo extends string {
4+
Foo() { this = "hello" }
5+
6+
string getBar() { result = "bar" }
7+
8+
/* Okay, because we don't write `this.some_method` anywhere */
9+
string getBarWithoutThis() { result = getBar() }
10+
11+
/* Okay, because this is the only way to cast `this`. */
12+
string useThisWithInlineCast() { result = this.(string).toUpperCase() }
13+
}

0 commit comments

Comments
 (0)