@@ -4,7 +4,11 @@ use oxc_span::GetSpan;
4
4
5
5
use crate :: {
6
6
Format , FormatResult , format_args,
7
- formatter:: { Formatter , prelude:: * } ,
7
+ formatter:: {
8
+ Formatter ,
9
+ prelude:: * ,
10
+ trivia:: { FormatLeadingComments , FormatTrailingComments } ,
11
+ } ,
8
12
generated:: ast_nodes:: { AstNode , AstNodes } ,
9
13
write,
10
14
} ;
@@ -13,40 +17,46 @@ use super::FormatWrite;
13
17
14
18
impl < ' a > Format < ' a > for AstNode < ' a , Vec < ' a , Decorator < ' a > > > {
15
19
fn fmt ( & self , f : & mut Formatter < ' _ , ' a > ) -> FormatResult < ( ) > {
16
- if self . is_empty ( ) {
20
+ let Some ( last ) = self . last ( ) else {
17
21
return Ok ( ( ) ) ;
18
- }
22
+ } ;
19
23
20
- // Check parent to determine formatting context
21
- match self . parent {
22
- AstNodes :: PropertyDefinition ( _)
23
- | AstNodes :: MethodDefinition ( _)
24
- | AstNodes :: AccessorProperty ( _) => {
25
- return write ! (
26
- f,
27
- [ group( & format_args!(
28
- format_once( |f| {
29
- f. join_nodes_with_soft_line( ) . entries( self . iter( ) ) . finish( )
30
- } ) ,
31
- soft_line_break_or_space( )
32
- ) )
33
- . should_expand( should_expand_decorators( self , f) ) ]
34
- ) ;
35
- }
36
- // Parameter decorators
37
- AstNodes :: FormalParameter ( _) => {
38
- write ! ( f, should_expand_decorators( self , f) . then_some( expand_parent( ) ) ) ?;
39
- }
40
- AstNodes :: ExportNamedDeclaration ( _) | AstNodes :: ExportDefaultDeclaration ( _) => {
41
- write ! ( f, [ hard_line_break( ) ] ) ?;
42
- }
43
- _ => {
44
- write ! ( f, [ expand_parent( ) ] ) ?;
24
+ let format_decorators = format_once ( |f| {
25
+ // Check parent to determine formatting context
26
+ match self . parent {
27
+ AstNodes :: PropertyDefinition ( _)
28
+ | AstNodes :: MethodDefinition ( _)
29
+ | AstNodes :: AccessorProperty ( _) => {
30
+ return write ! (
31
+ f,
32
+ [ group( & format_args!(
33
+ format_once( |f| {
34
+ f. join_nodes_with_soft_line( ) . entries( self . iter( ) ) . finish( )
35
+ } ) ,
36
+ soft_line_break_or_space( )
37
+ ) )
38
+ . should_expand( should_expand_decorators( self , f) ) ]
39
+ ) ;
40
+ }
41
+ // Parameter decorators
42
+ AstNodes :: FormalParameter ( _) => {
43
+ write ! ( f, should_expand_decorators( self , f) . then_some( expand_parent( ) ) ) ?;
44
+ }
45
+ AstNodes :: ExportNamedDeclaration ( _) | AstNodes :: ExportDefaultDeclaration ( _) => {
46
+ write ! ( f, [ hard_line_break( ) ] ) ?;
47
+ }
48
+ _ => {
49
+ write ! ( f, [ expand_parent( ) ] ) ?;
50
+ }
45
51
}
46
- }
47
52
48
- f. join_with ( & soft_line_break_or_space ( ) ) . entries ( self . iter ( ) ) . finish ( ) ?;
49
- write ! ( f, [ soft_line_break_or_space( ) ] )
53
+ f. join_with ( & soft_line_break_or_space ( ) ) . entries ( self . iter ( ) ) . finish ( ) ?;
54
+
55
+ write ! ( f, [ soft_line_break_or_space( ) ] )
56
+ } ) ;
57
+
58
+ format_decorators. fmt ( f) ?;
59
+ format_trailing_comments_for_last_decorator ( last. span . end , f)
50
60
}
51
61
}
52
62
@@ -103,3 +113,32 @@ fn should_expand_decorators<'a>(
103
113
) -> bool {
104
114
decorators. iter ( ) . any ( |decorator| f. source_text ( ) . lines_after ( decorator. span ( ) . end ) > 0 )
105
115
}
116
+
117
+ pub fn format_trailing_comments_for_last_decorator (
118
+ mut start : u32 ,
119
+ f : & mut Formatter < ' _ , ' _ > ,
120
+ ) -> FormatResult < ( ) > {
121
+ let mut comments = f. context ( ) . comments ( ) . unprinted_comments ( ) ;
122
+
123
+ for ( i, comment) in comments. iter ( ) . enumerate ( ) {
124
+ if !f. source_text ( ) . all_bytes_match ( start, comment. span . start , |b| b. is_ascii_whitespace ( ) )
125
+ {
126
+ comments = & comments[ ..i] ;
127
+ break ;
128
+ }
129
+
130
+ start = comment. span . end ;
131
+ }
132
+
133
+ if !comments. is_empty ( ) {
134
+ write ! (
135
+ f,
136
+ [ group( & format_args!(
137
+ FormatTrailingComments :: Comments ( comments) ,
138
+ soft_line_break_or_space( )
139
+ ) ) ]
140
+ ) ?;
141
+ }
142
+
143
+ Ok ( ( ) )
144
+ }
0 commit comments