diff --git a/README.md b/README.md index 547fb403b8..c9f39235d3 100644 --- a/README.md +++ b/README.md @@ -1422,7 +1422,7 @@ For more, see [flake8-self](https://pypi.org/project/flake8-self/) on PyPI. | RUF002 | ambiguous-unicode-character-docstring | Docstring contains ambiguous unicode character '{confusable}' (did you mean '{representant}'?) | 🛠 | | RUF003 | ambiguous-unicode-character-comment | Comment contains ambiguous unicode character '{confusable}' (did you mean '{representant}'?) | 🛠 | | RUF004 | keyword-argument-before-star-argument | Keyword argument `{name}` must come after starred arguments | | -| RUF005 | unpack-instead-of-concatenating-to-collection-literal | Consider `{expr}` instead of concatenation | | +| RUF005 | unpack-instead-of-concatenating-to-collection-literal | Consider `{expr}` instead of concatenation | 🛠 | | RUF100 | unused-noqa | Unused blanket `noqa` directive | 🛠 | diff --git a/crates/ruff/src/rules/ruff/rules/unpack_instead_of_concatenating_to_collection_literal.rs b/crates/ruff/src/rules/ruff/rules/unpack_instead_of_concatenating_to_collection_literal.rs index d3ab6940bc..5076a822d1 100644 --- a/crates/ruff/src/rules/ruff/rules/unpack_instead_of_concatenating_to_collection_literal.rs +++ b/crates/ruff/src/rules/ruff/rules/unpack_instead_of_concatenating_to_collection_literal.rs @@ -6,19 +6,36 @@ use crate::ast::types::Range; use crate::checkers::ast::Checker; use crate::fix::Fix; use crate::registry::Diagnostic; -use crate::violation::Violation; +use crate::violation::{Availability, Violation}; +use crate::AutofixKind; define_violation!( pub struct UnpackInsteadOfConcatenatingToCollectionLiteral { pub expr: String, + pub fixable: bool, } ); impl Violation for UnpackInsteadOfConcatenatingToCollectionLiteral { + const AUTOFIX: Option = Some(AutofixKind::new(Availability::Sometimes)); + #[derive_message_formats] fn message(&self) -> String { - let UnpackInsteadOfConcatenatingToCollectionLiteral { expr } = self; + let UnpackInsteadOfConcatenatingToCollectionLiteral { expr, .. } = self; format!("Consider `{expr}` instead of concatenation") } + + fn autofix_title_formatter(&self) -> Option String> { + let UnpackInsteadOfConcatenatingToCollectionLiteral { fixable, .. } = self; + if *fixable { + Some( + |UnpackInsteadOfConcatenatingToCollectionLiteral { expr, .. }| { + format!("Replace with `{expr}`") + }, + ) + } else { + None + } + } } fn make_splat_elts( @@ -86,24 +103,24 @@ pub fn unpack_instead_of_concatenating_to_collection_literal(checker: &mut Check }), }; - let mut new_expr_string = unparse_expr(&new_expr, checker.stylist); - - new_expr_string = match kind { + let contents = match kind { // Wrap the new expression in parentheses if it was a tuple - Kind::Tuple => format!("({new_expr_string})"), - Kind::List => new_expr_string, + Kind::Tuple => format!("({})", unparse_expr(&new_expr, checker.stylist)), + Kind::List => unparse_expr(&new_expr, checker.stylist), }; + let fixable = !has_comments(expr, checker.locator); let mut diagnostic = Diagnostic::new( UnpackInsteadOfConcatenatingToCollectionLiteral { - expr: new_expr_string.clone(), + expr: contents.clone(), + fixable, }, Range::from_located(expr), ); if checker.patch(diagnostic.kind.rule()) { - if !has_comments(expr, checker.locator) { + if fixable { diagnostic.amend(Fix::replacement( - new_expr_string, + contents, expr.location, expr.end_location.unwrap(), )); 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 6a0313af09..950d79681e 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 @@ -1,10 +1,11 @@ --- -source: src/rules/ruff/mod.rs +source: crates/ruff/src/rules/ruff/mod.rs expression: diagnostics --- - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "[1, 2, 3, *foo]" + fixable: true location: row: 10 column: 6 @@ -24,6 +25,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "(7, 8, 9, *zoob)" + fixable: true location: row: 12 column: 7 @@ -43,6 +45,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "(*quux, 10, 11, 12)" + fixable: true location: row: 13 column: 7 @@ -62,6 +65,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "[*spom, 13, 14, 15]" + fixable: true location: row: 15 column: 7 @@ -81,6 +85,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "(\"we all say\", *yay())" + fixable: true location: row: 16 column: 12 @@ -100,6 +105,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "(\"we all think\", *Fun().yay())" + fixable: true location: row: 17 column: 13 @@ -119,6 +125,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "(\"we all feel\", *Fun.words)" + fixable: true location: row: 18 column: 15 @@ -138,6 +145,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "[\"a\", \"b\", \"c\", *eggs]" + fixable: true location: row: 20 column: 8 @@ -157,6 +165,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "(\"yes\", \"no\", \"pants\", *zoob)" + fixable: true location: row: 20 column: 38 @@ -176,6 +185,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "(*zoob,)" + fixable: true location: row: 22 column: 6 @@ -195,6 +205,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "[*first, 4, 5, 6]" + fixable: false location: row: 32 column: 9 @@ -206,6 +217,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "[*foo]" + fixable: true location: row: 41 column: 0 @@ -225,6 +237,7 @@ expression: diagnostics - kind: UnpackInsteadOfConcatenatingToCollectionLiteral: expr: "[*foo]" + fixable: true location: row: 44 column: 0