-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathOmittableExists.ql
More file actions
39 lines (35 loc) · 1.46 KB
/
OmittableExists.ql
File metadata and controls
39 lines (35 loc) · 1.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* @name Omittable 'exists' variable
* @description Writing 'exists(x | pred(x))' is bad practice and can be omitted.
* @kind problem
* @problem.severity warning
* @precision high
* @id ql/omittable-exists
* @tags maintainability
*/
import ql
import codeql_ql.style.ConjunctionParent
/**
* Holds if `existsArgument` is the declaration of a variable in an `exists` formula,
* and `use` is both its only use and an argument of a predicate that doesn't restrict
* the corresponding parameter type.
*/
predicate omittableExists(VarDecl existsArgument, VarAccess use) {
existsArgument = any(Exists e).getAnArgument() and
use = unique( | | existsArgument.getAnAccess()) and
exists(Call c, int argPos, Type paramType |
c.getArgument(argPos) = use and paramType = c.getTarget().getParameterType(argPos)
|
existsArgument.getType() = paramType.getASuperType*() and
not paramType instanceof DatabaseType
)
}
/** Holds if `p` is an exists variable (either declaration or use) that can be omitted. */
predicate omittableExistsNode(AstNode p) { omittableExists(p, _) or omittableExists(_, p) }
from VarDecl existsArgument, VarAccess use
where
omittableExists(existsArgument, use) and
ConjunctionParent<omittableExistsNode/1>::getConjunctionParent(existsArgument) =
ConjunctionParent<omittableExistsNode/1>::getConjunctionParent(use)
select existsArgument, "This exists variable can be omitted by using a don't-care expression $@.",
use, "in this argument"