Skip to content

Commit c9db620

Browse files
committed
JS: Add call-graph test for accessor calls
1 parent 7d5c804 commit c9db620

File tree

3 files changed

+74
-12
lines changed

3 files changed

+74
-12
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
spuriousCallee
22
missingCallee
3-
| constructor-field.ts:40:5:40:14 | f3.build() | constructor-field.ts:13:3:13:12 | build() {} | -1 |
4-
| constructor-field.ts:71:1:71:11 | bf3.build() | constructor-field.ts:13:3:13:12 | build() {} | -1 |
3+
| constructor-field.ts:40:5:40:14 | f3.build() | constructor-field.ts:13:3:13:12 | build() {} | -1 | calls |
4+
| constructor-field.ts:71:1:71:11 | bf3.build() | constructor-field.ts:13:3:13:12 | build() {} | -1 | calls |
55
badAnnotation

javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/Test.ql

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,42 +25,60 @@ class AnnotatedFunction extends Function {
2525
}
2626

2727
/** A function annotated with `calls:NAME` */
28-
class AnnotatedCall extends InvokeExpr {
28+
class AnnotatedCall extends DataFlow::SourceNode {
2929
string calls;
30+
string kind;
3031

31-
AnnotatedCall() { calls = getAnnotation(this, "calls") }
32+
AnnotatedCall() {
33+
this instanceof DataFlow::InvokeNode and
34+
calls = getAnnotation(this.asExpr(), kind) and
35+
kind = "calls"
36+
or
37+
this instanceof DataFlow::PropRef and
38+
calls = getAnnotation(this.getAstNode(), kind) and
39+
kind = "callsAccessor"
40+
}
3241

3342
string getCallTargetName() { result = calls }
3443

35-
AnnotatedFunction getAnExpectedCallee() { result.getCalleeName() = getCallTargetName() }
44+
AnnotatedFunction getAnExpectedCallee(string kind_) {
45+
result.getCalleeName() = getCallTargetName() and
46+
kind = kind_
47+
}
3648

37-
int getBoundArgs() { result = getAnnotation(this, "boundArgs").toInt() }
49+
int getBoundArgs() { result = getAnnotation(this.getAstNode(), "boundArgs").toInt() }
3850

3951
int getBoundArgsOrMinusOne() {
4052
result = getBoundArgs()
4153
or
4254
not exists(getBoundArgs()) and
4355
result = -1
4456
}
57+
58+
string getKind() {
59+
result = kind
60+
}
4561
}
4662

4763
predicate callEdge(AnnotatedCall call, AnnotatedFunction target, int boundArgs) {
48-
FlowSteps::calls(call.flow(), target) and boundArgs = -1
64+
FlowSteps::calls(call, target) and boundArgs = -1
4965
or
50-
FlowSteps::callsBound(call.flow(), target, boundArgs)
66+
FlowSteps::callsBound(call, target, boundArgs)
5167
}
5268

53-
query predicate spuriousCallee(AnnotatedCall call, AnnotatedFunction target, int boundArgs) {
69+
query predicate spuriousCallee(AnnotatedCall call, AnnotatedFunction target, int boundArgs, string kind) {
5470
callEdge(call, target, boundArgs) and
71+
kind = call.getKind() and
5572
not (
56-
target = call.getAnExpectedCallee() and
73+
target = call.getAnExpectedCallee(kind) and
5774
boundArgs = call.getBoundArgsOrMinusOne()
5875
)
5976
}
6077

61-
query predicate missingCallee(AnnotatedCall call, AnnotatedFunction target, int boundArgs) {
78+
query predicate missingCallee(AnnotatedCall call, AnnotatedFunction target, int boundArgs, string kind) {
6279
not callEdge(call, target, boundArgs) and
63-
target = call.getAnExpectedCallee() and
80+
kind = call.getKind() and
81+
target = call.getAnExpectedCallee(kind) and
6482
boundArgs = call.getBoundArgsOrMinusOne()
6583
}
6684

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import 'dummy';
2+
3+
let obj = {
4+
/** name:obj.f.get */
5+
get f() {},
6+
7+
/** name:obj.f.set */
8+
set f(x) {}
9+
};
10+
11+
/** callsAccessor:obj.f.get */
12+
obj.f;
13+
14+
/** callsAccessor:obj.f.set */
15+
obj.f = 1;
16+
17+
class C {
18+
/** name:C.f.get */
19+
static get f() {}
20+
21+
/** name:C.f.set */
22+
static set f(x) {}
23+
}
24+
25+
/** callsAccessor:C.f.get */
26+
C.f;
27+
28+
/** callsAccessor:C.f.set */
29+
C.f = 1;
30+
31+
32+
class D {
33+
/** name:D.f.get */
34+
get f() {}
35+
36+
/** name:D.f.set */
37+
set f(x) {}
38+
}
39+
40+
/** callsAccessor:D.f.get */
41+
new D().f;
42+
43+
/** callsAccessor:D.f.set */
44+
new D().f = 1;

0 commit comments

Comments
 (0)