mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:10:09 +00:00
Avoid PERF401
if conditional depends on list var (#5603)
## Summary Avoid `PERF401` if conditional depends on list var ## Test Plan `cargo test` fixes: #5581
This commit is contained in:
parent
9dd05424c4
commit
6a4b216362
2 changed files with 40 additions and 5 deletions
|
@ -37,3 +37,11 @@ def f():
|
||||||
result = {}
|
result = {}
|
||||||
for i in items:
|
for i in items:
|
||||||
result[i].append(i) # OK
|
result[i].append(i) # OK
|
||||||
|
|
||||||
|
|
||||||
|
def f():
|
||||||
|
items = [1, 2, 3, 4]
|
||||||
|
result = []
|
||||||
|
for i in items:
|
||||||
|
if i not in result:
|
||||||
|
result.append(i) # OK
|
||||||
|
|
|
@ -57,26 +57,28 @@ pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, bo
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let (stmt, conditional) = match body {
|
let (stmt, if_test) = match body {
|
||||||
// ```python
|
// ```python
|
||||||
// for x in y:
|
// for x in y:
|
||||||
// if z:
|
// if z:
|
||||||
// filtered.append(x)
|
// filtered.append(x)
|
||||||
// ```
|
// ```
|
||||||
[Stmt::If(ast::StmtIf { body, orelse, .. })] => {
|
[Stmt::If(ast::StmtIf {
|
||||||
|
body, orelse, test, ..
|
||||||
|
})] => {
|
||||||
if !orelse.is_empty() {
|
if !orelse.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let [stmt] = body.as_slice() else {
|
let [stmt] = body.as_slice() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
(stmt, true)
|
(stmt, Some(test))
|
||||||
}
|
}
|
||||||
// ```python
|
// ```python
|
||||||
// for x in y:
|
// for x in y:
|
||||||
// filtered.append(f(x))
|
// filtered.append(f(x))
|
||||||
// ```
|
// ```
|
||||||
[stmt] => (stmt, false),
|
[stmt] => (stmt, None),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,7 +105,7 @@ pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, bo
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ignore direct list copies (e.g., `for x in y: filtered.append(x)`).
|
// Ignore direct list copies (e.g., `for x in y: filtered.append(x)`).
|
||||||
if !conditional {
|
if if_test.is_none() {
|
||||||
if arg.as_name_expr().map_or(false, |arg| arg.id == *id) {
|
if arg.as_name_expr().map_or(false, |arg| arg.id == *id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -124,6 +126,31 @@ pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, bo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Avoid if the value is used in the conditional test, e.g.,
|
||||||
|
//
|
||||||
|
// ```python
|
||||||
|
// for x in y:
|
||||||
|
// if x in filtered:
|
||||||
|
// filtered.append(x)
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Converting this to a list comprehension would raise a `NameError` as
|
||||||
|
// `filtered` is not defined yet:
|
||||||
|
//
|
||||||
|
// ```python
|
||||||
|
// filtered = [x for x in y if x in filtered]
|
||||||
|
// ```
|
||||||
|
if let Some(value_name) = value.as_name_expr() {
|
||||||
|
if if_test.map_or(false, |test| {
|
||||||
|
any_over_expr(test, &|expr| {
|
||||||
|
expr.as_name_expr()
|
||||||
|
.map_or(false, |expr| expr.id == value_name.id)
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
.push(Diagnostic::new(ManualListComprehension, *range));
|
.push(Diagnostic::new(ManualListComprehension, *range));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue