mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 14:21:24 +00:00
[flake8-bugbear
] Avoid false positive for usage after continue
(B031
) (#10539)
## Summary Closes #10337. I've fixed the code to count usage of variable. Usage count inside the block is reset when there is a following statement. - continue - break - return ## Test Plan Add test case.
This commit is contained in:
parent
021f0bdccb
commit
22f237fec6
3 changed files with 89 additions and 0 deletions
|
@ -174,6 +174,49 @@ for (_key1, _key2), (_value1, _value2) in groupby(
|
||||||
collect_shop_items("Jane", group[1])
|
collect_shop_items("Jane", group[1])
|
||||||
collect_shop_items("Joe", group[1])
|
collect_shop_items("Joe", group[1])
|
||||||
|
|
||||||
|
# Shouldn't trigger the warning when there is a continue, break statement.
|
||||||
|
for _section, section_items in groupby(items, key=lambda p: p[1]):
|
||||||
|
if _section == "greens":
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
continue
|
||||||
|
elif _section == "frozen items":
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
break
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
|
||||||
|
# Shouldn't trigger the warning when there is a return statement.
|
||||||
|
for _section, section_items in groupby(items, key=lambda p: p[1]):
|
||||||
|
if _section == "greens":
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
return
|
||||||
|
elif _section == "frozen items":
|
||||||
|
return section_items
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
|
||||||
|
# Should trigger the warning for duplicate access, even if is a return statement after.
|
||||||
|
for _section, section_items in groupby(items, key=lambda p: p[1]):
|
||||||
|
if _section == "greens":
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Should trigger the warning for duplicate access, even if is a return in another branch.
|
||||||
|
for _section, section_items in groupby(items, key=lambda p: p[1]):
|
||||||
|
if _section == "greens":
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
return
|
||||||
|
elif _section == "frozen items":
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
|
||||||
|
# Should trigger, since only one branch has a return statement.
|
||||||
|
for _section, section_items in groupby(items, key=lambda p: p[1]):
|
||||||
|
if _section == "greens":
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
return
|
||||||
|
elif _section == "frozen items":
|
||||||
|
collect_shop_items(shopper, section_items)
|
||||||
|
collect_shop_items(shopper, section_items) # B031
|
||||||
|
|
||||||
# Let's redefine the `groupby` function to make sure we pick up the correct one.
|
# Let's redefine the `groupby` function to make sure we pick up the correct one.
|
||||||
# NOTE: This should always be at the end of the file.
|
# NOTE: This should always be at the end of the file.
|
||||||
|
|
|
@ -100,6 +100,16 @@ impl<'a> GroupNameFinder<'a> {
|
||||||
self.usage_count += value;
|
self.usage_count += value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset the usage count for the group name by the given value.
|
||||||
|
/// This function is called when there is a `continue`, `break`, or `return` statement.
|
||||||
|
fn reset_usage_count(&mut self) {
|
||||||
|
if let Some(last) = self.counter_stack.last_mut() {
|
||||||
|
*last.last_mut().unwrap() = 0;
|
||||||
|
} else {
|
||||||
|
self.usage_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Visitor<'a> for GroupNameFinder<'a> {
|
impl<'a> Visitor<'a> for GroupNameFinder<'a> {
|
||||||
|
@ -197,6 +207,15 @@ impl<'a> Visitor<'a> for GroupNameFinder<'a> {
|
||||||
self.visit_expr(expr);
|
self.visit_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Stmt::Continue(_) | Stmt::Break(_) => {
|
||||||
|
self.reset_usage_count();
|
||||||
|
}
|
||||||
|
Stmt::Return(ast::StmtReturn { value, range: _ }) => {
|
||||||
|
if let Some(expr) = value {
|
||||||
|
self.visit_expr(expr);
|
||||||
|
}
|
||||||
|
self.reset_usage_count();
|
||||||
|
}
|
||||||
_ => visitor::walk_stmt(self, stmt),
|
_ => visitor::walk_stmt(self, stmt),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,4 +195,31 @@ B031.py:144:33: B031 Using the generator returned from `itertools.groupby()` mor
|
||||||
146 | for group in groupby(items, key=lambda p: p[1]):
|
146 | for group in groupby(items, key=lambda p: p[1]):
|
||||||
|
|
|
|
||||||
|
|
||||||
|
B031.py:200:37: B031 Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage
|
||||||
|
|
|
||||||
|
198 | if _section == "greens":
|
||||||
|
199 | collect_shop_items(shopper, section_items)
|
||||||
|
200 | collect_shop_items(shopper, section_items)
|
||||||
|
| ^^^^^^^^^^^^^ B031
|
||||||
|
201 | return
|
||||||
|
|
|
||||||
|
|
||||||
|
B031.py:210:37: B031 Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage
|
||||||
|
|
|
||||||
|
208 | elif _section == "frozen items":
|
||||||
|
209 | collect_shop_items(shopper, section_items)
|
||||||
|
210 | collect_shop_items(shopper, section_items)
|
||||||
|
| ^^^^^^^^^^^^^ B031
|
||||||
|
211 |
|
||||||
|
212 | # Should trigger, since only one branch has a return statement.
|
||||||
|
|
|
||||||
|
|
||||||
|
B031.py:219:33: B031 Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage
|
||||||
|
|
|
||||||
|
217 | elif _section == "frozen items":
|
||||||
|
218 | collect_shop_items(shopper, section_items)
|
||||||
|
219 | collect_shop_items(shopper, section_items) # B031
|
||||||
|
| ^^^^^^^^^^^^^ B031
|
||||||
|
220 |
|
||||||
|
221 | # Let's redefine the `groupby` function to make sure we pick up the correct one.
|
||||||
|
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue