Skip to content

Commit 9442cd8

Browse files
authored
Parenthesize match..case if guards (#13513)
1 parent 8012707 commit 9442cd8

File tree

7 files changed

+155
-88
lines changed

7 files changed

+155
-88
lines changed

Diff for: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py

+25
Original file line numberDiff line numberDiff line change
@@ -588,3 +588,28 @@ def foo():
588588
match x:
589589
case Child(aaaaaaaaa, bbbbbbbbbbbbbbb, cccccc), Doc(aaaaa, bbbbbbbbbb, ddddddddddddd):
590590
pass
591+
592+
593+
match guard_comments:
594+
case "abcd" if ( # trailing open parentheses comment
595+
aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2
596+
):
597+
pass
598+
599+
case "bcdef" if (
600+
aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2 # trailing end of line comment
601+
): # comment
602+
pass
603+
604+
case "efgh" if (
605+
# leading own line comment
606+
aaaaaahhhhhh == 1
607+
):
608+
pass
609+
610+
case "hijk" if (
611+
aaaaaaaaa == 1
612+
# trailing own line comment
613+
):
614+
pass
615+

Diff for: crates/ruff_python_formatter/src/expression/parentheses.rs

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ pub(crate) enum Parenthesize {
5959
/// Same as [`Self::IfBreaks`] except that it uses [`parenthesize_if_expands`] for expressions
6060
/// with the layout [`NeedsParentheses::BestFit`] which is used by non-splittable
6161
/// expressions like literals, name, and strings.
62+
///
63+
/// Use this layout over `IfBreaks` when there's a sequence of `maybe_parenthesize_expression`
64+
/// in a single logical-line and you want to break from right-to-left. Use `IfBreaks` for the
65+
/// first expression and `IfBreaksParenthesized` for the rest.
6266
IfBreaksParenthesized,
6367

6468
/// Same as [`Self::IfBreaksParenthesized`] but uses [`parenthesize_if_expands`] for nested

Diff for: crates/ruff_python_formatter/src/other/match_case.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use ruff_python_ast::AstNode;
33
use ruff_python_ast::MatchCase;
44

55
use crate::builders::parenthesize_if_expands;
6-
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses};
6+
use crate::expression::maybe_parenthesize_expression;
7+
use crate::expression::parentheses::{
8+
NeedsParentheses, OptionalParentheses, Parentheses, Parenthesize,
9+
};
710
use crate::pattern::maybe_parenthesize_pattern;
811
use crate::prelude::*;
912
use crate::preview::is_match_case_parentheses_enabled;
@@ -62,20 +65,27 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
6265
}
6366
});
6467

