mirror of https://github.com/astral-sh/ruff
Avoid removing too many imports in `redefined-while-unused` (#15585)
## Summary Closes https://github.com/astral-sh/ruff/issues/15583.
This commit is contained in:
parent
444f799f5e
commit
98fccec2e7
|
|
@ -0,0 +1,9 @@
|
|||
"""Regression test for: https://github.com/astral-sh/ruff/issues/15583"""
|
||||
|
||||
from typing import (
|
||||
List,
|
||||
List,
|
||||
)
|
||||
|
||||
|
||||
def foo() -> List[int]: ...
|
||||
|
|
@ -7,7 +7,7 @@ use libcst_native::{
|
|||
Codegen, CodegenState, Expression, ImportNames, NameOrAttribute, ParenthesizableWhitespace,
|
||||
SmallStatement, Statement,
|
||||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use unicode_normalization::UnicodeNormalization;
|
||||
|
||||
|
|
@ -81,10 +81,20 @@ pub(crate) fn remove_imports<'a>(
|
|||
// Preserve the trailing comma (or not) from the last entry.
|
||||
let trailing_comma = aliases.last().and_then(|alias| alias.comma.clone());
|
||||
|
||||
// Remove any imports that are specified in the `imports` iterator.
|
||||
let member_names = member_names.collect::<FxHashSet<_>>();
|
||||
// Remove any imports that are specified in the `imports` iterator (but, e.g., if the name is
|
||||
// provided once, only remove the first occurrence).
|
||||
let mut counts = member_names.fold(FxHashMap::<&str, usize>::default(), |mut map, name| {
|
||||
map.entry(name).and_modify(|c| *c += 1).or_insert(1);
|
||||
map
|
||||
});
|
||||
aliases.retain(|alias| {
|
||||
!member_names.contains(qualified_name_from_name_or_attribute(&alias.name).as_str())
|
||||
let name = qualified_name_from_name_or_attribute(&alias.name);
|
||||
if let Some(count) = counts.get_mut(name.as_str()).filter(|count| **count > 0) {
|
||||
*count -= 1;
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
// But avoid destroying any trailing comments.
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ mod tests {
|
|||
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_29.pyi"))]
|
||||
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_30.py"))]
|
||||
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_31.py"))]
|
||||
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_32.py"))]
|
||||
#[test_case(Rule::UndefinedName, Path::new("F821_0.py"))]
|
||||
#[test_case(Rule::UndefinedName, Path::new("F821_1.py"))]
|
||||
#[test_case(Rule::UndefinedName, Path::new("F821_2.py"))]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pyflakes/mod.rs
|
||||
---
|
||||
F811_32.py:5:5: F811 [*] Redefinition of unused `List` from line 4
|
||||
|
|
||||
3 | from typing import (
|
||||
4 | List,
|
||||
5 | List,
|
||||
| ^^^^ F811
|
||||
6 | )
|
||||
|
|
||||
= help: Remove definition: `List`
|
||||
|
||||
ℹ Safe fix
|
||||
2 2 |
|
||||
3 3 | from typing import (
|
||||
4 4 | List,
|
||||
5 |- List,
|
||||
6 5 | )
|
||||
7 6 |
|
||||
8 7 |
|
||||
Loading…
Reference in New Issue