1 use crate::algorithm::Printer;
2 use crate::path::PathKind;
3 use crate::token::Token;
4 use crate::INDENT;
5 use proc_macro2::{Delimiter, Spacing, TokenStream};
6 use syn::{Ident, Macro, MacroDelimiter};
7 
8 impl Printer {
mac(&mut self, mac: &Macro, ident: Option<&Ident>, semicolon: bool)9     pub fn mac(&mut self, mac: &Macro, ident: Option<&Ident>, semicolon: bool) {
10         if mac.path.is_ident("macro_rules") {
11             if let Some(ident) = ident {
12                 self.macro_rules(ident, &mac.tokens);
13                 return;
14             }
15         }
16         #[cfg(feature = "verbatim")]
17         if ident.is_none() && self.standard_library_macro(mac, semicolon) {
18             return;
19         }
20         self.path(&mac.path, PathKind::Simple);
21         self.word("!");
22         if let Some(ident) = ident {
23             self.nbsp();
24             self.ident(ident);
25         }
26         let (open, close, delimiter_break) = match mac.delimiter {
27             MacroDelimiter::Paren(_) => ("(", ")", Self::zerobreak as fn(&mut Self)),
28             MacroDelimiter::Brace(_) => (" {", "}", Self::hardbreak as fn(&mut Self)),
29             MacroDelimiter::Bracket(_) => ("[", "]", Self::zerobreak as fn(&mut Self)),
30         };
31         self.word(open);
32         if !mac.tokens.is_empty() {
33             self.cbox(INDENT);
34             delimiter_break(self);
35             self.ibox(0);
36             self.macro_rules_tokens(mac.tokens.clone(), false);
37             self.end();
38             delimiter_break(self);
39             self.offset(-INDENT);
40             self.end();
41         }
42         self.word(close);
43         if semicolon {
44             match mac.delimiter {
45                 MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => self.word(";"),
46                 MacroDelimiter::Brace(_) => {}
47             }
48         }
49     }
50 
macro_rules(&mut self, name: &Ident, rules: &TokenStream)51     fn macro_rules(&mut self, name: &Ident, rules: &TokenStream) {
52         enum State {
53             Start,
54             Matcher,
55             Equal,
56             Greater,
57             Expander,
58         }
59 
60         use State::*;
61 
62         self.word("macro_rules! ");
63         self.ident(name);
64         self.word(" {");
65         self.cbox(INDENT);
66         self.hardbreak_if_nonempty();
67         let mut state = State::Start;
68         for tt in rules.clone() {
69             let token = Token::from(tt);
70             match (state, token) {
71                 (Start, Token::Group(delimiter, stream)) => {
72                     self.delimiter_open(delimiter);
73                     if !stream.is_empty() {
74                         self.cbox(INDENT);
75                         self.zerobreak();
76                         self.ibox(0);
77                         self.macro_rules_tokens(stream, true);
78                         self.end();
79                         self.zerobreak();
80                         self.offset(-INDENT);
81                         self.end();
82                     }
83                     self.delimiter_close(delimiter);
84                     state = Matcher;
85                 }
86                 (Matcher, Token::Punct('=', Spacing::Joint)) => {
87                     self.word(" =");
88                     state = Equal;
89                 }
90                 (Equal, Token::Punct('>', Spacing::Alone)) => {
91                     self.word(">");
92                     state = Greater;
93                 }
94                 (Greater, Token::Group(_delimiter, stream)) => {
95                     self.word(" {");
96                     self.neverbreak();
97                     if !stream.is_empty() {
98                         self.cbox(INDENT);
99                         self.hardbreak();
100                         self.ibox(0);
101                         self.macro_rules_tokens(stream, false);
102                         self.end();
103                         self.hardbreak();
104                         self.offset(-INDENT);
105                         self.end();
106                     }
107                     self.word("}");
108                     state = Expander;
109                 }
110                 (Expander, Token::Punct(';', Spacing::Alone)) => {
111                     self.word(";");
112                     self.hardbreak();
113                     state = Start;
114                 }
115                 _ => unimplemented!("bad macro_rules syntax"),
116             }
117         }
118         match state {
119             Start => {}
120             Expander => {
121                 self.word(";");
122                 self.hardbreak();
123             }
124             _ => self.hardbreak(),
125         }
126         self.offset(-INDENT);
127         self.end();
128         self.word("}");
129     }
130 
macro_rules_tokens(&mut self, stream: TokenStream, matcher: bool)131     pub fn macro_rules_tokens(&mut self, stream: TokenStream, matcher: bool) {
132         #[derive(PartialEq)]
133         enum State {
134             Start,
135             Dollar,
136             DollarIdent,
137             DollarIdentColon,
138             DollarParen,
139             DollarParenSep,
140             Pound,
141             PoundBang,
142             Dot,
143             Colon,
144             Colon2,
145             Ident,
146             IdentBang,
147             Delim,
148             Other,
149         }
150 
151         use State::*;
152 
153         let mut state = Start;
154         let mut previous_is_joint = true;
155         for tt in stream {
156             let token = Token::from(tt);
157             let (needs_space, next_state) = match (&state, &token) {
158                 (Dollar, Token::Ident(_)) => (false, if matcher { DollarIdent } else { Other }),
159                 (DollarIdent, Token::Punct(':', Spacing::Alone)) => (false, DollarIdentColon),
160                 (DollarIdentColon, Token::Ident(_)) => (false, Other),
161                 (DollarParen, Token::Punct('+' | '*' | '?', Spacing::Alone)) => (false, Other),
162                 (DollarParen, Token::Ident(_) | Token::Literal(_)) => (false, DollarParenSep),
163                 (DollarParen, Token::Punct(_, Spacing::Joint)) => (false, DollarParen),
164                 (DollarParen, Token::Punct(_, Spacing::Alone)) => (false, DollarParenSep),
165                 (DollarParenSep, Token::Punct('+' | '*', _)) => (false, Other),
166                 (Pound, Token::Punct('!', _)) => (false, PoundBang),
167                 (Dollar, Token::Group(Delimiter::Parenthesis, _)) => (false, DollarParen),
168                 (Pound | PoundBang, Token::Group(Delimiter::Bracket, _)) => (false, Other),
169                 (Ident, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => {
170                     (false, Delim)
171                 }
172                 (Ident, Token::Punct('!', Spacing::Alone)) => (false, IdentBang),
173                 (IdentBang, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => {
174                     (false, Other)
175                 }
176                 (Colon, Token::Punct(':', _)) => (false, Colon2),
177                 (_, Token::Group(Delimiter::Parenthesis | Delimiter::Bracket, _)) => (true, Delim),
178                 (_, Token::Group(Delimiter::Brace | Delimiter::None, _)) => (true, Other),
179                 (_, Token::Ident(ident)) if !is_keyword(ident) => {
180                     (state != Dot && state != Colon2, Ident)
181                 }
182                 (_, Token::Literal(_)) => (state != Dot, Ident),
183                 (_, Token::Punct(',' | ';', _)) => (false, Other),
184                 (_, Token::Punct('.', _)) if !matcher => (state != Ident && state != Delim, Dot),
185                 (_, Token::Punct(':', Spacing::Joint)) => (state != Ident, Colon),
186                 (_, Token::Punct('$', _)) => (true, Dollar),
187                 (_, Token::Punct('#', _)) => (true, Pound),
188                 (_, _) => (true, Other),
189             };
190             if !previous_is_joint {
191                 if needs_space {
192                     self.space();
193                 } else if let Token::Punct('.', _) = token {
194                     self.zerobreak();
195                 }
196             }
197             previous_is_joint = match token {
198                 Token::Punct(_, Spacing::Joint) | Token::Punct('$', _) => true,
199                 _ => false,
200             };
201             self.single_token(
202                 token,
203                 if matcher {
204                     |printer, stream| printer.macro_rules_tokens(stream, true)
205                 } else {
206                     |printer, stream| printer.macro_rules_tokens(stream, false)
207                 },
208             );
209             state = next_state;
210         }
211     }
212 }
213 
is_keyword(ident: &Ident) -> bool214 fn is_keyword(ident: &Ident) -> bool {
215     match ident.to_string().as_str() {
216         "as" | "async" | "await" | "box" | "break" | "const" | "continue" | "crate" | "dyn"
217         | "else" | "enum" | "extern" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop"
218         | "macro" | "match" | "mod" | "move" | "mut" | "pub" | "ref" | "return" | "static"
219         | "struct" | "trait" | "type" | "unsafe" | "use" | "where" | "while" | "yield" => true,
220         _ => false,
221     }
222 }
223 
224 #[cfg(feature = "verbatim")]
225 mod standard_library {
226     use crate::algorithm::Printer;
227     use crate::iter::IterDelimited;
228     use crate::path::PathKind;
229     use crate::INDENT;
230     use syn::ext::IdentExt;
231     use syn::parse::{Parse, ParseStream, Parser, Result};
232     use syn::{
233         parenthesized, token, Attribute, Expr, ExprAssign, ExprPath, Ident, Lit, Macro, Pat, Path,
234         Token, Type, Visibility,
235     };
236 
237     enum KnownMacro {
238         Expr(Expr),
239         Exprs(Vec<Expr>),
240         Cfg(Cfg),
241         Matches(Matches),
242         ThreadLocal(Vec<ThreadLocal>),
243         VecArray(Vec<Expr>),
244         VecRepeat { elem: Expr, n: Expr },
245     }
246 
247     enum Cfg {
248         Eq(Ident, Option<Lit>),
249         Call(Ident, Vec<Cfg>),
250     }
251 
252     struct Matches {
253         expression: Expr,
254         pattern: Pat,
255         guard: Option<Expr>,
256     }
257 
258     struct ThreadLocal {
259         attrs: Vec<Attribute>,
260         vis: Visibility,
261         name: Ident,
262         ty: Type,
263         init: Expr,
264     }
265 
266     struct FormatArgs {
267         format_string: Expr,
268         args: Vec<Expr>,
269     }
270 
271     impl Parse for FormatArgs {
parse(input: ParseStream) -> Result<Self>272         fn parse(input: ParseStream) -> Result<Self> {
273             let format_string: Expr = input.parse()?;
274 
275             let mut args = Vec::new();
276             while !input.is_empty() {
277                 input.parse::<Token![,]>()?;
278                 if input.is_empty() {
279                     break;
280                 }
281                 let arg = if input.peek(Ident::peek_any)
282                     && input.peek2(Token![=])
283                     && !input.peek2(Token![==])
284                 {
285                     let key = input.call(Ident::parse_any)?;
286                     let eq_token: Token![=] = input.parse()?;
287                     let value: Expr = input.parse()?;
288                     Expr::Assign(ExprAssign {
289                         attrs: Vec::new(),
290                         left: Box::new(Expr::Path(ExprPath {
291                             attrs: Vec::new(),
292                             qself: None,
293                             path: Path::from(key),
294                         })),
295                         eq_token,
296                         right: Box::new(value),
297                     })
298                 } else {
299                     input.parse()?
300                 };
301                 args.push(arg);
302             }
303 
304             Ok(FormatArgs {
305                 format_string,
306                 args,
307             })
308         }
309     }
310 
311     impl KnownMacro {
parse_expr(input: ParseStream) -> Result<Self>312         fn parse_expr(input: ParseStream) -> Result<Self> {
313             let expr: Expr = input.parse()?;
314             Ok(KnownMacro::Expr(expr))
315         }
316 
parse_expr_comma(input: ParseStream) -> Result<Self>317         fn parse_expr_comma(input: ParseStream) -> Result<Self> {
318             let expr: Expr = input.parse()?;
319             input.parse::<Option<Token![,]>>()?;
320             Ok(KnownMacro::Exprs(vec![expr]))
321         }
322 
parse_exprs(input: ParseStream) -> Result<Self>323         fn parse_exprs(input: ParseStream) -> Result<Self> {
324             let exprs = input.parse_terminated(Expr::parse, Token![,])?;
325             Ok(KnownMacro::Exprs(Vec::from_iter(exprs)))
326         }
327 
parse_assert(input: ParseStream) -> Result<Self>328         fn parse_assert(input: ParseStream) -> Result<Self> {
329             let mut exprs = Vec::new();
330             let cond: Expr = input.parse()?;
331             exprs.push(cond);
332             if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
333                 let format_args: FormatArgs = input.parse()?;
334                 exprs.push(format_args.format_string);
335                 exprs.extend(format_args.args);
336             }
337             Ok(KnownMacro::Exprs(exprs))
338         }
339 
parse_assert_cmp(input: ParseStream) -> Result<Self>340         fn parse_assert_cmp(input: ParseStream) -> Result<Self> {
341             let mut exprs = Vec::new();
342             let left: Expr = input.parse()?;
343             exprs.push(left);
344             input.parse::<Token![,]>()?;
345             let right: Expr = input.parse()?;
346             exprs.push(right);
347             if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
348                 let format_args: FormatArgs = input.parse()?;
349                 exprs.push(format_args.format_string);
350                 exprs.extend(format_args.args);
351             }
352             Ok(KnownMacro::Exprs(exprs))
353         }
354 
parse_cfg(input: ParseStream) -> Result<Self>355         fn parse_cfg(input: ParseStream) -> Result<Self> {
356             fn parse_single(input: ParseStream) -> Result<Cfg> {
357                 let ident: Ident = input.parse()?;
358                 if input.peek(token::Paren) && (ident == "all" || ident == "any") {
359                     let content;
360                     parenthesized!(content in input);
361                     let list = content.call(parse_multiple)?;
362                     Ok(Cfg::Call(ident, list))
363                 } else if input.peek(token::Paren) && ident == "not" {
364                     let content;
365                     parenthesized!(content in input);
366                     let cfg = content.call(parse_single)?;
367                     content.parse::<Option<Token![,]>>()?;
368                     Ok(Cfg::Call(ident, vec![cfg]))
369                 } else if input.peek(Token![=]) {
370                     input.parse::<Token![=]>()?;
371                     let string: Lit = input.parse()?;
372                     Ok(Cfg::Eq(ident, Some(string)))
373                 } else {
374                     Ok(Cfg::Eq(ident, None))
375                 }
376             }
377 
378             fn parse_multiple(input: ParseStream) -> Result<Vec<Cfg>> {
379                 let mut vec = Vec::new();
380                 while !input.is_empty() {
381                     let cfg = input.call(parse_single)?;
382                     vec.push(cfg);
383                     if input.is_empty() {
384                         break;
385                     }
386                     input.parse::<Token![,]>()?;
387                 }
388                 Ok(vec)
389             }
390 
391             let cfg = input.call(parse_single)?;
392             input.parse::<Option<Token![,]>>()?;
393             Ok(KnownMacro::Cfg(cfg))
394         }
395 
parse_env(input: ParseStream) -> Result<Self>396         fn parse_env(input: ParseStream) -> Result<Self> {
397             let mut exprs = Vec::new();
398             let name: Expr = input.parse()?;
399             exprs.push(name);
400             if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
401                 let error_msg: Expr = input.parse()?;
402                 exprs.push(error_msg);
403                 input.parse::<Option<Token![,]>>()?;
404             }
405             Ok(KnownMacro::Exprs(exprs))
406         }
407 
parse_format_args(input: ParseStream) -> Result<Self>408         fn parse_format_args(input: ParseStream) -> Result<Self> {
409             let format_args: FormatArgs = input.parse()?;
410             let mut exprs = format_args.args;
411             exprs.insert(0, format_args.format_string);
412             Ok(KnownMacro::Exprs(exprs))
413         }
414 
parse_matches(input: ParseStream) -> Result<Self>415         fn parse_matches(input: ParseStream) -> Result<Self> {
416             let expression: Expr = input.parse()?;
417             input.parse::<Token![,]>()?;
418             let pattern = input.call(Pat::parse_multi_with_leading_vert)?;
419             let guard = if input.parse::<Option<Token![if]>>()?.is_some() {
420                 Some(input.parse()?)
421             } else {
422                 None
423             };
424             input.parse::<Option<Token![,]>>()?;
425             Ok(KnownMacro::Matches(Matches {
426                 expression,
427                 pattern,
428                 guard,
429             }))
430         }
431 
parse_thread_local(input: ParseStream) -> Result<Self>432         fn parse_thread_local(input: ParseStream) -> Result<Self> {
433             let mut items = Vec::new();
434             while !input.is_empty() {
435                 let attrs = input.call(Attribute::parse_outer)?;
436                 let vis: Visibility = input.parse()?;
437                 input.parse::<Token![static]>()?;
438                 let name: Ident = input.parse()?;
439                 input.parse::<Token![:]>()?;
440                 let ty: Type = input.parse()?;
441                 input.parse::<Token![=]>()?;
442                 let init: Expr = input.parse()?;
443                 if input.is_empty() {
444                     break;
445                 }
446                 input.parse::<Token![;]>()?;
447                 items.push(ThreadLocal {
448                     attrs,
449                     vis,
450                     name,
451                     ty,
452                     init,
453                 });
454             }
455             Ok(KnownMacro::ThreadLocal(items))
456         }
457 
parse_vec(input: ParseStream) -> Result<Self>458         fn parse_vec(input: ParseStream) -> Result<Self> {
459             if input.is_empty() {
460                 return Ok(KnownMacro::VecArray(Vec::new()));
461             }
462             let first: Expr = input.parse()?;
463             if input.parse::<Option<Token![;]>>()?.is_some() {
464                 let len: Expr = input.parse()?;
465                 Ok(KnownMacro::VecRepeat {
466                     elem: first,
467                     n: len,
468                 })
469             } else {
470                 let mut vec = vec![first];
471                 while !input.is_empty() {
472                     input.parse::<Token![,]>()?;
473                     if input.is_empty() {
474                         break;
475                     }
476                     let next: Expr = input.parse()?;
477                     vec.push(next);
478                 }
479                 Ok(KnownMacro::VecArray(vec))
480             }
481         }
482 
parse_write(input: ParseStream) -> Result<Self>483         fn parse_write(input: ParseStream) -> Result<Self> {
484             let mut exprs = Vec::new();
485             let dst: Expr = input.parse()?;
486             exprs.push(dst);
487             input.parse::<Token![,]>()?;
488             let format_args: FormatArgs = input.parse()?;
489             exprs.push(format_args.format_string);
490             exprs.extend(format_args.args);
491             Ok(KnownMacro::Exprs(exprs))
492         }
493 
parse_writeln(input: ParseStream) -> Result<Self>494         fn parse_writeln(input: ParseStream) -> Result<Self> {
495             let mut exprs = Vec::new();
496             let dst: Expr = input.parse()?;
497             exprs.push(dst);
498             if input.parse::<Option<Token![,]>>()?.is_some() && !input.is_empty() {
499                 let format_args: FormatArgs = input.parse()?;
500                 exprs.push(format_args.format_string);
501                 exprs.extend(format_args.args);
502             }
503             Ok(KnownMacro::Exprs(exprs))
504         }
505     }
506 
507     impl Printer {
standard_library_macro(&mut self, mac: &Macro, mut semicolon: bool) -> bool508         pub fn standard_library_macro(&mut self, mac: &Macro, mut semicolon: bool) -> bool {
509             let name = mac.path.segments.last().unwrap().ident.to_string();
510             let parser = match name.as_str() {
511                 "addr_of" | "addr_of_mut" => KnownMacro::parse_expr,
512                 "assert" | "debug_assert" => KnownMacro::parse_assert,
513                 "assert_eq" | "assert_ne" | "debug_assert_eq" | "debug_assert_ne" => {
514                     KnownMacro::parse_assert_cmp
515                 }
516                 "cfg" => KnownMacro::parse_cfg,
517                 "compile_error" | "include" | "include_bytes" | "include_str" | "option_env" => {
518                     KnownMacro::parse_expr_comma
519                 }
520                 "concat" | "concat_bytes" | "dbg" => KnownMacro::parse_exprs,
521                 "const_format_args" | "eprint" | "eprintln" | "format" | "format_args"
522                 | "format_args_nl" | "panic" | "print" | "println" | "todo" | "unimplemented"
523                 | "unreachable" => KnownMacro::parse_format_args,
524                 "env" => KnownMacro::parse_env,
525                 "matches" => KnownMacro::parse_matches,
526                 "thread_local" => KnownMacro::parse_thread_local,
527                 "vec" => KnownMacro::parse_vec,
528                 "write" => KnownMacro::parse_write,
529                 "writeln" => KnownMacro::parse_writeln,
530                 _ => return false,
531             };
532 
533             let known_macro = match parser.parse2(mac.tokens.clone()) {
534                 Ok(known_macro) => known_macro,
535                 Err(_) => return false,
536             };
537 
538             self.path(&mac.path, PathKind::Simple);
539             self.word("!");
540 
541             match &known_macro {
542                 KnownMacro::Expr(expr) => {
543                     self.word("(");
544                     self.cbox(INDENT);
545                     self.zerobreak();
546                     self.expr(expr);
547                     self.zerobreak();
548                     self.offset(-INDENT);
549                     self.end();
550                     self.word(")");
551                 }
552                 KnownMacro::Exprs(exprs) => {
553                     self.word("(");
554                     self.cbox(INDENT);
555                     self.zerobreak();
556                     for elem in exprs.iter().delimited() {
557                         self.expr(&elem);
558                         self.trailing_comma(elem.is_last);
559                     }
560                     self.offset(-INDENT);
561                     self.end();
562                     self.word(")");
563                 }
564                 KnownMacro::Cfg(cfg) => {
565                     self.word("(");
566                     self.cfg(cfg);
567                     self.word(")");
568                 }
569                 KnownMacro::Matches(matches) => {
570                     self.word("(");
571                     self.cbox(INDENT);
572                     self.zerobreak();
573                     self.expr(&matches.expression);
574                     self.word(",");
575                     self.space();
576                     self.pat(&matches.pattern);
577                     if let Some(guard) = &matches.guard {
578                         self.space();
579                         self.word("if ");
580                         self.expr(guard);
581                     }
582                     self.zerobreak();
583                     self.offset(-INDENT);
584                     self.end();
585                     self.word(")");
586                 }
587                 KnownMacro::ThreadLocal(items) => {
588                     self.word(" {");
589                     self.cbox(INDENT);
590                     self.hardbreak_if_nonempty();
591                     for item in items {
592                         self.outer_attrs(&item.attrs);
593                         self.cbox(0);
594                         self.visibility(&item.vis);
595                         self.word("static ");
596                         self.ident(&item.name);
597                         self.word(": ");
598                         self.ty(&item.ty);
599                         self.word(" = ");
600                         self.neverbreak();
601                         self.expr(&item.init);
602                         self.word(";");
603                         self.end();
604                         self.hardbreak();
605                     }
606                     self.offset(-INDENT);
607                     self.end();
608                     self.word("}");
609                     semicolon = false;
610                 }
611                 KnownMacro::VecArray(vec) => {
612                     self.word("[");
613                     self.cbox(INDENT);
614                     self.zerobreak();
615                     for elem in vec.iter().delimited() {
616                         self.expr(&elem);
617                         self.trailing_comma(elem.is_last);
618                     }
619                     self.offset(-INDENT);
620                     self.end();
621                     self.word("]");
622                 }
623                 KnownMacro::VecRepeat { elem, n } => {
624                     self.word("[");
625                     self.cbox(INDENT);
626                     self.zerobreak();
627                     self.expr(elem);
628                     self.word(";");
629                     self.space();
630                     self.expr(n);
631                     self.zerobreak();
632                     self.offset(-INDENT);
633                     self.end();
634                     self.word("]");
635                 }
636             }
637 
638             if semicolon {
639                 self.word(";");
640             }
641 
642             true
643         }
644 
cfg(&mut self, cfg: &Cfg)645         fn cfg(&mut self, cfg: &Cfg) {
646             match cfg {
647                 Cfg::Eq(ident, value) => {
648                     self.ident(ident);
649                     if let Some(value) = value {
650                         self.word(" = ");
651                         self.lit(value);
652                     }
653                 }
654                 Cfg::Call(ident, args) => {
655                     self.ident(ident);
656                     self.word("(");
657                     self.cbox(INDENT);
658                     self.zerobreak();
659                     for arg in args.iter().delimited() {
660                         self.cfg(&arg);
661                         self.trailing_comma(arg.is_last);
662                     }
663                     self.offset(-INDENT);
664                     self.end();
665                     self.word(")");
666                 }
667             }
668         }
669     }
670 }
671