Skip to content

Commit c0bb83b

Browse files
authored
[perflint] fix missing parentheses for lambda and ternary conditions (PERF401, PERF403) (#18412)
Closes #18405
1 parent 74a4e9a commit c0bb83b

8 files changed

+172
-9
lines changed

crates/ruff_linter/resources/test/fixtures/perflint/PERF401.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,15 @@ def f():
266266
result = list() # this should be replaced with a comprehension
267267
for i in values:
268268
result.append(i + 1) # PERF401
269+
270+
def f():
271+
src = [1]
272+
dst = []
273+
274+
for i in src:
275+
if True if True else False:
276+
dst.append(i)
277+
278+
for i in src:
279+
if lambda: 0:
280+
dst.append(i)

crates/ruff_linter/resources/test/fixtures/perflint/PERF403.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,16 @@ def foo():
151151
result = {}
152152
for idx, name in indices, fruit:
153153
result[name] = idx # PERF403
154+
155+
156+
def foo():
157+
src = (("x", 1),)
158+
dst = {}
159+
160+
for k, v in src:
161+
if True if True else False:
162+
dst[k] = v
163+
164+
for k, v in src:
165+
if lambda: 0:
166+
dst[k] = v

crates/ruff_linter/src/rules/perflint/rules/manual_dict_comprehension.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,10 +346,11 @@ fn convert_to_dict_comprehension(
346346
// since if the assignment expression appears
347347
// internally (e.g. as an operand in a boolean
348348
// operation) then it will already be parenthesized.
349-
if test.is_named_expr() {
350-
format!(" if ({})", locator.slice(test.range()))
351-
} else {
352-
format!(" if {}", locator.slice(test.range()))
349+
match test {
350+
Expr::Named(_) | Expr::If(_) | Expr::Lambda(_) => {
351+
format!(" if ({})", locator.slice(test.range()))
352+
}
353+
_ => format!(" if {}", locator.slice(test.range())),
353354
}
354355
}
355356
None => String::new(),

crates/ruff_linter/src/rules/perflint/rules/manual_list_comprehension.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ fn convert_to_list_extend(
358358
fix_type: ComprehensionType,
359359
binding: &Binding,
360360
for_stmt: &ast::StmtFor,
361-
if_test: Option<&ast::Expr>,
361+
if_test: Option<&Expr>,
362362
to_append: &Expr,
363363
checker: &Checker,
364364
) -> Result<Fix> {
@@ -374,10 +374,11 @@ fn convert_to_list_extend(
374374
// since if the assignment expression appears
375375
// internally (e.g. as an operand in a boolean
376376
// operation) then it will already be parenthesized.
377-
if test.is_named_expr() {
378-
format!(" if ({})", locator.slice(test.range()))
379-
} else {
380-
format!(" if {}", locator.slice(test.range()))
377+
match test {
378+
Expr::Named(_) | Expr::If(_) | Expr::Lambda(_) => {
379+
format!(" if ({})", locator.slice(test.range()))
380+
}
381+
_ => format!(" if {}", locator.slice(test.range())),
381382
}
382383
}
383384
None => String::new(),

crates/ruff_linter/src/rules/perflint/snapshots/ruff_linter__rules__perflint__tests__PERF401_PERF401.py.snap

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,5 +219,27 @@ PERF401.py:268:9: PERF401 Use a list comprehension to create a transformed list
219219
267 | for i in values:
220220
268 | result.append(i + 1) # PERF401
221221
| ^^^^^^^^^^^^^^^^^^^^ PERF401
222+
269 |
223+
270 | def f():
222224
|
223225
= help: Replace for loop with list comprehension
226+
227+
PERF401.py:276:13: PERF401 Use a list comprehension to create a transformed list
228+
|
229+
274 | for i in src:
230+
275 | if True if True else False:
231+
276 | dst.append(i)
232+
| ^^^^^^^^^^^^^ PERF401
233+
277 |
234+
278 | for i in src:
235+
|
236+
= help: Replace for loop with list comprehension
237+
238+
PERF401.py:280:13: PERF401 Use `list.extend` to create a transformed list
239+
|
240+
278 | for i in src:
241+
279 | if lambda: 0:
242+
280 | dst.append(i)
243+
| ^^^^^^^^^^^^^ PERF401
244+
|
245+
= help: Replace for loop with list.extend

crates/ruff_linter/src/rules/perflint/snapshots/ruff_linter__rules__perflint__tests__PERF403_PERF403.py.snap

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,23 @@ PERF403.py:153:9: PERF403 Use a dictionary comprehension instead of a for-loop
128128
| ^^^^^^^^^^^^^^^^^^ PERF403
129129
|
130130
= help: Replace for loop with dict comprehension
131+
132+
PERF403.py:162:13: PERF403 Use a dictionary comprehension instead of a for-loop
133+
|
134+
160 | for k, v in src:
135+
161 | if True if True else False:
136+
162 | dst[k] = v
137+
| ^^^^^^^^^^ PERF403
138+
163 |
139+
164 | for k, v in src:
140+
|
141+
= help: Replace for loop with dict comprehension
142+
143+
PERF403.py:166:13: PERF403 Use a dictionary comprehension instead of a for-loop
144+
|
145+
164 | for k, v in src:
146+
165 | if lambda: 0:
147+
166 | dst[k] = v
148+
| ^^^^^^^^^^ PERF403
149+
|
150+
= help: Replace for loop with dict comprehension

crates/ruff_linter/src/rules/perflint/snapshots/ruff_linter__rules__perflint__tests__preview__PERF401_PERF401.py.snap

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,8 @@ PERF401.py:268:9: PERF401 [*] Use a list comprehension to create a transformed l
517517
267 | for i in values:
518518
268 | result.append(i + 1) # PERF401
519519
| ^^^^^^^^^^^^^^^^^^^^ PERF401
520+
269 |
521+
270 | def f():
520522
|
521523
= help: Replace for loop with list comprehension
522524

@@ -529,3 +531,49 @@ PERF401.py:268:9: PERF401 [*] Use a list comprehension to create a transformed l
529531
268 |- result.append(i + 1) # PERF401
530532
266 |+ # this should be replaced with a comprehension
531533
267 |+ result = [i + 1 for i in values] # PERF401
534+
269 268 |
535+
270 269 | def f():
536+
271 270 | src = [1]
537+
538+
PERF401.py:276:13: PERF401 [*] Use a list comprehension to create a transformed list
539+
|
540+
274 | for i in src:
541+
275 | if True if True else False:
542+
276 | dst.append(i)
543+
| ^^^^^^^^^^^^^ PERF401
544+
277 |
545+
278 | for i in src:
546+
|
547+
= help: Replace for loop with list comprehension
548+
549+
Unsafe fix
550+
269 269 |
551+
270 270 | def f():
552+
271 271 | src = [1]
553+
272 |- dst = []
554+
273 272 |
555+
274 |- for i in src:
556+
275 |- if True if True else False:
557+
276 |- dst.append(i)
558+
273 |+ dst = [i for i in src if (True if True else False)]
559+
277 274 |
560+
278 275 | for i in src:
561+
279 276 | if lambda: 0:
562+
563+
PERF401.py:280:13: PERF401 [*] Use `list.extend` to create a transformed list
564+
|
565+
278 | for i in src:
566+
279 | if lambda: 0:
567+
280 | dst.append(i)
568+
| ^^^^^^^^^^^^^ PERF401
569+
|
570+
= help: Replace for loop with list.extend
571+
572+
Unsafe fix
573+
275 275 | if True if True else False:
574+
276 276 | dst.append(i)
575+
277 277 |
576+
278 |- for i in src:
577+
279 |- if lambda: 0:
578+
280 |- dst.append(i)
579+
278 |+ dst.extend(i for i in src if (lambda: 0))

crates/ruff_linter/src/rules/perflint/snapshots/ruff_linter__rules__perflint__tests__preview__PERF403_PERF403.py.snap

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,49 @@ PERF403.py:153:9: PERF403 [*] Use a dictionary comprehension instead of a for-lo
305305
152 |- for idx, name in indices, fruit:
306306
153 |- result[name] = idx # PERF403
307307
151 |+ result = {name: idx for idx, name in (indices, fruit)} # PERF403
308+
154 152 |
309+
155 153 |
310+
156 154 | def foo():
311+
312+
PERF403.py:162:13: PERF403 [*] Use a dictionary comprehension instead of a for-loop
313+
|
314+
160 | for k, v in src:
315+
161 | if True if True else False:
316+
162 | dst[k] = v
317+
| ^^^^^^^^^^ PERF403
318+
163 |
319+
164 | for k, v in src:
320+
|
321+
= help: Replace for loop with dict comprehension
322+
323+
Unsafe fix
324+
155 155 |
325+
156 156 | def foo():
326+
157 157 | src = (("x", 1),)
327+
158 |- dst = {}
328+
159 158 |
329+
160 |- for k, v in src:
330+
161 |- if True if True else False:
331+
162 |- dst[k] = v
332+
159 |+ dst = {k: v for k, v in src if (True if True else False)}
333+
163 160 |
334+
164 161 | for k, v in src:
335+
165 162 | if lambda: 0:
336+
337+
PERF403.py:166:13: PERF403 [*] Use `dict.update` instead of a for-loop
338+
|
339+
164 | for k, v in src:
340+
165 | if lambda: 0:
341+
166 | dst[k] = v
342+
| ^^^^^^^^^^ PERF403
343+
|
344+
= help: Replace for loop with `dict.update`
345+
346+
Unsafe fix
347+
161 161 | if True if True else False:
348+
162 162 | dst[k] = v
349+
163 163 |
350+
164 |- for k, v in src:
351+
165 |- if lambda: 0:
352+
166 |- dst[k] = v
353+
164 |+ dst.update({k: v for k, v in src if (lambda: 0)})

0 commit comments

Comments
 (0)