1
- use ruff_formatter:: { write, Buffer , FormatResult } ;
2
- use ruff_python_ast:: MatchCase ;
1
+ use ruff_formatter:: { format_args, write, Buffer , FormatResult } ;
2
+ use ruff_python_ast:: { MatchCase , Pattern , Ranged } ;
3
+ use ruff_python_trivia:: { SimpleTokenKind , SimpleTokenizer } ;
4
+ use ruff_text_size:: TextRange ;
3
5
4
- use crate :: comments:: { trailing_comments, SourceComment } ;
5
- use crate :: not_yet_implemented_custom_text ;
6
+ use crate :: comments:: { leading_comments , trailing_comments, SourceComment } ;
7
+ use crate :: expression :: parentheses :: parenthesized ;
6
8
use crate :: prelude:: * ;
7
- use crate :: { FormatNodeRule , PyFormatter } ;
9
+ use crate :: { FormatError , FormatNodeRule , PyFormatter } ;
8
10
9
11
#[ derive( Default ) ]
10
12
pub struct FormatMatchCase ;
@@ -21,24 +23,20 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
21
23
let comments = f. context ( ) . comments ( ) . clone ( ) ;
22
24
let dangling_item_comments = comments. dangling_comments ( item) ;
23
25
24
- write ! (
25
- f,
26
- [
27
- text( "case" ) ,
28
- space( ) ,
29
- format_with( |f: & mut PyFormatter | {
30
- let comments = f. context( ) . comments( ) ;
31
-
32
- for comment in comments. leading_trailing_comments( pattern) {
33
- // This is a lie, but let's go with it.
34
- comment. mark_formatted( ) ;
35
- }
36
-
37
- // Replace the whole `format_with` with `pattern.format()` once pattern formatting is implemented.
38
- not_yet_implemented_custom_text( "NOT_YET_IMPLEMENTED_Pattern" , pattern) . fmt( f)
39
- } ) ,
40
- ]
41
- ) ?;
26
+ write ! ( f, [ text( "case" ) , space( ) ] ) ?;
27
+ let leading_pattern_comments = comments. leading_comments ( pattern) ;
28
+ if !leading_pattern_comments. is_empty ( ) {
29
+ parenthesized (
30
+ "(" ,
31
+ & format_args ! [ leading_comments( leading_pattern_comments) , pattern. format( ) ] ,
32
+ ")" ,
33
+ )
34
+ . fmt ( f) ?;
35
+ } else if is_match_case_pattern_parenthesized ( item, pattern, f. context ( ) ) ? {
36
+ parenthesized ( "(" , & pattern. format ( ) , ")" ) . fmt ( f) ?;
37
+ } else {
38
+ pattern. format ( ) . fmt ( f) ?;
39
+ }
42
40
43
41
if let Some ( guard) = guard {
44
42
write ! ( f, [ space( ) , text( "if" ) , space( ) , guard. format( ) ] ) ?;
@@ -63,3 +61,33 @@ impl FormatNodeRule<MatchCase> for FormatMatchCase {
63
61
Ok ( ( ) )
64
62
}
65
63
}
64
+
65
+ fn is_match_case_pattern_parenthesized (
66
+ case : & MatchCase ,
67
+ pattern : & Pattern ,
68
+ context : & PyFormatContext ,
69
+ ) -> FormatResult < bool > {
70
+ let mut tokenizer = SimpleTokenizer :: new (
71
+ context. source ( ) ,
72
+ TextRange :: new ( case. range ( ) . start ( ) , pattern. range ( ) . start ( ) ) ,
73
+ )
74
+ . skip_trivia ( ) ;
75
+
76
+ let case_keyword = tokenizer. next ( ) . ok_or ( FormatError :: syntax_error (
77
+ "Expected a `case` keyword, didn't find any token" ,
78
+ ) ) ?;
79
+
80
+ debug_assert_eq ! (
81
+ case_keyword. kind( ) ,
82
+ SimpleTokenKind :: Case ,
83
+ "Expected `case` keyword but at {case_keyword:?}"
84
+ ) ;
85
+
86
+ match tokenizer. next ( ) {
87
+ Some ( left_paren) => {
88
+ debug_assert_eq ! ( left_paren. kind( ) , SimpleTokenKind :: LParen ) ;
89
+ Ok ( true )
90
+ }
91
+ None => Ok ( false ) ,
92
+ }
93
+ }
0 commit comments