]> git.lizzy.rs Git - rust.git/blob - src/macros.rs
Merge pull request #3472 from devinalvaro/add-print-current-config
[rust.git] / src / macros.rs
1 // Format list-like macro invocations. These are invocations whose token trees
2 // can be interpreted as expressions and separated by commas.
3 // Note that these token trees do not actually have to be interpreted as
4 // expressions by the compiler. An example of an invocation we would reformat is
5 // foo!( x, y, z ). The token x may represent an identifier in the code, but we
6 // interpreted as an expression.
7 // Macro uses which are not-list like, such as bar!(key => val), will not be
8 // reformatted.
9 // List-like invocations with parentheses will be formatted as function calls,
10 // and those with brackets will be formatted as array literals.
11
12 use std::collections::HashMap;
13
14 use syntax::parse::new_parser_from_tts;
15 use syntax::parse::parser::Parser;
16 use syntax::parse::token::{BinOpToken, DelimToken, Token};
17 use syntax::print::pprust;
18 use syntax::source_map::{BytePos, Span};
19 use syntax::symbol::keywords;
20 use syntax::tokenstream::{Cursor, TokenStream, TokenTree};
21 use syntax::ThinVec;
22 use syntax::{ast, parse, ptr};
23
24 use crate::comment::{
25     contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses,
26 };
27 use crate::config::lists::*;
28 use crate::expr::rewrite_array;
29 use crate::lists::{itemize_list, write_list, ListFormatting};
30 use crate::overflow;
31 use crate::rewrite::{Rewrite, RewriteContext};
32 use crate::shape::{Indent, Shape};
33 use crate::source_map::SpanUtils;
34 use crate::spanned::Spanned;
35 use crate::utils::{
36     format_visibility, indent_next_line, is_empty_line, mk_sp, remove_trailing_white_spaces,
37     rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt,
38 };
39 use crate::visitor::FmtVisitor;
40
41 const FORCED_BRACKET_MACROS: &[&str] = &["vec!"];
42
43 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
44 pub enum MacroPosition {
45     Item,
46     Statement,
47     Expression,
48     Pat,
49 }
50
51 #[derive(Debug)]
52 pub enum MacroArg {
53     Expr(ptr::P<ast::Expr>),
54     Ty(ptr::P<ast::Ty>),
55     Pat(ptr::P<ast::Pat>),
56     Item(ptr::P<ast::Item>),
57     Keyword(ast::Ident, Span),
58 }
59
60 impl MacroArg {
61     fn is_item(&self) -> bool {
62         match self {
63             MacroArg::Item(..) => true,
64             _ => false,
65         }
66     }
67 }
68
69 impl Rewrite for ast::Item {
70     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
71         let mut visitor = crate::visitor::FmtVisitor::from_context(context);
72         visitor.block_indent = shape.indent;
73         visitor.last_pos = self.span().lo();
74         visitor.visit_item(self);
75         Some(visitor.buffer.to_owned())
76     }
77 }
78
79 impl Rewrite for MacroArg {
80     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
81         match *self {
82             MacroArg::Expr(ref expr) => expr.rewrite(context, shape),
83             MacroArg::Ty(ref ty) => ty.rewrite(context, shape),
84             MacroArg::Pat(ref pat) => pat.rewrite(context, shape),
85             MacroArg::Item(ref item) => item.rewrite(context, shape),
86             MacroArg::Keyword(ident, _) => Some(ident.to_string()),
87         }
88     }
89 }
90
91 fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
92     macro_rules! parse_macro_arg {
93         ($macro_arg:ident, $parser:expr, $f:expr) => {
94             let mut cloned_parser = (*parser).clone();
95             match $parser(&mut cloned_parser) {
96                 Ok(x) => {
97                     if parser.sess.span_diagnostic.has_errors() {
98                         parser.sess.span_diagnostic.reset_err_count();
99                     } else {
100                         // Parsing succeeded.
101                         *parser = cloned_parser;
102                         return Some(MacroArg::$macro_arg($f(x)?));
103                     }
104                 }
105                 Err(mut e) => {
106                     e.cancel();
107                     parser.sess.span_diagnostic.reset_err_count();
108                 }
109             }
110         };
111     }
112
113     parse_macro_arg!(
114         Expr,
115         |parser: &mut parse::parser::Parser<'b>| parser.parse_expr(),
116         |x: ptr::P<ast::Expr>| Some(x)
117     );
118     parse_macro_arg!(
119         Ty,
120         |parser: &mut parse::parser::Parser<'b>| parser.parse_ty(),
121         |x: ptr::P<ast::Ty>| Some(x)
122     );
123     parse_macro_arg!(
124         Pat,
125         |parser: &mut parse::parser::Parser<'b>| parser.parse_pat(None),
126         |x: ptr::P<ast::Pat>| Some(x)
127     );
128     // `parse_item` returns `Option<ptr::P<ast::Item>>`.
129     parse_macro_arg!(
130         Item,
131         |parser: &mut parse::parser::Parser<'b>| parser.parse_item(),
132         |x: Option<ptr::P<ast::Item>>| x
133     );
134
135     None
136 }
137
138 /// Rewrite macro name without using pretty-printer if possible.
139 fn rewrite_macro_name(
140     context: &RewriteContext<'_>,
141     path: &ast::Path,
142     extra_ident: Option<ast::Ident>,
143 ) -> String {
144     let name = if path.segments.len() == 1 {
145         // Avoid using pretty-printer in the common case.
146         format!("{}!", rewrite_ident(context, path.segments[0].ident))
147     } else {
148         format!("{}!", path)
149     };
150     match extra_ident {
151         Some(ident) if ident != keywords::Invalid.ident() => format!("{} {}", name, ident),
152         _ => name,
153     }
154 }
155
156 // Use this on failing to format the macro call.
157 fn return_macro_parse_failure_fallback(
158     context: &RewriteContext<'_>,
159     indent: Indent,
160     span: Span,
161 ) -> Option<String> {
162     // Mark this as a failure however we format it
163     context.macro_rewrite_failure.replace(true);
164
165     // Heuristically determine whether the last line of the macro uses "Block" style
166     // rather than using "Visual" style, or another indentation style.
167     let is_like_block_indent_style = context
168         .snippet(span)
169         .lines()
170         .last()
171         .map(|closing_line| {
172             closing_line.trim().chars().all(|ch| match ch {
173                 '}' | ')' | ']' => true,
174                 _ => false,
175             })
176         })
177         .unwrap_or(false);
178     if is_like_block_indent_style {
179         return trim_left_preserve_layout(context.snippet(span), indent, &context.config);
180     }
181
182     // Return the snippet unmodified if the macro is not block-like
183     Some(context.snippet(span).to_owned())
184 }
185
186 struct InsideMacroGuard<'a> {
187     context: &'a RewriteContext<'a>,
188     is_nested: bool,
189 }
190
191 impl<'a> InsideMacroGuard<'a> {
192     fn inside_macro_context(context: &'a RewriteContext<'_>) -> InsideMacroGuard<'a> {
193         let is_nested = context.inside_macro.replace(true);
194         InsideMacroGuard { context, is_nested }
195     }
196 }
197
198 impl<'a> Drop for InsideMacroGuard<'a> {
199     fn drop(&mut self) {
200         self.context.inside_macro.replace(self.is_nested);
201     }
202 }
203
204 pub fn rewrite_macro(
205     mac: &ast::Mac,
206     extra_ident: Option<ast::Ident>,
207     context: &RewriteContext<'_>,
208     shape: Shape,
209     position: MacroPosition,
210 ) -> Option<String> {
211     let should_skip = context
212         .skip_macro_names
213         .borrow()
214         .contains(&context.snippet(mac.node.path.span).to_owned());
215     if should_skip {
216         None
217     } else {
218         let guard = InsideMacroGuard::inside_macro_context(context);
219         let result =
220             rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested);
221         if result.is_none() {
222             context.macro_rewrite_failure.replace(true);
223         }
224         result
225     }
226 }
227
228 fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
229     for &keyword in RUST_KEYWORDS.iter() {
230         if parser.token.is_keyword(keyword)
231             && parser.look_ahead(1, |t| {
232                 *t == Token::Eof
233                     || *t == Token::Comma
234                     || *t == Token::CloseDelim(DelimToken::NoDelim)
235             })
236         {
237             let macro_arg = MacroArg::Keyword(keyword.ident(), parser.span);
238             parser.bump();
239             return Some(macro_arg);
240         }
241     }
242     None
243 }
244
245 pub fn rewrite_macro_inner(
246     mac: &ast::Mac,
247     extra_ident: Option<ast::Ident>,
248     context: &RewriteContext<'_>,
249     shape: Shape,
250     position: MacroPosition,
251     is_nested_macro: bool,
252 ) -> Option<String> {
253     if context.config.use_try_shorthand() {
254         if let Some(expr) = convert_try_mac(mac, context) {
255             context.inside_macro.replace(false);
256             return expr.rewrite(context, shape);
257         }
258     }
259
260     let original_style = macro_style(mac, context);
261
262     let macro_name = rewrite_macro_name(context, &mac.node.path, extra_ident);
263
264     let style = if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) && !is_nested_macro {
265         DelimToken::Bracket
266     } else {
267         original_style
268     };
269
270     let ts: TokenStream = mac.node.stream();
271     let has_comment = contains_comment(context.snippet(mac.span));
272     if ts.is_empty() && !has_comment {
273         return match style {
274             DelimToken::Paren if position == MacroPosition::Item => {
275                 Some(format!("{}();", macro_name))
276             }
277             DelimToken::Paren => Some(format!("{}()", macro_name)),
278             DelimToken::Bracket => Some(format!("{}[]", macro_name)),
279             DelimToken::Brace => Some(format!("{} {{}}", macro_name)),
280             _ => unreachable!(),
281         };
282     }
283     // Format well-known macros which cannot be parsed as a valid AST.
284     if macro_name == "lazy_static!" && !has_comment {
285         if let success @ Some(..) = format_lazy_static(context, shape, &ts) {
286             return success;
287         }
288     }
289
290     let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());
291     let mut arg_vec = Vec::new();
292     let mut vec_with_semi = false;
293     let mut trailing_comma = false;
294
295     if DelimToken::Brace != style {
296         loop {
297             if let Some(arg) = parse_macro_arg(&mut parser) {
298                 arg_vec.push(arg);
299             } else if let Some(arg) = check_keyword(&mut parser) {
300                 arg_vec.push(arg);
301             } else {
302                 return return_macro_parse_failure_fallback(context, shape.indent, mac.span);
303             }
304
305             match parser.token {
306                 Token::Eof => break,
307                 Token::Comma => (),
308                 Token::Semi => {
309                     // Try to parse `vec![expr; expr]`
310                     if FORCED_BRACKET_MACROS.contains(&&macro_name[..]) {
311                         parser.bump();
312                         if parser.token != Token::Eof {
313                             match parse_macro_arg(&mut parser) {
314                                 Some(arg) => {
315                                     arg_vec.push(arg);
316                                     parser.bump();
317                                     if parser.token == Token::Eof && arg_vec.len() == 2 {
318                                         vec_with_semi = true;
319                                         break;
320                                     }
321                                 }
322                                 None => {
323                                     return return_macro_parse_failure_fallback(
324                                         context,
325                                         shape.indent,
326                                         mac.span,
327                                     );
328                                 }
329                             }
330                         }
331                     }
332                     return return_macro_parse_failure_fallback(context, shape.indent, mac.span);
333                 }
334                 _ if arg_vec.last().map_or(false, MacroArg::is_item) => continue,
335                 _ => return return_macro_parse_failure_fallback(context, shape.indent, mac.span),
336             }
337
338             parser.bump();
339
340             if parser.token == Token::Eof {
341                 trailing_comma = true;
342                 break;
343             }
344         }
345     }
346
347     if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) {
348         return rewrite_macro_with_items(
349             context,
350             &arg_vec,
351             &macro_name,
352             shape,
353             style,
354             position,
355             mac.span,
356         );
357     }
358
359     match style {
360         DelimToken::Paren => {
361             // Format macro invocation as function call, preserve the trailing
362             // comma because not all macros support them.
363             overflow::rewrite_with_parens(
364                 context,
365                 &macro_name,
366                 arg_vec.iter(),
367                 shape,
368                 mac.span,
369                 context.config.width_heuristics().fn_call_width,
370                 if trailing_comma {
371                     Some(SeparatorTactic::Always)
372                 } else {
373                     Some(SeparatorTactic::Never)
374                 },
375             )
376             .map(|rw| match position {
377                 MacroPosition::Item => format!("{};", rw),
378                 _ => rw,
379             })
380         }
381         DelimToken::Bracket => {
382             // Handle special case: `vec![expr; expr]`
383             if vec_with_semi {
384                 let mac_shape = shape.offset_left(macro_name.len())?;
385                 // 8 = `vec![]` + `; `
386                 let total_overhead = 8;
387                 let nested_shape = mac_shape.block_indent(context.config.tab_spaces());
388                 let lhs = arg_vec[0].rewrite(context, nested_shape)?;
389                 let rhs = arg_vec[1].rewrite(context, nested_shape)?;
390                 if !lhs.contains('\n')
391                     && !rhs.contains('\n')
392                     && lhs.len() + rhs.len() + total_overhead <= shape.width
393                 {
394                     Some(format!("{}[{}; {}]", macro_name, lhs, rhs))
395                 } else {
396                     Some(format!(
397                         "{}[{}{};{}{}{}]",
398                         macro_name,
399                         nested_shape.indent.to_string_with_newline(context.config),
400                         lhs,
401                         nested_shape.indent.to_string_with_newline(context.config),
402                         rhs,
403                         shape.indent.to_string_with_newline(context.config),
404                     ))
405                 }
406             } else {
407                 // If we are rewriting `vec!` macro or other special macros,
408                 // then we can rewrite this as an usual array literal.
409                 // Otherwise, we must preserve the original existence of trailing comma.
410                 let macro_name = &macro_name.as_str();
411                 let mut force_trailing_comma = if trailing_comma {
412                     Some(SeparatorTactic::Always)
413                 } else {
414                     Some(SeparatorTactic::Never)
415                 };
416                 if FORCED_BRACKET_MACROS.contains(macro_name) && !is_nested_macro {
417                     context.inside_macro.replace(false);
418                     if context.use_block_indent() {
419                         force_trailing_comma = Some(SeparatorTactic::Vertical);
420                     };
421                 }
422                 let rewrite = rewrite_array(
423                     macro_name,
424                     arg_vec.iter(),
425                     mac.span,
426                     context,
427                     shape,
428                     force_trailing_comma,
429                     Some(original_style),
430                 )?;
431                 let comma = match position {
432                     MacroPosition::Item => ";",
433                     _ => "",
434                 };
435
436                 Some(format!("{}{}", rewrite, comma))
437             }
438         }
439         DelimToken::Brace => {
440             // For macro invocations with braces, always put a space between
441             // the `macro_name!` and `{ /* macro_body */ }` but skip modifying
442             // anything in between the braces (for now).
443             let snippet = context.snippet(mac.span).trim_start_matches(|c| c != '{');
444             match trim_left_preserve_layout(snippet, shape.indent, &context.config) {
445                 Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
446                 None => Some(format!("{} {}", macro_name, snippet)),
447             }
448         }
449         _ => unreachable!(),
450     }
451 }
452
453 pub fn rewrite_macro_def(
454     context: &RewriteContext<'_>,
455     shape: Shape,
456     indent: Indent,
457     def: &ast::MacroDef,
458     ident: ast::Ident,
459     vis: &ast::Visibility,
460     span: Span,
461 ) -> Option<String> {
462     let snippet = Some(remove_trailing_white_spaces(context.snippet(span)));
463     if snippet.as_ref().map_or(true, |s| s.ends_with(';')) {
464         return snippet;
465     }
466
467     let mut parser = MacroParser::new(def.stream().into_trees());
468     let parsed_def = match parser.parse() {
469         Some(def) => def,
470         None => return snippet,
471     };
472
473     let mut result = if def.legacy {
474         String::from("macro_rules!")
475     } else {
476         format!("{}macro", format_visibility(context, vis))
477     };
478
479     result += " ";
480     result += rewrite_ident(context, ident);
481
482     let multi_branch_style = def.legacy || parsed_def.branches.len() != 1;
483
484     let arm_shape = if multi_branch_style {
485         shape
486             .block_indent(context.config.tab_spaces())
487             .with_max_width(context.config)
488     } else {
489         shape
490     };
491
492     let branch_items = itemize_list(
493         context.snippet_provider,
494         parsed_def.branches.iter(),
495         "}",
496         ";",
497         |branch| branch.span.lo(),
498         |branch| branch.span.hi(),
499         |branch| match branch.rewrite(context, arm_shape, multi_branch_style) {
500             Some(v) => Some(v),
501             // if the rewrite returned None because a macro could not be rewritten, then return the
502             // original body
503             None if *context.macro_rewrite_failure.borrow() => {
504                 Some(context.snippet(branch.body).trim().to_string())
505             }
506             None => None,
507         },
508         context.snippet_provider.span_after(span, "{"),
509         span.hi(),
510         false,
511     )
512     .collect::<Vec<_>>();
513
514     let fmt = ListFormatting::new(arm_shape, context.config)
515         .separator(if def.legacy { ";" } else { "" })
516         .trailing_separator(SeparatorTactic::Always)
517         .preserve_newline(true);
518
519     if multi_branch_style {
520         result += " {";
521         result += &arm_shape.indent.to_string_with_newline(context.config);
522     }
523
524     match write_list(&branch_items, &fmt) {
525         Some(ref s) => result += s,
526         None => return snippet,
527     }
528
529     if multi_branch_style {
530         result += &indent.to_string_with_newline(context.config);
531         result += "}";
532     }
533
534     Some(result)
535 }
536
537 fn register_metavariable(
538     map: &mut HashMap<String, String>,
539     result: &mut String,
540     name: &str,
541     dollar_count: usize,
542 ) {
543     let mut new_name = String::new();
544     let mut old_name = String::new();
545
546     old_name.push('$');
547     for _ in 0..(dollar_count - 1) {
548         new_name.push('$');
549         old_name.push('$');
550     }
551     new_name.push('z');
552     new_name.push_str(&name);
553     old_name.push_str(&name);
554
555     result.push_str(&new_name);
556     map.insert(old_name, new_name);
557 }
558
559 // Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we
560 // aren't causing problems.
561 // This should also work for escaped `$` variables, where we leave earlier `$`s.
562 fn replace_names(input: &str) -> Option<(String, HashMap<String, String>)> {
563     // Each substitution will require five or six extra bytes.
564     let mut result = String::with_capacity(input.len() + 64);
565     let mut substs = HashMap::new();
566     let mut dollar_count = 0;
567     let mut cur_name = String::new();
568
569     for (kind, c) in CharClasses::new(input.chars()) {
570         if kind != FullCodeCharKind::Normal {
571             result.push(c);
572         } else if c == '$' {
573             dollar_count += 1;
574         } else if dollar_count == 0 {
575             result.push(c);
576         } else if !c.is_alphanumeric() && !cur_name.is_empty() {
577             // Terminates a name following one or more dollars.
578             register_metavariable(&mut substs, &mut result, &cur_name, dollar_count);
579
580             result.push(c);
581             dollar_count = 0;
582             cur_name.clear();
583         } else if c == '(' && cur_name.is_empty() {
584             // FIXME: Support macro def with repeat.
585             return None;
586         } else if c.is_alphanumeric() || c == '_' {
587             cur_name.push(c);
588         }
589     }
590
591     if !cur_name.is_empty() {
592         register_metavariable(&mut substs, &mut result, &cur_name, dollar_count);
593     }
594
595     debug!("replace_names `{}` {:?}", result, substs);
596
597     Some((result, substs))
598 }
599
600 #[derive(Debug, Clone)]
601 enum MacroArgKind {
602     /// e.g., `$x: expr`.
603     MetaVariable(ast::Ident, String),
604     /// e.g., `$($foo: expr),*`
605     Repeat(
606         /// `()`, `[]` or `{}`.
607         DelimToken,
608         /// Inner arguments inside delimiters.
609         Vec<ParsedMacroArg>,
610         /// Something after the closing delimiter and the repeat token, if available.
611         Option<Box<ParsedMacroArg>>,
612         /// The repeat token. This could be one of `*`, `+` or `?`.
613         Token,
614     ),
615     /// e.g., `[derive(Debug)]`
616     Delimited(DelimToken, Vec<ParsedMacroArg>),
617     /// A possible separator. e.g., `,` or `;`.
618     Separator(String, String),
619     /// Other random stuff that does not fit to other kinds.
620     /// e.g., `== foo` in `($x: expr == foo)`.
621     Other(String, String),
622 }
623
624 fn delim_token_to_str(
625     context: &RewriteContext<'_>,
626     delim_token: DelimToken,
627     shape: Shape,
628     use_multiple_lines: bool,
629     inner_is_empty: bool,
630 ) -> (String, String) {
631     let (lhs, rhs) = match delim_token {
632         DelimToken::Paren => ("(", ")"),
633         DelimToken::Bracket => ("[", "]"),
634         DelimToken::Brace => {
635             if inner_is_empty || use_multiple_lines {
636                 ("{", "}")
637             } else {
638                 ("{ ", " }")
639             }
640         }
641         DelimToken::NoDelim => ("", ""),
642     };
643     if use_multiple_lines {
644         let indent_str = shape.indent.to_string_with_newline(context.config);
645         let nested_indent_str = shape
646             .indent
647             .block_indent(context.config)
648             .to_string_with_newline(context.config);
649         (
650             format!("{}{}", lhs, nested_indent_str),
651             format!("{}{}", indent_str, rhs),
652         )
653     } else {
654         (lhs.to_owned(), rhs.to_owned())
655     }
656 }
657
658 impl MacroArgKind {
659     fn starts_with_brace(&self) -> bool {
660         match *self {
661             MacroArgKind::Repeat(DelimToken::Brace, _, _, _)
662             | MacroArgKind::Delimited(DelimToken::Brace, _) => true,
663             _ => false,
664         }
665     }
666
667     fn starts_with_dollar(&self) -> bool {
668         match *self {
669             MacroArgKind::Repeat(..) | MacroArgKind::MetaVariable(..) => true,
670             _ => false,
671         }
672     }
673
674     fn ends_with_space(&self) -> bool {
675         match *self {
676             MacroArgKind::Separator(..) => true,
677             _ => false,
678         }
679     }
680
681     fn has_meta_var(&self) -> bool {
682         match *self {
683             MacroArgKind::MetaVariable(..) => true,
684             MacroArgKind::Repeat(_, ref args, _, _) => args.iter().any(|a| a.kind.has_meta_var()),
685             _ => false,
686         }
687     }
688
689     fn rewrite(
690         &self,
691         context: &RewriteContext<'_>,
692         shape: Shape,
693         use_multiple_lines: bool,
694     ) -> Option<String> {
695         let rewrite_delimited_inner = |delim_tok, args| -> Option<(String, String, String)> {
696             let inner = wrap_macro_args(context, args, shape)?;
697             let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, false, inner.is_empty());
698             if lhs.len() + inner.len() + rhs.len() <= shape.width {
699                 return Some((lhs, inner, rhs));
700             }
701
702             let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, true, false);
703             let nested_shape = shape
704                 .block_indent(context.config.tab_spaces())
705                 .with_max_width(context.config);
706             let inner = wrap_macro_args(context, args, nested_shape)?;
707             Some((lhs, inner, rhs))
708         };
709
710         match *self {
711             MacroArgKind::MetaVariable(ty, ref name) => {
712                 Some(format!("${}:{}", name, ty.name.as_str()))
713             }
714             MacroArgKind::Repeat(delim_tok, ref args, ref another, ref tok) => {
715                 let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?;
716                 let another = another
717                     .as_ref()
718                     .and_then(|a| a.rewrite(context, shape, use_multiple_lines))
719                     .unwrap_or_else(|| "".to_owned());
720                 let repeat_tok = pprust::token_to_string(tok);
721
722                 Some(format!("${}{}{}{}{}", lhs, inner, rhs, another, repeat_tok))
723             }
724             MacroArgKind::Delimited(delim_tok, ref args) => {
725                 rewrite_delimited_inner(delim_tok, args)
726                     .map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs))
727             }
728             MacroArgKind::Separator(ref sep, ref prefix) => Some(format!("{}{} ", prefix, sep)),
729             MacroArgKind::Other(ref inner, ref prefix) => Some(format!("{}{}", prefix, inner)),
730         }
731     }
732 }
733
734 #[derive(Debug, Clone)]
735 struct ParsedMacroArg {
736     kind: MacroArgKind,
737     span: Span,
738 }
739
740 impl ParsedMacroArg {
741     pub fn rewrite(
742         &self,
743         context: &RewriteContext<'_>,
744         shape: Shape,
745         use_multiple_lines: bool,
746     ) -> Option<String> {
747         self.kind.rewrite(context, shape, use_multiple_lines)
748     }
749 }
750
751 /// Parses macro arguments on macro def.
752 struct MacroArgParser {
753     /// Either a name of the next metavariable, a separator, or junk.
754     buf: String,
755     /// The start position on the current buffer.
756     lo: BytePos,
757     /// The first token of the current buffer.
758     start_tok: Token,
759     /// `true` if we are parsing a metavariable or a repeat.
760     is_meta_var: bool,
761     /// The position of the last token.
762     hi: BytePos,
763     /// The last token parsed.
764     last_tok: Token,
765     /// Holds the parsed arguments.
766     result: Vec<ParsedMacroArg>,
767 }
768
769 fn last_tok(tt: &TokenTree) -> Token {
770     match *tt {
771         TokenTree::Token(_, ref t) => t.clone(),
772         TokenTree::Delimited(_, delim, _) => Token::CloseDelim(delim),
773     }
774 }
775
776 impl MacroArgParser {
777     pub fn new() -> MacroArgParser {
778         MacroArgParser {
779             lo: BytePos(0),
780             hi: BytePos(0),
781             buf: String::new(),
782             is_meta_var: false,
783             last_tok: Token::Eof,
784             start_tok: Token::Eof,
785             result: vec![],
786         }
787     }
788
789     fn set_last_tok(&mut self, tok: &TokenTree) {
790         self.hi = tok.span().hi();
791         self.last_tok = last_tok(tok);
792     }
793
794     fn add_separator(&mut self) {
795         let prefix = if self.need_space_prefix() {
796             " ".to_owned()
797         } else {
798             "".to_owned()
799         };
800         self.result.push(ParsedMacroArg {
801             kind: MacroArgKind::Separator(self.buf.clone(), prefix),
802             span: mk_sp(self.lo, self.hi),
803         });
804         self.buf.clear();
805     }
806
807     fn add_other(&mut self) {
808         let prefix = if self.need_space_prefix() {
809             " ".to_owned()
810         } else {
811             "".to_owned()
812         };
813         self.result.push(ParsedMacroArg {
814             kind: MacroArgKind::Other(self.buf.clone(), prefix),
815             span: mk_sp(self.lo, self.hi),
816         });
817         self.buf.clear();
818     }
819
820     fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> {
821         match iter.next() {
822             Some(TokenTree::Token(sp, Token::Ident(ref ident, _))) => {
823                 self.result.push(ParsedMacroArg {
824                     kind: MacroArgKind::MetaVariable(*ident, self.buf.clone()),
825                     span: mk_sp(self.lo, sp.hi()),
826                 });
827
828                 self.buf.clear();
829                 self.is_meta_var = false;
830                 Some(())
831             }
832             _ => None,
833         }
834     }
835
836     fn add_delimited(&mut self, inner: Vec<ParsedMacroArg>, delim: DelimToken, span: Span) {
837         self.result.push(ParsedMacroArg {
838             kind: MacroArgKind::Delimited(delim, inner),
839             span,
840         });
841     }
842
843     // $($foo: expr),?
844     fn add_repeat(
845         &mut self,
846         inner: Vec<ParsedMacroArg>,
847         delim: DelimToken,
848         iter: &mut Cursor,
849         span: Span,
850     ) -> Option<()> {
851         let mut buffer = String::new();
852         let mut first = false;
853         let mut lo = span.lo();
854         let mut hi = span.hi();
855
856         // Parse '*', '+' or '?.
857         for tok in iter {
858             self.set_last_tok(&tok);
859             if first {
860                 first = false;
861                 lo = tok.span().lo();
862             }
863
864             match tok {
865                 TokenTree::Token(_, Token::BinOp(BinOpToken::Plus))
866                 | TokenTree::Token(_, Token::Question)
867                 | TokenTree::Token(_, Token::BinOp(BinOpToken::Star)) => {
868                     break;
869                 }
870                 TokenTree::Token(sp, ref t) => {
871                     buffer.push_str(&pprust::token_to_string(t));
872                     hi = sp.hi();
873                 }
874                 _ => return None,
875             }
876         }
877
878         // There could be some random stuff between ')' and '*', '+' or '?'.
879         let another = if buffer.trim().is_empty() {
880             None
881         } else {
882             Some(Box::new(ParsedMacroArg {
883                 kind: MacroArgKind::Other(buffer, "".to_owned()),
884                 span: mk_sp(lo, hi),
885             }))
886         };
887
888         self.result.push(ParsedMacroArg {
889             kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()),
890             span: mk_sp(self.lo, self.hi),
891         });
892         Some(())
893     }
894
895     fn update_buffer(&mut self, lo: BytePos, t: &Token) {
896         if self.buf.is_empty() {
897             self.lo = lo;
898             self.start_tok = t.clone();
899         } else {
900             let needs_space = match next_space(&self.last_tok) {
901                 SpaceState::Ident => ident_like(t),
902                 SpaceState::Punctuation => !ident_like(t),
903                 SpaceState::Always => true,
904                 SpaceState::Never => false,
905             };
906             if force_space_before(t) || needs_space {
907                 self.buf.push(' ');
908             }
909         }
910
911         self.buf.push_str(&pprust::token_to_string(t));
912     }
913
914     fn need_space_prefix(&self) -> bool {
915         if self.result.is_empty() {
916             return false;
917         }
918
919         let last_arg = self.result.last().unwrap();
920         if let MacroArgKind::MetaVariable(..) = last_arg.kind {
921             if ident_like(&self.start_tok) {
922                 return true;
923             }
924             if self.start_tok == Token::Colon {
925                 return true;
926             }
927         }
928
929         if force_space_before(&self.start_tok) {
930             return true;
931         }
932
933         false
934     }
935
936     /// Returns a collection of parsed macro def's arguments.
937     pub fn parse(mut self, tokens: TokenStream) -> Option<Vec<ParsedMacroArg>> {
938         let stream: TokenStream = tokens.into();
939         let mut iter = stream.trees();
940
941         while let Some(tok) = iter.next() {
942             match tok {
943                 TokenTree::Token(sp, Token::Dollar) => {
944                     // We always want to add a separator before meta variables.
945                     if !self.buf.is_empty() {
946                         self.add_separator();
947                     }
948
949                     // Start keeping the name of this metavariable in the buffer.
950                     self.is_meta_var = true;
951                     self.lo = sp.lo();
952                     self.start_tok = Token::Dollar;
953                 }
954                 TokenTree::Token(_, Token::Colon) if self.is_meta_var => {
955                     self.add_meta_variable(&mut iter)?;
956                 }
957                 TokenTree::Token(sp, ref t) => self.update_buffer(sp.lo(), t),
958                 TokenTree::Delimited(delimited_span, delimited, ref tts) => {
959                     if !self.buf.is_empty() {
960                         if next_space(&self.last_tok) == SpaceState::Always {
961                             self.add_separator();
962                         } else {
963                             self.add_other();
964                         }
965                     }
966
967                     // Parse the stuff inside delimiters.
968                     let mut parser = MacroArgParser::new();
969                     parser.lo = delimited_span.open.lo();
970                     let delimited_arg = parser.parse(tts.clone())?;
971
972                     let span = delimited_span.entire();
973                     if self.is_meta_var {
974                         self.add_repeat(delimited_arg, delimited, &mut iter, span)?;
975                         self.is_meta_var = false;
976                     } else {
977                         self.add_delimited(delimited_arg, delimited, span);
978                     }
979                 }
980             }
981
982             self.set_last_tok(&tok);
983         }
984
985         // We are left with some stuff in the buffer. Since there is nothing
986         // left to separate, add this as `Other`.
987         if !self.buf.is_empty() {
988             self.add_other();
989         }
990
991         Some(self.result)
992     }
993 }
994
995 fn wrap_macro_args(
996     context: &RewriteContext<'_>,
997     args: &[ParsedMacroArg],
998     shape: Shape,
999 ) -> Option<String> {
1000     wrap_macro_args_inner(context, args, shape, false)
1001         .or_else(|| wrap_macro_args_inner(context, args, shape, true))
1002 }
1003
1004 fn wrap_macro_args_inner(
1005     context: &RewriteContext<'_>,
1006     args: &[ParsedMacroArg],
1007     shape: Shape,
1008     use_multiple_lines: bool,
1009 ) -> Option<String> {
1010     let mut result = String::with_capacity(128);
1011     let mut iter = args.iter().peekable();
1012     let indent_str = shape.indent.to_string_with_newline(context.config);
1013
1014     while let Some(ref arg) = iter.next() {
1015         result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?);
1016
1017         if use_multiple_lines
1018             && (arg.kind.ends_with_space() || iter.peek().map_or(false, |a| a.kind.has_meta_var()))
1019         {
1020             if arg.kind.ends_with_space() {
1021                 result.pop();
1022             }
1023             result.push_str(&indent_str);
1024         } else if let Some(ref next_arg) = iter.peek() {
1025             let space_before_dollar =
1026                 !arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar();
1027             let space_before_brace = next_arg.kind.starts_with_brace();
1028             if space_before_dollar || space_before_brace {
1029                 result.push(' ');
1030             }
1031         }
1032     }
1033
1034     if !use_multiple_lines && result.len() >= shape.width {
1035         None
1036     } else {
1037         Some(result)
1038     }
1039 }
1040
1041 // This is a bit sketchy. The token rules probably need tweaking, but it works
1042 // for some common cases. I hope the basic logic is sufficient. Note that the
1043 // meaning of some tokens is a bit different here from usual Rust, e.g., `*`
1044 // and `(`/`)` have special meaning.
1045 //
1046 // We always try and format on one line.
1047 // FIXME: Use multi-line when every thing does not fit on one line.
1048 fn format_macro_args(
1049     context: &RewriteContext<'_>,
1050     toks: TokenStream,
1051     shape: Shape,
1052 ) -> Option<String> {
1053     if !context.config.format_macro_matchers() {
1054         let token_stream: TokenStream = toks.into();
1055         let span = span_for_token_stream(&token_stream);
1056         return Some(match span {
1057             Some(span) => context.snippet(span).to_owned(),
1058             None => String::new(),
1059         });
1060     }
1061     let parsed_args = MacroArgParser::new().parse(toks)?;
1062     wrap_macro_args(context, &parsed_args, shape)
1063 }
1064
1065 fn span_for_token_stream(token_stream: &TokenStream) -> Option<Span> {
1066     token_stream.trees().next().map(|tt| tt.span())
1067 }
1068
1069 // We should insert a space if the next token is a:
1070 #[derive(Copy, Clone, PartialEq)]
1071 enum SpaceState {
1072     Never,
1073     Punctuation,
1074     Ident, // Or ident/literal-like thing.
1075     Always,
1076 }
1077
1078 fn force_space_before(tok: &Token) -> bool {
1079     debug!("tok: force_space_before {:?}", tok);
1080
1081     match tok {
1082         Token::Eq
1083         | Token::Lt
1084         | Token::Le
1085         | Token::EqEq
1086         | Token::Ne
1087         | Token::Ge
1088         | Token::Gt
1089         | Token::AndAnd
1090         | Token::OrOr
1091         | Token::Not
1092         | Token::Tilde
1093         | Token::BinOpEq(_)
1094         | Token::At
1095         | Token::RArrow
1096         | Token::LArrow
1097         | Token::FatArrow
1098         | Token::BinOp(_)
1099         | Token::Pound
1100         | Token::Dollar => true,
1101         _ => false,
1102     }
1103 }
1104
1105 fn ident_like(tok: &Token) -> bool {
1106     match tok {
1107         Token::Ident(..) | Token::Literal(..) | Token::Lifetime(_) => true,
1108         _ => false,
1109     }
1110 }
1111
1112 fn next_space(tok: &Token) -> SpaceState {
1113     debug!("next_space: {:?}", tok);
1114
1115     match tok {
1116         Token::Not
1117         | Token::BinOp(BinOpToken::And)
1118         | Token::Tilde
1119         | Token::At
1120         | Token::Comma
1121         | Token::Dot
1122         | Token::DotDot
1123         | Token::DotDotDot
1124         | Token::DotDotEq
1125         | Token::Question => SpaceState::Punctuation,
1126
1127         Token::ModSep
1128         | Token::Pound
1129         | Token::Dollar
1130         | Token::OpenDelim(_)
1131         | Token::CloseDelim(_)
1132         | Token::Whitespace => SpaceState::Never,
1133
1134         Token::Literal(..) | Token::Ident(..) | Token::Lifetime(_) => SpaceState::Ident,
1135
1136         _ => SpaceState::Always,
1137     }
1138 }
1139
1140 /// Tries to convert a macro use into a short hand try expression. Returns `None`
1141 /// when the macro is not an instance of `try!` (or parsing the inner expression
1142 /// failed).
1143 pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option<ast::Expr> {
1144     if &mac.node.path.to_string() == "try" {
1145         let ts: TokenStream = mac.node.tts.clone().into();
1146         let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());
1147
1148         Some(ast::Expr {
1149             id: ast::NodeId::root(), // dummy value
1150             node: ast::ExprKind::Try(parser.parse_expr().ok()?),
1151             span: mac.span, // incorrect span, but shouldn't matter too much
1152             attrs: ThinVec::new(),
1153         })
1154     } else {
1155         None
1156     }
1157 }
1158
1159 fn macro_style(mac: &ast::Mac, context: &RewriteContext<'_>) -> DelimToken {
1160     let snippet = context.snippet(mac.span);
1161     let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value());
1162     let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value());
1163     let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value());
1164
1165     if paren_pos < bracket_pos && paren_pos < brace_pos {
1166         DelimToken::Paren
1167     } else if bracket_pos < brace_pos {
1168         DelimToken::Bracket
1169     } else {
1170         DelimToken::Brace
1171     }
1172 }
1173
1174 // A very simple parser that just parses a macros 2.0 definition into its branches.
1175 // Currently we do not attempt to parse any further than that.
1176 #[derive(new)]
1177 struct MacroParser {
1178     toks: Cursor,
1179 }
1180
1181 impl MacroParser {
1182     // (`(` ... `)` `=>` `{` ... `}`)*
1183     fn parse(&mut self) -> Option<Macro> {
1184         let mut branches = vec![];
1185         while self.toks.look_ahead(1).is_some() {
1186             branches.push(self.parse_branch()?);
1187         }
1188
1189         Some(Macro { branches })
1190     }
1191
1192     // `(` ... `)` `=>` `{` ... `}`
1193     fn parse_branch(&mut self) -> Option<MacroBranch> {
1194         let tok = self.toks.next()?;
1195         let (lo, args_paren_kind) = match tok {
1196             TokenTree::Token(..) => return None,
1197             TokenTree::Delimited(delimited_span, d, _) => (delimited_span.open.lo(), d),
1198         };
1199         let args = tok.joint().into();
1200         match self.toks.next()? {
1201             TokenTree::Token(_, Token::FatArrow) => {}
1202             _ => return None,
1203         }
1204         let (mut hi, body, whole_body) = match self.toks.next()? {
1205             TokenTree::Token(..) => return None,
1206             TokenTree::Delimited(delimited_span, ..) => {
1207                 let data = delimited_span.entire().data();
1208                 (
1209                     data.hi,
1210                     Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt),
1211                     delimited_span.entire(),
1212                 )
1213             }
1214         };
1215         if let Some(TokenTree::Token(sp, Token::Semi)) = self.toks.look_ahead(0) {
1216             self.toks.next();
1217             hi = sp.hi();
1218         }
1219         Some(MacroBranch {
1220             span: mk_sp(lo, hi),
1221             args_paren_kind,
1222             args,
1223             body,
1224             whole_body,
1225         })
1226     }
1227 }
1228
1229 // A parsed macros 2.0 macro definition.
1230 struct Macro {
1231     branches: Vec<MacroBranch>,
1232 }
1233
1234 // FIXME: it would be more efficient to use references to the token streams
1235 // rather than clone them, if we can make the borrowing work out.
1236 struct MacroBranch {
1237     span: Span,
1238     args_paren_kind: DelimToken,
1239     args: TokenStream,
1240     body: Span,
1241     whole_body: Span,
1242 }
1243
1244 impl MacroBranch {
1245     fn rewrite(
1246         &self,
1247         context: &RewriteContext<'_>,
1248         shape: Shape,
1249         multi_branch_style: bool,
1250     ) -> Option<String> {
1251         // Only attempt to format function-like macros.
1252         if self.args_paren_kind != DelimToken::Paren {
1253             // FIXME(#1539): implement for non-sugared macros.
1254             return None;
1255         }
1256
1257         // 5 = " => {"
1258         let mut result = format_macro_args(context, self.args.clone(), shape.sub_width(5)?)?;
1259
1260         if multi_branch_style {
1261             result += " =>";
1262         }
1263
1264         if !context.config.format_macro_bodies() {
1265             result += " ";
1266             result += context.snippet(self.whole_body);
1267             return Some(result);
1268         }
1269
1270         // The macro body is the most interesting part. It might end up as various
1271         // AST nodes, but also has special variables (e.g, `$foo`) which can't be
1272         // parsed as regular Rust code (and note that these can be escaped using
1273         // `$$`). We'll try and format like an AST node, but we'll substitute
1274         // variables for new names with the same length first.
1275
1276         let old_body = context.snippet(self.body).trim();
1277         let (body_str, substs) = replace_names(old_body)?;
1278         let has_block_body = old_body.starts_with('{');
1279
1280         let mut config = context.config.clone();
1281         config.set().hide_parse_errors(true);
1282
1283         result += " {";
1284
1285         let body_indent = if has_block_body {
1286             shape.indent
1287         } else {
1288             shape.indent.block_indent(&config)
1289         };
1290         let new_width = config.max_width() - body_indent.width();
1291         config.set().max_width(new_width);
1292
1293         // First try to format as items, then as statements.
1294         let new_body_snippet = match crate::format_snippet(&body_str, &config) {
1295             Some(new_body) => new_body,
1296             None => {
1297                 let new_width = new_width + config.tab_spaces();
1298                 config.set().max_width(new_width);
1299                 match crate::format_code_block(&body_str, &config) {
1300                     Some(new_body) => new_body,
1301                     None => return None,
1302                 }
1303             }
1304         };
1305         let new_body = wrap_str(
1306             new_body_snippet.snippet.to_string(),
1307             config.max_width(),
1308             shape,
1309         )?;
1310
1311         // Indent the body since it is in a block.
1312         let indent_str = body_indent.to_string(&config);
1313         let mut new_body = LineClasses::new(new_body.trim_end())
1314             .enumerate()
1315             .fold(
1316                 (String::new(), true),
1317                 |(mut s, need_indent), (i, (kind, ref l))| {
1318                     if !is_empty_line(l)
1319                         && need_indent
1320                         && !new_body_snippet.is_line_non_formatted(i + 1)
1321                     {
1322                         s += &indent_str;
1323                     }
1324                     (s + l + "\n", indent_next_line(kind, &l, &config))
1325                 },
1326             )
1327             .0;
1328
1329         // Undo our replacement of macro variables.
1330         // FIXME: this could be *much* more efficient.
1331         for (old, new) in &substs {
1332             if old_body.find(new).is_some() {
1333                 debug!("rewrite_macro_def: bailing matching variable: `{}`", new);
1334                 return None;
1335             }
1336             new_body = new_body.replace(new, old);
1337         }
1338
1339         if has_block_body {
1340             result += new_body.trim();
1341         } else if !new_body.is_empty() {
1342             result += "\n";
1343             result += &new_body;
1344             result += &shape.indent.to_string(&config);
1345         }
1346
1347         result += "}";
1348
1349         Some(result)
1350     }
1351 }
1352
1353 /// Format `lazy_static!` from https://crates.io/crates/lazy_static.
1354 ///
1355 /// # Expected syntax
1356 ///
1357 /// ```ignore
1358 /// lazy_static! {
1359 ///     [pub] static ref NAME_1: TYPE_1 = EXPR_1;
1360 ///     [pub] static ref NAME_2: TYPE_2 = EXPR_2;
1361 ///     ...
1362 ///     [pub] static ref NAME_N: TYPE_N = EXPR_N;
1363 /// }
1364 /// ```
1365 fn format_lazy_static(
1366     context: &RewriteContext<'_>,
1367     shape: Shape,
1368     ts: &TokenStream,
1369 ) -> Option<String> {
1370     let mut result = String::with_capacity(1024);
1371     let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());
1372     let nested_shape = shape
1373         .block_indent(context.config.tab_spaces())
1374         .with_max_width(context.config);
1375
1376     result.push_str("lazy_static! {");
1377     result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
1378
1379     macro_rules! parse_or {
1380         ($method:ident $(,)* $($arg:expr),* $(,)*) => {
1381             match parser.$method($($arg,)*) {
1382                 Ok(val) => {
1383                     if parser.sess.span_diagnostic.has_errors() {
1384                         parser.sess.span_diagnostic.reset_err_count();
1385                         return None;
1386                     } else {
1387                         val
1388                     }
1389                 }
1390                 Err(mut err) => {
1391                     err.cancel();
1392                     parser.sess.span_diagnostic.reset_err_count();
1393                     return None;
1394                 }
1395             }
1396         }
1397     }
1398
1399     while parser.token != Token::Eof {
1400         // Parse a `lazy_static!` item.
1401         let vis = crate::utils::format_visibility(context, &parse_or!(parse_visibility, false));
1402         parser.eat_keyword(keywords::Static);
1403         parser.eat_keyword(keywords::Ref);
1404         let id = parse_or!(parse_ident);
1405         parser.eat(&Token::Colon);
1406         let ty = parse_or!(parse_ty);
1407         parser.eat(&Token::Eq);
1408         let expr = parse_or!(parse_expr);
1409         parser.eat(&Token::Semi);
1410
1411         // Rewrite as a static item.
1412         let mut stmt = String::with_capacity(128);
1413         stmt.push_str(&format!(
1414             "{}static ref {}: {} =",
1415             vis,
1416             id,
1417             ty.rewrite(context, nested_shape)?
1418         ));
1419         result.push_str(&crate::expr::rewrite_assign_rhs(
1420             context,
1421             stmt,
1422             &*expr,
1423             nested_shape.sub_width(1)?,
1424         )?);
1425         result.push(';');
1426         if parser.token != Token::Eof {
1427             result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
1428         }
1429     }
1430
1431     result.push_str(&shape.indent.to_string_with_newline(context.config));
1432     result.push('}');
1433
1434     Some(result)
1435 }
1436
1437 fn rewrite_macro_with_items(
1438     context: &RewriteContext<'_>,
1439     items: &[MacroArg],
1440     macro_name: &str,
1441     shape: Shape,
1442     style: DelimToken,
1443     position: MacroPosition,
1444     span: Span,
1445 ) -> Option<String> {
1446     let (opener, closer) = match style {
1447         DelimToken::Paren => ("(", ")"),
1448         DelimToken::Bracket => ("[", "]"),
1449         DelimToken::Brace => (" {", "}"),
1450         _ => return None,
1451     };
1452     let trailing_semicolon = match style {
1453         DelimToken::Paren | DelimToken::Bracket if position == MacroPosition::Item => ";",
1454         _ => "",
1455     };
1456
1457     let mut visitor = FmtVisitor::from_context(context);
1458     visitor.block_indent = shape.indent.block_indent(context.config);
1459     visitor.last_pos = context.snippet_provider.span_after(span, opener.trim());
1460     for item in items {
1461         let item = match item {
1462             MacroArg::Item(item) => item,
1463             _ => return None,
1464         };
1465         visitor.visit_item(&item);
1466     }
1467
1468     let mut result = String::with_capacity(256);
1469     result.push_str(&macro_name);
1470     result.push_str(opener);
1471     result.push_str(&visitor.block_indent.to_string_with_newline(context.config));
1472     result.push_str(visitor.buffer.trim());
1473     result.push_str(&shape.indent.to_string_with_newline(context.config));
1474     result.push_str(closer);
1475     result.push_str(trailing_semicolon);
1476     Some(result)
1477 }
1478
1479 const RUST_KEYWORDS: [keywords::Keyword; 60] = [
1480     keywords::PathRoot,
1481     keywords::DollarCrate,
1482     keywords::Underscore,
1483     keywords::As,
1484     keywords::Box,
1485     keywords::Break,
1486     keywords::Const,
1487     keywords::Continue,
1488     keywords::Crate,
1489     keywords::Else,
1490     keywords::Enum,
1491     keywords::Extern,
1492     keywords::False,
1493     keywords::Fn,
1494     keywords::For,
1495     keywords::If,
1496     keywords::Impl,
1497     keywords::In,
1498     keywords::Let,
1499     keywords::Loop,
1500     keywords::Match,
1501     keywords::Mod,
1502     keywords::Move,
1503     keywords::Mut,
1504     keywords::Pub,
1505     keywords::Ref,
1506     keywords::Return,
1507     keywords::SelfLower,
1508     keywords::SelfUpper,
1509     keywords::Static,
1510     keywords::Struct,
1511     keywords::Super,
1512     keywords::Trait,
1513     keywords::True,
1514     keywords::Type,
1515     keywords::Unsafe,
1516     keywords::Use,
1517     keywords::Where,
1518     keywords::While,
1519     keywords::Abstract,
1520     keywords::Become,
1521     keywords::Do,
1522     keywords::Final,
1523     keywords::Macro,
1524     keywords::Override,
1525     keywords::Priv,
1526     keywords::Typeof,
1527     keywords::Unsized,
1528     keywords::Virtual,
1529     keywords::Yield,
1530     keywords::Dyn,
1531     keywords::Async,
1532     keywords::Try,
1533     keywords::UnderscoreLifetime,
1534     keywords::StaticLifetime,
1535     keywords::Auto,
1536     keywords::Catch,
1537     keywords::Default,
1538     keywords::Existential,
1539     keywords::Union,
1540 ];