mirror of https://github.com/astral-sh/ruff
Avoid duplicates in if-with-same-arms (#2827)
This commit is contained in:
parent
5a34504149
commit
8b35b052b8
|
|
@ -1259,7 +1259,7 @@ For more, see [flake8-simplify](https://pypi.org/project/flake8-simplify/) on Py
|
||||||
| SIM110 | convert-loop-to-any | Use `{any}` instead of `for` loop | 🛠 |
|
| SIM110 | convert-loop-to-any | Use `{any}` instead of `for` loop | 🛠 |
|
||||||
| SIM111 | convert-loop-to-all | Use `{all}` instead of `for` loop | 🛠 |
|
| SIM111 | convert-loop-to-all | Use `{all}` instead of `for` loop | 🛠 |
|
||||||
| SIM112 | use-capital-environment-variables | Use capitalized environment variable `{expected}` instead of `{original}` | 🛠 |
|
| SIM112 | use-capital-environment-variables | Use capitalized environment variable `{expected}` instead of `{original}` | 🛠 |
|
||||||
| SIM114 | [if-with-same-arms](https://github.com/charliermarsh/ruff/blob/main/docs/rules/if-with-same-arms.md) | Combine `if` statements using `or` | |
|
| SIM114 | [if-with-same-arms](https://github.com/charliermarsh/ruff/blob/main/docs/rules/if-with-same-arms.md) | Combine `if` branches using logical `or` operator | |
|
||||||
| SIM115 | open-file-with-context-handler | Use context handler for opening files | |
|
| SIM115 | open-file-with-context-handler | Use context handler for opening files | |
|
||||||
| SIM117 | multiple-with-statements | Use a single `with` statement with multiple contexts instead of nested `with` statements | 🛠 |
|
| SIM117 | multiple-with-statements | Use a single `with` statement with multiple contexts instead of nested `with` statements | 🛠 |
|
||||||
| SIM118 | key-in-dict | Use `{key} in {dict}` instead of `{key} in {dict}.keys()` | 🛠 |
|
| SIM118 | key-in-dict | Use `{key} in {dict}` instead of `{key} in {dict}.keys()` | 🛠 |
|
||||||
|
|
|
||||||
|
|
@ -55,16 +55,13 @@ if (
|
||||||
elif 1 == 2:
|
elif 1 == 2:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
failures = errors = skipped = disabled = 0
|
|
||||||
if result.eofs == "O":
|
if result.eofs == "O":
|
||||||
pass
|
pass
|
||||||
elif result.eofs == "S":
|
elif result.eofs == "S":
|
||||||
skipped = 1
|
skipped = 1
|
||||||
elif result.eofs == "F":
|
elif result.eofs == "F":
|
||||||
failures = 1
|
|
||||||
elif result.eofs == "E":
|
|
||||||
errors = 1
|
errors = 1
|
||||||
else:
|
elif result.eofs == "E":
|
||||||
errors = 1
|
errors = 1
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -91,3 +88,9 @@ elif b:
|
||||||
z = 2
|
z = 2
|
||||||
elif c:
|
elif c:
|
||||||
z = 1
|
z = 1
|
||||||
|
|
||||||
|
# False negative (or arguably a different rule)
|
||||||
|
if result.eofs == "F":
|
||||||
|
errors = 1
|
||||||
|
else:
|
||||||
|
errors = 1
|
||||||
|
|
|
||||||
|
|
@ -1513,7 +1513,11 @@ where
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if self.settings.rules.enabled(&Rule::IfWithSameArms) {
|
if self.settings.rules.enabled(&Rule::IfWithSameArms) {
|
||||||
flake8_simplify::rules::if_with_same_arms(self, body, orelse);
|
flake8_simplify::rules::if_with_same_arms(
|
||||||
|
self,
|
||||||
|
stmt,
|
||||||
|
self.current_stmt_parent().map(std::convert::Into::into),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if self.settings.rules.enabled(&Rule::NeedlessBool) {
|
if self.settings.rules.enabled(&Rule::NeedlessBool) {
|
||||||
flake8_simplify::rules::return_bool_condition_directly(self, stmt);
|
flake8_simplify::rules::return_bool_condition_directly(self, stmt);
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ define_violation!(
|
||||||
impl Violation for IfWithSameArms {
|
impl Violation for IfWithSameArms {
|
||||||
#[derive_message_formats]
|
#[derive_message_formats]
|
||||||
fn message(&self) -> String {
|
fn message(&self) -> String {
|
||||||
format!("Combine `if` statements using `or`")
|
format!("Combine `if` branches using logical `or` operator")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -497,57 +497,73 @@ pub fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: Option<&
|
||||||
checker.diagnostics.push(diagnostic);
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_if_body_pairs(orelse: &[Stmt], result: &mut Vec<Vec<Stmt>>) {
|
fn get_if_body_pairs<'a>(
|
||||||
if orelse.is_empty() {
|
test: &'a Expr,
|
||||||
return;
|
body: &'a [Stmt],
|
||||||
}
|
orelse: &'a [Stmt],
|
||||||
let mut current_vec: Vec<Stmt> = vec![];
|
) -> Vec<(&'a Expr, &'a [Stmt])> {
|
||||||
for if_line in orelse {
|
let mut pairs = vec![(test, body)];
|
||||||
if let StmtKind::If {
|
let mut orelse = orelse;
|
||||||
body: orelse_body,
|
loop {
|
||||||
orelse: orelse_orelse,
|
if orelse.len() != 1 {
|
||||||
..
|
break;
|
||||||
} = &if_line.node
|
|
||||||
{
|
|
||||||
if !current_vec.is_empty() {
|
|
||||||
result.push(current_vec.clone());
|
|
||||||
current_vec = vec![];
|
|
||||||
}
|
|
||||||
if !orelse_body.is_empty() {
|
|
||||||
result.push(orelse_body.clone());
|
|
||||||
}
|
|
||||||
get_if_body_pairs(orelse_orelse, result);
|
|
||||||
} else {
|
|
||||||
current_vec.push(if_line.clone());
|
|
||||||
}
|
}
|
||||||
|
let StmtKind::If { test, body, orelse: orelse_orelse, .. } = &orelse[0].node else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
pairs.push((test, body));
|
||||||
|
orelse = orelse_orelse;
|
||||||
}
|
}
|
||||||
if !current_vec.is_empty() {
|
pairs
|
||||||
result.push(current_vec.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SIM114
|
/// SIM114
|
||||||
pub fn if_with_same_arms(checker: &mut Checker, body: &[Stmt], orelse: &[Stmt]) {
|
pub fn if_with_same_arms(checker: &mut Checker, stmt: &Stmt, parent: Option<&Stmt>) {
|
||||||
if orelse.is_empty() {
|
let StmtKind::If { test, body, orelse } = &stmt.node else {
|
||||||
return;
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// It's part of a bigger if-elif block:
|
||||||
|
// https://github.com/MartinThoma/flake8-simplify/issues/115
|
||||||
|
if let Some(StmtKind::If {
|
||||||
|
orelse: parent_orelse,
|
||||||
|
..
|
||||||
|
}) = parent.map(|parent| &parent.node)
|
||||||
|
{
|
||||||
|
if parent_orelse.len() == 1 && stmt == &parent_orelse[0] {
|
||||||
|
// TODO(charlie): These two cases have the same AST:
|
||||||
|
//
|
||||||
|
// if True:
|
||||||
|
// pass
|
||||||
|
// elif a:
|
||||||
|
// b = 1
|
||||||
|
// else:
|
||||||
|
// b = 2
|
||||||
|
//
|
||||||
|
// if True:
|
||||||
|
// pass
|
||||||
|
// else:
|
||||||
|
// if a:
|
||||||
|
// b = 1
|
||||||
|
// else:
|
||||||
|
// b = 2
|
||||||
|
//
|
||||||
|
// We want to flag the latter, but not the former. Right now, we flag neither.
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's not all combinations because of this:
|
let if_body_pairs = get_if_body_pairs(test, body, orelse);
|
||||||
// https://github.com/MartinThoma/flake8-simplify/issues/70#issuecomment-924074984
|
for i in 0..(if_body_pairs.len() - 1) {
|
||||||
let mut final_stmts: Vec<Vec<Stmt>> = vec![body.to_vec()];
|
let (test, body) = &if_body_pairs[i];
|
||||||
get_if_body_pairs(orelse, &mut final_stmts);
|
let (.., next_body) = &if_body_pairs[i + 1];
|
||||||
let if_statements = final_stmts.len();
|
if compare_body(body, next_body) {
|
||||||
if if_statements <= 1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 0..(if_statements - 1) {
|
|
||||||
if compare_body(&final_stmts[i], &final_stmts[i + 1]) {
|
|
||||||
let first = &final_stmts[i].first().unwrap();
|
|
||||||
let last = &final_stmts[i].last().unwrap();
|
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
IfWithSameArms,
|
IfWithSameArms,
|
||||||
Range::new(first.location, last.end_location.unwrap()),
|
Range::new(
|
||||||
|
if i == 0 { stmt.location } else { test.location },
|
||||||
|
next_body.last().unwrap().end_location.unwrap(),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,30 +5,40 @@ expression: diagnostics
|
||||||
- kind:
|
- kind:
|
||||||
IfWithSameArms: ~
|
IfWithSameArms: ~
|
||||||
location:
|
location:
|
||||||
row: 3
|
row: 2
|
||||||
column: 4
|
column: 0
|
||||||
end_location:
|
end_location:
|
||||||
row: 3
|
row: 5
|
||||||
column: 5
|
column: 5
|
||||||
fix: ~
|
fix: ~
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
IfWithSameArms: ~
|
IfWithSameArms: ~
|
||||||
location:
|
location:
|
||||||
row: 8
|
row: 7
|
||||||
column: 4
|
column: 0
|
||||||
end_location:
|
end_location:
|
||||||
row: 9
|
row: 12
|
||||||
column: 22
|
column: 22
|
||||||
fix: ~
|
fix: ~
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
IfWithSameArms: ~
|
IfWithSameArms: ~
|
||||||
location:
|
location:
|
||||||
row: 15
|
row: 14
|
||||||
column: 4
|
column: 0
|
||||||
end_location:
|
end_location:
|
||||||
row: 17
|
row: 21
|
||||||
|
column: 26
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
IfWithSameArms: ~
|
||||||
|
location:
|
||||||
|
row: 23
|
||||||
|
column: 0
|
||||||
|
end_location:
|
||||||
|
row: 36
|
||||||
column: 26
|
column: 26
|
||||||
fix: ~
|
fix: ~
|
||||||
parent: ~
|
parent: ~
|
||||||
|
|
@ -45,70 +55,30 @@ expression: diagnostics
|
||||||
- kind:
|
- kind:
|
||||||
IfWithSameArms: ~
|
IfWithSameArms: ~
|
||||||
location:
|
location:
|
||||||
row: 25
|
row: 31
|
||||||
column: 8
|
column: 4
|
||||||
end_location:
|
end_location:
|
||||||
row: 26
|
row: 36
|
||||||
column: 26
|
column: 26
|
||||||
fix: ~
|
fix: ~
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
IfWithSameArms: ~
|
IfWithSameArms: ~
|
||||||
location:
|
location:
|
||||||
row: 32
|
row: 38
|
||||||
column: 8
|
column: 0
|
||||||
end_location:
|
end_location:
|
||||||
row: 33
|
row: 56
|
||||||
column: 26
|
|
||||||
fix: ~
|
|
||||||
parent: ~
|
|
||||||
- kind:
|
|
||||||
IfWithSameArms: ~
|
|
||||||
location:
|
|
||||||
row: 54
|
|
||||||
column: 4
|
|
||||||
end_location:
|
|
||||||
row: 54
|
|
||||||
column: 8
|
column: 8
|
||||||
fix: ~
|
fix: ~
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind:
|
- kind:
|
||||||
IfWithSameArms: ~
|
IfWithSameArms: ~
|
||||||
location:
|
location:
|
||||||
row: 66
|
row: 62
|
||||||
column: 4
|
column: 5
|
||||||
end_location:
|
end_location:
|
||||||
row: 66
|
row: 65
|
||||||
column: 14
|
|
||||||
fix: ~
|
|
||||||
parent: ~
|
|
||||||
- kind:
|
|
||||||
IfWithSameArms: ~
|
|
||||||
location:
|
|
||||||
row: 66
|
|
||||||
column: 4
|
|
||||||
end_location:
|
|
||||||
row: 66
|
|
||||||
column: 14
|
|
||||||
fix: ~
|
|
||||||
parent: ~
|
|
||||||
- kind:
|
|
||||||
IfWithSameArms: ~
|
|
||||||
location:
|
|
||||||
row: 66
|
|
||||||
column: 4
|
|
||||||
end_location:
|
|
||||||
row: 66
|
|
||||||
column: 14
|
|
||||||
fix: ~
|
|
||||||
parent: ~
|
|
||||||
- kind:
|
|
||||||
IfWithSameArms: ~
|
|
||||||
location:
|
|
||||||
row: 66
|
|
||||||
column: 4
|
|
||||||
end_location:
|
|
||||||
row: 66
|
|
||||||
column: 14
|
column: 14
|
||||||
fix: ~
|
fix: ~
|
||||||
parent: ~
|
parent: ~
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue