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