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