Skip to content

Commit c364b58

Browse files
[flake8-pie] Correctly remove wrapping parentheses (PIE800) (#15394)
Co-authored-by: Micha Reiser <[email protected]>
1 parent 73d424e commit c364b58

File tree

3 files changed

+263
-8
lines changed

3 files changed

+263
-8
lines changed

crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE800.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,59 @@
1818

1919
{**foo, **buzz, **{bar: 10}} # PIE800
2020

21+
# https://github.com/astral-sh/ruff/issues/15366
22+
{
23+
"data": [],
24+
**({"count": 1 if include_count else {}}),
25+
}
26+
27+
{
28+
"data": [],
29+
**( # Comment
30+
{ # Comment
31+
"count": 1 if include_count else {}}),
32+
}
33+
34+
{
35+
"data": [],
36+
**(
37+
{
38+
"count": (a := 1),}),
39+
}
40+
41+
{
42+
"data": [],
43+
**(
44+
{
45+
"count": (a := 1)
46+
}
47+
)
48+
,
49+
}
50+
51+
{
52+
"data": [],
53+
**(
54+
{
55+
"count": (a := 1), # Comment
56+
} # Comment
57+
) # Comment
58+
,
59+
}
60+
61+
({
62+
"data": [],
63+
**( # Comment
64+
( # Comment
65+
{ # Comment
66+
"count": (a := 1), # Comment
67+
} # Comment
68+
)
69+
) # Comment
70+
,
71+
})
72+
73+
2174
{**foo, "bar": True } # OK
2275

2376
{"foo": 1, "buzz": {"bar": 1}} # OK

crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_spread.rs

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,54 @@ fn unnecessary_spread_fix(
7777
if let Some(last) = dict.iter_values().last() {
7878
// Ex) `**{a: 1, b: 2}`
7979
let mut edits = vec![];
80+
let mut open_parens: u32 = 0;
81+
82+
for tok in SimpleTokenizer::starts_at(doublestar.end(), locator.contents()).skip_trivia() {
83+
match tok.kind() {
84+
SimpleTokenKind::LParen => {
85+
edits.push(Edit::range_deletion(tok.range()));
86+
open_parens += 1;
87+
}
88+
SimpleTokenKind::LBrace => {
89+
edits.push(Edit::range_deletion(tok.range()));
90+
break;
91+
}
92+
_ => {
93+
// Unexpected token, bail
94+
return None;
95+
}
96+
}
97+
}
98+
99+
let mut found_r_curly = false;
80100
for tok in SimpleTokenizer::starts_at(last.end(), locator.contents()).skip_trivia() {
101+
if found_r_curly && open_parens == 0 {
102+
break;
103+
}
104+
81105
match tok.kind() {
82106
SimpleTokenKind::Comma => {
83107
edits.push(Edit::range_deletion(tok.range()));
84108
}
109+
SimpleTokenKind::RParen => {
110+
if found_r_curly {
111+
edits.push(Edit::range_deletion(tok.range()));
112+
open_parens -= 1;
113+
}
114+
}
85115
SimpleTokenKind::RBrace => {
86116
edits.push(Edit::range_deletion(tok.range()));
87-
break;
117+
found_r_curly = true;
118+
}
119+
_ => {
120+
// Unexpected token, bail
121+
return None;
88122
}
89-
_ => {}
90123
}
91124
}
125+
92126
Some(Fix::safe_edits(
93-
// Delete the first `**{`
94-
Edit::deletion(doublestar.start(), dict.start() + TextSize::from(1)),
95-
// Delete the trailing `}`
127+
Edit::range_deletion(doublestar.range()),
96128
edits,
97129
))
98130
} else {

crates/ruff_linter/src/rules/flake8_pie/snapshots/ruff_linter__rules__flake8_pie__tests__PIE800_PIE800.py.snap

Lines changed: 173 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ PIE800.py:19:19: PIE800 [*] Unnecessary spread `**`
118118
19 | {**foo, **buzz, **{bar: 10}} # PIE800
119119
| ^^^^^^^^^ PIE800
120120
20 |
121-
21 | {**foo, "bar": True } # OK
121+
21 | # https://github.com/astral-sh/ruff/issues/15366
122122
|
123123
= help: Remove unnecessary dict
124124

@@ -129,5 +129,175 @@ PIE800.py:19:19: PIE800 [*] Unnecessary spread `**`
129129
19 |-{**foo, **buzz, **{bar: 10}} # PIE800
130130
19 |+{**foo, **buzz, bar: 10} # PIE800
131131
20 20 |
132-
21 21 | {**foo, "bar": True } # OK
133-
22 22 |
132+
21 21 | # https://github.com/astral-sh/ruff/issues/15366
133+
22 22 | {
134+
135+
PIE800.py:24:8: PIE800 [*] Unnecessary spread `**`
136+
|
137+
22 | {
138+
23 | "data": [],
139+
24 | **({"count": 1 if include_count else {}}),
140+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PIE800
141+
25 | }
142+
|
143+
= help: Remove unnecessary dict
144+
145+
Safe fix
146+
21 21 | # https://github.com/astral-sh/ruff/issues/15366
147+
22 22 | {
148+
23 23 | "data": [],
149+
24 |- **({"count": 1 if include_count else {}}),
150+
24 |+ "count": 1 if include_count else {},
151+
25 25 | }
152+
26 26 |
153+
27 27 | {
154+
155+
PIE800.py:30:9: PIE800 [*] Unnecessary spread `**`
156+
|
157+
28 | "data": [],
158+
29 | **( # Comment
159+
30 | { # Comment
160+
| _________^
161+
31 | | "count": 1 if include_count else {}}),
162+
| |________________________________________________^ PIE800
163+
32 | }
164+
|
165+
= help: Remove unnecessary dict
166+
167+
Safe fix
168+
26 26 |
169+
27 27 | {
170+
28 28 | "data": [],
171+
29 |- **( # Comment
172+
30 |- { # Comment
173+
31 |- "count": 1 if include_count else {}}),
174+
29 |+ # Comment
175+
30 |+ # Comment
176+
31 |+ "count": 1 if include_count else {},
177+
32 32 | }
178+
33 33 |
179+
34 34 | {
180+
181+
PIE800.py:37:9: PIE800 [*] Unnecessary spread `**`
182+
|
183+
35 | "data": [],
184+
36 | **(
185+
37 | {
186+
| _________^
187+
38 | | "count": (a := 1),}),
188+
| |_______________________________^ PIE800
189+
39 | }
190+
|
191+
= help: Remove unnecessary dict
192+
193+
Safe fix
194+
33 33 |
195+
34 34 | {
196+
35 35 | "data": [],
197+
36 |- **(
198+
37 |- {
199+
38 |- "count": (a := 1),}),
200+
36 |+
201+
37 |+
202+
38 |+ "count": (a := 1),
203+
39 39 | }
204+
40 40 |
205+
41 41 | {
206+
207+
PIE800.py:44:9: PIE800 [*] Unnecessary spread `**`
208+
|
209+
42 | "data": [],
210+
43 | **(
211+
44 | {
212+
| _________^
213+
45 | | "count": (a := 1)
214+
46 | | }
215+
| |_____________^ PIE800
216+
47 | )
217+
48 | ,
218+
|
219+
= help: Remove unnecessary dict
220+
221+
Safe fix
222+
40 40 |
223+
41 41 | {
224+
42 42 | "data": [],
225+
43 |- **(
226+
44 |- {
227+
43 |+
228+
44 |+
229+
45 45 | "count": (a := 1)
230+
46 |- }
231+
47 |- )
232+
46 |+
233+
47 |+
234+
48 48 | ,
235+
49 49 | }
236+
50 50 |
237+
238+
PIE800.py:54:9: PIE800 [*] Unnecessary spread `**`
239+
|
240+
52 | "data": [],
241+
53 | **(
242+
54 | {
243+
| _________^
244+
55 | | "count": (a := 1), # Comment
245+
56 | | } # Comment
246+
| |_____________^ PIE800
247+
57 | ) # Comment
248+
58 | ,
249+
|
250+
= help: Remove unnecessary dict
251+
252+
Safe fix
253+
50 50 |
254+
51 51 | {
255+
52 52 | "data": [],
256+
53 |- **(
257+
54 |- {
258+
55 |- "count": (a := 1), # Comment
259+
56 |- } # Comment
260+
57 |- ) # Comment
261+
53 |+
262+
54 |+
263+
55 |+ "count": (a := 1) # Comment
264+
56 |+ # Comment
265+
57 |+ # Comment
266+
58 58 | ,
267+
59 59 | }
268+
60 60 |
269+
270+
PIE800.py:65:1: PIE800 [*] Unnecessary spread `**`
271+
|
272+
63 | **( # Comment
273+
64 | ( # Comment
274+
65 | / { # Comment
275+
66 | | "count": (a := 1), # Comment
276+
67 | | } # Comment
277+
| |_________^ PIE800
278+
68 | )
279+
69 | ) # Comment
280+
|
281+
= help: Remove unnecessary dict
282+
283+
Safe fix
284+
60 60 |
285+
61 61 | ({
286+
62 62 | "data": [],
287+
63 |- **( # Comment
288+
64 |- ( # Comment
289+
65 |-{ # Comment
290+
66 |- "count": (a := 1), # Comment
291+
67 |- } # Comment
292+
68 |- )
293+
69 |- ) # Comment
294+
63 |+ # Comment
295+
64 |+ # Comment
296+
65 |+ # Comment
297+
66 |+ "count": (a := 1) # Comment
298+
67 |+ # Comment
299+
68 |+
300+
69 |+ # Comment
301+
70 70 | ,
302+
71 71 | })
303+
72 72 |

0 commit comments

Comments
 (0)