-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathUnusedImport.ql
More file actions
74 lines (67 loc) · 2.16 KB
/
UnusedImport.ql
File metadata and controls
74 lines (67 loc) · 2.16 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
63
64
65
66
67
68
69
70
71
72
73
/**
* @name Unused import
* @description Import is not required as it is not used
* @kind problem
* @tags maintainability
* useless-code
* @problem.severity recommendation
* @sub-severity high
* @precision very-high
* @id py/unused-import
*/
import python
import Variables.Definition
predicate global_name_used(Module m, Variable name) {
exists (Name u, GlobalVariable v |
u.uses(v) and
v.getId() = name.getId() and
u.getEnclosingModule() = m
)
or
/* A use of an undefined class local variable, will use the global variable */
exists(Name u, LocalVariable v |
u.uses(v) and
v.getId() = name.getId() and
u.getEnclosingModule() = m and
not v.getScope().getEnclosingScope*() instanceof Function
)
}
/** Holds if a module has `__all__` but we don't understand it */
predicate all_not_understood(Module m) {
exists(GlobalVariable a |
a.getId() = "__all__" and a.getScope() = m |
/* __all__ is not defined as a simple list */
not m.declaredInAll(_)
or
/* __all__ is modified */
exists(Call c | c.getFunc().(Attribute).getObject() = a.getALoad())
)
}
predicate unused_import(Import imp, Variable name) {
((Name)imp.getAName().getAsname()).getVariable() = name
and
not imp.getAnImportedModuleName() = "__future__"
and
not imp.getEnclosingModule().declaredInAll(name.getId())
and
imp.getScope() = imp.getEnclosingModule()
and
not global_name_used(imp.getScope(), name)
and
/* Imports in __init__.py are used to force module loading */
not imp.getEnclosingModule().isPackageInit()
and
/* Name may be imported for use in epytext documentation */
not exists(Comment cmt |
cmt.getText().matches("%L{" + name.getId() + "}%") |
cmt.getLocation().getFile() = imp.getLocation().getFile()
)
and
not name_acceptable_for_unused_variable(name)
and
/* Assume that opaque `__all__` includes imported module */
not all_not_understood(imp.getEnclosingModule())
}
from Stmt s, Variable name
where unused_import(s, name)
select s, "Import of '" + name.getId() + "' is not used."