@@ -33,6 +33,7 @@ use syntax::util::ThinVec;
33
33
use codemap:: SpanUtils ;
34
34
use comment:: { contains_comment, remove_trailing_white_spaces, FindUncommented } ;
35
35
use expr:: { rewrite_array, rewrite_call_inner} ;
36
+ use lists:: { itemize_list, write_list, DefinitiveListTactic , ListFormatting , SeparatorPlace , SeparatorTactic } ;
36
37
use rewrite:: { Rewrite , RewriteContext } ;
37
38
use shape:: { Indent , Shape } ;
38
39
use utils:: { format_visibility, mk_sp} ;
@@ -283,6 +284,7 @@ pub fn rewrite_macro(
283
284
284
285
pub fn rewrite_macro_def (
285
286
context : & RewriteContext ,
287
+ shape : Shape ,
286
288
indent : Indent ,
287
289
def : & ast:: MacroDef ,
288
290
ident : ast:: Ident ,
@@ -317,101 +319,132 @@ pub fn rewrite_macro_def(
317
319
318
320
let mac_indent_str = mac_indent. to_string ( context. config ) ;
319
321
320
- for branch in parsed_def. branches {
321
- // Only attempt to format function-like macros.
322
- if branch. args_paren_kind != DelimToken :: Paren {
323
- // FIXME(#1539): implement for non-sugared macros.
324
- return snippet;
325
- }
322
+ let branch_items = itemize_list (
323
+ context. codemap ,
324
+ parsed_def. branches . iter ( ) ,
325
+ "" ,
326
+ "" ,
327
+ |branch| branch. args_span . lo ( ) ,
328
+ |branch| branch. body . hi ( ) ,
329
+ |branch| {
330
+ let mut result = String :: new ( ) ;
331
+
332
+ // Only attempt to format function-like macros.
333
+ if branch. args_paren_kind != DelimToken :: Paren {
334
+ // FIXME(#1539): implement for non-sugared macros.
335
+ return None ;
336
+ }
326
337
327
- let args = format_macro_args ( branch. args ) ?;
338
+ let args = format_macro_args ( branch. args . clone ( ) ) ?;
328
339
329
- if multi_branch_style {
330
- result += "\n " ;
331
- result += & mac_indent_str;
332
- result += & args;
333
- result += " =>" ;
334
- } else {
335
- result += & args;
336
- }
340
+ if multi_branch_style {
341
+ result += "\n " ;
342
+ result += & mac_indent_str;
343
+ result += & args;
344
+ result += " =>" ;
345
+ } else {
346
+ result += & args;
347
+ }
337
348
338
- // The macro body is the most interesting part. It might end up as various
339
- // AST nodes, but also has special variables (e.g, `$foo`) which can't be
340
- // parsed as regular Rust code (and note that these can be escaped using
341
- // `$$`). We'll try and format like an AST node, but we'll substitute
342
- // variables for new names with the same length first.
349
+ // The macro body is the most interesting part. It might end up as various
350
+ // AST nodes, but also has special variables (e.g, `$foo`) which can't be
351
+ // parsed as regular Rust code (and note that these can be escaped using
352
+ // `$$`). We'll try and format like an AST node, but we'll substitute
353
+ // variables for new names with the same length first.
343
354
344
- let old_body = context. snippet ( branch. body ) . trim ( ) ;
345
- let ( body_str, substs) = match replace_names ( old_body) {
346
- Some ( result) => result,
347
- None => return snippet,
348
- } ;
355
+ let old_body = context. snippet ( branch. body ) . trim ( ) ;
356
+ let ( body_str, substs) = match replace_names ( old_body) {
357
+ Some ( result) => result,
358
+ None => return snippet,
359
+ } ;
349
360
350
- let mut config = context. config . clone ( ) ;
351
- config. set ( ) . hide_parse_errors ( true ) ;
361
+ let mut config = context. config . clone ( ) ;
362
+ config. set ( ) . hide_parse_errors ( true ) ;
352
363
353
- result += " {" ;
364
+ result += " {" ;
354
365
355
- let has_block_body = old_body. starts_with ( "{" ) ;
366
+ let has_block_body = old_body. starts_with ( '{' ) ;
356
367
357
- let body_indent = if has_block_body {
358
- mac_indent
359
- } else {
360
- // We'll hack the indent below, take this into account when formatting,
361
- let body_indent = mac_indent. block_indent ( & config) ;
362
- let new_width = config. max_width ( ) - body_indent. width ( ) ;
363
- config. set ( ) . max_width ( new_width) ;
364
- body_indent
365
- } ;
368
+ let body_indent = if has_block_body {
369
+ mac_indent
370
+ } else {
371
+ // We'll hack the indent below, take this into account when formatting,
372
+ let body_indent = mac_indent. block_indent ( & config) ;
373
+ let new_width = config. max_width ( ) - body_indent. width ( ) ;
374
+ config. set ( ) . max_width ( new_width) ;
375
+ body_indent
376
+ } ;
366
377
367
- // First try to format as items, then as statements.
368
- let new_body = match :: format_snippet ( & body_str, & config) {
369
- Some ( new_body) => new_body,
370
- None => match :: format_code_block ( & body_str, & config) {
378
+ // First try to format as items, then as statements.
379
+ let new_body = match :: format_snippet ( & body_str, & config) {
371
380
Some ( new_body) => new_body,
372
- None => return snippet,
373
- } ,
374
- } ;
381
+ None => match :: format_code_block ( & body_str, & config) {
382
+ Some ( new_body) => new_body,
383
+ None => return None ,
384
+ } ,
385
+ } ;
375
386
376
- // Indent the body since it is in a block.
377
- let indent_str = body_indent. to_string ( & config) ;
378
- let mut new_body = new_body
379
- . trim_right ( )
380
- . lines ( )
381
- . fold ( String :: new ( ) , |mut s, l| {
382
- if !l. is_empty ( ) {
383
- s += & indent_str;
387
+ // Indent the body since it is in a block.
388
+ let indent_str = body_indent. to_string ( & config) ;
389
+ let mut new_body = new_body
390
+ . trim_right ( )
391
+ . lines ( )
392
+ . fold ( String :: new ( ) , |mut s, l| {
393
+ if !l. is_empty ( ) {
394
+ s += & indent_str;
395
+ }
396
+ s + l + "\n "
397
+ } ) ;
398
+
399
+ // Undo our replacement of macro variables.
400
+ // FIXME: this could be *much* more efficient.
401
+ for ( old, new) in & substs {
402
+ if old_body. find ( new) . is_some ( ) {
403
+ debug ! (
404
+ "rewrite_macro_def: bailing matching variable: `{}` in `{}`" ,
405
+ new, ident
406
+ ) ;
407
+ return None ;
384
408
}
385
- s + l + "\n "
386
- } ) ;
387
-
388
- // Undo our replacement of macro variables.
389
- // FIXME: this could be *much* more efficient.
390
- for ( old, new) in & substs {
391
- if old_body. find ( new) . is_some ( ) {
392
- debug ! (
393
- "rewrite_macro_def: bailing matching variable: `{}` in `{}`" ,
394
- new, ident
395
- ) ;
396
- return snippet;
409
+ new_body = new_body. replace ( new, old) ;
397
410
}
398
- new_body = new_body. replace ( new, old) ;
399
- }
400
411
401
- if has_block_body {
402
- result += new_body. trim ( ) ;
403
- } else if !new_body. is_empty ( ) {
412
+ if has_block_body {
413
+ result += new_body. trim ( ) ;
414
+ } else if !new_body. is_empty ( ) {
415
+ result += "\n " ;
416
+ result += & new_body;
417
+ result += & mac_indent_str;
418
+ }
419
+
420
+ result += "}" ;
421
+ if def. legacy {
422
+ result += ";" ;
423
+ }
404
424
result += "\n " ;
405
- result += & new_body;
406
- result += & mac_indent_str;
407
- }
425
+ Some ( result)
426
+ } ,
427
+ span. lo ( ) ,
428
+ span. hi ( ) ,
429
+ false
430
+ ) . collect :: < Vec < _ > > ( ) ;
431
+
432
+ let arm_shape = shape
433
+ . block_indent ( context. config . tab_spaces ( ) )
434
+ . with_max_width ( context. config ) ;
435
+
436
+ let fmt = ListFormatting {
437
+ tactic : DefinitiveListTactic :: Vertical ,
438
+ separator : "" ,
439
+ trailing_separator : SeparatorTactic :: Never ,
440
+ separator_place : SeparatorPlace :: Back ,
441
+ shape : arm_shape,
442
+ ends_with_newline : false ,
443
+ preserve_newline : true ,
444
+ config : context. config ,
445
+ } ;
408
446
409
- result += "}" ;
410
- if def. legacy {
411
- result += ";" ;
412
- }
413
- result += "\n " ;
414
- }
447
+ result += write_list ( & branch_items, & fmt) ?. as_str ( ) ;
415
448
416
449
if multi_branch_style {
417
450
result += & indent. to_string ( context. config ) ;
@@ -759,9 +792,9 @@ impl MacroParser {
759
792
// `(` ... `)` `=>` `{` ... `}`
760
793
fn parse_branch ( & mut self ) -> Option < MacroBranch > {
761
794
let tok = self . toks . next ( ) ?;
762
- let args_paren_kind = match tok {
795
+ let ( args_span , args_paren_kind) = match tok {
763
796
TokenTree :: Token ( ..) => return None ,
764
- TokenTree :: Delimited ( _ , ref d) => d. delim ,
797
+ TokenTree :: Delimited ( sp , ref d) => ( sp , d. delim ) ,
765
798
} ;
766
799
let args = tok. joint ( ) . into ( ) ;
767
800
match self . toks . next ( ) ? {
@@ -779,8 +812,9 @@ impl MacroParser {
779
812
self . toks . next ( ) ;
780
813
}
781
814
Some ( MacroBranch {
782
- args,
783
815
args_paren_kind,
816
+ args_span,
817
+ args,
784
818
body,
785
819
} )
786
820
}
@@ -794,8 +828,9 @@ struct Macro {
794
828
// FIXME: it would be more efficient to use references to the token streams
795
829
// rather than clone them, if we can make the borrowing work out.
796
830
struct MacroBranch {
797
- args : ThinTokenStream ,
798
831
args_paren_kind : DelimToken ,
832
+ args_span : Span ,
833
+ args : ThinTokenStream ,
799
834
body : Span ,
800
835
}
801
836
0 commit comments