@@ -87,16 +87,19 @@ pub(crate) fn format(
8787 formatter. format_block_comment ( token, & mut formatted_query) ;
8888 }
8989 TokenKind :: ReservedTopLevel => {
90- formatter. format_top_level_reserved_word ( token, & mut formatted_query) ;
91- formatter. set_top_level_span ( token) ;
90+ let span_info =
91+ formatter. format_top_level_reserved_word ( token, & mut formatted_query) ;
92+ formatter. set_top_level_span ( token, span_info) ;
9293 }
9394 TokenKind :: ReservedTopLevelNoIndent => {
94- formatter. format_top_level_reserved_word_no_indent ( token, & mut formatted_query) ;
95- formatter. set_top_level_span ( token) ;
95+ let span_info =
96+ formatter. format_top_level_reserved_word_no_indent ( token, & mut formatted_query) ;
97+ formatter. set_top_level_span ( token, span_info) ;
9698 }
9799 TokenKind :: ReservedNewlineAfter => {
98- formatter. format_newline_after_reserved_word ( token, & mut formatted_query) ;
99- formatter. set_top_level_span ( token) ;
100+ let span_info =
101+ formatter. format_newline_after_reserved_word ( token, & mut formatted_query) ;
102+ formatter. set_top_level_span ( token, span_info) ;
100103 }
101104 TokenKind :: ReservedNewline => {
102105 formatter. format_newline_reserved_word ( token, & mut formatted_query) ;
@@ -167,8 +170,7 @@ impl<'a> Formatter<'a> {
167170 }
168171 }
169172
170- fn set_top_level_span ( & mut self , token : & ' a Token < ' a > ) {
171- let span_info = self . top_level_tokens_info ( ) ;
173+ fn set_top_level_span ( & mut self , token : & ' a Token < ' a > , span_info : SpanInfo ) {
172174 self . indentation . set_previous_top_level ( token, span_info) ;
173175 }
174176
@@ -207,57 +209,54 @@ impl<'a> Formatter<'a> {
207209 self . add_new_line ( query) ;
208210 }
209211
210- // if we are inside an inline block we decide our behaviour as if were inline
211- fn top_level_behavior ( & self , span_info : & SpanInfo ) -> ( bool , bool ) {
212- let span_len = span_info. full_span ;
213- let block_len = self . inline_block . cur_len ( ) ;
214- if block_len > 0 {
215- let limit = self . options . max_inline_top_level . unwrap_or ( 0 ) ;
216- ( limit < block_len, limit < span_len)
217- } else {
218- (
219- true ,
220- self . options
221- . max_inline_top_level
222- . is_none_or ( |limit| limit < span_len) ,
223- )
224- }
225- }
226-
227- fn format_top_level_reserved_word ( & mut self , token : & Token < ' _ > , query : & mut String ) {
212+ fn format_top_level_reserved_word (
213+ & mut self ,
214+ token : & Token < ' _ > ,
215+ query : & mut String ,
216+ ) -> SpanInfo {
228217 let span_info = self . top_level_tokens_info ( ) ;
229- let ( newline_before, newline_after) = self . top_level_behavior ( & span_info) ;
230218
231- if newline_before {
219+ if span_info . newline_before {
232220 self . indentation . decrease_top_level ( ) ;
233221 self . add_new_line ( query) ;
234222 }
235223 query. push_str ( & self . equalize_whitespace ( & self . format_reserved_word ( token. value ) ) ) ;
236- if newline_after && token. alias != "CREATE" {
237- self . indentation . increase_top_level ( span_info) ;
224+ if span_info . newline_after && token. alias != "CREATE" {
225+ self . indentation . increase_top_level ( span_info. clone ( ) ) ;
238226 self . add_new_line ( query) ;
239227 } else {
240228 query. push ( ' ' ) ;
241229 }
230+
231+ span_info
242232 }
243233
244- fn format_top_level_reserved_word_no_indent ( & mut self , token : & Token < ' _ > , query : & mut String ) {
234+ fn format_top_level_reserved_word_no_indent (
235+ & mut self ,
236+ token : & Token < ' _ > ,
237+ query : & mut String ,
238+ ) -> SpanInfo {
245239 let span_info = self . top_level_tokens_info ( ) ;
246- let ( newline_before, newline_after) = self . top_level_behavior ( & span_info) ;
247240
248- if newline_before {
241+ if span_info . newline_before {
249242 self . indentation . decrease_top_level ( ) ;
250243 self . add_new_line ( query) ;
251244 }
252245 query. push_str ( & self . equalize_whitespace ( & self . format_reserved_word ( token. value ) ) ) ;
253- if newline_after {
246+ if span_info . newline_after {
254247 self . add_new_line ( query) ;
255248 } else {
256249 query. push ( ' ' ) ;
257250 }
251+
252+ span_info
258253 }
259254
260- fn format_newline_after_reserved_word ( & mut self , token : & Token < ' _ > , query : & mut String ) {
255+ fn format_newline_after_reserved_word (
256+ & mut self ,
257+ token : & Token < ' _ > ,
258+ query : & mut String ,
259+ ) -> SpanInfo {
261260 let span_info = self . top_level_tokens_info ( ) ;
262261
263262 let newline_before = match (
@@ -278,8 +277,10 @@ impl<'a> Formatter<'a> {
278277
279278 query. push_str ( & self . equalize_whitespace ( & self . format_reserved_word ( token. value ) ) ) ;
280279
281- self . indentation . increase_top_level ( span_info) ;
280+ self . indentation . increase_top_level ( span_info. clone ( ) ) ;
282281 self . add_new_line ( query) ;
282+
283+ span_info
283284 }
284285
285286 fn format_newline_reserved_word ( & mut self , token : & Token < ' _ > , query : & mut String ) {
@@ -318,6 +319,19 @@ impl<'a> Formatter<'a> {
318319 TokenKind :: LineComment ,
319320 ] ;
320321
322+ let inlined = self . inline_block . begin_if_possible ( self . tokens , self . index ) ;
323+ let fold_in_top_level = !inlined
324+ && self . options . max_inline_top_level . is_some ( )
325+ && self
326+ . previous_non_whitespace_token ( 1 )
327+ . is_some_and ( |t| t. kind == TokenKind :: ReservedTopLevel )
328+ && self
329+ . indentation
330+ . previous_top_level_reserved ( )
331+ . is_some_and ( |( _, span) | {
332+ span. blocks == 1 && span. newline_after && span. arguments == 1
333+ } ) ;
334+
321335 // Take out the preceding space unless there was whitespace there in the original query
322336 // or another opening parens or line comment
323337 let previous_token = self . previous_token ( 1 ) ;
@@ -348,11 +362,14 @@ impl<'a> Formatter<'a> {
348362 _ => Cow :: Borrowed ( token. value ) ,
349363 } ;
350364
351- query. push_str ( & value) ;
365+ if fold_in_top_level {
366+ self . trim_all_spaces_end ( query) ;
367+ query. push ( ' ' ) ;
368+ }
352369
353- self . inline_block . begin_if_possible ( self . tokens , self . index ) ;
370+ self . indentation . increase_block_level ( fold_in_top_level ) ;
354371
355- self . indentation . increase_block_level ( ) ;
372+ query . push_str ( & value ) ;
356373
357374 if !self . inline_block . is_active ( ) {
358375 self . add_new_line ( query) ;
@@ -388,7 +405,7 @@ impl<'a> Formatter<'a> {
388405
389406 token. value = & value;
390407
391- self . indentation . decrease_block_level ( ) ;
408+ let folded = self . indentation . decrease_block_level ( ) ;
392409
393410 if self . inline_block . is_active ( ) {
394411 self . inline_block . end ( ) ;
@@ -400,7 +417,7 @@ impl<'a> Formatter<'a> {
400417 self . format_with_space_after ( & token, query) ;
401418 }
402419 } else {
403- self . add_new_line ( query) ;
420+ self . add_new_line_inner ( query, folded ) ;
404421 self . format_with_spaces ( & token, query) ;
405422 }
406423 }
@@ -458,7 +475,7 @@ impl<'a> Formatter<'a> {
458475 }
459476 }
460477
461- fn add_new_line ( & self , query : & mut String ) {
478+ fn add_new_line_inner ( & self , query : & mut String , folded : bool ) {
462479 self . trim_spaces_end ( query) ;
463480 if self . options . inline {
464481 query. push ( ' ' ) ;
@@ -467,7 +484,11 @@ impl<'a> Formatter<'a> {
467484 if !query. ends_with ( '\n' ) {
468485 query. push ( '\n' ) ;
469486 }
470- query. push_str ( & self . indentation . get_indent ( ) ) ;
487+ query. push_str ( & self . indentation . get_indent ( folded) ) ;
488+ }
489+
490+ fn add_new_line ( & self , query : & mut String ) {
491+ self . add_new_line_inner ( query, false ) ;
471492 }
472493
473494 fn trim_spaces_end ( & self , query : & mut String ) {
@@ -484,7 +505,7 @@ impl<'a> Formatter<'a> {
484505 if i == 0 {
485506 combined. push_str ( line)
486507 } else if line. starts_with ( [ ' ' , '\t' ] ) {
487- let indent = self . indentation . get_indent ( ) ;
508+ let indent = self . indentation . get_indent ( false ) ;
488509 let start_trimmed = line. trim_start_matches ( [ ' ' , '\t' ] ) ;
489510 combined. reserve ( indent. len ( ) + start_trimmed. len ( ) + 2 ) ;
490511 combined. push ( '\n' ) ;
@@ -553,13 +574,30 @@ impl<'a> Formatter<'a> {
553574 }
554575 }
555576
577+ fn previous_non_whitespace_token ( & self , idx : usize ) -> Option < & Token < ' _ > > {
578+ let index = self . index . checked_sub ( idx) ;
579+ if let Some ( index) = index {
580+ self . tokens [ ..=index]
581+ . iter ( )
582+ . rev ( )
583+ . find ( |t| t. kind != TokenKind :: Whitespace )
584+ } else {
585+ None
586+ }
587+ }
588+
556589 fn top_level_tokens_info ( & self ) -> SpanInfo {
557590 let mut block_level = self . block_level ;
558591 let mut full_span = 0 ;
592+ let mut blocks = 0 ;
593+ let mut arguments = 0 ;
559594
560595 for token in self . tokens [ self . index ..] . iter ( ) . skip ( 1 ) {
561596 match token. kind {
562597 TokenKind :: OpenParen => {
598+ if block_level == self . block_level {
599+ blocks += 1 ;
600+ }
563601 block_level += 1 ;
564602 }
565603 TokenKind :: CloseParen => {
@@ -579,14 +617,43 @@ impl<'a> Formatter<'a> {
579617 full_span += 1 ;
580618 continue ;
581619 }
620+ TokenKind :: Operator if token. value == "," => {
621+ if block_level == self . block_level {
622+ arguments += 1 ;
623+ }
624+ }
582625
583- _ => { }
626+ _ => {
627+ if arguments == 0 {
628+ arguments += 1
629+ }
630+ }
584631 }
585632
586633 full_span += token. value . len ( ) ;
587634 }
588635
589- SpanInfo { full_span }
636+ // if we are inside an inline block we decide our behaviour as if were inline
637+ let block_len = self . inline_block . cur_len ( ) ;
638+ let ( newline_before, newline_after) = if block_len > 0 {
639+ let limit = self . options . max_inline_top_level . unwrap_or ( 0 ) ;
640+ ( limit < block_len, limit < full_span)
641+ } else {
642+ (
643+ true ,
644+ self . options
645+ . max_inline_top_level
646+ . is_none_or ( |limit| limit < full_span) ,
647+ )
648+ } ;
649+
650+ SpanInfo {
651+ full_span,
652+ blocks,
653+ newline_before,
654+ newline_after,
655+ arguments,
656+ }
590657 }
591658
592659 fn format_no_change ( & self , token : & Token < ' _ > , query : & mut String ) {
0 commit comments