Skip to content

Commit 99f4c68

Browse files
authored
Format PatternMatchOr (#6905)
1 parent 30ebf7f commit 99f4c68

7 files changed

+142
-913
lines changed

crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/match.py

+34
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,37 @@ def foo():
467467
# e
468468
):
469469
pass
470+
471+
472+
match pattern_match_or:
473+
case ( # leading 1
474+
a # trailing 1
475+
# own line 1
476+
| # trailing 2
477+
# own line 2
478+
b # trailing 3
479+
# own line 3
480+
| # trailing 4
481+
# own line 4
482+
c # trailing 5
483+
):
484+
...
485+
486+
case (
487+
(a)
488+
| # trailing
489+
( b )
490+
):
491+
...
492+
493+
case (a|b|c):
494+
...
495+
496+
case foo | bar | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh:
497+
...
498+
499+
case ( # end of line
500+
a | b
501+
# own line
502+
):
503+
...

crates/ruff_python_formatter/src/lib.rs

+1-42
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
use thiserror::Error;
22

3-
use ruff_formatter::format_element::tag;
43
use ruff_formatter::prelude::*;
54
use ruff_formatter::{format, FormatError, Formatted, PrintError, Printed, SourceCode};
6-
use ruff_python_ast::node::{AnyNodeRef, AstNode};
5+
use ruff_python_ast::node::AstNode;
76
use ruff_python_ast::Mod;
87
use ruff_python_index::{CommentRanges, CommentRangesBuilder};
98
use ruff_python_parser::lexer::{lex, LexicalError};
109
use ruff_python_parser::{parse_tokens, Mode, ParseError};
1110
use ruff_source_file::Locator;
12-
use ruff_text_size::TextLen;
1311

1412
use crate::comments::{
1513
dangling_comments, leading_comments, trailing_comments, Comments, SourceComment,
@@ -178,45 +176,6 @@ pub fn pretty_comments(formatted: &Formatted<PyFormatContext>, source: &str) ->
178176
)
179177
}
180178

181-
pub(crate) struct NotYetImplementedCustomText<'a> {
182-
text: &'static str,
183-
node: AnyNodeRef<'a>,
184-
}
185-
186-
/// Formats a placeholder for nodes that have not yet been implemented
187-
pub(crate) fn not_yet_implemented_custom_text<'a, T>(
188-
text: &'static str,
189-
node: T,
190-
) -> NotYetImplementedCustomText<'a>
191-
where
192-
T: Into<AnyNodeRef<'a>>,
193-
{
194-
NotYetImplementedCustomText {
195-
text,
196-
node: node.into(),
197-
}
198-
}
199-
200-
impl Format<PyFormatContext<'_>> for NotYetImplementedCustomText<'_> {
201-
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
202-
f.write_element(FormatElement::Tag(Tag::StartVerbatim(
203-
tag::VerbatimKind::Verbatim {
204-
length: self.text.text_len(),
205-
},
206-
)));
207-
208-
text(self.text).fmt(f)?;
209-
210-
f.write_element(FormatElement::Tag(Tag::EndVerbatim));
211-
212-
f.context()
213-
.comments()
214-
.mark_verbatim_node_comments_formatted(self.node);
215-
216-
Ok(())
217-
}
218-
}
219-
220179
#[cfg(test)]
221180
mod tests {
222181
use std::path::Path;

crates/ruff_python_formatter/src/pattern/pattern_match_or.rs

+33-9
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,46 @@ use ruff_formatter::write;
22
use ruff_python_ast::node::AnyNodeRef;
33
use ruff_python_ast::PatternMatchOr;
44

5-
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
6-
use crate::not_yet_implemented_custom_text;
5+
use crate::comments::leading_comments;
6+
use crate::expression::parentheses::{
7+
in_parentheses_only_soft_line_break_or_space, NeedsParentheses, OptionalParentheses,
8+
};
79
use crate::prelude::*;
810

911
#[derive(Default)]
1012
pub struct FormatPatternMatchOr;
1113

1214
impl FormatNodeRule<PatternMatchOr> for FormatPatternMatchOr {
1315
fn fmt_fields(&self, item: &PatternMatchOr, f: &mut PyFormatter) -> FormatResult<()> {
14-
write!(
15-
f,
16-
[not_yet_implemented_custom_text(
17-
"NOT_YET_IMPLEMENTED_PatternMatchOf | (y)",
18-
item
19-
)]
20-
)
16+
let PatternMatchOr { range: _, patterns } = item;
17+
let inner = format_with(|f: &mut PyFormatter| {
18+
let mut patterns = patterns.iter();
19+
let comments = f.context().comments().clone();
20+
21+
let Some(first) = patterns.next() else {
22+
return Ok(());
23+
};
24+
25+
first.format().fmt(f)?;
26+
27+
for pattern in patterns {
28+
let leading_value_comments = comments.leading(pattern);
29+
// Format the expressions leading comments **before** the operator
30+
if leading_value_comments.is_empty() {
31+
write!(f, [in_parentheses_only_soft_line_break_or_space()])?;
32+
} else {
33+
write!(
34+
f,
35+
[hard_line_break(), leading_comments(leading_value_comments)]
36+
)?;
37+
}
38+
write!(f, [text("|"), space(), pattern.format()])?;
39+
}
40+
41+
Ok(())
42+
});
43+
44+
inner.fmt(f)
2145
}
2246
}
2347

0 commit comments

Comments
 (0)