mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +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() }
|
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 */
|
/* Expression Contexts */
|
||||||
/** A context in which an expression used */
|
/** A context in which an expression used */
|
||||||
class ExprContext extends ExprContext_ { }
|
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) {
|
predicate unused_global(Name unused, GlobalVariable v) {
|
||||||
not exists(ImportingStmt is | is.contains(unused)) and
|
not exists(ImportingStmt is | is.contains(unused)) and
|
||||||
forex(DefinitionNode defn | defn.getNode() = unused |
|
forex(DefinitionNode defn | defn.getNode() = unused |
|
||||||
@@ -55,7 +63,8 @@ predicate unused_global(Name unused, GlobalVariable v) {
|
|||||||
unused.defines(v) and
|
unused.defines(v) and
|
||||||
not name_acceptable_for_unused_variable(v) and
|
not name_acceptable_for_unused_variable(v) and
|
||||||
not complex_all(unused.getEnclosingModule())
|
not complex_all(unused.getEnclosingModule())
|
||||||
)
|
) and
|
||||||
|
not used_in_forward_declaration(unused, unused.getEnclosingModule())
|
||||||
}
|
}
|
||||||
|
|
||||||
from Name unused, GlobalVariable v
|
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(','):
|
for tag in value.split(','):
|
||||||
queryset = queryset.filter(**{field_name + '__name': tag})
|
queryset = queryset.filter(**{field_name + '__name': tag})
|
||||||
return queryset
|
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