Skip to content

Commit

Permalink
astral-sh#10323: Fixed incorrect rule transformation rule C409 (unnec…
Browse files Browse the repository at this point in the history
…essary-literal-within-tuple-call)
  • Loading branch information
WindowGenerator committed Mar 20, 2024
1 parent ad84eed commit 18c90be
Showing 1 changed file with 24 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::{Ranged, TextSize};
use ruff_text_size::Ranged;

use crate::checkers::ast::Checker;

Expand Down Expand Up @@ -71,9 +71,12 @@ pub(crate) fn unnecessary_literal_within_tuple_call(checker: &mut Checker, call:
if !call.arguments.keywords.is_empty() {
return;
}
let Some(argument) =
helpers::first_argument_with_matching_function("tuple", &call.func, &call.arguments.args)
else {
let Some(argument) = helpers::exactly_one_argument_with_matching_function(
"tuple",
&call.func,
&call.arguments.args,
&call.arguments.keywords,
) else {
return;
};
if !checker.semantic().is_builtin("tuple") {
Expand All @@ -92,23 +95,26 @@ pub(crate) fn unnecessary_literal_within_tuple_call(checker: &mut Checker, call:
call.range(),
);

// Convert `tuple([1, 2])` to `tuple(1, 2)`
// Convert `tuple([1, 2])` to `(1, 2)`
diagnostic.set_fix({
// Replace from the start of the call to the start of the inner list or tuple with `(`.
let call_start = Edit::replacement(
"(".to_string(),
call.start(),
argument.start() + TextSize::from(1),
);
let elts: Vec<Expr> = match argument {
Expr::List(list_expr) => list_expr.elts.clone(),
Expr::Tuple(tuple_expr) => tuple_expr.elts.clone(),
_ => return,
};

// Replace from the end of the inner list or tuple to the end of the call with `)`.
let call_end = Edit::replacement(
")".to_string(),
argument.end() - TextSize::from(1),
call.end(),
);
// Replace [1, 2] -> (1, 2) or [1] -> (1,)
let tuple: String = if let [elt] = elts.as_slice() {
let elt: &str = checker.locator().slice(elt);
format!("({},)", elt)
} else {
let elt_set: &str = checker.locator().slice(argument);
format!("({})", &elt_set[1..elt_set.len() - 1])
};

let edit = Edit::replacement(tuple, call.start(), call.end());

Fix::unsafe_edits(call_start, [call_end])
Fix::unsafe_edit(edit)
});

checker.diagnostics.push(diagnostic);
Expand Down

0 comments on commit 18c90be

Please sign in to comment.