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