mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
Python: Remove a few false positives from py/unused-import.
This commit is contained in:
@@ -58,16 +58,28 @@ predicate imported_module_used_in_doctest(Import imp) {
|
||||
}
|
||||
|
||||
predicate imported_module_used_in_typehint(Import imp) {
|
||||
exists(string modname |
|
||||
imp.getAName().getAsname().(Name).getId() = modname
|
||||
and
|
||||
exists(string modname, Location loc |
|
||||
imp.getAName().getAsname().(Name).getId() = modname and
|
||||
loc.getFile() = imp.getScope().(Module).getFile()
|
||||
|
|
||||
/* Look for typehints containing the patterns:
|
||||
* # type: …name…
|
||||
*/
|
||||
exists(Comment typehint |
|
||||
typehint.getLocation().getFile() = imp.getScope().(Module).getFile() and
|
||||
loc = typehint.getLocation() and
|
||||
typehint.getText().regexpMatch("# type:.*" + modname + ".*")
|
||||
)
|
||||
or
|
||||
// Type hint is inside a string annotation, as needed for forward references
|
||||
exists(string typehint, Expr annotation |
|
||||
annotation = any(Arguments a).getAnAnnotation()
|
||||
or
|
||||
annotation = any(AnnAssign a).getAnnotation()
|
||||
|
|
||||
annotation.pointsTo(Value::forString(typehint)) and
|
||||
loc = annotation.getLocation() and
|
||||
typehint.regexpMatch(".*\\b" + modname + "\\b.*")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -100,6 +112,11 @@ predicate unused_import(Import imp, Variable name) {
|
||||
not imported_module_used_in_doctest(imp)
|
||||
and
|
||||
not imported_module_used_in_typehint(imp)
|
||||
and
|
||||
/* Only consider import statements that actually point-to something (possibly an unknown module).
|
||||
* If this is not the case, it's likely that the import statement never gets executed.
|
||||
*/
|
||||
imp.getAName().getValue().pointsTo(_)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -76,3 +76,17 @@ import typing
|
||||
|
||||
foo = None # type: typing.Optional[int]
|
||||
|
||||
|
||||
# OK since the import statement is never executed
|
||||
if False:
|
||||
import never_imported
|
||||
|
||||
# OK since the imported module is used in a forward-referenced type annotation.
|
||||
import only_used_in_parameter_annotation
|
||||
|
||||
def func(x: 'Optional[only_used_in_parameter_annotation]'):
|
||||
pass
|
||||
|
||||
import only_used_in_annotated_assignment
|
||||
|
||||
var : 'Optional[only_used_in_annotated_assignment]' = 5
|
||||
|
||||
Reference in New Issue
Block a user