Python: Modernise py/unused-loop-variable

This commit is contained in:
Rasmus Wriedt Larsen
2019-12-16 13:19:17 +01:00
parent 8f7ba0a06d
commit 81e27aab8d
3 changed files with 31 additions and 18 deletions

View File

@@ -15,7 +15,7 @@ import Definition
predicate is_increment(Stmt s) {
/* x += n */
s.(AugAssign).getValue() instanceof IntegerLiteral
s.(AugAssign).getValue() instanceof IntegerLiteral
or
/* x = x + n */
exists(Name t, BinaryExpr add |
@@ -36,7 +36,7 @@ predicate empty_loop(For f) {
predicate one_item_only(For f) {
not exists(Continue c | f.contains(c)) and
exists(Stmt s |
exists(Stmt s |
s = f.getBody().getLastItem() |
s instanceof Return
or
@@ -45,13 +45,13 @@ predicate one_item_only(For f) {
}
predicate points_to_call_to_range(ControlFlowNode f) {
/* (x)range is a function in Py2 and a class in Py3, so we must treat it as a plain object */
exists(Object range, Object call |
range = Object::builtin("range") or
range = Object::builtin("xrange")
/* (x)range is a function in Py2 and a class in Py3, so we must treat it as a plain object */
exists(Value range, Value call |
range = Value::named("range") or
range = Value::named("xrange")
|
f.refersTo(call) and
call.(CallNode).getFunction().refersTo(range)
f.pointsTo(call) and
call.getACall().getFunction().pointsTo(range)
)
or
/* In case points-to fails due to 'from six.moves import range' or similar. */
@@ -60,11 +60,10 @@ predicate points_to_call_to_range(ControlFlowNode f) {
range = "range" or range = "xrange"
)
or
/* If range is wrapped in a list it is still a range */
exists(CallNode call |
f.refersTo(call) and
call = theListType().getACall() and
points_to_call_to_range(call.getArg(0))
/* Handle list(range(...)) and list(list(range(...))) */
(
f.(CallNode).pointsTo().getClass() = ClassValue::list() and
points_to_call_to_range(f.(CallNode).getArg(0))
)
}
@@ -100,7 +99,7 @@ predicate implicit_repeat(For f) {
* E.g. gets `x` from `{ y for y in x }`.
*/
ControlFlowNode get_comp_iterable(For f) {
exists(Comp c |
exists(Comp c |
c.getFunction().getStmt(0) = f |
c.getAFlowNode().getAPredecessor() = result
)

View File

@@ -211,7 +211,7 @@ module Value {
}
/** Gets the `Value` for the integer constant `i`, if it exists.
* There will be no `Value` for most integers, but the following are
* There will be no `Value` for most integers, but the following are
* guaranteed to exist:
* * From zero to 511 inclusive.
* * All powers of 2 (up to 2**30)
@@ -634,6 +634,11 @@ module ClassValue {
result = TBuiltinClassObject(Builtin::special("float"))
}
/** Get the `ClassValue` for the `list` class. */
ClassValue list() {
result = TBuiltinClassObject(Builtin::special("list"))
}
/** Get the `ClassValue` for the `bytes` class (also called `str` in Python 2). */
ClassValue bytes() {
result = TBuiltinClassObject(Builtin::special("bytes"))

View File

@@ -10,7 +10,7 @@ def OK1(seq):
for _ in seq:
do_something()
print("Hi")
#OK counting
def OK2(seq):
i = 3
@@ -29,7 +29,7 @@ def OK4(n):
r = range(n)
for i in r:
print("x")
#OK named as unused
def OK5(seq):
for unused_x in seq:
@@ -77,7 +77,7 @@ def fail4(coll, sequence):
x = coll.pop()
for s in sequence:
do_something(x+1)
#OK See ODASA-4153 and ODASA-4533
def fail5(t):
x, y = t
@@ -106,3 +106,12 @@ def cleanup(sessions):
for sess in sessions:
# Original code had some comment about deleting sessions
del sess
# For SuspiciousUnusedLoopIterationVariable.ql
# ok
for x in list(range(100)):
print('hi')
# ok
for y in list(list(range(100))):
print('hi')