Skip to content

Commit 13cf3e6

Browse files
authored
[flake8-comprehensions] Parenthesize sorted when needed for unnecessary-call-around-sorted (C413) (#15825)
If there is any `ParenthesizedWhitespace` (in the sense of LibCST) after the function name `sorted` and before the arguments, then we must wrap `sorted` with parentheses after removing the surrounding function. Closes #15789
1 parent 56f956a commit 13cf3e6

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

crates/ruff_linter/resources/test/fixtures/flake8_comprehensions/C413.py

+10
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,13 @@
1717
# Regression test for: https://github.com/astral-sh/ruff/issues/10335
1818
reversed(sorted([1, 2, 3], reverse=False or True))
1919
reversed(sorted([1, 2, 3], reverse=(False or True)))
20+
21+
# These fixes need to be parenthesized to avoid syntax errors and behavior
22+
# changes.
23+
# See https://github.com/astral-sh/ruff/issues/15789
24+
reversed(sorted
25+
(""))
26+
list(sorted
27+
(""))
28+
list(sorted
29+
("xy"))

crates/ruff_linter/src/rules/flake8_comprehensions/fixes.rs

+11
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,17 @@ pub(crate) fn fix_unnecessary_call_around_sorted(
416416
}
417417
};
418418

419+
let inner_needs_parens = matches!(
420+
inner_call.whitespace_after_func,
421+
ParenthesizableWhitespace::ParenthesizedWhitespace(_)
422+
);
423+
419424
if let Expression::Name(outer_name) = &*outer_call.func {
420425
if outer_name.value == "list" {
421426
tree = Expression::Call(Box::new((*inner_call).clone()));
427+
if inner_needs_parens {
428+
tree = tree.with_parens(LeftParen::default(), RightParen::default());
429+
};
422430
} else {
423431
// If the `reverse` argument is used...
424432
let args = if inner_call.args.iter().any(|arg| {
@@ -503,6 +511,9 @@ pub(crate) fn fix_unnecessary_call_around_sorted(
503511
whitespace_after_func: inner_call.whitespace_after_func.clone(),
504512
whitespace_before_args: inner_call.whitespace_before_args.clone(),
505513
}));
514+
if inner_needs_parens {
515+
tree = tree.with_parens(LeftParen::default(), RightParen::default());
516+
}
506517
}
507518
}
508519

crates/ruff_linter/src/rules/flake8_comprehensions/snapshots/ruff_linter__rules__flake8_comprehensions__tests__C413_C413.py.snap

+71
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,17 @@ C413.py:18:1: C413 [*] Unnecessary `reversed()` call around `sorted()`
244244
18 |-reversed(sorted([1, 2, 3], reverse=False or True))
245245
18 |+sorted([1, 2, 3], reverse=not (False or True))
246246
19 19 | reversed(sorted([1, 2, 3], reverse=(False or True)))
247+
20 20 |
248+
21 21 | # These fixes need to be parenthesized to avoid syntax errors and behavior
247249

248250
C413.py:19:1: C413 [*] Unnecessary `reversed()` call around `sorted()`
249251
|
250252
17 | # Regression test for: https://github.com/astral-sh/ruff/issues/10335
251253
18 | reversed(sorted([1, 2, 3], reverse=False or True))
252254
19 | reversed(sorted([1, 2, 3], reverse=(False or True)))
253255
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C413
256+
20 |
257+
21 | # These fixes need to be parenthesized to avoid syntax errors and behavior
254258
|
255259
= help: Remove unnecessary `reversed()` call
256260

@@ -260,3 +264,70 @@ C413.py:19:1: C413 [*] Unnecessary `reversed()` call around `sorted()`
260264
18 18 | reversed(sorted([1, 2, 3], reverse=False or True))
261265
19 |-reversed(sorted([1, 2, 3], reverse=(False or True)))
262266
19 |+sorted([1, 2, 3], reverse=not (False or True))
267+
20 20 |
268+
21 21 | # These fixes need to be parenthesized to avoid syntax errors and behavior
269+
22 22 | # changes.
270+
271+
C413.py:24:1: C413 [*] Unnecessary `reversed()` call around `sorted()`
272+
|
273+
22 | # changes.
274+
23 | # See https://github.com/astral-sh/ruff/issues/15789
275+
24 | / reversed(sorted
276+
25 | | (""))
277+
| |_____^ C413
278+
26 | list(sorted
279+
27 | (""))
280+
|
281+
= help: Remove unnecessary `reversed()` call
282+
283+
Unsafe fix
284+
21 21 | # These fixes need to be parenthesized to avoid syntax errors and behavior
285+
22 22 | # changes.
286+
23 23 | # See https://github.com/astral-sh/ruff/issues/15789
287+
24 |-reversed(sorted
288+
25 |-(""))
289+
24 |+(sorted
290+
25 |+("", reverse=True))
291+
26 26 | list(sorted
292+
27 27 | (""))
293+
28 28 | list(sorted
294+
295+
C413.py:26:1: C413 [*] Unnecessary `list()` call around `sorted()`
296+
|
297+
24 | reversed(sorted
298+
25 | (""))
299+
26 | / list(sorted
300+
27 | | (""))
301+
| |_________^ C413
302+
28 | list(sorted
303+
29 | ("xy"))
304+
|
305+
= help: Remove unnecessary `list()` call
306+
307+
Safe fix
308+
23 23 | # See https://github.com/astral-sh/ruff/issues/15789
309+
24 24 | reversed(sorted
310+
25 25 | (""))
311+
26 |-list(sorted
312+
26 |+(sorted
313+
27 27 | (""))
314+
28 28 | list(sorted
315+
29 29 | ("xy"))
316+
317+
C413.py:28:1: C413 [*] Unnecessary `list()` call around `sorted()`
318+
|
319+
26 | list(sorted
320+
27 | (""))
321+
28 | / list(sorted
322+
29 | | ("xy"))
323+
| |_______^ C413
324+
|
325+
= help: Remove unnecessary `list()` call
326+
327+
Safe fix
328+
25 25 | (""))
329+
26 26 | list(sorted
330+
27 27 | (""))
331+
28 |-list(sorted
332+
28 |+(sorted
333+
29 29 | ("xy"))

0 commit comments

Comments
 (0)