mirror of
https://github.com/github/codeql.git
synced 2025-12-16 08:43:11 +01:00
Merge pull request #18921 from github/tausbn/python-fix-unused-global-variable-in-forward-annotation-fp
Python: Add support for forward references in unused var query
This commit is contained in:
@@ -746,6 +746,24 @@ class Guard extends Guard_ {
|
||||
override Expr getASubExpression() { result = this.getTest() }
|
||||
}
|
||||
|
||||
/** An annotation, such as the `int` part of `x: int` */
|
||||
class Annotation extends Expr {
|
||||
Annotation() {
|
||||
this = any(AnnAssign a).getAnnotation()
|
||||
or
|
||||
exists(Arguments args |
|
||||
this in [
|
||||
args.getAnAnnotation(),
|
||||
args.getAKwAnnotation(),
|
||||
args.getKwargannotation(),
|
||||
args.getVarargannotation()
|
||||
]
|
||||
)
|
||||
or
|
||||
this = any(FunctionExpr f).getReturns()
|
||||
}
|
||||
}
|
||||
|
||||
/* Expression Contexts */
|
||||
/** A context in which an expression used */
|
||||
class ExprContext extends ExprContext_ { }
|
||||
|
||||
@@ -34,6 +34,14 @@ predicate complex_all(Module m) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate used_in_forward_declaration(Name used, Module mod) {
|
||||
exists(StringLiteral s, Annotation annotation |
|
||||
s.getS() = used.getId() and
|
||||
s.getEnclosingModule() = mod and
|
||||
annotation.getASubExpression*() = s
|
||||
)
|
||||
}
|
||||
|
||||
predicate unused_global(Name unused, GlobalVariable v) {
|
||||
not exists(ImportingStmt is | is.contains(unused)) and
|
||||
forex(DefinitionNode defn | defn.getNode() = unused |
|
||||
@@ -55,7 +63,8 @@ predicate unused_global(Name unused, GlobalVariable v) {
|
||||
unused.defines(v) and
|
||||
not name_acceptable_for_unused_variable(v) and
|
||||
not complex_all(unused.getEnclosingModule())
|
||||
)
|
||||
) and
|
||||
not used_in_forward_declaration(unused, unused.getEnclosingModule())
|
||||
}
|
||||
|
||||
from Name unused, GlobalVariable v
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
|
||||
- The `py/unused-global-variable` now no longer flags variables that are only used in forward references (e.g. the `Foo` in `def bar(x: "Foo"): ...`).
|
||||
@@ -137,3 +137,21 @@ def test_dict_unpacking(queryset, field_name, value):
|
||||
for tag in value.split(','):
|
||||
queryset = queryset.filter(**{field_name + '__name': tag})
|
||||
return queryset
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
ParamAnnotation = int
|
||||
ReturnAnnotation = int
|
||||
AssignmentAnnotation = int
|
||||
ForwardParamAnnotation = int
|
||||
ForwardReturnAnnotation = int
|
||||
ForwardAssignmentAnnotation = int
|
||||
|
||||
def test_direct_annotation(x: ParamAnnotation) -> ReturnAnnotation:
|
||||
if x:
|
||||
y : AssignmentAnnotation = 1
|
||||
|
||||
def test_forward_annotation(x: "ForwardParamAnnotation") -> "ForwardReturnAnnotation":
|
||||
if x:
|
||||
y : "ForwardAssignmentAnnotation" = 1
|
||||
|
||||
Reference in New Issue
Block a user