mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00
Warn instead of error when removed rules are used in ignore (#14435)
Closes https://github.com/astral-sh/ruff/issues/13505
This commit is contained in:
parent
dc05b38165
commit
52f526eb38
5 changed files with 125 additions and 1 deletions
|
@ -1250,6 +1250,68 @@ fn removed_indirect() {
|
|||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn removed_ignore_direct() {
|
||||
let mut cmd = RuffCheck::default().args(["--ignore", "UP027"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
All checks passed!
|
||||
|
||||
----- stderr -----
|
||||
warning: The following rules have been removed and ignoring them has no effect:
|
||||
- UP027
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn removed_ignore_multiple_direct() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--ignore", "UP027", "--ignore", "PLR1706"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
All checks passed!
|
||||
|
||||
----- stderr -----
|
||||
warning: The following rules have been removed and ignoring them has no effect:
|
||||
- PLR1706
|
||||
- UP027
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn removed_ignore_remapped_direct() {
|
||||
let mut cmd = RuffCheck::default().args(["--ignore", "PGH001"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
All checks passed!
|
||||
|
||||
----- stderr -----
|
||||
warning: `PGH001` has been remapped to `S307`.
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn removed_ignore_indirect() {
|
||||
// `PLR170` includes removed rules but should not select or warn
|
||||
// since it is not a "direct" selection
|
||||
let mut cmd = RuffCheck::default().args(["--ignore", "PLR170"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
All checks passed!
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redirect_direct() {
|
||||
// Selection of a redirected rule directly should use the new rule and warn
|
||||
|
|
|
@ -513,6 +513,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Pyupgrade, "024") => (RuleGroup::Stable, rules::pyupgrade::rules::OSErrorAlias),
|
||||
(Pyupgrade, "025") => (RuleGroup::Stable, rules::pyupgrade::rules::UnicodeKindPrefix),
|
||||
(Pyupgrade, "026") => (RuleGroup::Stable, rules::pyupgrade::rules::DeprecatedMockImport),
|
||||
(Pyupgrade, "027") => (RuleGroup::Removed, rules::pyupgrade::rules::UnpackedListComprehension),
|
||||
(Pyupgrade, "028") => (RuleGroup::Stable, rules::pyupgrade::rules::YieldInForLoop),
|
||||
(Pyupgrade, "029") => (RuleGroup::Stable, rules::pyupgrade::rules::UnnecessaryBuiltinImport),
|
||||
(Pyupgrade, "030") => (RuleGroup::Stable, rules::pyupgrade::rules::FormatLiterals),
|
||||
|
|
|
@ -31,6 +31,7 @@ pub(crate) use unnecessary_coding_comment::*;
|
|||
pub(crate) use unnecessary_default_type_args::*;
|
||||
pub(crate) use unnecessary_encode_utf8::*;
|
||||
pub(crate) use unnecessary_future_import::*;
|
||||
pub(crate) use unpacked_list_comprehension::*;
|
||||
pub(crate) use use_pep585_annotation::*;
|
||||
pub(crate) use use_pep604_annotation::*;
|
||||
pub(crate) use use_pep604_isinstance::*;
|
||||
|
@ -73,6 +74,7 @@ mod unnecessary_coding_comment;
|
|||
mod unnecessary_default_type_args;
|
||||
mod unnecessary_encode_utf8;
|
||||
mod unnecessary_future_import;
|
||||
mod unpacked_list_comprehension;
|
||||
mod use_pep585_annotation;
|
||||
mod use_pep604_annotation;
|
||||
mod use_pep604_isinstance;
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
use ruff_diagnostics::Violation;
|
||||
use ruff_macros::violation;
|
||||
|
||||
/// ## Removed
|
||||
/// There's no [evidence](https://github.com/astral-sh/ruff/issues/12754) that generators are
|
||||
/// meaningfully faster than list comprehensions when combined with unpacking.
|
||||
///
|
||||
/// ## What it does
|
||||
/// Checks for list comprehensions that are immediately unpacked.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// There is no reason to use a list comprehension if the result is immediately
|
||||
/// unpacked. Instead, use a generator expression, which avoids allocating
|
||||
/// an intermediary list.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// a, b, c = [foo(x) for x in items]
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// a, b, c = (foo(x) for x in items)
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: Generator expressions](https://docs.python.org/3/reference/expressions.html#generator-expressions)
|
||||
/// - [Python documentation: List comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions)
|
||||
#[violation]
|
||||
pub struct UnpackedListComprehension;
|
||||
|
||||
impl Violation for UnpackedListComprehension {
|
||||
fn message(&self) -> String {
|
||||
unreachable!("UP027 has been removed")
|
||||
}
|
||||
|
||||
fn message_formats() -> &'static [&'static str] {
|
||||
&["Replace unpacked list comprehension with a generator expression"]
|
||||
}
|
||||
}
|
|
@ -775,6 +775,7 @@ impl LintConfiguration {
|
|||
let mut redirects = FxHashMap::default();
|
||||
let mut deprecated_selectors = FxHashSet::default();
|
||||
let mut removed_selectors = FxHashSet::default();
|
||||
let mut removed_ignored_rules = FxHashSet::default();
|
||||
let mut ignored_preview_selectors = FxHashSet::default();
|
||||
|
||||
// Track which docstring rules are specifically enabled
|
||||
|
@ -926,9 +927,13 @@ impl LintConfiguration {
|
|||
// Removed rules
|
||||
if selector.is_exact() {
|
||||
if selector.all_rules().all(|rule| rule.is_removed()) {
|
||||
if kind.is_disable() {
|
||||
removed_ignored_rules.insert(selector);
|
||||
} else {
|
||||
removed_selectors.insert(selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Redirected rules
|
||||
if let RuleSelector::Prefix {
|
||||
|
@ -968,6 +973,20 @@ impl LintConfiguration {
|
|||
}
|
||||
}
|
||||
|
||||
if !removed_ignored_rules.is_empty() {
|
||||
let mut rules = String::new();
|
||||
for selection in removed_ignored_rules.iter().sorted() {
|
||||
let (prefix, code) = selection.prefix_and_code();
|
||||
rules.push_str("\n - ");
|
||||
rules.push_str(prefix);
|
||||
rules.push_str(code);
|
||||
}
|
||||
rules.push('\n');
|
||||
warn_user_once_by_message!(
|
||||
"The following rules have been removed and ignoring them has no effect:{rules}"
|
||||
);
|
||||
}
|
||||
|
||||
for (from, target) in redirects.iter().sorted_by_key(|item| item.0) {
|
||||
// TODO(martin): This belongs into the ruff crate.
|
||||
warn_user_once_by_id!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue