diff --git a/crates/ruff_linter/resources/test/fixtures/pylint/binary_op_and_normal_assignment.py b/crates/ruff_linter/resources/test/fixtures/pylint/non_augmented_assignment.py similarity index 100% rename from crates/ruff_linter/resources/test/fixtures/pylint/binary_op_and_normal_assignment.py rename to crates/ruff_linter/resources/test/fixtures/pylint/non_augmented_assignment.py diff --git a/crates/ruff_linter/src/checkers/ast/analyze/statement.rs b/crates/ruff_linter/src/checkers/ast/analyze/statement.rs index 86053d79f53db9..90676d3c89b304 100644 --- a/crates/ruff_linter/src/checkers/ast/analyze/statement.rs +++ b/crates/ruff_linter/src/checkers/ast/analyze/statement.rs @@ -1478,8 +1478,8 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { if checker.settings.rules.enabled(Rule::TypeBivariance) { pylint::rules::type_bivariance(checker, value); } - if checker.enabled(Rule::BinaryOpAndNormalAssignment) { - pylint::rules::binary_op_and_normal_assignment(checker, assign); + if checker.enabled(Rule::NonAugmentedAssignment) { + pylint::rules::non_augmented_assignment(checker, assign); } if checker.settings.rules.enabled(Rule::UnsortedDunderAll) { ruff::rules::sort_dunder_all_assign(checker, assign); diff --git a/crates/ruff_linter/src/codes.rs b/crates/ruff_linter/src/codes.rs index fffef2009d0d36..30d4e461b5dd71 100644 --- a/crates/ruff_linter/src/codes.rs +++ b/crates/ruff_linter/src/codes.rs @@ -293,7 +293,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Pylint, "R2004") => (RuleGroup::Stable, rules::pylint::rules::MagicValueComparison), (Pylint, "R2044") => (RuleGroup::Preview, rules::pylint::rules::EmptyComment), (Pylint, "R5501") => (RuleGroup::Stable, rules::pylint::rules::CollapsibleElseIf), - (Pylint, "R6104") => (RuleGroup::Preview, rules::pylint::rules::BinaryOpAndNormalAssignment), + (Pylint, "R6104") => (RuleGroup::Preview, rules::pylint::rules::NonAugmentedAssignment), (Pylint, "R6201") => (RuleGroup::Preview, rules::pylint::rules::LiteralMembership), #[allow(deprecated)] (Pylint, "R6301") => (RuleGroup::Nursery, rules::pylint::rules::NoSelfUse), diff --git a/crates/ruff_linter/src/rules/pylint/mod.rs b/crates/ruff_linter/src/rules/pylint/mod.rs index 977546a02d361e..b71a5f92ed38e5 100644 --- a/crates/ruff_linter/src/rules/pylint/mod.rs +++ b/crates/ruff_linter/src/rules/pylint/mod.rs @@ -186,10 +186,7 @@ mod tests { Rule::UnnecessaryDictIndexLookup, Path::new("unnecessary_dict_index_lookup.py") )] - #[test_case( - Rule::BinaryOpAndNormalAssignment, - Path::new("binary_op_and_normal_assignment.py") - )] + #[test_case(Rule::NonAugmentedAssignment, Path::new("non_augmented_assignment.py"))] #[test_case( Rule::UselessExceptionStatement, Path::new("useless_exception_statement.py") diff --git a/crates/ruff_linter/src/rules/pylint/rules/mod.rs b/crates/ruff_linter/src/rules/pylint/rules/mod.rs index 6298d0e5eb96fa..0c388ef91c5d15 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/mod.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/mod.rs @@ -8,7 +8,6 @@ pub(crate) use bad_str_strip_call::*; pub(crate) use bad_string_format_character::BadStringFormatCharacter; pub(crate) use bad_string_format_type::*; pub(crate) use bidirectional_unicode::*; -pub(crate) use binary_op_and_normal_assignment::*; pub(crate) use binary_op_exception::*; pub(crate) use collapsible_else_if::*; pub(crate) use compare_to_empty_string::*; @@ -48,6 +47,7 @@ pub(crate) use no_method_decorator::*; pub(crate) use no_self_use::*; pub(crate) use non_ascii_module_import::*; pub(crate) use non_ascii_name::*; +pub(crate) use non_augmented_assignment::*; pub(crate) use non_slot_assignment::*; pub(crate) use nonlocal_and_global::*; pub(crate) use nonlocal_without_binding::*; @@ -105,7 +105,6 @@ mod bad_str_strip_call; pub(crate) mod bad_string_format_character; mod bad_string_format_type; mod bidirectional_unicode; -mod binary_op_and_normal_assignment; mod binary_op_exception; mod collapsible_else_if; mod compare_to_empty_string; @@ -145,6 +144,7 @@ mod no_method_decorator; mod no_self_use; mod non_ascii_module_import; mod non_ascii_name; +mod non_augmented_assignment; mod non_slot_assignment; mod nonlocal_and_global; mod nonlocal_without_binding; diff --git a/crates/ruff_linter/src/rules/pylint/rules/binary_op_and_normal_assignment.rs b/crates/ruff_linter/src/rules/pylint/rules/non_augmented_assignment.rs similarity index 90% rename from crates/ruff_linter/src/rules/pylint/rules/binary_op_and_normal_assignment.rs rename to crates/ruff_linter/src/rules/pylint/rules/non_augmented_assignment.rs index fa9efe0608b7e9..9dad8c84f1efcf 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/binary_op_and_normal_assignment.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/non_augmented_assignment.rs @@ -1,5 +1,5 @@ use ast::{Expr, StmtAugAssign}; -use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; +use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast as ast; use ruff_python_ast::comparable::ComparableExpr; @@ -57,26 +57,24 @@ use crate::checkers::ast::Checker; /// assert (foo, bar) == ([1, 2], [1, 2]) /// ``` #[violation] -pub struct BinaryOpAndNormalAssignment { +pub struct NonAugmentedAssignment { operator: AugmentedOperator, } -impl Violation for BinaryOpAndNormalAssignment { - const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes; - +impl AlwaysFixableViolation for NonAugmentedAssignment { #[derive_message_formats] fn message(&self) -> String { - let BinaryOpAndNormalAssignment { operator } = self; + let NonAugmentedAssignment { operator } = self; format!("Use `{operator}` to perform an augmented assignment directly") } - fn fix_title(&self) -> Option { - Some("Replace with augmented assignment".to_string()) + fn fix_title(&self) -> String { + "Replace with augmented assignment".to_string() } } /// PLR6104 -pub(crate) fn binary_op_and_normal_assignment(checker: &mut Checker, assign: &ast::StmtAssign) { +pub(crate) fn non_augmented_assignment(checker: &mut Checker, assign: &ast::StmtAssign) { // Ignore multiple assignment targets. let [target] = assign.targets.as_slice() else { return; @@ -90,7 +88,7 @@ pub(crate) fn binary_op_and_normal_assignment(checker: &mut Checker, assign: &as // Match, e.g., `x = x + 1`. if ComparableExpr::from(target) == ComparableExpr::from(&value.left) { let mut diagnostic = Diagnostic::new( - BinaryOpAndNormalAssignment { + NonAugmentedAssignment { operator: AugmentedOperator::from(value.op), }, assign.range(), @@ -109,7 +107,7 @@ pub(crate) fn binary_op_and_normal_assignment(checker: &mut Checker, assign: &as // Match, e.g., `x = 1 + x`. if ComparableExpr::from(target) == ComparableExpr::from(&value.right) { let mut diagnostic = Diagnostic::new( - BinaryOpAndNormalAssignment { + NonAugmentedAssignment { operator: AugmentedOperator::from(value.op), }, assign.range(), diff --git a/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLR6104_binary_op_and_normal_assignment.py.snap b/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLR6104_non_augmented_assignment.py.snap similarity index 82% rename from crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLR6104_binary_op_and_normal_assignment.py.snap rename to crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLR6104_non_augmented_assignment.py.snap index b62f5e80b6d805..9e2557b9ed7c8c 100644 --- a/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLR6104_binary_op_and_normal_assignment.py.snap +++ b/crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLR6104_non_augmented_assignment.py.snap @@ -1,7 +1,7 @@ --- source: crates/ruff_linter/src/rules/pylint/mod.rs --- -binary_op_and_normal_assignment.py:16:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly +non_augmented_assignment.py:16:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly | 14 | mat1, mat2 = None, None 15 | @@ -22,7 +22,7 @@ binary_op_and_normal_assignment.py:16:1: PLR6104 [*] Use `+=` to perform an augm 18 18 | a_list = a_list + ["to concat"] 19 19 | some_set = some_set | {"to concat"} -binary_op_and_normal_assignment.py:17:1: PLR6104 [*] Use `-=` to perform an augmented assignment directly +non_augmented_assignment.py:17:1: PLR6104 [*] Use `-=` to perform an augmented assignment directly | 16 | some_string = some_string + "a very long end of string" 17 | index = index - 1 @@ -42,7 +42,7 @@ binary_op_and_normal_assignment.py:17:1: PLR6104 [*] Use `-=` to perform an augm 19 19 | some_set = some_set | {"to concat"} 20 20 | to_multiply = to_multiply * 5 -binary_op_and_normal_assignment.py:18:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly +non_augmented_assignment.py:18:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly | 16 | some_string = some_string + "a very long end of string" 17 | index = index - 1 @@ -63,7 +63,7 @@ binary_op_and_normal_assignment.py:18:1: PLR6104 [*] Use `+=` to perform an augm 20 20 | to_multiply = to_multiply * 5 21 21 | to_divide = to_divide / 5 -binary_op_and_normal_assignment.py:19:1: PLR6104 [*] Use `|=` to perform an augmented assignment directly +non_augmented_assignment.py:19:1: PLR6104 [*] Use `|=` to perform an augmented assignment directly | 17 | index = index - 1 18 | a_list = a_list + ["to concat"] @@ -84,7 +84,7 @@ binary_op_and_normal_assignment.py:19:1: PLR6104 [*] Use `|=` to perform an augm 21 21 | to_divide = to_divide / 5 22 22 | to_divide = to_divide // 5 -binary_op_and_normal_assignment.py:20:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly +non_augmented_assignment.py:20:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly | 18 | a_list = a_list + ["to concat"] 19 | some_set = some_set | {"to concat"} @@ -105,7 +105,7 @@ binary_op_and_normal_assignment.py:20:1: PLR6104 [*] Use `*=` to perform an augm 22 22 | to_divide = to_divide // 5 23 23 | to_cube = to_cube**3 -binary_op_and_normal_assignment.py:21:1: PLR6104 [*] Use `/=` to perform an augmented assignment directly +non_augmented_assignment.py:21:1: PLR6104 [*] Use `/=` to perform an augmented assignment directly | 19 | some_set = some_set | {"to concat"} 20 | to_multiply = to_multiply * 5 @@ -126,7 +126,7 @@ binary_op_and_normal_assignment.py:21:1: PLR6104 [*] Use `/=` to perform an augm 23 23 | to_cube = to_cube**3 24 24 | to_cube = 3**to_cube -binary_op_and_normal_assignment.py:22:1: PLR6104 [*] Use `//=` to perform an augmented assignment directly +non_augmented_assignment.py:22:1: PLR6104 [*] Use `//=` to perform an augmented assignment directly | 20 | to_multiply = to_multiply * 5 21 | to_divide = to_divide / 5 @@ -147,7 +147,7 @@ binary_op_and_normal_assignment.py:22:1: PLR6104 [*] Use `//=` to perform an aug 24 24 | to_cube = 3**to_cube 25 25 | to_cube = to_cube**to_cube -binary_op_and_normal_assignment.py:23:1: PLR6104 [*] Use `**=` to perform an augmented assignment directly +non_augmented_assignment.py:23:1: PLR6104 [*] Use `**=` to perform an augmented assignment directly | 21 | to_divide = to_divide / 5 22 | to_divide = to_divide // 5 @@ -168,7 +168,7 @@ binary_op_and_normal_assignment.py:23:1: PLR6104 [*] Use `**=` to perform an aug 25 25 | to_cube = to_cube**to_cube 26 26 | timeDiffSeconds = timeDiffSeconds % 60 -binary_op_and_normal_assignment.py:24:1: PLR6104 [*] Use `**=` to perform an augmented assignment directly +non_augmented_assignment.py:24:1: PLR6104 [*] Use `**=` to perform an augmented assignment directly | 22 | to_divide = to_divide // 5 23 | to_cube = to_cube**3 @@ -189,7 +189,7 @@ binary_op_and_normal_assignment.py:24:1: PLR6104 [*] Use `**=` to perform an aug 26 26 | timeDiffSeconds = timeDiffSeconds % 60 27 27 | flags = flags & 0x1 -binary_op_and_normal_assignment.py:25:1: PLR6104 [*] Use `**=` to perform an augmented assignment directly +non_augmented_assignment.py:25:1: PLR6104 [*] Use `**=` to perform an augmented assignment directly | 23 | to_cube = to_cube**3 24 | to_cube = 3**to_cube @@ -210,7 +210,7 @@ binary_op_and_normal_assignment.py:25:1: PLR6104 [*] Use `**=` to perform an aug 27 27 | flags = flags & 0x1 28 28 | flags = flags | 0x1 -binary_op_and_normal_assignment.py:26:1: PLR6104 [*] Use `%=` to perform an augmented assignment directly +non_augmented_assignment.py:26:1: PLR6104 [*] Use `%=` to perform an augmented assignment directly | 24 | to_cube = 3**to_cube 25 | to_cube = to_cube**to_cube @@ -231,7 +231,7 @@ binary_op_and_normal_assignment.py:26:1: PLR6104 [*] Use `%=` to perform an augm 28 28 | flags = flags | 0x1 29 29 | flags = flags ^ 0x1 -binary_op_and_normal_assignment.py:27:1: PLR6104 [*] Use `&=` to perform an augmented assignment directly +non_augmented_assignment.py:27:1: PLR6104 [*] Use `&=` to perform an augmented assignment directly | 25 | to_cube = to_cube**to_cube 26 | timeDiffSeconds = timeDiffSeconds % 60 @@ -252,7 +252,7 @@ binary_op_and_normal_assignment.py:27:1: PLR6104 [*] Use `&=` to perform an augm 29 29 | flags = flags ^ 0x1 30 30 | flags = flags << 1 -binary_op_and_normal_assignment.py:28:1: PLR6104 [*] Use `|=` to perform an augmented assignment directly +non_augmented_assignment.py:28:1: PLR6104 [*] Use `|=` to perform an augmented assignment directly | 26 | timeDiffSeconds = timeDiffSeconds % 60 27 | flags = flags & 0x1 @@ -273,7 +273,7 @@ binary_op_and_normal_assignment.py:28:1: PLR6104 [*] Use `|=` to perform an augm 30 30 | flags = flags << 1 31 31 | flags = flags >> 1 -binary_op_and_normal_assignment.py:29:1: PLR6104 [*] Use `^=` to perform an augmented assignment directly +non_augmented_assignment.py:29:1: PLR6104 [*] Use `^=` to perform an augmented assignment directly | 27 | flags = flags & 0x1 28 | flags = flags | 0x1 @@ -294,7 +294,7 @@ binary_op_and_normal_assignment.py:29:1: PLR6104 [*] Use `^=` to perform an augm 31 31 | flags = flags >> 1 32 32 | mat1 = mat1 @ mat2 -binary_op_and_normal_assignment.py:30:1: PLR6104 [*] Use `<<=` to perform an augmented assignment directly +non_augmented_assignment.py:30:1: PLR6104 [*] Use `<<=` to perform an augmented assignment directly | 28 | flags = flags | 0x1 29 | flags = flags ^ 0x1 @@ -315,7 +315,7 @@ binary_op_and_normal_assignment.py:30:1: PLR6104 [*] Use `<<=` to perform an aug 32 32 | mat1 = mat1 @ mat2 33 33 | a_list[1] = a_list[1] + 1 -binary_op_and_normal_assignment.py:31:1: PLR6104 [*] Use `>>=` to perform an augmented assignment directly +non_augmented_assignment.py:31:1: PLR6104 [*] Use `>>=` to perform an augmented assignment directly | 29 | flags = flags ^ 0x1 30 | flags = flags << 1 @@ -336,7 +336,7 @@ binary_op_and_normal_assignment.py:31:1: PLR6104 [*] Use `>>=` to perform an aug 33 33 | a_list[1] = a_list[1] + 1 34 34 | -binary_op_and_normal_assignment.py:32:1: PLR6104 [*] Use `@=` to perform an augmented assignment directly +non_augmented_assignment.py:32:1: PLR6104 [*] Use `@=` to perform an augmented assignment directly | 30 | flags = flags << 1 31 | flags = flags >> 1 @@ -356,7 +356,7 @@ binary_op_and_normal_assignment.py:32:1: PLR6104 [*] Use `@=` to perform an augm 34 34 | 35 35 | a_list[0:2] = a_list[0:2] * 3 -binary_op_and_normal_assignment.py:33:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly +non_augmented_assignment.py:33:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly | 31 | flags = flags >> 1 32 | mat1 = mat1 @ mat2 @@ -377,7 +377,7 @@ binary_op_and_normal_assignment.py:33:1: PLR6104 [*] Use `+=` to perform an augm 35 35 | a_list[0:2] = a_list[0:2] * 3 36 36 | a_list[:2] = a_list[:2] * 3 -binary_op_and_normal_assignment.py:35:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly +non_augmented_assignment.py:35:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly | 33 | a_list[1] = a_list[1] + 1 34 | @@ -398,7 +398,7 @@ binary_op_and_normal_assignment.py:35:1: PLR6104 [*] Use `*=` to perform an augm 37 37 | a_list[1:] = a_list[1:] * 3 38 38 | a_list[:] = a_list[:] * 3 -binary_op_and_normal_assignment.py:36:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly +non_augmented_assignment.py:36:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly | 35 | a_list[0:2] = a_list[0:2] * 3 36 | a_list[:2] = a_list[:2] * 3 @@ -418,7 +418,7 @@ binary_op_and_normal_assignment.py:36:1: PLR6104 [*] Use `*=` to perform an augm 38 38 | a_list[:] = a_list[:] * 3 39 39 | -binary_op_and_normal_assignment.py:37:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly +non_augmented_assignment.py:37:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly | 35 | a_list[0:2] = a_list[0:2] * 3 36 | a_list[:2] = a_list[:2] * 3 @@ -438,7 +438,7 @@ binary_op_and_normal_assignment.py:37:1: PLR6104 [*] Use `*=` to perform an augm 39 39 | 40 40 | index = index * (index + 10) -binary_op_and_normal_assignment.py:38:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly +non_augmented_assignment.py:38:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly | 36 | a_list[:2] = a_list[:2] * 3 37 | a_list[1:] = a_list[1:] * 3 @@ -459,7 +459,7 @@ binary_op_and_normal_assignment.py:38:1: PLR6104 [*] Use `*=` to perform an augm 40 40 | index = index * (index + 10) 41 41 | -binary_op_and_normal_assignment.py:40:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly +non_augmented_assignment.py:40:1: PLR6104 [*] Use `*=` to perform an augmented assignment directly | 38 | a_list[:] = a_list[:] * 3 39 | @@ -478,7 +478,7 @@ binary_op_and_normal_assignment.py:40:1: PLR6104 [*] Use `*=` to perform an augm 42 42 | 43 43 | class T: -binary_op_and_normal_assignment.py:45:9: PLR6104 [*] Use `+=` to perform an augmented assignment directly +non_augmented_assignment.py:45:9: PLR6104 [*] Use `+=` to perform an augmented assignment directly | 43 | class T: 44 | def t(self): @@ -497,7 +497,7 @@ binary_op_and_normal_assignment.py:45:9: PLR6104 [*] Use `+=` to perform an augm 47 47 | 48 48 | obj = T() -binary_op_and_normal_assignment.py:49:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly +non_augmented_assignment.py:49:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly | 48 | obj = T() 49 | obj.a = obj.a + 1