68+
let format_guard = guard.as_deref().map(|guard| {
69+
format_with(|f| {
70+
write!(f, [space(), token("if"), space()])?;
71+
72+
if is_match_case_parentheses_enabled(f.context()) {
73+
maybe_parenthesize_expression(guard, item, Parenthesize::IfBreaksParenthesized)
74+
.fmt(f)
75+
} else {
76+
guard.format().fmt(f)
77+
}
78+
})
79+
});
80+
6581
write!(
6682
f,
6783
[
6884
clause_header(
6985
ClauseHeader::MatchCase(item),
7086
dangling_item_comments,
7187
&format_with(|f| {
72-
write!(f, [token("case"), space(), format_pattern])?;
73-
74-
if let Some(guard) = guard {
75-
write!(f, [space(), token("if"), space(), guard.format()])?;
76-
}
77-
78-
Ok(())
88+
write!(f, [token("case"), space(), format_pattern, format_guard])
7989
}),
8090
),
8191
clause_body(

Diff for: crates/ruff_python_formatter/src/preview.rs

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ pub(crate) fn is_empty_parameters_no_unnecessary_parentheses_around_return_value
3939

4040
/// See [#6933](https://github.com/astral-sh/ruff/issues/6933).
4141
/// This style also covers the black preview styles `remove_redundant_guard_parens` and `parens_for_long_if_clauses_in_case_block `.
42+
/// WARNING: This preview style depends on `is_empty_parameters_no_unnecessary_parentheses_around_return_value_enabled`
43+
/// because it relies on the new semantic of `IfBreaksParenthesized`.
4244
pub(crate) fn is_match_case_parentheses_enabled(context: &PyFormatContext) -> bool {
4345
context.is_preview()
4446
}

Diff for: crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__pattern_matching_with_if_stmt.py.snap

+16-45
Original file line numberDiff line numberDiff line change
@@ -44,36 +44,9 @@ match x:
4444
```diff
4545
--- Black
4646
+++ Ruff
47-
@@ -3,34 +3,36 @@
47+
@@ -21,11 +21,17 @@
4848
pass
49-
50-
match smth:
51-
- case "test" if (
52-
- "any long condition" != "another long condition" and "this is a long condition"
53-
- ):
54-
+ case "test" if "any long condition" != "another long condition" and "this is a long condition":
55-
pass
56-
- case test if (
57-
- "any long condition" != "another long condition"
58-
- and "this is a looooong condition"
59-
- ):
60-
+ case (
61-
+ test
62-
+ ) if "any long condition" != "another long condition" and "this is a looooong condition":
63-
pass
64-
- case test if (
65-
- "any long condition" != "another long condition"
66-
- and "this is a looooong condition"
67-
- ): # some additional comments
68-
+ case (
69-
+ test
70-
+ ) if "any long condition" != "another long condition" and "this is a looooong condition": # some additional comments
71-
pass
72-
- case test if True: # some comment
73-
+ case test if (True): # some comment
74-
pass
75-
- case test if False: # some comment
76-
+ case test if (False): # some comment
49+
case test if False: # some comment
7750
pass
7851
- case test if True: # some comment
7952
+ case test if (
@@ -92,12 +65,6 @@ match x:
9265
pass # some comment
9366
9467
# case black_test_patma_052 (originally in the pattern_matching_complex test case)
95-
match x:
96-
case [1, 0] if x := x[:0]:
97-
y = 1
98-
- case [1, 0] if x := x[:0]:
99-
+ case [1, 0] if (x := x[:0]):
100-
y = 1
10168
```
10269

10370
## Ruff Output
@@ -108,19 +75,23 @@ match match:
10875
pass
10976
11077
match smth:
111-
case "test" if "any long condition" != "another long condition" and "this is a long condition":
78+
case "test" if (
79+
"any long condition" != "another long condition" and "this is a long condition"
80+
):
11281
pass
113-
case (
114-
test
115-
) if "any long condition" != "another long condition" and "this is a looooong condition":
82+
case test if (
83+
"any long condition" != "another long condition"
84+
and "this is a looooong condition"
85+
):
11686
pass
117-
case (
118-
test
119-
) if "any long condition" != "another long condition" and "this is a looooong condition": # some additional comments
87+
case test if (
88+
"any long condition" != "another long condition"
89+
and "this is a looooong condition"
90+
): # some additional comments
12091
pass
121-
case test if (True): # some comment
92+
case test if True: # some comment
12293
pass
123-
case test if (False): # some comment
94+
case test if False: # some comment
12495
pass
12596
case test if (
12697
True # some comment
@@ -139,7 +110,7 @@ match smth:
139110
match x:
140111
case [1, 0] if x := x[:0]:
141112
y = 1
142-
case [1, 0] if (x := x[:0]):
113+
case [1, 0] if x := x[:0]:
143114
y = 1
144115
```
145116

Diff for: crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__remove_redundant_parens_in_case_guard.py.snap

+6-32
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,7 @@ match 1:
6969
```diff
7070
--- Black
7171
+++ Ruff
72-
@@ -1,10 +1,10 @@
73-
match 1:
74-
- case _ if True:
75-
+ case _ if (True):
76-
pass
77-
78-
79-
match 1:
80-
- case _ if True:
81-
+ case _ if (True):
82-
pass
83-
84-
85-
@@ -25,27 +25,33 @@
72+
@@ -25,12 +25,16 @@
8673
8774
8875
match 1:
@@ -101,18 +88,7 @@ match 1:
10188
pass
10289
10390
104-
match 1:
105-
- case _ if True: # this is a comment
106-
+ case _ if (True): # this is a comment
107-
pass
108-
109-
110-
match 1:
111-
- case _ if True: # comment over the line limit unless parens are removed x
112-
+ case _ if (
113-
+ True
114-
+ ): # comment over the line limit unless parens are removed x
115-
pass
91+
@@ -45,7 +49,7 @@
11692
11793
11894
match 1:
@@ -129,12 +105,12 @@ match 1:
129105

130106
```python
131107
match 1:
132-
case _ if (True):
108+
case _ if True:
133109
pass
134110
135111
136112
match 1:
137-
case _ if (True):
113+
case _ if True:
138114
pass
139115
140116
@@ -169,14 +145,12 @@ match 1:
169145
170146
171147
match 1:
172-
case _ if (True): # this is a comment
148+
case _ if True: # this is a comment
173149
pass
174150
175151
176152
match 1:
177-
case _ if (
178-
True
179-
): # comment over the line limit unless parens are removed x
153+
case _ if True: # comment over the line limit unless parens are removed x
180154
pass
181155
182156

Diff for: crates/ruff_python_formatter/tests/snapshots/format@statement__match.py.snap

+84-3
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,31 @@ match n % 3, n % 5:
594594
match x:
595595
case Child(aaaaaaaaa, bbbbbbbbbbbbbbb, cccccc), Doc(aaaaa, bbbbbbbbbb, ddddddddddddd):
596596
pass
597+
598+
599+
match guard_comments:
600+
case "abcd" if ( # trailing open parentheses comment
601+
aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2
602+
):
603+
pass
604+
605+
case "bcdef" if (
606+
aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2 # trailing end of line comment
607+
): # comment
608+
pass
609+
610+
case "efgh" if (
611+
# leading own line comment
612+
aaaaaahhhhhh == 1
613+
):
614+
pass
615+
616+
case "hijk" if (
617+
aaaaaaaaa == 1
618+
# trailing own line comment
619+
):
620+
pass
621+
597622
```
598623

599624
## Output
@@ -1232,24 +1257,80 @@ match x:
12321257
aaaaa, bbbbbbbbbb, ddddddddddddd
12331258
):
12341259
pass
1260+
1261+
1262+
match guard_comments:
1263+
case "abcd" if ( # trailing open parentheses comment
1264+
aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2
1265+
):
1266+
pass
1267+
1268+
case "bcdef" if (
1269+
aaaaaaaaahhhhhhhh == 1
1270+
and bbbbbbaaaaaaaaaaa == 2 # trailing end of line comment
1271+
): # comment
1272+
pass
1273+
1274+
case "efgh" if (
1275+
# leading own line comment
1276+
aaaaaahhhhhh == 1
1277+
):
1278+
pass
1279+
1280+
case "hijk" if (
1281+
aaaaaaaaa == 1
1282+
# trailing own line comment
1283+
):
1284+
pass
12351285
```
12361286

12371287

12381288
## Preview changes
12391289
```diff
12401290
--- Stable
12411291
+++ Preview
1292+
@@ -69,7 +69,7 @@
1293+
case "case comment with newlines" if foo == 2: # second
1294+
pass
1295+
1296+
- case "one", "newline" if (foo := 1): # third
1297+
+ case "one", "newline" if foo := 1: # third
1298+
pass
1299+
1300+
case "two newlines":
12421301
@@ -82,7 +82,9 @@
12431302
12441303
12451304
match long_lines:
12461305
- case "this is a long line for if condition" if aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2: # comment
1247-
+ case (
1248-
+ "this is a long line for if condition"
1249-
+ ) if aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2: # comment
1306+
+ case "this is a long line for if condition" if (
1307+
+ aaaaaaaaahhhhhhhh == 1 and bbbbbbaaaaaaaaaaa == 2
1308+
+ ): # comment
12501309
pass
12511310
12521311
case "this is a long line for if condition with parentheses" if (
1312+
@@ -93,7 +95,7 @@
1313+
case "named expressions aren't special" if foo := 1:
1314+
pass
1315+
1316+
- case "named expressions aren't that special" if (foo := 1):
1317+
+ case "named expressions aren't that special" if foo := 1:
1318+
pass
1319+
1320+
case "but with already broken long lines" if (
1321+
@@ -101,9 +103,9 @@
1322+
): # another comment
1323+
pass
1324+
1325+
- case {
1326+
- "long_long_long_key": str(long_long_long_key)
1327+
- } if value := "long long long long long long long long long long long value":
1328+
+ case {"long_long_long_key": str(long_long_long_key)} if (
1329+
+ value := "long long long long long long long long long long long value"
1330+
+ ):
1331+
pass
1332+
1333+
12531334
@@ -198,7 +200,9 @@
12541335
# trailing own 2
12551336
):

0 commit comments

Comments
 (0)