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