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