-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathUnusedModuleVariable.ql
More file actions
62 lines (58 loc) · 2.26 KB
/
UnusedModuleVariable.ql
File metadata and controls
62 lines (58 loc) · 2.26 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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* @name Unused global variable
* @description Global variable is defined but not used
* @kind problem
* @tags efficiency
* useless-code
* external/cwe/cwe-563
* @problem.severity recommendation
* @sub-severity low
* @precision high
* @id py/unused-global-variable
*/
import python
import Definition
/** Whether the module contains an __all__ definition,
* but it is more complex than a simple list of strings */
predicate complex_all(Module m) {
exists(Assign a, GlobalVariable all |
a.defines(all) and a.getScope() = m and all.getId() = "__all__" |
not a.getValue() instanceof List or
exists(Expr e |
e = a.getValue().(List).getAnElt() |
not e instanceof StrConst
)
)
or
exists(Call c, GlobalVariable all |
c.getFunc().(Attribute).getObject() = all.getALoad() and
c.getScope() = m and all.getId() = "__all__"
)
}
predicate unused_global(Name unused, GlobalVariable v) {
not exists(ImportingStmt is | is.contains(unused)) and
forex(DefinitionNode defn |
defn.getNode() = unused |
not defn.getValue().getNode() instanceof FunctionExpr and
not defn.getValue().getNode() instanceof ClassExpr and
not exists(Name u |
// A use of the variable
u.uses(v) |
// That is reachable from this definition, directly
defn.strictlyReaches(u.getAFlowNode())
or // indirectly
defn.getBasicBlock().reachesExit() and u.getScope() != unused.getScope()
) and
not unused.getEnclosingModule().getAnExport() = v.getId() and
not exists(unused.getParentNode().(ClassDef).getDefinedClass().getADecorator()) and
not exists(unused.getParentNode().(FunctionDef).getDefinedFunction().getADecorator()) and
unused.defines(v) and
not name_acceptable_for_unused_variable(v) and
not complex_all(unused.getEnclosingModule())
)
}
from Name unused, GlobalVariable v
where unused_global(unused, v) and
// If unused is part of a tuple, count it as unused if all elements of that tuple are unused.
forall(Name el | el = unused.getParentNode().(Tuple).getAnElt() | unused_global(el, _))
select unused, "The global variable '" + v.getId() + "' is not used."