From a2b8487ae3c3efa99deb21376dcd504a81276a3f Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Wed, 10 May 2023 09:21:15 +0200 Subject: [PATCH] Remove functor from autofix title (#4245) --- .../rules/unused_loop_control_variable.rs | 18 +++---- ...__flake8_bugbear__tests__B007_B007.py.snap | 4 ++ .../unnecessary_comprehension_any_all.rs | 4 +- .../rules/unnecessary_map.rs | 13 +++-- crates/ruff/src/rules/flake8_errmsg/rules.rs | 50 ++++++------------- ...__rules__flake8_errmsg__tests__custom.snap | 4 ++ ...rules__flake8_errmsg__tests__defaults.snap | 4 ++ .../flake8_pytest_style/rules/assertion.rs | 23 +++------ .../flake8_pytest_style/rules/parametrize.rs | 8 ++- ...es__flake8_pytest_style__tests__PT009.snap | 3 ++ ...es__flake8_pytest_style__tests__PT018.snap | 3 ++ .../flake8_simplify/rules/ast_bool_op.rs | 23 ++++----- .../rules/flake8_simplify/rules/ast_expr.rs | 8 ++- .../src/rules/flake8_simplify/rules/ast_if.rs | 47 +++++++---------- .../rules/flake8_simplify/rules/ast_ifexp.rs | 8 ++- .../rules/flake8_simplify/rules/ast_with.rs | 11 ++-- .../rules/reimplemented_builtin.rs | 8 ++- .../rules/suppressible_exception.rs | 8 ++- .../flake8_simplify/rules/yoda_conditions.rs | 13 ++--- ...ke8_simplify__tests__SIM101_SIM101.py.snap | 1 + ...ke8_simplify__tests__SIM102_SIM102.py.snap | 1 + ...ke8_simplify__tests__SIM103_SIM103.py.snap | 2 + ...8_simplify__tests__SIM105_SIM105_0.py.snap | 1 + ...ke8_simplify__tests__SIM108_SIM108.py.snap | 4 ++ ...ke8_simplify__tests__SIM117_SIM117.py.snap | 1 + .../flake8_tidy_imports/relative_imports.rs | 9 ++-- .../src/rules/isort/rules/organize_imports.rs | 4 +- .../pandas_vet/rules/inplace_argument.rs | 12 ++--- ...es__pandas_vet__tests__PD002_PD002.py.snap | 3 ++ .../pycodestyle/rules/lambda_assignment.rs | 8 ++- ...les__pycodestyle__tests__E731_E731.py.snap | 1 + .../pydocstyle/rules/blank_after_summary.rs | 11 +--- .../rules/no_surrounding_whitespace.rs | 4 +- .../src/rules/pydocstyle/rules/one_liner.rs | 4 +- ...__rules__pydocstyle__tests__D205_D.py.snap | 1 + .../ruff/src/rules/pyflakes/rules/imports.rs | 19 +++---- .../src/rules/pyflakes/rules/repeated_keys.rs | 22 ++++---- .../rules/pyflakes/rules/unused_variable.rs | 8 ++- ...les__pyflakes__tests__F401_F401_10.py.snap | 1 + .../rules/pylint/rules/manual_import_from.rs | 12 ++--- .../src/rules/pylint/rules/nested_min_max.rs | 22 +++----- .../src/rules/pylint/rules/sys_exit_alias.rs | 5 +- ...nt__tests__PLR0402_import_aliasing.py.snap | 1 + ...int__tests__PLW3301_nested_min_max.py.snap | 1 + ...convert_named_tuple_functional_to_class.rs | 13 ++--- .../convert_typed_dict_functional_to_class.rs | 8 ++- .../pyupgrade/rules/datetime_utc_alias.rs | 8 +-- .../pyupgrade/rules/deprecated_import.rs | 11 ++-- .../rules/pyupgrade/rules/format_literals.rs | 4 +- .../src/rules/pyupgrade/rules/open_alias.rs | 11 ++-- .../pyupgrade/rules/use_pep585_annotation.rs | 11 ++-- .../pyupgrade/rules/use_pep604_annotation.rs | 12 ++--- ...ff__rules__pyupgrade__tests__UP006.py.snap | 4 ++ ...ff__rules__pyupgrade__tests__UP007.py.snap | 2 + ...ff__rules__pyupgrade__tests__UP020.py.snap | 1 + ...ff__rules__pyupgrade__tests__UP035.py.snap | 1 + ...rade__tests__datetime_utc_alias_py311.snap | 3 ++ .../rules/collection_literal_concatenation.rs | 12 ++--- ..._rules__ruff__tests__RUF005_RUF005.py.snap | 1 + crates/ruff_diagnostics/src/violation.rs | 15 +++--- crates/ruff_macros/src/violation.rs | 4 +- 61 files changed, 234 insertions(+), 305 deletions(-) diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs index d46721614d..aca4ad2762 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs @@ -65,18 +65,12 @@ impl Violation for UnusedLoopControlVariable { } } - fn autofix_title_formatter(&self) -> Option String> { - let UnusedLoopControlVariable { - certainty, rename, .. - } = self; - if certainty.to_bool() && rename.is_some() { - Some(|UnusedLoopControlVariable { name, rename, .. }| { - let rename = rename.as_ref().unwrap(); - format!("Rename unused `{name}` to `{rename}`") - }) - } else { - None - } + fn autofix_title(&self) -> Option { + let UnusedLoopControlVariable { rename, name, .. } = self; + + rename + .as_ref() + .map(|rename| format!("Rename unused `{name}` to `{rename}`")) } } diff --git a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B007_B007.py.snap b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B007_B007.py.snap index 5e33cdf7db..bb9c28d9e3 100644 --- a/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B007_B007.py.snap +++ b/crates/ruff/src/rules/flake8_bugbear/snapshots/ruff__rules__flake8_bugbear__tests__B007_B007.py.snap @@ -65,6 +65,7 @@ B007.py:34:10: B007 Loop control variable `bar` may not be used within loop body 36 | if foo: 37 | print(FMT.format(**locals())) | + = help: Rename unused `bar` to `_bar` B007.py:38:10: B007 Loop control variable `bar` may not be used within loop body | @@ -75,6 +76,7 @@ B007.py:38:10: B007 Loop control variable `bar` may not be used within loop body 41 | if foo: 42 | print(FMT.format(**globals())) | + = help: Rename unused `bar` to `_bar` B007.py:42:10: B007 Loop control variable `bar` may not be used within loop body | @@ -85,6 +87,7 @@ B007.py:42:10: B007 Loop control variable `bar` may not be used within loop body 45 | if foo: 46 | print(FMT.format(**vars())) | + = help: Rename unused `bar` to `_bar` B007.py:46:10: B007 Loop control variable `bar` may not be used within loop body | @@ -94,6 +97,7 @@ B007.py:46:10: B007 Loop control variable `bar` may not be used within loop body | ^^^ B007 49 | print(FMT.format(foo=foo, bar=eval("bar"))) | + = help: Rename unused `bar` to `_bar` B007.py:52:14: B007 [*] Loop control variable `bar` not used within loop body | diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs index b8bc0fd29e..9074c53c86 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs @@ -50,8 +50,8 @@ impl Violation for UnnecessaryComprehensionAnyAll { format!("Unnecessary list comprehension.") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|_| "Remove unnecessary list comprehension".to_string()) + fn autofix_title(&self) -> Option { + Some("Remove unnecessary list comprehension".to_string()) } } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs index e96d355798..e184c44d3e 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs @@ -56,13 +56,12 @@ impl Violation for UnnecessaryMap { } } - fn autofix_title_formatter(&self) -> Option String> { - Some(|UnnecessaryMap { obj_type }| { - if obj_type == "generator" { - format!("Replace `map` using a generator expression") - } else { - format!("Replace `map` using a `{obj_type}` comprehension") - } + fn autofix_title(&self) -> Option { + let UnnecessaryMap { obj_type } = self; + Some(if obj_type == "generator" { + format!("Replace `map` using a generator expression") + } else { + format!("Replace `map` using a `{obj_type}` comprehension") }) } } diff --git a/crates/ruff/src/rules/flake8_errmsg/rules.rs b/crates/ruff/src/rules/flake8_errmsg/rules.rs index 46fe28a5c8..453b5aa4ac 100644 --- a/crates/ruff/src/rules/flake8_errmsg/rules.rs +++ b/crates/ruff/src/rules/flake8_errmsg/rules.rs @@ -47,9 +47,7 @@ use crate::registry::{AsRule, Rule}; /// RuntimeError: 'Some value' is incorrect /// ``` #[violation] -pub struct RawStringInException { - fixable: bool, -} +pub struct RawStringInException; impl Violation for RawStringInException { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -59,9 +57,8 @@ impl Violation for RawStringInException { format!("Exception must not use a string literal, assign to variable first") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|_| format!("Assign to variable; remove string literal")) + fn autofix_title(&self) -> Option { + Some("Assign to variable; remove string literal".to_string()) } } @@ -104,9 +101,7 @@ impl Violation for RawStringInException { /// RuntimeError: 'Some value' is incorrect /// ``` #[violation] -pub struct FStringInException { - fixable: bool, -} +pub struct FStringInException; impl Violation for FStringInException { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -116,9 +111,8 @@ impl Violation for FStringInException { format!("Exception must not use an f-string literal, assign to variable first") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|_| format!("Assign to variable; remove f-string literal")) + fn autofix_title(&self) -> Option { + Some("Assign to variable; remove f-string literal".to_string()) } } @@ -163,9 +157,7 @@ impl Violation for FStringInException { /// RuntimeError: 'Some value' is incorrect /// ``` #[violation] -pub struct DotFormatInException { - fixable: bool, -} +pub struct DotFormatInException; impl Violation for DotFormatInException { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -175,9 +167,8 @@ impl Violation for DotFormatInException { format!("Exception must not use a `.format()` string directly, assign to variable first") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|_| format!("Assign to variable; remove `.format()` string")) + fn autofix_title(&self) -> Option { + Some("Assign to variable; remove `.format()` string".to_string()) } } @@ -241,12 +232,8 @@ pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) { None } }); - let mut diagnostic = Diagnostic::new( - RawStringInException { - fixable: indentation.is_some(), - }, - first.range(), - ); + let mut diagnostic = + Diagnostic::new(RawStringInException, first.range()); if let Some(indentation) = indentation { if checker.patch(diagnostic.kind.rule()) { diagnostic.set_fix(generate_fix( @@ -273,12 +260,7 @@ pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) { } }, ); - let mut diagnostic = Diagnostic::new( - FStringInException { - fixable: indentation.is_some(), - }, - first.range(), - ); + let mut diagnostic = Diagnostic::new(FStringInException, first.range()); if let Some(indentation) = indentation { if checker.patch(diagnostic.kind.rule()) { diagnostic.set_fix(generate_fix( @@ -305,12 +287,8 @@ pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) { None } }); - let mut diagnostic = Diagnostic::new( - DotFormatInException { - fixable: indentation.is_some(), - }, - first.range(), - ); + let mut diagnostic = + Diagnostic::new(DotFormatInException, first.range()); if let Some(indentation) = indentation { if checker.patch(diagnostic.kind.rule()) { diagnostic.set_fix(generate_fix( diff --git a/crates/ruff/src/rules/flake8_errmsg/snapshots/ruff__rules__flake8_errmsg__tests__custom.snap b/crates/ruff/src/rules/flake8_errmsg/snapshots/ruff__rules__flake8_errmsg__tests__custom.snap index 73074676c1..bb126d05ea 100644 --- a/crates/ruff/src/rules/flake8_errmsg/snapshots/ruff__rules__flake8_errmsg__tests__custom.snap +++ b/crates/ruff/src/rules/flake8_errmsg/snapshots/ruff__rules__flake8_errmsg__tests__custom.snap @@ -66,6 +66,7 @@ EM.py:28:24: EM101 Exception must not use a string literal, assign to variable f 30 | raise RuntimeError("This is an example exception") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EM101 | + = help: Assign to variable; remove string literal EM.py:35:24: EM101 [*] Exception must not use a string literal, assign to variable first | @@ -93,6 +94,7 @@ EM.py:42:28: EM101 Exception must not use a string literal, assign to variable f 43 | raise RuntimeError("This is an example exception") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EM101 | + = help: Assign to variable; remove string literal EM.py:47:28: EM101 [*] Exception must not use a string literal, assign to variable first | @@ -164,6 +166,7 @@ EM.py:55:28: EM101 Exception must not use a string literal, assign to variable f | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EM101 57 | if foo: x = 1; raise RuntimeError("This is an example exception") | + = help: Assign to variable; remove string literal EM.py:56:35: EM101 Exception must not use a string literal, assign to variable first | @@ -172,5 +175,6 @@ EM.py:56:35: EM101 Exception must not use a string literal, assign to variable f 58 | if foo: x = 1; raise RuntimeError("This is an example exception") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EM101 | + = help: Assign to variable; remove string literal diff --git a/crates/ruff/src/rules/flake8_errmsg/snapshots/ruff__rules__flake8_errmsg__tests__defaults.snap b/crates/ruff/src/rules/flake8_errmsg/snapshots/ruff__rules__flake8_errmsg__tests__defaults.snap index 87af51141d..3052d2da59 100644 --- a/crates/ruff/src/rules/flake8_errmsg/snapshots/ruff__rules__flake8_errmsg__tests__defaults.snap +++ b/crates/ruff/src/rules/flake8_errmsg/snapshots/ruff__rules__flake8_errmsg__tests__defaults.snap @@ -85,6 +85,7 @@ EM.py:28:24: EM101 Exception must not use a string literal, assign to variable f 30 | raise RuntimeError("This is an example exception") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EM101 | + = help: Assign to variable; remove string literal EM.py:35:24: EM101 [*] Exception must not use a string literal, assign to variable first | @@ -112,6 +113,7 @@ EM.py:42:28: EM101 Exception must not use a string literal, assign to variable f 43 | raise RuntimeError("This is an example exception") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EM101 | + = help: Assign to variable; remove string literal EM.py:47:28: EM101 [*] Exception must not use a string literal, assign to variable first | @@ -183,6 +185,7 @@ EM.py:55:28: EM101 Exception must not use a string literal, assign to variable f | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EM101 57 | if foo: x = 1; raise RuntimeError("This is an example exception") | + = help: Assign to variable; remove string literal EM.py:56:35: EM101 Exception must not use a string literal, assign to variable first | @@ -191,5 +194,6 @@ EM.py:56:35: EM101 Exception must not use a string literal, assign to variable f 58 | if foo: x = 1; raise RuntimeError("This is an example exception") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EM101 | + = help: Assign to variable; remove string literal diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs index 17391be70a..0865725789 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs @@ -51,9 +51,7 @@ use super::unittest_assert::UnittestAssert; /// assert not something_else /// ``` #[violation] -pub struct PytestCompositeAssertion { - fixable: bool, -} +pub struct PytestCompositeAssertion; impl Violation for PytestCompositeAssertion { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -63,9 +61,8 @@ impl Violation for PytestCompositeAssertion { format!("Assertion should be broken down into multiple parts") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|_| format!("Break down assertion into multiple parts")) + fn autofix_title(&self) -> Option { + Some("Break down assertion into multiple parts".to_string()) } } @@ -97,7 +94,6 @@ impl Violation for PytestAssertAlwaysFalse { #[violation] pub struct PytestUnittestAssertion { assertion: String, - fixable: bool, } impl Violation for PytestUnittestAssertion { @@ -105,15 +101,13 @@ impl Violation for PytestUnittestAssertion { #[derive_message_formats] fn message(&self) -> String { - let PytestUnittestAssertion { assertion, .. } = self; + let PytestUnittestAssertion { assertion } = self; format!("Use a regular `assert` instead of unittest-style `{assertion}`") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|PytestUnittestAssertion { assertion, .. }| { - format!("Replace `{assertion}(...)` with `assert ...`") - }) + fn autofix_title(&self) -> Option { + let PytestUnittestAssertion { assertion } = self; + Some(format!("Replace `{assertion}(...)` with `assert ...`")) } } @@ -198,7 +192,6 @@ pub fn unittest_assertion( let mut diagnostic = Diagnostic::new( PytestUnittestAssertion { assertion: unittest_assert.to_string(), - fixable, }, func.range(), ); @@ -426,7 +419,7 @@ pub fn composite_condition(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: let fixable = matches!(composite, CompositionKind::Simple) && msg.is_none() && !has_comments_in(stmt.range(), checker.locator); - let mut diagnostic = Diagnostic::new(PytestCompositeAssertion { fixable }, stmt.range()); + let mut diagnostic = Diagnostic::new(PytestCompositeAssertion, stmt.range()); if fixable && checker.patch(diagnostic.kind.rule()) { #[allow(deprecated)] diagnostic.try_set_fix_from_edit(|| { diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs index 3fcc6fa09c..c462722f1f 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs @@ -26,11 +26,9 @@ impl Violation for PytestParametrizeNamesWrongType { format!("Wrong name(s) type in `@pytest.mark.parametrize`, expected `{expected}`") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|violation| { - let PytestParametrizeNamesWrongType { expected } = violation; - format!("Use a `{expected}` for parameter names") - }) + fn autofix_title(&self) -> Option { + let PytestParametrizeNamesWrongType { expected } = self; + Some(format!("Use a `{expected}` for parameter names")) } } diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT009.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT009.snap index a148d42275..7e6b1d43ce 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT009.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT009.snap @@ -159,6 +159,7 @@ PT009.py:21:13: PT009 Use a regular `assert` instead of unittest-style `assertIs 24 | if expect_condition 25 | else self.assertIsNone(value) # Error, unfixable | + = help: Replace `assertIsNotNone(...)` with `assert ...` PT009.py:23:18: PT009 Use a regular `assert` instead of unittest-style `assertIsNone` | @@ -169,6 +170,7 @@ PT009.py:23:18: PT009 Use a regular `assert` instead of unittest-style `assertIs 26 | ) 27 | return self.assertEqual(True, False) # Error, unfixable | + = help: Replace `assertIsNone(...)` with `assert ...` PT009.py:25:16: PT009 Use a regular `assert` instead of unittest-style `assertEqual` | @@ -179,6 +181,7 @@ PT009.py:25:16: PT009 Use a regular `assert` instead of unittest-style `assertEq 28 | 29 | def test_assert_false(self): | + = help: Replace `assertEqual(...)` with `assert ...` PT009.py:28:9: PT009 [*] Use a regular `assert` instead of unittest-style `assertFalse` | diff --git a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT018.snap b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT018.snap index aa8b1ac95b..9f9bfe2b70 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT018.snap +++ b/crates/ruff/src/rules/flake8_pytest_style/snapshots/ruff__rules__flake8_pytest_style__tests__PT018.snap @@ -229,6 +229,7 @@ PT018.py:30:5: PT018 Assertion should be broken down into multiple parts 32 | assert not (something or something_else and something_third), "with message" 33 | # detected, but no autofix for mixed conditions (e.g. `a or b and c`) | + = help: Break down assertion into multiple parts PT018.py:31:5: PT018 Assertion should be broken down into multiple parts | @@ -239,6 +240,7 @@ PT018.py:31:5: PT018 Assertion should be broken down into multiple parts 34 | # detected, but no autofix for mixed conditions (e.g. `a or b and c`) 35 | assert not (something or something_else and something_third) | + = help: Break down assertion into multiple parts PT018.py:33:5: PT018 Assertion should be broken down into multiple parts | @@ -249,6 +251,7 @@ PT018.py:33:5: PT018 Assertion should be broken down into multiple parts 36 | # detected, but no autofix for parenthesized conditions 37 | assert ( | + = help: Break down assertion into multiple parts PT018.py:35:5: PT018 Assertion should be broken down into multiple parts | diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs index 3f505c2a6d..6d0a585f9a 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs @@ -47,8 +47,7 @@ use crate::registry::AsRule; /// - [Python: "isinstance"](https://docs.python.org/3/library/functions.html#isinstance) #[violation] pub struct DuplicateIsinstanceCall { - pub name: Option, - fixable: bool, + name: Option, } impl Violation for DuplicateIsinstanceCall { @@ -56,7 +55,7 @@ impl Violation for DuplicateIsinstanceCall { #[derive_message_formats] fn message(&self) -> String { - let DuplicateIsinstanceCall { name, .. } = self; + let DuplicateIsinstanceCall { name } = self; if let Some(name) = name { format!("Multiple `isinstance` calls for `{name}`, merge into a single call") } else { @@ -64,15 +63,14 @@ impl Violation for DuplicateIsinstanceCall { } } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|DuplicateIsinstanceCall { name, .. }| { - if let Some(name) = name { - format!("Merge `isinstance` calls for `{name}`") - } else { - format!("Merge `isinstance` calls") - } - }) + fn autofix_title(&self) -> Option { + let DuplicateIsinstanceCall { name } = self; + + Some(if let Some(name) = name { + format!("Merge `isinstance` calls for `{name}`") + } else { + "Merge `isinstance` calls".to_string() + }) } } @@ -305,7 +303,6 @@ pub fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { } else { None }, - fixable, }, expr.range(), ); diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs index 64f6898844..7823293a97 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs @@ -22,11 +22,9 @@ impl Violation for UncapitalizedEnvironmentVariables { format!("Use capitalized environment variable `{expected}` instead of `{original}`") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|violation| { - let UncapitalizedEnvironmentVariables { expected, original } = violation; - format!("Replace `{original}` with `{expected}`") - }) + fn autofix_title(&self) -> Option { + let UncapitalizedEnvironmentVariables { expected, original } = self; + Some(format!("Replace `{original}` with `{expected}`")) } } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs index e6e9b5fb27..a4734048f1 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs @@ -37,9 +37,7 @@ fn compare_body(body1: &[Stmt], body2: &[Stmt]) -> bool { } #[violation] -pub struct CollapsibleIf { - fixable: bool, -} +pub struct CollapsibleIf; impl Violation for CollapsibleIf { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -49,16 +47,14 @@ impl Violation for CollapsibleIf { format!("Use a single `if` statement instead of nested `if` statements") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|_| format!("Combine `if` statements using `and`")) + fn autofix_title(&self) -> Option { + Some("Combine `if` statements using `and`".to_string()) } } #[violation] pub struct NeedlessBool { condition: String, - fixable: bool, } impl Violation for NeedlessBool { @@ -66,14 +62,13 @@ impl Violation for NeedlessBool { #[derive_message_formats] fn message(&self) -> String { - let NeedlessBool { condition, .. } = self; + let NeedlessBool { condition } = self; format!("Return the condition `{condition}` directly") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable.then_some(|NeedlessBool { condition, .. }| { - format!("Replace with `return {condition}`") - }) + fn autofix_title(&self) -> Option { + let NeedlessBool { condition } = self; + Some(format!("Replace with `return {condition}`")) } } @@ -110,7 +105,6 @@ impl Violation for IfElseBlockInsteadOfDictLookup { #[violation] pub struct IfElseBlockInsteadOfIfExp { contents: String, - fixable: bool, } impl Violation for IfElseBlockInsteadOfIfExp { @@ -118,15 +112,13 @@ impl Violation for IfElseBlockInsteadOfIfExp { #[derive_message_formats] fn message(&self) -> String { - let IfElseBlockInsteadOfIfExp { contents, .. } = self; + let IfElseBlockInsteadOfIfExp { contents } = self; format!("Use ternary operator `{contents}` instead of `if`-`else`-block") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|IfElseBlockInsteadOfIfExp { contents, .. }| { - format!("Replace `if`-`else`-block with `{contents}`") - }) + fn autofix_title(&self) -> Option { + let IfElseBlockInsteadOfIfExp { contents } = self; + Some(format!("Replace `if`-`else`-block with `{contents}`")) } } @@ -163,7 +155,6 @@ impl Violation for IfWithSameArms { #[violation] pub struct IfElseBlockInsteadOfDictGet { contents: String, - fixable: bool, } impl Violation for IfElseBlockInsteadOfDictGet { @@ -171,15 +162,13 @@ impl Violation for IfElseBlockInsteadOfDictGet { #[derive_message_formats] fn message(&self) -> String { - let IfElseBlockInsteadOfDictGet { contents, .. } = self; + let IfElseBlockInsteadOfDictGet { contents } = self; format!("Use `{contents}` instead of an `if` block") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|IfElseBlockInsteadOfDictGet { contents, .. }| { - format!("Replace with `{contents}`") - }) + fn autofix_title(&self) -> Option { + let IfElseBlockInsteadOfDictGet { contents } = self; + Some(format!("Replace with `{contents}`")) } } @@ -289,7 +278,7 @@ pub fn nested_if_statements( ); let mut diagnostic = Diagnostic::new( - CollapsibleIf { fixable }, + CollapsibleIf, colon.map_or_else( || stmt.range(), |colon| TextRange::new(stmt.start(), colon.end()), @@ -367,7 +356,7 @@ pub fn needless_bool(checker: &mut Checker, stmt: &Stmt) { && !has_comments(stmt, checker.locator) && (matches!(test.node, ExprKind::Compare { .. }) || checker.ctx.is_builtin("bool")); - let mut diagnostic = Diagnostic::new(NeedlessBool { condition, fixable }, stmt.range()); + let mut diagnostic = Diagnostic::new(NeedlessBool { condition }, stmt.range()); if fixable && checker.patch(diagnostic.kind.rule()) { if matches!(test.node, ExprKind::Compare { .. }) { // If the condition is a comparison, we can replace it with the condition. @@ -526,7 +515,6 @@ pub fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: Option<& let mut diagnostic = Diagnostic::new( IfElseBlockInsteadOfIfExp { contents: contents.clone(), - fixable, }, stmt.range(), ); @@ -877,7 +865,6 @@ pub fn use_dict_get_with_default( let mut diagnostic = Diagnostic::new( IfElseBlockInsteadOfDictGet { contents: contents.clone(), - fixable, }, stmt.range(), ); diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs index 9823c2c3ce..d49878e59a 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs @@ -21,11 +21,9 @@ impl Violation for IfExprWithTrueFalse { format!("Use `bool({expr})` instead of `True if {expr} else False`") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|violation| { - let IfExprWithTrueFalse { expr } = violation; - format!("Replace with `not {expr}") - }) + fn autofix_title(&self) -> Option { + let IfExprWithTrueFalse { expr } = self; + Some(format!("Replace with `not {expr}")) } } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs index d7ab2d8089..2b09e476fb 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_with.rs @@ -42,9 +42,7 @@ use super::fix_with; /// ## References /// - [Python: "The with statement"](https://docs.python.org/3/reference/compound_stmts.html#the-with-statement) #[violation] -pub struct MultipleWithStatements { - fixable: bool, -} +pub struct MultipleWithStatements; impl Violation for MultipleWithStatements { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -57,9 +55,8 @@ impl Violation for MultipleWithStatements { ) } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|_| format!("Combine `with` statements")) + fn autofix_title(&self) -> Option { + Some("Combine `with` statements".to_string()) } } @@ -99,7 +96,7 @@ pub fn multiple_with_statements( checker.locator, ); let mut diagnostic = Diagnostic::new( - MultipleWithStatements { fixable }, + MultipleWithStatements, colon.map_or_else( || with_stmt.range(), |colon| TextRange::new(with_stmt.start(), colon.end()), diff --git a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs index 63124e4447..7d3f8582fc 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs @@ -26,11 +26,9 @@ impl Violation for ReimplementedBuiltin { format!("Use `{repl}` instead of `for` loop") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|violation| { - let ReimplementedBuiltin { repl } = violation; - format!("Replace with `{repl}`") - }) + fn autofix_title(&self) -> Option { + let ReimplementedBuiltin { repl } = self; + Some(format!("Replace with `{repl}`")) } } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs b/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs index cae85a79ed..e6ec3bdf56 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs @@ -28,11 +28,9 @@ impl Violation for SuppressibleException { format!("Use `contextlib.suppress({exception})` instead of `try`-`except`-`pass`") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|SuppressibleException { exception, .. }| { - format!("Replace with `contextlib.suppress({exception})`") - }) + fn autofix_title(&self) -> Option { + let SuppressibleException { exception, .. } = self; + Some(format!("Replace with `contextlib.suppress({exception})`")) } } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs index 31dee60304..4ad87463f6 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/yoda_conditions.rs @@ -29,16 +29,11 @@ impl Violation for YodaConditions { } } - fn autofix_title_formatter(&self) -> Option String> { + fn autofix_title(&self) -> Option { let YodaConditions { suggestion } = self; - if suggestion.is_some() { - Some(|YodaConditions { suggestion }| { - let suggestion = suggestion.as_ref().unwrap(); - format!("Replace Yoda condition with `{suggestion}`") - }) - } else { - None - } + suggestion + .as_ref() + .map(|suggestion| format!("Replace Yoda condition with `{suggestion}`")) } } diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM101_SIM101.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM101_SIM101.py.snap index 64414aa6ff..94b53c1d32 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM101_SIM101.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM101_SIM101.py.snap @@ -144,5 +144,6 @@ SIM101.py:22:4: SIM101 Multiple `isinstance` calls for expression, merge into a | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM101 25 | pass | + = help: Merge `isinstance` calls diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM102_SIM102.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM102_SIM102.py.snap index 4842f290f6..a3fd9f8f35 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM102_SIM102.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM102_SIM102.py.snap @@ -81,6 +81,7 @@ SIM102.py:20:1: SIM102 Use a single `if` statement instead of nested `if` statem | |_________^ SIM102 24 | c | + = help: Combine `if` statements using `and` SIM102.py:26:1: SIM102 [*] Use a single `if` statement instead of nested `if` statements | diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM103_SIM103.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM103_SIM103.py.snap index b05d2fb6f7..0ca6d59b5a 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM103_SIM103.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM103_SIM103.py.snap @@ -115,6 +115,7 @@ SIM103.py:57:5: SIM103 Return the condition `a` directly 62 | | return True | |___________________^ SIM103 | + = help: Replace with `return a` SIM103.py:83:5: SIM103 Return the condition `a` directly | @@ -127,5 +128,6 @@ SIM103.py:83:5: SIM103 Return the condition `a` directly 88 | | return False | |____________________^ SIM103 | + = help: Replace with `return a` diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM105_SIM105_0.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM105_SIM105_0.py.snap index 3955e25aa9..4ea22d8805 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM105_SIM105_0.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM105_SIM105_0.py.snap @@ -175,5 +175,6 @@ SIM105_0.py:93:5: SIM105 Use `contextlib.suppress(ValueError, OSError)` instead 97 | | pass # Trailing comment. | |____________^ SIM105 | + = help: Replace with `contextlib.suppress(ValueError, OSError)` diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM108_SIM108.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM108_SIM108.py.snap index f5880f24ad..520f6f1c2e 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM108_SIM108.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM108_SIM108.py.snap @@ -36,6 +36,7 @@ SIM108.py:58:1: SIM108 Use ternary operator `abc = x if x > 0 else -x` instead o 64 | | abc = -x | |____________^ SIM108 | + = help: Replace `if`-`else`-block with `abc = x if x > 0 else -x` SIM108.py:82:1: SIM108 [*] Use ternary operator `b = cccccccccccccccccccccccccccccccccccc if a else ddddddddddddddddddddddddddddddddddddd` instead of `if`-`else`-block | @@ -70,6 +71,7 @@ SIM108.py:97:1: SIM108 Use ternary operator `exitcode = 0 if True else 1` instea 101 | | exitcode = 1 # Trailing comment | |________________^ SIM108 | + = help: Replace `if`-`else`-block with `exitcode = 0 if True else 1` SIM108.py:104:1: SIM108 Use ternary operator `x = 3 if True else 5` instead of `if`-`else`-block | @@ -78,6 +80,7 @@ SIM108.py:104:1: SIM108 Use ternary operator `x = 3 if True else 5` instead of ` 106 | | else: x = 5 | |___________^ SIM108 | + = help: Replace `if`-`else`-block with `x = 3 if True else 5` SIM108.py:109:1: SIM108 Use ternary operator `x = 3 if True else 5` instead of `if`-`else`-block | @@ -88,5 +91,6 @@ SIM108.py:109:1: SIM108 Use ternary operator `x = 3 if True else 5` instead of ` 113 | | x = 5 | |_________^ SIM108 | + = help: Replace `if`-`else`-block with `x = 3 if True else 5` diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM117_SIM117.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM117_SIM117.py.snap index 452b0c5b7a..0cb4bd04bf 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM117_SIM117.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM117_SIM117.py.snap @@ -57,6 +57,7 @@ SIM117.py:13:1: SIM117 Use a single `with` statement with multiple contexts inst | |__________________^ SIM117 17 | print("hello") | + = help: Combine `with` statements SIM117.py:19:1: SIM117 [*] Use a single `with` statement with multiple contexts instead of nested `with` statements | diff --git a/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs b/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs index f8c70eabe5..7ef710538c 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/relative_imports.rs @@ -73,12 +73,13 @@ impl Violation for RelativeImports { } } - fn autofix_title_formatter(&self) -> Option String> { - Some(|RelativeImports { strictness }| match strictness { + fn autofix_title(&self) -> Option { + let RelativeImports { strictness } = self; + Some(match strictness { Strictness::Parents => { - format!("Replace relative imports from parent modules with absolute imports") + "Replace relative imports from parent modules with absolute imports".to_string() } - Strictness::All => format!("Replace relative imports with absolute imports"), + Strictness::All => "Replace relative imports with absolute imports".to_string(), }) } } diff --git a/crates/ruff/src/rules/isort/rules/organize_imports.rs b/crates/ruff/src/rules/isort/rules/organize_imports.rs index 3d4cab1851..1477fc84b9 100644 --- a/crates/ruff/src/rules/isort/rules/organize_imports.rs +++ b/crates/ruff/src/rules/isort/rules/organize_imports.rs @@ -48,8 +48,8 @@ impl Violation for UnsortedImports { format!("Import block is un-sorted or un-formatted") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|_| "Organize imports".to_string()) + fn autofix_title(&self) -> Option { + Some("Organize imports".to_string()) } } diff --git a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs index 5c3bdcdb89..8b027f2942 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs @@ -32,9 +32,7 @@ use crate::rules::pandas_vet::fixes::convert_inplace_argument_to_assignment; /// ## References /// - [_Why You Should Probably Never Use pandas inplace=True_](https://towardsdatascience.com/why-you-should-probably-never-use-pandas-inplace-true-9f9f211849e4) #[violation] -pub struct PandasUseOfInplaceArgument { - fixable: bool, -} +pub struct PandasUseOfInplaceArgument; impl Violation for PandasUseOfInplaceArgument { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -44,9 +42,8 @@ impl Violation for PandasUseOfInplaceArgument { format!("`inplace=True` should be avoided; it has inconsistent behavior") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|_| format!("Assign to variable; remove `inplace` arg")) + fn autofix_title(&self) -> Option { + Some("Assign to variable; remove `inplace` arg".to_string()) } } @@ -85,8 +82,7 @@ pub fn inplace_argument( && matches!(checker.ctx.stmt().node, StmtKind::Expr { .. }) && checker.ctx.expr_parent().is_none() && !checker.ctx.scope().kind.is_lambda(); - let mut diagnostic = - Diagnostic::new(PandasUseOfInplaceArgument { fixable }, keyword.range()); + let mut diagnostic = Diagnostic::new(PandasUseOfInplaceArgument, keyword.range()); if fixable && checker.patch(diagnostic.kind.rule()) { if let Some(fix) = convert_inplace_argument_to_assignment( checker.locator, diff --git a/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD002_PD002.py.snap b/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD002_PD002.py.snap index 9ce53ebcb7..91eb4d6aba 100644 --- a/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD002_PD002.py.snap +++ b/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD002_PD002.py.snap @@ -114,6 +114,7 @@ PD002.py:23:23: PD002 `inplace=True` should be avoided; it has inconsistent beha | ^^^^^^^^^^^^ PD002 25 | f(x.drop(["a"], axis=1, inplace=True)) | + = help: Assign to variable; remove `inplace` arg PD002.py:24:25: PD002 `inplace=True` should be avoided; it has inconsistent behavior | @@ -124,6 +125,7 @@ PD002.py:24:25: PD002 `inplace=True` should be avoided; it has inconsistent beha 27 | 28 | x.apply(lambda x: x.sort_values('a', inplace=True)) | + = help: Assign to variable; remove `inplace` arg PD002.py:26:38: PD002 `inplace=True` should be avoided; it has inconsistent behavior | @@ -132,5 +134,6 @@ PD002.py:26:38: PD002 `inplace=True` should be avoided; it has inconsistent beha 28 | x.apply(lambda x: x.sort_values('a', inplace=True)) | ^^^^^^^^^^^^ PD002 | + = help: Assign to variable; remove `inplace` arg diff --git a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs index 6f82651ea9..3d3484b82f 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs @@ -39,7 +39,6 @@ use crate::registry::AsRule; #[violation] pub struct LambdaAssignment { name: String, - fixable: bool, } impl Violation for LambdaAssignment { @@ -50,9 +49,9 @@ impl Violation for LambdaAssignment { format!("Do not assign a `lambda` expression, use a `def`") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|LambdaAssignment { name, .. }| format!("Rewrite `{name}` as a `def`")) + fn autofix_title(&self) -> Option { + let LambdaAssignment { name } = self; + Some(format!("Rewrite `{name}` as a `def`")) } } @@ -77,7 +76,6 @@ pub fn lambda_assignment( let mut diagnostic = Diagnostic::new( LambdaAssignment { name: id.to_string(), - fixable, }, stmt.range(), ); diff --git a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E731_E731.py.snap b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E731_E731.py.snap index db72312da9..891132f635 100644 --- a/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E731_E731.py.snap +++ b/crates/ruff/src/rules/pycodestyle/snapshots/ruff__rules__pycodestyle__tests__E731_E731.py.snap @@ -115,6 +115,7 @@ E731.py:14:5: E731 Do not assign a `lambda` expression, use a `def` 16 | f = lambda x: 2 * x | ^^^^^^^^^^^^^^^^^^^ E731 | + = help: Rewrite `f` as a `def` E731.py:32:1: E731 [*] Do not assign a `lambda` expression, use a `def` | diff --git a/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs b/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs index 5fbb28d0e2..19db784791 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs @@ -11,9 +11,6 @@ pub struct BlankLineAfterSummary { num_lines: usize, } -fn fmt_blank_line_after_summary_autofix_msg(_: &BlankLineAfterSummary) -> String { - "Insert single blank line".to_string() -} impl Violation for BlankLineAfterSummary { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -29,12 +26,8 @@ impl Violation for BlankLineAfterSummary { } } - fn autofix_title_formatter(&self) -> Option String> { - let BlankLineAfterSummary { num_lines } = self; - if *num_lines > 0 { - return Some(fmt_blank_line_after_summary_autofix_msg); - } - None + fn autofix_title(&self) -> Option { + Some("Insert single blank line".to_string()) } } diff --git a/crates/ruff/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs b/crates/ruff/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs index 5bb1db413a..26e3427643 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs @@ -19,8 +19,8 @@ impl Violation for SurroundingWhitespace { format!("No whitespaces allowed surrounding docstring text") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|_| "Trim surrounding whitespace".to_string()) + fn autofix_title(&self) -> Option { + Some("Trim surrounding whitespace".to_string()) } } diff --git a/crates/ruff/src/rules/pydocstyle/rules/one_liner.rs b/crates/ruff/src/rules/pydocstyle/rules/one_liner.rs index 2d2f9f7e48..dc48bd3e3e 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/one_liner.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/one_liner.rs @@ -18,8 +18,8 @@ impl Violation for FitsOnOneLine { format!("One-line docstring should fit on one line") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|_| "Reformat to one line".to_string()) + fn autofix_title(&self) -> Option { + Some("Reformat to one line".to_string()) } } diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D205_D.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D205_D.py.snap index bc0e009965..f524800896 100644 --- a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D205_D.py.snap +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D205_D.py.snap @@ -12,6 +12,7 @@ D.py:200:5: D205 1 blank line required between summary line and description 205 | | """ | |_______^ D205 | + = help: Insert single blank line D.py:210:5: D205 [*] 1 blank line required between summary line and description (found 2) | diff --git a/crates/ruff/src/rules/pyflakes/rules/imports.rs b/crates/ruff/src/rules/pyflakes/rules/imports.rs index 223140b8e5..7b6b3ebf18 100644 --- a/crates/ruff/src/rules/pyflakes/rules/imports.rs +++ b/crates/ruff/src/rules/pyflakes/rules/imports.rs @@ -44,17 +44,14 @@ impl Violation for UnusedImport { } } - fn autofix_title_formatter(&self) -> Option String> { - let UnusedImport { context, .. } = self; - context - .is_none() - .then_some(|UnusedImport { name, multiple, .. }| { - if *multiple { - "Remove unused import".to_string() - } else { - format!("Remove unused import: `{name}`") - } - }) + fn autofix_title(&self) -> Option { + let UnusedImport { name, multiple, .. } = self; + + Some(if *multiple { + "Remove unused import".to_string() + } else { + format!("Remove unused import: `{name}`") + }) } } #[violation] diff --git a/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs b/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs index 4d39e5c401..f8a2121a94 100644 --- a/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs +++ b/crates/ruff/src/rules/pyflakes/rules/repeated_keys.rs @@ -26,12 +26,13 @@ impl Violation for MultiValueRepeatedKeyLiteral { format!("Dictionary key literal `{name}` repeated") } - fn autofix_title_formatter(&self) -> Option String> { - let MultiValueRepeatedKeyLiteral { repeated_value, .. } = self; + fn autofix_title(&self) -> Option { + let MultiValueRepeatedKeyLiteral { + repeated_value, + name, + } = self; if *repeated_value { - Some(|MultiValueRepeatedKeyLiteral { name, .. }| { - format!("Remove repeated key literal `{name}`") - }) + Some(format!("Remove repeated key literal `{name}`")) } else { None } @@ -52,12 +53,13 @@ impl Violation for MultiValueRepeatedKeyVariable { format!("Dictionary key `{name}` repeated") } - fn autofix_title_formatter(&self) -> Option String> { - let MultiValueRepeatedKeyVariable { repeated_value, .. } = self; + fn autofix_title(&self) -> Option { + let MultiValueRepeatedKeyVariable { + repeated_value, + name, + } = self; if *repeated_value { - Some(|MultiValueRepeatedKeyVariable { name, .. }| { - format!("Remove repeated key `{name}`") - }) + Some(format!("Remove repeated key `{name}`")) } else { None } diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs index 748b6d1602..a5b79ee513 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs @@ -57,11 +57,9 @@ impl Violation for UnusedVariable { format!("Local variable `{name}` is assigned to but never used") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|violation| { - let UnusedVariable { name } = violation; - format!("Remove assignment to unused variable `{name}`") - }) + fn autofix_title(&self) -> Option { + let UnusedVariable { name } = self; + Some(format!("Remove assignment to unused variable `{name}`")) } } diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_10.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_10.py.snap index a20abcf698..ecfce29bf5 100644 --- a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_10.py.snap +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_10.py.snap @@ -10,6 +10,7 @@ F401_10.py:6:16: F401 `orjson` imported but unused; consider using `importlib.ut 9 | 10 | return True | + = help: Remove unused import: `orjson` F401_10.py:15:16: F401 [*] `orjson` imported but unused | diff --git a/crates/ruff/src/rules/pylint/rules/manual_import_from.rs b/crates/ruff/src/rules/pylint/rules/manual_import_from.rs index b5bbbeeb87..94fb48a7c9 100644 --- a/crates/ruff/src/rules/pylint/rules/manual_import_from.rs +++ b/crates/ruff/src/rules/pylint/rules/manual_import_from.rs @@ -11,7 +11,6 @@ use crate::registry::AsRule; pub struct ManualFromImport { module: String, name: String, - fixable: bool, } impl Violation for ManualFromImport { @@ -19,15 +18,13 @@ impl Violation for ManualFromImport { #[derive_message_formats] fn message(&self) -> String { - let ManualFromImport { module, name, .. } = self; + let ManualFromImport { module, name } = self; format!("Use `from {module} import {name}` in lieu of alias") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|ManualFromImport { module, name, .. }| { - format!("Replace with `from {module} import {name}`") - }) + fn autofix_title(&self) -> Option { + let ManualFromImport { module, name } = self; + Some(format!("Replace with `from {module} import {name}`")) } } @@ -48,7 +45,6 @@ pub fn manual_from_import(checker: &mut Checker, stmt: &Stmt, alias: &Alias, nam ManualFromImport { module: module.to_string(), name: name.to_string(), - fixable, }, alias.range(), ); diff --git a/crates/ruff/src/rules/pylint/rules/nested_min_max.rs b/crates/ruff/src/rules/pylint/rules/nested_min_max.rs index 8771232f74..8ea7901063 100644 --- a/crates/ruff/src/rules/pylint/rules/nested_min_max.rs +++ b/crates/ruff/src/rules/pylint/rules/nested_min_max.rs @@ -1,4 +1,4 @@ -use ruff_text_size::TextSize; +use ruff_text_size::TextRange; use rustpython_parser::ast::{Expr, ExprKind, Keyword}; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; @@ -17,7 +17,6 @@ pub enum MinMax { #[violation] pub struct NestedMinMax { func: MinMax, - fixable: bool, } impl Violation for NestedMinMax { @@ -28,9 +27,9 @@ impl Violation for NestedMinMax { format!("Nested `{}` calls can be flattened", self.func) } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|NestedMinMax { func, .. }| format!("Flatten nested `{func}` calls")) + fn autofix_title(&self) -> Option { + let NestedMinMax { func } = self; + Some(format!("Flatten nested `{func}` calls")) } } @@ -106,22 +105,15 @@ pub fn nested_min_max( MinMax::try_from_call(func, keywords, &checker.ctx) == Some(min_max) }) { let fixable = !has_comments(expr, checker.locator); - let mut diagnostic = Diagnostic::new( - NestedMinMax { - func: min_max, - fixable, - }, - expr.range(), - ); + let mut diagnostic = Diagnostic::new(NestedMinMax { func: min_max }, expr.range()); if fixable && checker.patch(diagnostic.kind.rule()) { - let flattened_expr = Expr::new( - TextSize::default(), - TextSize::default(), + let flattened_expr = Expr::with_range( ExprKind::Call { func: Box::new(func.clone()), args: collect_nested_args(&checker.ctx, min_max, args), keywords: keywords.to_owned(), }, + TextRange::default(), ); #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( diff --git a/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs b/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs index 6ee7507482..9028013b87 100644 --- a/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs +++ b/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs @@ -21,8 +21,9 @@ impl Violation for SysExitAlias { format!("Use `sys.exit()` instead of `{name}`") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|SysExitAlias { name }| format!("Replace `{name}` with `sys.exit()`")) + fn autofix_title(&self) -> Option { + let SysExitAlias { name } = self; + Some(format!("Replace `{name}` with `sys.exit()`")) } } diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0402_import_aliasing.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0402_import_aliasing.py.snap index 32a35232d5..4816274fa5 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0402_import_aliasing.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLR0402_import_aliasing.py.snap @@ -52,5 +52,6 @@ import_aliasing.py:12:8: PLR0402 Use `from foo.bar import foobar` in lieu of ali 15 | import os 16 | import os as OS | + = help: Replace with `from foo.bar import foobar` diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW3301_nested_min_max.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW3301_nested_min_max.py.snap index 73e80d040f..b4f1448cc1 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW3301_nested_min_max.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLW3301_nested_min_max.py.snap @@ -192,5 +192,6 @@ nested_min_max.py:18:1: PLW3301 Nested `min` calls can be flattened 22 | | ) | |_^ PLW3301 | + = help: Flatten nested `min` calls diff --git a/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs b/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs index 237c1be4fe..40c18824fd 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs @@ -14,7 +14,6 @@ use crate::registry::AsRule; #[violation] pub struct ConvertNamedTupleFunctionalToClass { name: String, - fixable: bool, } impl Violation for ConvertNamedTupleFunctionalToClass { @@ -22,15 +21,14 @@ impl Violation for ConvertNamedTupleFunctionalToClass { #[derive_message_formats] fn message(&self) -> String { - let ConvertNamedTupleFunctionalToClass { name, .. } = self; + let ConvertNamedTupleFunctionalToClass { name } = self; format!("Convert `{name}` from `NamedTuple` functional to class syntax") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|ConvertNamedTupleFunctionalToClass { name, .. }| { - format!("Convert `{name}` to class syntax") - }) + fn autofix_title(&self) -> Option { + let ConvertNamedTupleFunctionalToClass { name } = self; + + Some(format!("Convert `{name}` to class syntax")) } } @@ -197,7 +195,6 @@ pub fn convert_named_tuple_functional_to_class( let mut diagnostic = Diagnostic::new( ConvertNamedTupleFunctionalToClass { name: typename.to_string(), - fixable, }, stmt.range(), ); diff --git a/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs b/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs index dee89608fc..761f27bffb 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs @@ -26,11 +26,9 @@ impl Violation for ConvertTypedDictFunctionalToClass { format!("Convert `{name}` from `TypedDict` functional to class syntax") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|ConvertTypedDictFunctionalToClass { name, .. }| { - format!("Convert `{name}` to class syntax") - }) + fn autofix_title(&self) -> Option { + let ConvertTypedDictFunctionalToClass { name, .. } = self; + Some(format!("Convert `{name}` to class syntax")) } } diff --git a/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs index 6548bffb4a..5afe1081d2 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs @@ -20,12 +20,8 @@ impl Violation for DatetimeTimezoneUTC { format!("Use `datetime.UTC` alias") } - fn autofix_title_formatter(&self) -> Option String> { - if self.straight_import { - Some(|_| "Convert to `datetime.UTC` alias".to_string()) - } else { - None - } + fn autofix_title(&self) -> Option { + Some("Convert to `datetime.UTC` alias".to_string()) } } diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs index 40af7306db..c4310a39c1 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs @@ -62,14 +62,9 @@ impl Violation for DeprecatedImport { } } - fn autofix_title_formatter(&self) -> Option String> { - if let Deprecation::WithoutRename(WithoutRename { fixable, .. }) = self.deprecation { - fixable.then_some(|DeprecatedImport { deprecation }| { - let Deprecation::WithoutRename(WithoutRename { target, .. }) = deprecation else { - unreachable!(); - }; - format!("Import from `{target}`") - }) + fn autofix_title(&self) -> Option { + if let Deprecation::WithoutRename(WithoutRename { target, .. }) = &self.deprecation { + Some(format!("Import from `{target}`")) } else { None } diff --git a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs index 9c1df4a2e3..68d27b23b4 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/format_literals.rs @@ -24,8 +24,8 @@ impl Violation for FormatLiterals { format!("Use implicit references for positional format fields") } - fn autofix_title_formatter(&self) -> Option String> { - Some(|_| "Remove explicit positional indices".to_string()) + fn autofix_title(&self) -> Option { + Some("Remove explicit positional indices".to_string()) } } diff --git a/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs index 4f3578bf42..21f697501c 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs @@ -7,9 +7,7 @@ use crate::checkers::ast::Checker; use crate::registry::AsRule; #[violation] -pub struct OpenAlias { - fixable: bool, -} +pub struct OpenAlias; impl Violation for OpenAlias { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -19,9 +17,8 @@ impl Violation for OpenAlias { format!("Use builtin `open`") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|_| format!("Replace with builtin `open`")) + fn autofix_title(&self) -> Option { + Some("Replace with builtin `open`".to_string()) } } @@ -36,7 +33,7 @@ pub fn open_alias(checker: &mut Checker, expr: &Expr, func: &Expr) { .ctx .find_binding("open") .map_or(true, |binding| binding.kind.is_builtin()); - let mut diagnostic = Diagnostic::new(OpenAlias { fixable }, expr.range()); + let mut diagnostic = Diagnostic::new(OpenAlias, expr.range()); if fixable && checker.patch(diagnostic.kind.rule()) { #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs index 6d44c807f9..6d7fe89729 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs @@ -10,7 +10,6 @@ use crate::registry::AsRule; #[violation] pub struct NonPEP585Annotation { name: String, - fixable: bool, } impl Violation for NonPEP585Annotation { @@ -18,7 +17,7 @@ impl Violation for NonPEP585Annotation { #[derive_message_formats] fn message(&self) -> String { - let NonPEP585Annotation { name, .. } = self; + let NonPEP585Annotation { name } = self; format!( "Use `{}` instead of `{}` for type annotations", name.to_lowercase(), @@ -26,10 +25,9 @@ impl Violation for NonPEP585Annotation { ) } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable.then_some(|NonPEP585Annotation { name, .. }| { - format!("Replace `{name}` with `{}`", name.to_lowercase()) - }) + fn autofix_title(&self) -> Option { + let NonPEP585Annotation { name } = self; + Some(format!("Replace `{name}` with `{}`", name.to_lowercase())) } } @@ -48,7 +46,6 @@ pub fn use_pep585_annotation(checker: &mut Checker, expr: &Expr) { let mut diagnostic = Diagnostic::new( NonPEP585Annotation { name: binding.to_string(), - fixable, }, expr.range(), ); diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs index 5820321193..f8163bd354 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs @@ -10,9 +10,7 @@ use crate::checkers::ast::Checker; use crate::registry::AsRule; #[violation] -pub struct NonPEP604Annotation { - fixable: bool, -} +pub struct NonPEP604Annotation; impl Violation for NonPEP604Annotation { const AUTOFIX: AutofixKind = AutofixKind::Sometimes; @@ -22,8 +20,8 @@ impl Violation for NonPEP604Annotation { format!("Use `X | Y` for type annotations") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable.then_some(|_| format!("Convert to `X | Y`")) + fn autofix_title(&self) -> Option { + Some("Convert to `X | Y`".to_string()) } } @@ -110,7 +108,7 @@ pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, s match typing_member { TypingMember::Optional => { - let mut diagnostic = Diagnostic::new(NonPEP604Annotation { fixable }, expr.range()); + let mut diagnostic = Diagnostic::new(NonPEP604Annotation, expr.range()); if fixable && checker.patch(diagnostic.kind.rule()) { #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( @@ -121,7 +119,7 @@ pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, s checker.diagnostics.push(diagnostic); } TypingMember::Union => { - let mut diagnostic = Diagnostic::new(NonPEP604Annotation { fixable }, expr.range()); + let mut diagnostic = Diagnostic::new(NonPEP604Annotation, expr.range()); if fixable && checker.patch(diagnostic.kind.rule()) { match &slice.node { ExprKind::Slice { .. } => { diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006.py.snap index 19db55b0de..066862e749 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006.py.snap @@ -151,6 +151,7 @@ UP006.py:45:10: UP006 Use `list` instead of `List` for type annotations | ^^^^^^^^^^^^^^ UP006 46 | ... | + = help: Replace `List` with `list` UP006.py:49:11: UP006 [*] Use `list` instead of `List` for type annotations | @@ -212,6 +213,7 @@ UP006.py:53:16: UP006 Use `list` instead of `List` for type annotations | ^^^^^^^^^^^^^^ UP006 54 | ... | + = help: Replace `List` with `list` UP006.py:57:10: UP006 Use `list` instead of `List` for type annotations | @@ -219,6 +221,7 @@ UP006.py:57:10: UP006 Use `list` instead of `List` for type annotations | ^^^^^^^^^^^^^^^^^^^^^^ UP006 58 | ... | + = help: Replace `List` with `list` UP006.py:57:10: UP006 Use `list` instead of `List` for type annotations | @@ -226,5 +229,6 @@ UP006.py:57:10: UP006 Use `list` instead of `List` for type annotations | ^^^^^^^^^^^^^^^^^^^^^^ UP006 58 | ... | + = help: Replace `List` with `list` diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP007.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP007.py.snap index b844f6a84b..dc6c3fa764 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP007.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP007.py.snap @@ -209,6 +209,7 @@ UP007.py:48:9: UP007 Use `X | Y` for type annotations 51 | 52 | x = Union[str, int] | + = help: Convert to `X | Y` UP007.py:50:9: UP007 Use `X | Y` for type annotations | @@ -219,6 +220,7 @@ UP007.py:50:9: UP007 Use `X | Y` for type annotations 53 | x = Union["str", "int"] 54 | x: Union[str, int] | + = help: Convert to `X | Y` UP007.py:52:8: UP007 [*] Use `X | Y` for type annotations | diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP020.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP020.py.snap index b219ec28d9..e4a5fedc98 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP020.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP020.py.snap @@ -28,5 +28,6 @@ UP020.py:8:6: UP020 Use builtin `open` | ^^^^^^^^^^^^^ UP020 11 | print(f.read()) | + = help: Replace with builtin `open` diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP035.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP035.py.snap index c57bb255da..64d92cbd74 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP035.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP035.py.snap @@ -418,5 +418,6 @@ UP035.py:46:10: UP035 Import from `collections.abc` instead: `Mapping` 50 | 51 | # OK | + = help: Import from `collections.abc` diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__datetime_utc_alias_py311.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__datetime_utc_alias_py311.snap index 5aace83b43..65807c0e0f 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__datetime_utc_alias_py311.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__datetime_utc_alias_py311.snap @@ -8,6 +8,7 @@ UP017.py:7:7: UP017 Use `datetime.UTC` alias | ^^^^^^^^^^^^ UP017 9 | print(tz.utc) | + = help: Convert to `datetime.UTC` alias UP017.py:8:7: UP017 Use `datetime.UTC` alias | @@ -18,6 +19,7 @@ UP017.py:8:7: UP017 Use `datetime.UTC` alias 11 | 12 | print(datetime.timezone.utc) | + = help: Convert to `datetime.UTC` alias UP017.py:10:7: UP017 [*] Use `datetime.UTC` alias | @@ -43,5 +45,6 @@ UP017.py:11:7: UP017 Use `datetime.UTC` alias 12 | print(dt.timezone.utc) | ^^^^^^^^^^^^^^^ UP017 | + = help: Convert to `datetime.UTC` alias diff --git a/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs b/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs index 4a383643b0..52d0fed36b 100644 --- a/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs +++ b/crates/ruff/src/rules/ruff/rules/collection_literal_concatenation.rs @@ -10,7 +10,6 @@ use crate::registry::AsRule; #[violation] pub struct CollectionLiteralConcatenation { expr: String, - fixable: bool, } impl Violation for CollectionLiteralConcatenation { @@ -18,15 +17,13 @@ impl Violation for CollectionLiteralConcatenation { #[derive_message_formats] fn message(&self) -> String { - let CollectionLiteralConcatenation { expr, .. } = self; + let CollectionLiteralConcatenation { expr } = self; format!("Consider `{expr}` instead of concatenation") } - fn autofix_title_formatter(&self) -> Option String> { - self.fixable - .then_some(|CollectionLiteralConcatenation { expr, .. }| { - format!("Replace with `{expr}`") - }) + fn autofix_title(&self) -> Option { + let CollectionLiteralConcatenation { expr } = self; + Some(format!("Replace with `{expr}`")) } } @@ -102,7 +99,6 @@ pub fn collection_literal_concatenation(checker: &mut Checker, expr: &Expr) { let mut diagnostic = Diagnostic::new( CollectionLiteralConcatenation { expr: contents.clone(), - fixable, }, expr.range(), ); diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF005_RUF005.py.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF005_RUF005.py.snap index 88464a0979..4a0263ba1a 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF005_RUF005.py.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF005_RUF005.py.snap @@ -226,6 +226,7 @@ RUF005.py:32:10: RUF005 Consider `[*first, 4, 5, 6]` instead of concatenation 42 | 43 | [] + foo + [ | + = help: Replace with `[*first, 4, 5, 6]` RUF005.py:41:1: RUF005 [*] Consider `[*foo]` instead of concatenation | diff --git a/crates/ruff_diagnostics/src/violation.rs b/crates/ruff_diagnostics/src/violation.rs index e4bb9034ae..4c8d19c0a0 100644 --- a/crates/ruff_diagnostics/src/violation.rs +++ b/crates/ruff_diagnostics/src/violation.rs @@ -30,10 +30,13 @@ pub trait Violation: Debug + PartialEq + Eq { None } - /// If autofix is (potentially) available for this violation returns another - /// function that in turn can be used to obtain a string describing the - /// autofix. - fn autofix_title_formatter(&self) -> Option String> { + // TODO micha: Move `autofix_title` to `Fix`, add new `advice` method that is shown as an advice. + // Change the `Diagnostic` renderer to show the advice, and render the fix message after the `Suggested fix: ` + + /// Returns the title for the autofix. The message is also shown as an advice as part of the diagnostics. + /// + /// Required for rules that have autofixes. + fn autofix_title(&self) -> Option { None } @@ -72,8 +75,8 @@ impl Violation for VA { ::explanation() } - fn autofix_title_formatter(&self) -> Option String> { - Some(Self::autofix_title) + fn autofix_title(&self) -> Option { + Some(::autofix_title(self)) } fn message_formats() -> &'static [&'static str] { diff --git a/crates/ruff_macros/src/violation.rs b/crates/ruff_macros/src/violation.rs index 31ac91b41f..0104007228 100644 --- a/crates/ruff_macros/src/violation.rs +++ b/crates/ruff_macros/src/violation.rs @@ -59,7 +59,7 @@ pub fn violation(violation: &ItemStruct) -> Result { Self { body: Violation::message(&value), - suggestion: value.autofix_title_formatter().map(|f| f(&value)), + suggestion: Violation::autofix_title(&value), name: stringify!(#ident).to_string(), } } @@ -82,7 +82,7 @@ pub fn violation(violation: &ItemStruct) -> Result { Self { body: Violation::message(&value), - suggestion: value.autofix_title_formatter().map(|f| f(&value)), + suggestion: Violation::autofix_title(&value), name: stringify!(#ident).to_string(), } }