-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[
flake8-pyi
] Implement PYI018 (#6018)
## Summary Check for unused private `TypeVar`. See [original implementation](https://github.com/PyCQA/flake8-pyi/blob/2a86db8271dc500247a8a69419536240334731cf/pyi.py#L1958). ``` $ flake8 --select Y018 crates/ruff/resources/test/fixtures/flake8_pyi/PYI018.pyi crates/ruff/resources/test/fixtures/flake8_pyi/PYI018.pyi:4:1: Y018 TypeVar "_T" is not used crates/ruff/resources/test/fixtures/flake8_pyi/PYI018.pyi:5:1: Y018 TypeVar "_P" is not used ``` ``` $ ./target/debug/ruff --select PYI018 crates/ruff/resources/test/fixtures/flake8_pyi/PYI018.pyi --no-cache crates/ruff/resources/test/fixtures/flake8_pyi/PYI018.pyi:4:1: PYI018 TypeVar `_T` is never used crates/ruff/resources/test/fixtures/flake8_pyi/PYI018.pyi:5:1: PYI018 TypeVar `_P` is never used Found 2 errors. ``` In the file `unused_private_type_declaration.rs`, I'm planning to add other rules that are similar to `PYI018` like the `PYI046`, `PYI047` and `PYI049`. ref #848 ## Test Plan Snapshots and manual runs of flake8.
- Loading branch information
1 parent
788643f
commit c0dbcb3
Showing
12 changed files
with
149 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import typing | ||
from typing import TypeVar | ||
|
||
_T = typing.TypeVar("_T") | ||
_P = TypeVar("_P") | ||
|
||
# OK | ||
_UsedTypeVar = TypeVar("_UsedTypeVar") | ||
def func(arg: _UsedTypeVar) -> _UsedTypeVar: ... | ||
|
||
_A, _B = TypeVar("_A"), TypeVar("_B") | ||
_C = _D = TypeVar("_C") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import typing | ||
from typing import TypeVar | ||
|
||
_T = typing.TypeVar("_T") | ||
_P = TypeVar("_P") | ||
|
||
# OK | ||
_UsedTypeVar = TypeVar("_UsedTypeVar") | ||
def func(arg: _UsedTypeVar) -> _UsedTypeVar: ... | ||
|
||
_A, _B = TypeVar("_A"), TypeVar("_B") | ||
_C = _D = TypeVar("_C") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
crates/ruff/src/rules/flake8_pyi/rules/unused_private_type_definition.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use ruff_diagnostics::{Diagnostic, Violation}; | ||
use ruff_macros::{derive_message_formats, violation}; | ||
use ruff_python_semantic::Binding; | ||
use rustpython_parser::ast::{self, Expr, Stmt}; | ||
|
||
use crate::checkers::ast::Checker; | ||
|
||
/// ## What it does | ||
/// Checks for the presence of unused private `TypeVar` declarations. | ||
/// | ||
/// ## Why is this bad? | ||
/// A private `TypeVar` that is defined but not used is likely a mistake, and | ||
/// should be removed to avoid confusion. | ||
/// | ||
/// ## Example | ||
/// ```python | ||
/// import typing | ||
/// | ||
/// _T = typing.TypeVar("_T") | ||
/// ``` | ||
#[violation] | ||
pub struct UnusedPrivateTypeVar { | ||
name: String, | ||
} | ||
|
||
impl Violation for UnusedPrivateTypeVar { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
let UnusedPrivateTypeVar { name } = self; | ||
format!("Private TypeVar `{name}` is never used") | ||
} | ||
} | ||
|
||
/// PYI018 | ||
pub(crate) fn unused_private_type_var(checker: &Checker, binding: &Binding) -> Option<Diagnostic> { | ||
if !(binding.kind.is_assignment() && binding.is_private_variable()) { | ||
return None; | ||
} | ||
if binding.is_used() { | ||
return None; | ||
} | ||
|
||
let Some(source) = binding.source else { | ||
return None; | ||
}; | ||
let Stmt::Assign(ast::StmtAssign { targets, value, .. }) = checker.semantic().stmts[source] | ||
else { | ||
return None; | ||
}; | ||
let [Expr::Name(ast::ExprName { id, .. })] = &targets[..] else { | ||
return None; | ||
}; | ||
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else { | ||
return None; | ||
}; | ||
if !checker.semantic().match_typing_expr(func, "TypeVar") { | ||
return None; | ||
} | ||
|
||
Some(Diagnostic::new( | ||
UnusedPrivateTypeVar { | ||
name: id.to_string(), | ||
}, | ||
binding.range, | ||
)) | ||
} |
4 changes: 4 additions & 0 deletions
4
...ruff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI018_PYI018.py.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
source: crates/ruff/src/rules/flake8_pyi/mod.rs | ||
--- | ||
|
22 changes: 22 additions & 0 deletions
22
...uff/src/rules/flake8_pyi/snapshots/ruff__rules__flake8_pyi__tests__PYI018_PYI018.pyi.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--- | ||
source: crates/ruff/src/rules/flake8_pyi/mod.rs | ||
--- | ||
PYI018.pyi:4:1: PYI018 Private TypeVar `_T` is never used | ||
| | ||
2 | from typing import TypeVar | ||
3 | | ||
4 | _T = typing.TypeVar("_T") | ||
| ^^ PYI018 | ||
5 | _P = TypeVar("_P") | ||
| | ||
|
||
PYI018.pyi:5:1: PYI018 Private TypeVar `_P` is never used | ||
| | ||
4 | _T = typing.TypeVar("_T") | ||
5 | _P = TypeVar("_P") | ||
| ^^ PYI018 | ||
6 | | ||
7 | # OK | ||
| | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.