diff --git a/README.md b/README.md index 2382fd95a5..97917ecaeb 100644 --- a/README.md +++ b/README.md @@ -1303,8 +1303,7 @@ For more, see [flake8-simplify](https://pypi.org/project/flake8-simplify/) on Py | SIM107 | return-in-try-except-finally | Don't use `return` in `try`/`except` and `finally` | | | SIM108 | use-ternary-operator | Use ternary operator `{contents}` instead of if-else-block | 🛠 | | SIM109 | compare-with-tuple | Use `{replacement}` instead of multiple equality comparisons | 🛠 | -| SIM110 | convert-loop-to-any | Use `{any}` instead of `for` loop | 🛠 | -| SIM111 | convert-loop-to-all | Use `{all}` instead of `for` loop | 🛠 | +| SIM110 | reimplemented-builtin | Use `{repl}` instead of `for` loop | 🛠 | | SIM112 | use-capital-environment-variables | Use capitalized environment variable `{expected}` instead of `{original}` | 🛠 | | SIM114 | [if-with-same-arms](https://beta.ruff.rs/docs/rules/if-with-same-arms/) | Combine `if` branches using logical `or` operator | | | SIM115 | open-file-with-context-handler | Use context handler for opening files | | diff --git a/crates/ruff/src/checkers/ast.rs b/crates/ruff/src/checkers/ast.rs index 67ddb98d08..ef5534fc02 100644 --- a/crates/ruff/src/checkers/ast.rs +++ b/crates/ruff/src/checkers/ast.rs @@ -1643,9 +1643,7 @@ where pylint::rules::useless_else_on_loop(self, stmt, body, orelse); } if matches!(stmt.node, StmtKind::For { .. }) { - if self.settings.rules.enabled(&Rule::ConvertLoopToAny) - || self.settings.rules.enabled(&Rule::ConvertLoopToAll) - { + if self.settings.rules.enabled(&Rule::ReimplementedBuiltin) { flake8_simplify::rules::convert_for_loop_to_any_all( self, stmt, diff --git a/crates/ruff/src/codes.rs b/crates/ruff/src/codes.rs index c506e43dd8..0674e78a1a 100644 --- a/crates/ruff/src/codes.rs +++ b/crates/ruff/src/codes.rs @@ -270,8 +270,8 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option { (Flake8Simplify, "107") => Rule::ReturnInTryExceptFinally, (Flake8Simplify, "108") => Rule::UseTernaryOperator, (Flake8Simplify, "109") => Rule::CompareWithTuple, - (Flake8Simplify, "110") => Rule::ConvertLoopToAny, - (Flake8Simplify, "111") => Rule::ConvertLoopToAll, + (Flake8Simplify, "110") => Rule::ReimplementedBuiltin, + // (Flake8Simplify, "111") => Rule::ReimplementedBuiltin, (Flake8Simplify, "112") => Rule::UseCapitalEnvironmentVariables, (Flake8Simplify, "114") => Rule::IfWithSameArms, (Flake8Simplify, "115") => Rule::OpenFileWithContextHandler, diff --git a/crates/ruff/src/registry.rs b/crates/ruff/src/registry.rs index 60c6d0a497..080b9c74ce 100644 --- a/crates/ruff/src/registry.rs +++ b/crates/ruff/src/registry.rs @@ -259,8 +259,7 @@ ruff_macros::register_rules!( rules::flake8_simplify::rules::ReturnInTryExceptFinally, rules::flake8_simplify::rules::UseTernaryOperator, rules::flake8_simplify::rules::CompareWithTuple, - rules::flake8_simplify::rules::ConvertLoopToAny, - rules::flake8_simplify::rules::ConvertLoopToAll, + rules::flake8_simplify::rules::ReimplementedBuiltin, rules::flake8_simplify::rules::UseCapitalEnvironmentVariables, rules::flake8_simplify::rules::IfWithSameArms, rules::flake8_simplify::rules::OpenFileWithContextHandler, diff --git a/crates/ruff/src/rule_redirects.rs b/crates/ruff/src/rule_redirects.rs index b0b9844072..5505785689 100644 --- a/crates/ruff/src/rule_redirects.rs +++ b/crates/ruff/src/rule_redirects.rs @@ -15,6 +15,9 @@ pub(crate) fn get_redirect(code: &str) -> Option<(&'static str, &'static str)> { static REDIRECTS: Lazy> = Lazy::new(|| { HashMap::from_iter([ + // The following are here because we don't yet have the many-to-one mapping enabled. + ("SIM111", "SIM110"), + // The following are deprecated. ("C", "C4"), ("C9", "C90"), ("T", "T10"), diff --git a/crates/ruff/src/rules/flake8_simplify/mod.rs b/crates/ruff/src/rules/flake8_simplify/mod.rs index f9bda94f1b..b5f6a5c6a2 100644 --- a/crates/ruff/src/rules/flake8_simplify/mod.rs +++ b/crates/ruff/src/rules/flake8_simplify/mod.rs @@ -19,8 +19,8 @@ mod tests { #[test_case(Rule::ReturnInTryExceptFinally, Path::new("SIM107.py"); "SIM107")] #[test_case(Rule::UseTernaryOperator, Path::new("SIM108.py"); "SIM108")] #[test_case(Rule::CompareWithTuple, Path::new("SIM109.py"); "SIM109")] - #[test_case(Rule::ConvertLoopToAny, Path::new("SIM110.py"); "SIM110")] - #[test_case(Rule::ConvertLoopToAll, Path::new("SIM111.py"); "SIM111")] + #[test_case(Rule::ReimplementedBuiltin, Path::new("SIM110.py"); "SIM110")] + #[test_case(Rule::ReimplementedBuiltin, Path::new("SIM111.py"); "SIM111")] #[test_case(Rule::UseCapitalEnvironmentVariables, Path::new("SIM112.py"); "SIM112")] #[test_case(Rule::OpenFileWithContextHandler, Path::new("SIM115.py"); "SIM115")] #[test_case(Rule::MultipleWithStatements, Path::new("SIM117.py"); "SIM117")] diff --git a/crates/ruff/src/rules/flake8_simplify/rules/mod.rs b/crates/ruff/src/rules/flake8_simplify/rules/mod.rs index c28e6e2b30..0670c06a86 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/mod.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/mod.rs @@ -3,7 +3,6 @@ pub use ast_bool_op::{ AAndNotA, AOrNotA, AndFalse, CompareWithTuple, DuplicateIsinstanceCall, OrTrue, }; pub use ast_expr::{use_capital_environment_variables, UseCapitalEnvironmentVariables}; -pub use ast_for::{convert_for_loop_to_any_all, ConvertLoopToAll, ConvertLoopToAny}; pub use ast_if::{ if_with_same_arms, nested_if_statements, return_bool_condition_directly, use_dict_get_with_default, use_ternary_operator, CollapsibleIf, DictGetWithDefault, @@ -22,13 +21,13 @@ pub use key_in_dict::{key_in_dict_compare, key_in_dict_for, KeyInDict}; pub use open_file_with_context_handler::{ open_file_with_context_handler, OpenFileWithContextHandler, }; +pub use reimplemented_builtin::{convert_for_loop_to_any_all, ReimplementedBuiltin}; pub use return_in_try_except_finally::{return_in_try_except_finally, ReturnInTryExceptFinally}; pub use use_contextlib_suppress::{use_contextlib_suppress, UseContextlibSuppress}; pub use yoda_conditions::{yoda_conditions, YodaConditions}; mod ast_bool_op; mod ast_expr; -mod ast_for; mod ast_if; mod ast_ifexp; mod ast_unary_op; @@ -37,6 +36,7 @@ mod fix_if; mod fix_with; mod key_in_dict; mod open_file_with_context_handler; +mod reimplemented_builtin; mod return_in_try_except_finally; mod use_contextlib_suppress; mod yoda_conditions; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_for.rs b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs similarity index 90% rename from crates/ruff/src/rules/flake8_simplify/rules/ast_for.rs rename to crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs index 304c7dbfa8..7ad8f81e64 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_for.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs @@ -12,38 +12,20 @@ use crate::source_code::Stylist; use crate::violation::AlwaysAutofixableViolation; define_violation!( - pub struct ConvertLoopToAny { - pub any: String, + pub struct ReimplementedBuiltin { + pub repl: String, } ); -impl AlwaysAutofixableViolation for ConvertLoopToAny { +impl AlwaysAutofixableViolation for ReimplementedBuiltin { #[derive_message_formats] fn message(&self) -> String { - let ConvertLoopToAny { any } = self; - format!("Use `{any}` instead of `for` loop") + let ReimplementedBuiltin { repl } = self; + format!("Use `{repl}` instead of `for` loop") } fn autofix_title(&self) -> String { - let ConvertLoopToAny { any } = self; - format!("Replace with `{any}`") - } -} - -define_violation!( - pub struct ConvertLoopToAll { - pub all: String, - } -); -impl AlwaysAutofixableViolation for ConvertLoopToAll { - #[derive_message_formats] - fn message(&self) -> String { - let ConvertLoopToAll { all } = self; - format!("Use `{all}` instead of `for` loop") - } - - fn autofix_title(&self) -> String { - let ConvertLoopToAll { all } = self; - format!("Replace with `{all}`") + let ReimplementedBuiltin { repl } = self; + format!("Replace with `{repl}`") } } @@ -219,7 +201,7 @@ pub fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt, sibling: .or_else(|| sibling.and_then(|sibling| return_values_for_siblings(stmt, sibling))) { if loop_info.return_value && !loop_info.next_return_value { - if checker.settings.rules.enabled(&Rule::ConvertLoopToAny) { + if checker.settings.rules.enabled(&Rule::ReimplementedBuiltin) { let contents = return_stmt( "any", loop_info.test, @@ -234,8 +216,8 @@ pub fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt, sibling: } let mut diagnostic = Diagnostic::new( - ConvertLoopToAny { - any: contents.clone(), + ReimplementedBuiltin { + repl: contents.clone(), }, Range::from_located(stmt), ); @@ -251,7 +233,7 @@ pub fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt, sibling: } if !loop_info.return_value && loop_info.next_return_value { - if checker.settings.rules.enabled(&Rule::ConvertLoopToAll) { + if checker.settings.rules.enabled(&Rule::ReimplementedBuiltin) { // Invert the condition. let test = { if let ExprKind::UnaryOp { @@ -311,8 +293,8 @@ pub fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt, sibling: } let mut diagnostic = Diagnostic::new( - ConvertLoopToAll { - all: contents.clone(), + ReimplementedBuiltin { + repl: contents.clone(), }, Range::from_located(stmt), ); diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM110.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM110.py.snap index 71d25f431a..58fb11c80c 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM110.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM110.py.snap @@ -1,10 +1,10 @@ --- -source: src/rules/flake8_simplify/mod.rs +source: crates/ruff/src/rules/flake8_simplify/mod.rs expression: diagnostics --- - kind: - ConvertLoopToAny: - any: return any(check(x) for x in iterable) + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) location: row: 3 column: 4 @@ -22,8 +22,46 @@ expression: diagnostics column: 16 parent: ~ - kind: - ConvertLoopToAny: - any: return any(check(x) for x in iterable) + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 25 + column: 4 + end_location: + row: 27 + column: 24 + fix: + content: + - return all(not check(x) for x in iterable) + location: + row: 25 + column: 4 + end_location: + row: 28 + column: 15 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(x.is_empty() for x in iterable) + location: + row: 33 + column: 4 + end_location: + row: 35 + column: 24 + fix: + content: + - return all(x.is_empty() for x in iterable) + location: + row: 33 + column: 4 + end_location: + row: 36 + column: 15 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) location: row: 55 column: 4 @@ -41,8 +79,27 @@ expression: diagnostics column: 20 parent: ~ - kind: - ConvertLoopToAny: - any: return any(check(x) for x in iterable) + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 64 + column: 4 + end_location: + row: 68 + column: 19 + fix: + content: + - return all(not check(x) for x in iterable) + location: + row: 64 + column: 4 + end_location: + row: 68 + column: 19 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) location: row: 73 column: 4 @@ -60,8 +117,27 @@ expression: diagnostics column: 20 parent: ~ - kind: - ConvertLoopToAny: - any: return any(check(x) for x in iterable) + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 83 + column: 4 + end_location: + row: 87 + column: 19 + fix: + content: + - return all(not check(x) for x in iterable) + location: + row: 83 + column: 4 + end_location: + row: 87 + column: 19 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) location: row: 124 column: 4 @@ -71,8 +147,19 @@ expression: diagnostics fix: ~ parent: ~ - kind: - ConvertLoopToAny: - any: return any(check(x) for x in iterable) + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 134 + column: 4 + end_location: + row: 136 + column: 24 + fix: ~ + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) location: row: 144 column: 4 @@ -89,4 +176,23 @@ expression: diagnostics row: 147 column: 16 parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 154 + column: 4 + end_location: + row: 156 + column: 24 + fix: + content: + - return all(not check(x) for x in iterable) + location: + row: 154 + column: 4 + end_location: + row: 157 + column: 15 + parent: ~ diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM111.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM111.py.snap new file mode 100644 index 0000000000..78edd2fbbe --- /dev/null +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM111.py.snap @@ -0,0 +1,236 @@ +--- +source: crates/ruff/src/rules/flake8_simplify/mod.rs +expression: diagnostics +--- +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) + location: + row: 3 + column: 4 + end_location: + row: 5 + column: 23 + fix: + content: + - return any(check(x) for x in iterable) + location: + row: 3 + column: 4 + end_location: + row: 6 + column: 16 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 25 + column: 4 + end_location: + row: 27 + column: 24 + fix: + content: + - return all(not check(x) for x in iterable) + location: + row: 25 + column: 4 + end_location: + row: 28 + column: 15 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(x.is_empty() for x in iterable) + location: + row: 33 + column: 4 + end_location: + row: 35 + column: 24 + fix: + content: + - return all(x.is_empty() for x in iterable) + location: + row: 33 + column: 4 + end_location: + row: 36 + column: 15 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) + location: + row: 55 + column: 4 + end_location: + row: 59 + column: 20 + fix: + content: + - return any(check(x) for x in iterable) + location: + row: 55 + column: 4 + end_location: + row: 59 + column: 20 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 64 + column: 4 + end_location: + row: 68 + column: 19 + fix: + content: + - return all(not check(x) for x in iterable) + location: + row: 64 + column: 4 + end_location: + row: 68 + column: 19 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) + location: + row: 73 + column: 4 + end_location: + row: 77 + column: 20 + fix: + content: + - return any(check(x) for x in iterable) + location: + row: 73 + column: 4 + end_location: + row: 77 + column: 20 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 83 + column: 4 + end_location: + row: 87 + column: 19 + fix: + content: + - return all(not check(x) for x in iterable) + location: + row: 83 + column: 4 + end_location: + row: 87 + column: 19 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) + location: + row: 124 + column: 4 + end_location: + row: 126 + column: 23 + fix: ~ + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 134 + column: 4 + end_location: + row: 136 + column: 24 + fix: ~ + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return any(check(x) for x in iterable) + location: + row: 144 + column: 4 + end_location: + row: 146 + column: 23 + fix: + content: + - return any(check(x) for x in iterable) + location: + row: 144 + column: 4 + end_location: + row: 147 + column: 16 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(not check(x) for x in iterable) + location: + row: 154 + column: 4 + end_location: + row: 156 + column: 24 + fix: + content: + - return all(not check(x) for x in iterable) + location: + row: 154 + column: 4 + end_location: + row: 157 + column: 15 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(x in y for x in iterable) + location: + row: 162 + column: 4 + end_location: + row: 164 + column: 24 + fix: + content: + - return all(x in y for x in iterable) + location: + row: 162 + column: 4 + end_location: + row: 165 + column: 15 + parent: ~ +- kind: + ReimplementedBuiltin: + repl: return all(x <= y for x in iterable) + location: + row: 170 + column: 4 + end_location: + row: 172 + column: 24 + fix: + content: + - return all(x <= y for x in iterable) + location: + row: 170 + column: 4 + end_location: + row: 173 + column: 15 + parent: ~ + diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM111_SIM111.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM111_SIM111.py.snap deleted file mode 100644 index 589531aa48..0000000000 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM111_SIM111.py.snap +++ /dev/null @@ -1,149 +0,0 @@ ---- -source: crates/ruff/src/rules/flake8_simplify/mod.rs -expression: diagnostics ---- -- kind: - ConvertLoopToAll: - all: return all(not check(x) for x in iterable) - location: - row: 25 - column: 4 - end_location: - row: 27 - column: 24 - fix: - content: - - return all(not check(x) for x in iterable) - location: - row: 25 - column: 4 - end_location: - row: 28 - column: 15 - parent: ~ -- kind: - ConvertLoopToAll: - all: return all(x.is_empty() for x in iterable) - location: - row: 33 - column: 4 - end_location: - row: 35 - column: 24 - fix: - content: - - return all(x.is_empty() for x in iterable) - location: - row: 33 - column: 4 - end_location: - row: 36 - column: 15 - parent: ~ -- kind: - ConvertLoopToAll: - all: return all(not check(x) for x in iterable) - location: - row: 64 - column: 4 - end_location: - row: 68 - column: 19 - fix: - content: - - return all(not check(x) for x in iterable) - location: - row: 64 - column: 4 - end_location: - row: 68 - column: 19 - parent: ~ -- kind: - ConvertLoopToAll: - all: return all(not check(x) for x in iterable) - location: - row: 83 - column: 4 - end_location: - row: 87 - column: 19 - fix: - content: - - return all(not check(x) for x in iterable) - location: - row: 83 - column: 4 - end_location: - row: 87 - column: 19 - parent: ~ -- kind: - ConvertLoopToAll: - all: return all(not check(x) for x in iterable) - location: - row: 134 - column: 4 - end_location: - row: 136 - column: 24 - fix: ~ - parent: ~ -- kind: - ConvertLoopToAll: - all: return all(not check(x) for x in iterable) - location: - row: 154 - column: 4 - end_location: - row: 156 - column: 24 - fix: - content: - - return all(not check(x) for x in iterable) - location: - row: 154 - column: 4 - end_location: - row: 157 - column: 15 - parent: ~ -- kind: - ConvertLoopToAll: - all: return all(x in y for x in iterable) - location: - row: 162 - column: 4 - end_location: - row: 164 - column: 24 - fix: - content: - - return all(x in y for x in iterable) - location: - row: 162 - column: 4 - end_location: - row: 165 - column: 15 - parent: ~ -- kind: - ConvertLoopToAll: - all: return all(x <= y for x in iterable) - location: - row: 170 - column: 4 - end_location: - row: 172 - column: 24 - fix: - content: - - return all(x <= y for x in iterable) - location: - row: 170 - column: 4 - end_location: - row: 173 - column: 15 - parent: ~ - diff --git a/ruff.schema.json b/ruff.schema.json index e07abfd8be..bd33b91b8f 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -1912,7 +1912,6 @@ "SIM109", "SIM11", "SIM110", - "SIM111", "SIM112", "SIM114", "SIM115",