Skip to content

Commit 112cd9d

Browse files
committed
move use-set-literal implementation to Query.qll file
1 parent 33d363e commit 112cd9d

File tree

2 files changed

+126
-102
lines changed

2 files changed

+126
-102
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import ql
2+
3+
/**
4+
* A chain of disjunctions treated as one object. For example the following is
5+
* a chain of disjunctions with three operands:
6+
* ```
7+
* a or b or c
8+
* ```
9+
*/
10+
class DisjunctionChain extends Disjunction {
11+
DisjunctionChain() { not exists(Disjunction parent | parent.getAnOperand() = this) }
12+
13+
/**
14+
* Gets any operand of the chain.
15+
*/
16+
Formula getOperand(int i) {
17+
result =
18+
rank[i + 1](Formula operand, Location l |
19+
operand = getAnOperand*() and
20+
not operand instanceof Disjunction and
21+
l = operand.getLocation()
22+
|
23+
operand order by l.getStartLine(), l.getStartColumn()
24+
)
25+
}
26+
}
27+
28+
/**
29+
* An equality comparison with a `Literal`. For example:
30+
* ```
31+
* x = 4
32+
* ```
33+
*/
34+
class EqualsLiteral extends ComparisonFormula {
35+
EqualsLiteral() {
36+
getOperator() = "=" and
37+
getAnOperand() instanceof Literal
38+
}
39+
40+
AstNode getOther() {
41+
result = getAnOperand() and
42+
not result instanceof Literal
43+
}
44+
45+
Literal getLiteral() { result = getAnOperand() }
46+
}
47+
48+
/**
49+
* A chain of disjunctions where each operand is an equality comparison between
50+
* the same thing and various `Literal`s. For example:
51+
* ```
52+
* x = 4 or
53+
* x = 5 or
54+
* x = 6
55+
* ```
56+
*/
57+
class DisjunctionEqualsLiteral extends DisjunctionChain {
58+
AstNode firstOperand;
59+
60+
DisjunctionEqualsLiteral() {
61+
// VarAccess on the same variable
62+
exists(VarDef v |
63+
forex(Formula f | f = getOperand(_) |
64+
f.(EqualsLiteral).getAnOperand().(VarAccess).getDeclaration() = v
65+
) and
66+
firstOperand = getOperand(0).(EqualsLiteral).getAnOperand() and
67+
firstOperand.(VarAccess).getDeclaration() = v
68+
)
69+
or
70+
// FieldAccess on the same variable
71+
exists(VarDecl v |
72+
forex(Formula f | f = getOperand(_) |
73+
f.(EqualsLiteral).getAnOperand().(FieldAccess).getDeclaration() = v
74+
) and
75+
firstOperand = getOperand(0).(EqualsLiteral).getAnOperand() and
76+
firstOperand.(FieldAccess).getDeclaration() = v
77+
)
78+
or
79+
// ThisAccess
80+
forex(Formula f | f = getOperand(_) | f.(EqualsLiteral).getAnOperand() instanceof ThisAccess) and
81+
firstOperand = getOperand(0).(EqualsLiteral).getAnOperand().(ThisAccess)
82+
or
83+
// ResultAccess
84+
forex(Formula f | f = getOperand(_) | f.(EqualsLiteral).getAnOperand() instanceof ResultAccess) and
85+
firstOperand = getOperand(0).(EqualsLiteral).getAnOperand().(ResultAccess)
86+
// (in principle something like GlobalValueNumbering could be used to generalize this)
87+
}
88+
89+
/**
90+
* Gets the first "thing" that is the same thing in this chain of equalities.
91+
*/
92+
AstNode getFirstOperand() { result = firstOperand }
93+
}
94+
95+
/**
96+
* A call with a single `Literal` argument. For example:
97+
* ```
98+
* myPredicate(4)
99+
* ```
100+
*/
101+
class CallLiteral extends Call {
102+
CallLiteral() {
103+
getNumberOfArguments() = 1 and
104+
getArgument(0) instanceof Literal
105+
}
106+
}
107+
108+
/**
109+
* A chain of disjunctions where each operand is a call to the same predicate
110+
* using various `Literal`s. For example:
111+
* ```
112+
* myPredicate(4) or
113+
* myPredicate(5) or
114+
* myPredicate(6)
115+
* ```
116+
*/
117+
class DisjunctionPredicateLiteral extends DisjunctionChain {
118+
DisjunctionPredicateLiteral() {
119+
// Call to the same target
120+
exists(PredicateOrBuiltin target |
121+
forex(Formula f | f = getOperand(_) | f.(CallLiteral).getTarget() = target)
122+
)
123+
}
124+
}

ql/src/queries/style/UseSetLiteral.ql

Lines changed: 2 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -9,107 +9,7 @@
99
*/
1010

1111
import ql
12-
13-
/**
14-
* A chain of disjunctions treated as one object. For example the following is
15-
* a chain of disjunctions with three operands:
16-
* ```
17-
* a or b or c
18-
* ```
19-
*/
20-
class DisjunctionChain extends Disjunction {
21-
DisjunctionChain() { not exists(Disjunction parent | parent.getAnOperand() = this) }
22-
23-
/**
24-
* Gets any operand of the chain.
25-
*/
26-
Formula getAnOperandRec() {
27-
result = getAnOperand*() and
28-
not result instanceof Disjunction
29-
}
30-
}
31-
32-
/**
33-
* An equality comparison with a `Literal`. For example:
34-
* ```
35-
* x = 4
36-
* ```
37-
*/
38-
class EqualsLiteral extends ComparisonFormula {
39-
EqualsLiteral() {
40-
getSymbol() = "=" and
41-
getAnOperand() instanceof Literal
42-
}
43-
}
44-
45-
/**
46-
* A chain of disjunctions where each operand is an equality comparison between
47-
* the same thing and various `Literal`s. For example:
48-
* ```
49-
* x = 4 or
50-
* x = 5 or
51-
* x = 6
52-
* ```
53-
*/
54-
class DisjunctionEqualsLiteral extends DisjunctionChain {
55-
DisjunctionEqualsLiteral() {
56-
// VarAccess on the same variable
57-
exists(VarDef v |
58-
forex(Formula f | f = getAnOperandRec() |
59-
f.(EqualsLiteral).getAnOperand().(VarAccess).getDeclaration() = v
60-
)
61-
)
62-
or
63-
// FieldAccess on the same variable
64-
exists(VarDecl v |
65-
forex(Formula f | f = getAnOperandRec() |
66-
f.(EqualsLiteral).getAnOperand().(FieldAccess).getDeclaration() = v
67-
)
68-
)
69-
or
70-
// ThisAccess
71-
forex(Formula f | f = getAnOperandRec() |
72-
f.(EqualsLiteral).getAnOperand() instanceof ThisAccess
73-
)
74-
or
75-
// ResultAccess
76-
forex(Formula f | f = getAnOperandRec() |
77-
f.(EqualsLiteral).getAnOperand() instanceof ResultAccess
78-
)
79-
// (in principle something like GlobalValueNumbering could be used to generalize this)
80-
}
81-
}
82-
83-
/**
84-
* A call with a single `Literal` argument. For example:
85-
* ```
86-
* myPredicate(4)
87-
* ```
88-
*/
89-
class CallLiteral extends Call {
90-
CallLiteral() {
91-
getNumberOfArguments() = 1 and
92-
getArgument(0) instanceof Literal
93-
}
94-
}
95-
96-
/**
97-
* A chain of disjunctions where each operand is a call to the same predicate
98-
* using various `Literal`s. For example:
99-
* ```
100-
* myPredicate(4) or
101-
* myPredicate(5) or
102-
* myPredicate(6)
103-
* ```
104-
*/
105-
class DisjunctionPredicateLiteral extends DisjunctionChain {
106-
DisjunctionPredicateLiteral() {
107-
// Call to the same target
108-
exists(PredicateOrBuiltin target |
109-
forex(Formula f | f = getAnOperandRec() | f.(CallLiteral).getTarget() = target)
110-
)
111-
}
112-
}
12+
import codeql_ql.style.UseSetLiteralQuery
11313

11414
from DisjunctionChain d, string msg, int c
11515
where
@@ -124,6 +24,6 @@ where
12424
"This formula of " + c.toString() +
12525
" predicate calls can be replaced with a single call on a set literal, improving readability."
12626
) and
127-
c = count(d.getAnOperandRec()) and
27+
c = count(d.getOperand(_)) and
12828
c >= 4
12929
select d, msg

0 commit comments

Comments
 (0)