Skip to content

Commit 8012707

Browse files
authored
Align formatting of patterns in match-cases with expression formatting in clause headers (#13510)
1 parent d7ffe46 commit 8012707

File tree

12 files changed

+1608
-40
lines changed

12 files changed

+1608
-40
lines changed
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
# Patterns that use BestFit should be parenthesized if they exceed the configured line width
2+
# but fit within parentheses.
3+
match x:
4+
case (
5+
"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPar"
6+
):
7+
pass
8+
9+
10+
match x:
11+
case (
12+
b"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa"
13+
):
14+
pass
15+
16+
match x:
17+
case (
18+
f"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsPa"
19+
):
20+
pass
21+
22+
23+
match x:
24+
case (
25+
5444444444444444444444444444444444444444444444444444444444444444444444444444444j
26+
):
27+
pass
28+
29+
30+
match x:
31+
case (
32+
5444444444444444444444444444444444444444444444444444444444444444444444444444444
33+
):
34+
pass
35+
36+
37+
match x:
38+
case (
39+
5.44444444444444444444444444444444444444444444444444444444444444444444444444444
40+
):
41+
pass
42+
43+
44+
match x:
45+
case (
46+
averyLongIdentThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsParenth
47+
):
48+
pass
49+
50+
51+
# But they aren't parenthesized when they exceed the line length even parenthesized
52+
match x:
53+
case "averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsParenthesized":
54+
pass
55+
56+
57+
match x:
58+
case b"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsParenthesized":
59+
pass
60+
61+
match x:
62+
case f"averyLongStringThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsParenthesized":
63+
pass
64+
65+
66+
match x:
67+
case 54444444444444444444444444444444444444444444444444444444444444444444444444444444444j:
68+
pass
69+
70+
71+
match x:
72+
case 5444444444444444444444444444444444444444444444444444444444444444444444444444444444:
73+
pass
74+
75+
76+
match x:
77+
case 5.444444444444444444444444444444444444444444444444444444444444444444444444444444444:
78+
pass
79+
80+
81+
match x:
82+
case averyLongIdentifierThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsParenthesized:
83+
pass
84+
85+
86+
# It uses the Multiline layout when there's an alias.
87+
match x:
88+
case (
89+
averyLongIdentifierThatGetsParenthesizedOnceItExceedsTheConfiguredLineWidthFitsParenthe as b
90+
):
91+
pass
92+
93+
94+
95+
match x:
96+
case (
97+
"an implicit concatenated" "string literal" "in a match case" "that goes over multiple lines"
98+
):
99+
pass
100+
101+
102+
## Patterns ending with a sequence, mapping, class, or parenthesized pattern should break the parenthesized-like pattern first
103+
match x:
104+
case A | [
105+
aaaaaa,
106+
bbbbbbbbbbbbbbbb,
107+
cccccccccccccccccc,
108+
ddddddddddddddddddddddddddd,
109+
]:
110+
pass
111+
112+
match x:
113+
case A | (
114+
aaaaaa,
115+
bbbbbbbbbbbbbbbb,
116+
cccccccccccccccccc,
117+
ddddddddddddddddddddddddddd,
118+
):
119+
pass
120+
121+
122+
match x:
123+
case A | {
124+
"a": aaaaaa,
125+
"b": bbbbbbbbbbbbbbbb,
126+
"c": cccccccccccccccccc,
127+
"d": ddddddddddddddddddddddddddd,
128+
}:
129+
pass
130+
131+
132+
match x:
133+
case A | Class(
134+
aaaaaa,
135+
bbbbbbbbbbbbbbbb,
136+
cccccccccccccccccc,
137+
ddddddddddddddddddddddddddd,
138+
):
139+
pass
140+
141+
142+
143+
match x:
144+
case A | (
145+
aaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccc.ddddddddddddddddddddddd
146+
):
147+
pass
148+
149+
150+
## Patterns starting with a sequence, mapping, class, or parenthesized pattern should break the parenthesized-like pattern first
151+
match x:
152+
case [
153+
aaaaaa,
154+
bbbbbbbbbbbbbbbb,
155+
cccccccccccccccccc,
156+
ddddddddddddddddddddddddddd,
157+
] | A:
158+
pass
159+
160+
match x:
161+
case (
162+
aaaaaa,
163+
bbbbbbbbbbbbbbbb,
164+
cccccccccccccccccc,
165+
ddddddddddddddddddddddddddd,
166+
) | A:
167+
pass
168+
169+
170+
match x:
171+
case {
172+
"a": aaaaaa,
173+
"b": bbbbbbbbbbbbbbbb,
174+
"c": cccccccccccccccccc,
175+
"d": ddddddddddddddddddddddddddd,
176+
} | A:
177+
pass
178+
179+
180+
match x:
181+
case Class(
182+
aaaaaa,
183+
bbbbbbbbbbbbbbbb,
184+
cccccccccccccccccc,
185+
ddddddddddddddddddddddddddd,
186+
):
187+
pass
188+
189+
190+
## Not for non-parenthesized sequence patterns
191+
match x:
192+
case (
193+
(1) | aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
194+
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
195+
ccccccccccccccccccccccccccccccccc,
196+
):
197+
pass
198+
199+
## Parenthesize patterns that start with a token
200+
match x:
201+
case (
202+
A(
203+
aaaaaaaaaaaaaaaaaaa.bbbbbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccccccccccc.ddddddddddddddddddddddd
204+
)
205+
| B
206+
):
207+
pass
208+
209+
210+
## Always use parentheses for implicitly concatenated strings
211+
match x:
212+
case (
213+
"implicit"
214+
"concatenated"
215+
"string"
216+
| [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
217+
):
218+
pass
219+
220+
221+
match x:
222+
case (
223+
b"implicit"
224+
b"concatenated"
225+
b"string"
226+
| [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
227+
):
228+
pass
229+
230+
231+
match x:
232+
case (
233+
f"implicit"
234+
"concatenated"
235+
"string"
236+
| [aaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccccc, ddddddddddddddddddddddddddd]
237+
):
238+
pass
239+
240+
241+
## Complex number expressions and unary expressions
242+
243+
match x:
244+
case 4 - 3j | [
245+
aaaaaaaaaaaaaaaaaaaaaaaa,
246+
bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
247+
cccccccccccccccccccccccccccccccccccccccc,
248+
]:
249+
pass
250+
251+
252+
match x:
253+
case 4 + 3j | [
254+
aaaaaaaaaaaaaaaaaaaaaaaa,
255+
bbbbbbbbbbbbbbbbbbbbbbbbbbbb,
256+
cccccccccccccccccccccccccccccccccccccccc,
257+
]:
258+
pass
259+
260+
261+
match x:
262+
case -1 | [
263+
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
264+
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
265+
ccccccccccccccccccccccccccccccccc,
266+
]:
267+
pass
268+
269+
270+
271+
### Parenthesized patterns
272+
match x:
273+
case (1) | [
274+
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
275+
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
276+
ccccccccccccccccccccccccccccccccc,
277+
]:
278+
pass
279+
280+
281+
match x:
282+
case ( # comment
283+
1
284+
) | [
285+
aaaaaaaaaaaaaaaaaaaaaaaaaaaa,
286+
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
287+
ccccccccccccccccccccccccccccccccc,
288+
]:
289+
pass
290+
291+
292+

crates/ruff_python_formatter/src/other/match_case.rs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use ruff_python_ast::MatchCase;
44

55
use crate::builders::parenthesize_if_expands;
66
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses, Parentheses};
7+
use crate::pattern::maybe_parenthesize_pattern;
78
use crate::prelude::*;
9+
use crate::preview::is_match_case_parentheses_enabled;
810
use crate::statement::clause::{clause_body, clause_header, ClauseHeader};
911
use crate::statement::suite::SuiteKind;
1012

@@ -34,39 +36,40 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
3436
let comments = f.context().comments().clone();
3537
let dangling_item_comments = comments.dangling(item);
3638

39+
let format_pattern = format_with(|f| {
40+
if is_match_case_parentheses_enabled(f.context()) {
41+
maybe_parenthesize_pattern(pattern, item).fmt(f)
42+
} else {
43+
let has_comments =
44+
comments.has_leading(pattern) || comments.has_trailing_own_line(pattern);
45+
46+
if has_comments {
47+
pattern.format().with_options(Parentheses::Always).fmt(f)
48+
} else {
49+
match pattern.needs_parentheses(item.as_any_node_ref(), f.context()) {
50+
OptionalParentheses::Multiline => parenthesize_if_expands(
51+
&pattern.format().with_options(Parentheses::Never),
52+
)
53+
.fmt(f),
54+
OptionalParentheses::Always => {
55+
pattern.format().with_options(Parentheses::Always).fmt(f)
56+
}
57+
OptionalParentheses::Never | OptionalParentheses::BestFit => {
58+
pattern.format().with_options(Parentheses::Never).fmt(f)
59+
}
60+
}
61+
}
62+
}
63+
});
64+
3765
write!(
3866
f,
3967
[
4068
clause_header(
4169
ClauseHeader::MatchCase(item),
4270
dangling_item_comments,
4371
&format_with(|f| {
44-
write!(f, [token("case"), space()])?;
45-
46-
let has_comments = comments.has_leading(pattern)
47-
|| comments.has_trailing_own_line(pattern);
48-
49-
if has_comments {
50-
pattern.format().with_options(Parentheses::Always).fmt(f)?;
51-
} else {
52-
match pattern.needs_parentheses(item.as_any_node_ref(), f.context()) {
53-
OptionalParentheses::Multiline => {
54-
parenthesize_if_expands(
55-
&pattern.format().with_options(Parentheses::Never),
56-
)
57-
.fmt(f)?;
58-
}
59-
OptionalParentheses::Always => {
60-
pattern.format().with_options(Parentheses::Always).fmt(f)?;
61-
}
62-
OptionalParentheses::Never => {
63-
pattern.format().with_options(Parentheses::Never).fmt(f)?;
64-
}
65-
OptionalParentheses::BestFit => {
66-
pattern.format().with_options(Parentheses::Never).fmt(f)?;
67-
}
68-
}
69-
}
72+
write!(f, [token("case"), space(), format_pattern])?;
7073

7174
if let Some(guard) = guard {
7275
write!(f, [space(), token("if"), space(), guard.format()])?;

0 commit comments

Comments
 (0)