]> git.lizzy.rs Git - rust.git/blob - crates/mbe/src/tests/expand.rs
internal: drop duplicated test
[rust.git] / crates / mbe / src / tests / expand.rs
1 use ::parser::ParserEntryPoint;
2 use syntax::{
3     SyntaxKind::{ERROR, IDENT},
4     T,
5 };
6 use test_utils::assert_eq_text;
7
8 use super::*;
9
10 // Good first issue (although a slightly challenging one):
11 //
12 // * Pick a random test from here
13 //   https://github.com/intellij-rust/intellij-rust/blob/c4e9feee4ad46e7953b1948c112533360b6087bb/src/test/kotlin/org/rust/lang/core/macros/RsMacroExpansionTest.kt
14 // * Port the test to rust and add it to this module
15 // * Make it pass :-)
16
17 #[test]
18 fn test_token_id_shift() {
19     let expansion = parse_macro(
20         r#"
21 macro_rules! foobar {
22     ($e:ident) => { foo bar $e }
23 }
24 "#,
25     )
26     .expand_tt("foobar!(baz);");
27
28     fn get_id(t: &tt::TokenTree) -> Option<u32> {
29         if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t {
30             return Some(ident.id.0);
31         }
32         None
33     }
34
35     assert_eq!(expansion.token_trees.len(), 3);
36     // {($e:ident) => { foo bar $e }}
37     // 012345      67 8 9   T   12
38     assert_eq!(get_id(&expansion.token_trees[0]), Some(9));
39     assert_eq!(get_id(&expansion.token_trees[1]), Some(10));
40
41     // The input args of macro call include parentheses:
42     // (baz)
43     // So baz should be 12+1+1
44     assert_eq!(get_id(&expansion.token_trees[2]), Some(14));
45 }
46
47 #[test]
48 fn test_token_map() {
49     let expanded = parse_macro(
50         r#"
51 macro_rules! foobar {
52     ($e:ident) => { fn $e() {} }
53 }
54 "#,
55     )
56     .expand_tt("foobar!(baz);");
57
58     let (node, token_map) = token_tree_to_syntax_node(&expanded, ParserEntryPoint::Items).unwrap();
59     let content = node.syntax_node().to_string();
60
61     let get_text = |id, kind| -> String {
62         content[token_map.first_range_by_token(id, kind).unwrap()].to_string()
63     };
64
65     assert_eq!(expanded.token_trees.len(), 4);
66     // {($e:ident) => { fn $e() {} }}
67     // 012345      67 8 9  T12  3
68
69     assert_eq!(get_text(tt::TokenId(9), IDENT), "fn");
70     assert_eq!(get_text(tt::TokenId(12), T!['(']), "(");
71     assert_eq!(get_text(tt::TokenId(13), T!['{']), "{");
72 }
73
74 fn to_subtree(tt: &tt::TokenTree) -> &tt::Subtree {
75     if let tt::TokenTree::Subtree(subtree) = tt {
76         return subtree;
77     }
78     unreachable!("It is not a subtree");
79 }
80 fn to_literal(tt: &tt::TokenTree) -> &tt::Literal {
81     if let tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) = tt {
82         return lit;
83     }
84     unreachable!("It is not a literal");
85 }
86
87 fn to_punct(tt: &tt::TokenTree) -> &tt::Punct {
88     if let tt::TokenTree::Leaf(tt::Leaf::Punct(lit)) = tt {
89         return lit;
90     }
91     unreachable!("It is not a Punct");
92 }
93
94 #[test]
95 fn test_attr_to_token_tree() {
96     let expansion = parse_to_token_tree_by_syntax(
97         r#"
98             #[derive(Copy)]
99             struct Foo;
100             "#,
101     );
102
103     assert_eq!(to_punct(&expansion.token_trees[0]).char, '#');
104     assert_eq!(
105         to_subtree(&expansion.token_trees[1]).delimiter_kind(),
106         Some(tt::DelimiterKind::Bracket)
107     );
108 }
109
110 #[test]
111 fn test_two_idents() {
112     parse_macro(
113         r#"
114         macro_rules! foo {
115             ($ i:ident, $ j:ident) => {
116                 fn foo() { let a = $ i; let b = $j; }
117             }
118         }
119 "#,
120     )
121     .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}");
122 }
123
124 #[test]
125 fn test_tt_to_stmts() {
126     let stmts = parse_macro(
127         r#"
128         macro_rules! foo {
129             () => {
130                  let a = 0;
131                  a = 10 + 1;
132                  a
133             }
134         }
135 "#,
136     )
137     .expand_statements("foo!{}");
138
139     assert_eq!(
140         format!("{:#?}", stmts).trim(),
141         r#"MACRO_STMTS@0..15
142   LET_STMT@0..7
143     LET_KW@0..3 "let"
144     IDENT_PAT@3..4
145       NAME@3..4
146         IDENT@3..4 "a"
147     EQ@4..5 "="
148     LITERAL@5..6
149       INT_NUMBER@5..6 "0"
150     SEMICOLON@6..7 ";"
151   EXPR_STMT@7..14
152     BIN_EXPR@7..13
153       PATH_EXPR@7..8
154         PATH@7..8
155           PATH_SEGMENT@7..8
156             NAME_REF@7..8
157               IDENT@7..8 "a"
158       EQ@8..9 "="
159       BIN_EXPR@9..13
160         LITERAL@9..11
161           INT_NUMBER@9..11 "10"
162         PLUS@11..12 "+"
163         LITERAL@12..13
164           INT_NUMBER@12..13 "1"
165     SEMICOLON@13..14 ";"
166   PATH_EXPR@14..15
167     PATH@14..15
168       PATH_SEGMENT@14..15
169         NAME_REF@14..15
170           IDENT@14..15 "a""#,
171     );
172 }
173
174 #[test]
175 fn test_match_literal() {
176     parse_macro(
177         r#"
178     macro_rules! foo {
179         ('(') => {
180             fn foo() {}
181         }
182     }
183 "#,
184     )
185     .assert_expand_items("foo! ['('];", "fn foo () {}");
186 }
187
188 #[test]
189 fn test_parse_macro_def_simple() {
190     cov_mark::check!(parse_macro_def_simple);
191
192     parse_macro2(
193         r#"
194 macro foo($id:ident) {
195     fn $id() {}
196 }
197 "#,
198     )
199     .assert_expand_items("foo!(bar);", "fn bar () {}");
200 }
201
202 #[test]
203 fn test_parse_macro_def_rules() {
204     cov_mark::check!(parse_macro_def_rules);
205
206     parse_macro2(
207         r#"
208 macro foo {
209     ($id:ident) => {
210         fn $id() {}
211     }
212 }
213 "#,
214     )
215     .assert_expand_items("foo!(bar);", "fn bar () {}");
216 }
217
218 #[test]
219 fn test_macro_2_0_panic_2015() {
220     parse_macro2(
221         r#"
222 macro panic_2015 {
223     () => (
224     ),
225     (bar) => (
226     ),
227 }
228 "#,
229     )
230     .assert_expand_items("panic_2015!(bar);", "");
231 }
232
233 #[test]
234 fn test_path() {
235     parse_macro(
236         r#"
237         macro_rules! foo {
238             ($ i:path) => {
239                 fn foo() { let a = $ i; }
240             }
241         }
242 "#,
243     )
244     .assert_expand_items("foo! { foo }", "fn foo () {let a = foo ;}")
245     .assert_expand_items(
246         "foo! { bar::<u8>::baz::<u8> }",
247         "fn foo () {let a = bar ::< u8 >:: baz ::< u8 > ;}",
248     );
249 }
250
251 #[test]
252 fn test_two_paths() {
253     parse_macro(
254         r#"
255         macro_rules! foo {
256             ($ i:path, $ j:path) => {
257                 fn foo() { let a = $ i; let b = $j; }
258             }
259         }
260 "#,
261     )
262     .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}");
263 }
264
265 #[test]
266 fn test_path_with_path() {
267     parse_macro(
268         r#"
269         macro_rules! foo {
270             ($ i:path) => {
271                 fn foo() { let a = $ i :: bar; }
272             }
273         }
274 "#,
275     )
276     .assert_expand_items("foo! { foo }", "fn foo () {let a = foo :: bar ;}");
277 }
278
279 #[test]
280 fn test_expr() {
281     parse_macro(
282         r#"
283         macro_rules! foo {
284             ($ i:expr) => {
285                  fn bar() { $ i; }
286             }
287         }
288 "#,
289     )
290     .assert_expand_items(
291         "foo! { 2 + 2 * baz(3).quux() }",
292         "fn bar () {2 + 2 * baz (3) . quux () ;}",
293     );
294 }
295
296 #[test]
297 fn test_last_expr() {
298     parse_macro(
299         r#"
300         macro_rules! vec {
301             ($($item:expr),*) => {
302                 {
303                     let mut v = Vec::new();
304                     $(
305                         v.push($item);
306                     )*
307                     v
308                 }
309             };
310         }
311 "#,
312     )
313     .assert_expand_items(
314         "vec!(1,2,3);",
315         "{let mut v = Vec :: new () ; v . push (1) ; v . push (2) ; v . push (3) ; v}",
316     );
317 }
318
319 #[test]
320 fn test_expr_with_attr() {
321     parse_macro(
322         r#"
323 macro_rules! m {
324     ($a:expr) => {0}
325 }
326 "#,
327     )
328     .assert_expand_items("m!(#[allow(a)]())", "0");
329 }
330
331 #[test]
332 fn test_ty() {
333     parse_macro(
334         r#"
335         macro_rules! foo {
336             ($ i:ty) => (
337                 fn bar() -> $ i { unimplemented!() }
338             )
339         }
340 "#,
341     )
342     .assert_expand_items("foo! { Baz<u8> }", "fn bar () -> Baz < u8 > {unimplemented ! ()}");
343 }
344
345 #[test]
346 fn test_ty_with_complex_type() {
347     parse_macro(
348         r#"
349         macro_rules! foo {
350             ($ i:ty) => (
351                 fn bar() -> $ i { unimplemented!() }
352             )
353         }
354 "#,
355     )
356     // Reference lifetime struct with generic type
357     .assert_expand_items(
358         "foo! { &'a Baz<u8> }",
359         "fn bar () -> & 'a Baz < u8 > {unimplemented ! ()}",
360     )
361     // extern "Rust" func type
362     .assert_expand_items(
363         r#"foo! { extern "Rust" fn() -> Ret }"#,
364         r#"fn bar () -> extern "Rust" fn () -> Ret {unimplemented ! ()}"#,
365     );
366 }
367
368 #[test]
369 fn test_pat_() {
370     parse_macro(
371         r#"
372         macro_rules! foo {
373             ($ i:pat) => { fn foo() { let $ i; } }
374         }
375 "#,
376     )
377     .assert_expand_items("foo! { (a, b) }", "fn foo () {let (a , b) ;}");
378 }
379
380 #[test]
381 fn test_stmt() {
382     parse_macro(
383         r#"
384         macro_rules! foo {
385             ($ i:stmt) => (
386                 fn bar() { $ i; }
387             )
388         }
389 "#,
390     )
391     .assert_expand_items("foo! { 2 }", "fn bar () {2 ;}")
392     .assert_expand_items("foo! { let a = 0 }", "fn bar () {let a = 0 ;}");
393 }
394
395 #[test]
396 fn test_single_item() {
397     parse_macro(
398         r#"
399         macro_rules! foo {
400             ($ i:item) => (
401                 $ i
402             )
403         }
404 "#,
405     )
406     .assert_expand_items("foo! {mod c {}}", "mod c {}");
407 }
408
409 #[test]
410 fn test_all_items() {
411     parse_macro(
412         r#"
413         macro_rules! foo {
414             ($ ($ i:item)*) => ($ (
415                 $ i
416             )*)
417         }
418 "#,
419     ).
420     assert_expand_items(
421         r#"
422         foo! {
423             extern crate a;
424             mod b;
425             mod c {}
426             use d;
427             const E: i32 = 0;
428             static F: i32 = 0;
429             impl G {}
430             struct H;
431             enum I { Foo }
432             trait J {}
433             fn h() {}
434             extern {}
435             type T = u8;
436         }
437 "#,
438         r#"extern crate a ; mod b ; mod c {} use d ; const E : i32 = 0 ; static F : i32 = 0 ; impl G {} struct H ; enum I {Foo} trait J {} fn h () {} extern {} type T = u8 ;"#,
439     );
440 }
441
442 #[test]
443 fn test_block() {
444     parse_macro(
445         r#"
446         macro_rules! foo {
447             ($ i:block) => { fn foo() $ i }
448         }
449 "#,
450     )
451     .assert_expand_statements("foo! { { 1; } }", "fn foo () {1 ;}");
452 }
453
454 #[test]
455 fn test_meta() {
456     parse_macro(
457         r#"
458         macro_rules! foo {
459             ($ i:meta) => (
460                 #[$ i]
461                 fn bar() {}
462             )
463         }
464 "#,
465     )
466     .assert_expand_items(
467         r#"foo! { cfg(target_os = "windows") }"#,
468         r#"# [cfg (target_os = "windows")] fn bar () {}"#,
469     )
470     .assert_expand_items(r#"foo! { hello::world }"#, r#"# [hello :: world] fn bar () {}"#);
471 }
472
473 #[test]
474 fn test_meta_doc_comments() {
475     parse_macro(
476         r#"
477         macro_rules! foo {
478             ($(#[$ i:meta])+) => (
479                 $(#[$ i])+
480                 fn bar() {}
481             )
482         }
483 "#,
484     ).
485     assert_expand_items(
486         r#"foo! {
487             /// Single Line Doc 1
488             /**
489                 MultiLines Doc
490             */
491         }"#,
492         "# [doc = \" Single Line Doc 1\"] # [doc = \"\\n                MultiLines Doc\\n            \"] fn bar () {}",
493     );
494 }
495
496 #[test]
497 fn test_meta_extended_key_value_attributes() {
498     parse_macro(
499         r#"
500 macro_rules! foo {
501     (#[$i:meta]) => (
502         #[$ i]
503         fn bar() {}
504     )
505 }
506 "#,
507     )
508     .assert_expand_items(
509         r#"foo! { #[doc = concat!("The `", "bla", "` lang item.")] }"#,
510         r#"# [doc = concat ! ("The `" , "bla" , "` lang item.")] fn bar () {}"#,
511     );
512 }
513
514 #[test]
515 fn test_meta_doc_comments_non_latin() {
516     parse_macro(
517         r#"
518         macro_rules! foo {
519             ($(#[$ i:meta])+) => (
520                 $(#[$ i])+
521                 fn bar() {}
522             )
523         }
524 "#,
525     ).
526     assert_expand_items(
527         r#"foo! {
528             /// 錦瑟無端五十弦,一弦一柱思華年。
529             /**
530                 莊生曉夢迷蝴蝶,望帝春心託杜鵑。
531             */
532         }"#,
533         "# [doc = \" 錦瑟無端五十弦,一弦一柱思華年。\"] # [doc = \"\\n                莊生曉夢迷蝴蝶,望帝春心託杜鵑。\\n            \"] fn bar () {}",
534     );
535 }
536
537 #[test]
538 fn test_meta_doc_comments_escaped_characters() {
539     parse_macro(
540         r#"
541         macro_rules! foo {
542             ($(#[$ i:meta])+) => (
543                 $(#[$ i])+
544                 fn bar() {}
545             )
546         }
547 "#,
548     )
549     .assert_expand_items(
550         r#"foo! {
551             /// \ " '
552         }"#,
553         r#"# [doc = " \\ \" \'"] fn bar () {}"#,
554     );
555 }
556
557 #[test]
558 fn test_tt_block() {
559     parse_macro(
560         r#"
561             macro_rules! foo {
562                 ($ i:tt) => { fn foo() $ i }
563             }
564     "#,
565     )
566     .assert_expand_items(r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#);
567 }
568
569 #[test]
570 fn test_tt_group() {
571     parse_macro(
572         r#"
573             macro_rules! foo {
574                  ($($ i:tt)*) => { $($ i)* }
575             }
576     "#,
577     )
578     .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#);
579 }
580
581 #[test]
582 fn test_tt_composite() {
583     parse_macro(
584         r#"
585             macro_rules! foo {
586                  ($i:tt) => { 0 }
587             }
588     "#,
589     )
590     .assert_expand_items(r#"foo! { => }"#, r#"0"#);
591 }
592
593 #[test]
594 fn test_tt_composite2() {
595     let node = parse_macro(
596         r#"
597             macro_rules! foo {
598                 ($($tt:tt)*) => { abs!(=> $($tt)*) }
599             }
600     "#,
601     )
602     .expand_items(r#"foo!{#}"#);
603
604     let res = format!("{:#?}", &node);
605     assert_eq_text!(
606         r###"MACRO_ITEMS@0..10
607   MACRO_CALL@0..10
608     PATH@0..3
609       PATH_SEGMENT@0..3
610         NAME_REF@0..3
611           IDENT@0..3 "abs"
612     BANG@3..4 "!"
613     TOKEN_TREE@4..10
614       L_PAREN@4..5 "("
615       EQ@5..6 "="
616       R_ANGLE@6..7 ">"
617       WHITESPACE@7..8 " "
618       POUND@8..9 "#"
619       R_PAREN@9..10 ")""###,
620         res.trim()
621     );
622 }
623
624 #[test]
625 fn test_tt_with_composite_without_space() {
626     parse_macro(
627         r#"
628         macro_rules! foo {
629             ($ op:tt, $j:path) => (
630                 0
631             )
632         }
633 "#,
634     )
635     // Test macro input without any spaces
636     // See https://github.com/rust-analyzer/rust-analyzer/issues/6692
637     .assert_expand_items("foo!(==,Foo::Bool)", "0");
638 }
639
640 #[test]
641 fn test_underscore() {
642     parse_macro(
643         r#"
644             macro_rules! foo {
645                  ($_:tt) => { 0 }
646             }
647     "#,
648     )
649     .assert_expand_items(r#"foo! { => }"#, r#"0"#);
650 }
651
652 #[test]
653 fn test_underscore_not_greedily() {
654     parse_macro(
655         r#"
656 macro_rules! q {
657     ($($a:ident)* _) => {0};
658 }
659 "#,
660     )
661     // `_` overlaps with `$a:ident` but rustc matches it under the `_` token
662     .assert_expand_items(r#"q![a b c d _]"#, r#"0"#);
663
664     parse_macro(
665         r#"
666 macro_rules! q {
667     ($($a:expr => $b:ident)* _ => $c:expr) => {0};
668 }
669 "#,
670     )
671     // `_ => ou` overlaps with `$a:expr => $b:ident` but rustc matches it under `_ => $c:expr`
672     .assert_expand_items(r#"q![a => b c => d _ => ou]"#, r#"0"#);
673 }
674
675 #[test]
676 fn test_underscore_as_type() {
677     parse_macro(
678         r#"
679 macro_rules! q {
680     ($a:ty) => {0};
681 }
682 "#,
683     )
684     // Underscore is a type
685     .assert_expand_items(r#"q![_]"#, r#"0"#);
686 }
687
688 #[test]
689 fn test_underscore_lifetime() {
690     parse_macro(r#"macro_rules! q { ($a:lifetime) => {0}; }"#)
691         .assert_expand_items(r#"q!['_]"#, r#"0"#);
692 }
693
694 #[test]
695 fn test_vertical_bar_with_pat() {
696     parse_macro(
697         r#"
698             macro_rules! foo {
699                  (| $pat:pat | ) => { 0 }
700             }
701     "#,
702     )
703     .assert_expand_items(r#"foo! { | x | }"#, r#"0"#);
704 }
705
706 #[test]
707 fn test_dollar_crate_lhs_is_not_meta() {
708     parse_macro(
709         r#"
710 macro_rules! foo {
711     ($crate) => {};
712     () => {0};
713 }
714     "#,
715     )
716     .assert_expand_items(r#"foo!{}"#, r#"0"#);
717 }
718
719 #[test]
720 fn test_lifetime() {
721     parse_macro(
722         r#"
723         macro_rules! foo {
724               ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } }
725         }
726 "#,
727     )
728     .assert_expand_items(r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#);
729 }
730
731 #[test]
732 fn test_literal() {
733     parse_macro(
734         r#"
735         macro_rules! foo {
736               ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;};
737         }
738 "#,
739     )
740     .assert_expand_items(r#"foo!(u8,0);"#, r#"const VALUE : u8 = 0 ;"#);
741
742     parse_macro(
743         r#"
744         macro_rules! foo {
745               ($ type:ty , $ lit:literal) => { const VALUE: $ type = $ lit;};
746         }
747 "#,
748     )
749     .assert_expand_items(r#"foo!(i32,-1);"#, r#"const VALUE : i32 = - 1 ;"#);
750 }
751
752 #[test]
753 fn test_boolean_is_ident() {
754     parse_macro(
755         r#"
756         macro_rules! foo {
757               ($lit0:literal, $lit1:literal) => { const VALUE: (bool,bool) = ($lit0,$lit1); };
758         }
759 "#,
760     )
761     .assert_expand(
762         r#"foo!(true,false);"#,
763         r#"
764 SUBTREE $
765   IDENT   const 14
766   IDENT   VALUE 15
767   PUNCH   : [alone] 16
768   SUBTREE () 17
769     IDENT   bool 18
770     PUNCH   , [alone] 19
771     IDENT   bool 20
772   PUNCH   = [alone] 21
773   SUBTREE () 22
774     IDENT   true 29
775     PUNCH   , [joint] 25
776     IDENT   false 31
777   PUNCH   ; [alone] 28
778 "#,
779     );
780 }
781
782 #[test]
783 fn test_vis() {
784     parse_macro(
785         r#"
786         macro_rules! foo {
787               ($ vis:vis $ name:ident) => { $ vis fn $ name() {}};
788         }
789 "#,
790     )
791     .assert_expand_items(r#"foo!(pub foo);"#, r#"pub fn foo () {}"#)
792     // test optional cases
793     .assert_expand_items(r#"foo!(foo);"#, r#"fn foo () {}"#);
794 }
795
796 #[test]
797 fn test_inner_macro_rules() {
798     parse_macro(
799         r#"
800 macro_rules! foo {
801     ($a:ident, $b:ident, $c:tt) => {
802
803         macro_rules! bar {
804             ($bi:ident) => {
805                 fn $bi() -> u8 {$c}
806             }
807         }
808
809         bar!($a);
810         fn $b() -> u8 {$c}
811     }
812 }
813 "#,
814     ).
815     assert_expand_items(
816         r#"foo!(x,y, 1);"#,
817         r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#,
818     );
819 }
820
821 #[test]
822 fn test_expr_after_path_colons() {
823     assert!(parse_macro(
824         r#"
825 macro_rules! m {
826     ($k:expr) => {
827             f(K::$k);
828        }
829 }
830 "#,
831     )
832     .expand_statements(r#"m!(C("0"))"#)
833     .descendants()
834     .any(|token| token.kind() == ERROR));
835 }
836
837 #[test]
838 fn test_match_is_not_greedy() {
839     parse_macro(
840         r#"
841 macro_rules! foo {
842     ($($i:ident $(,)*),*) => {};
843 }
844 "#,
845     )
846     .assert_expand_items(r#"foo!(a,b);"#, r#""#);
847 }
848
849 // The following tests are based on real world situations
850 #[test]
851 fn test_vec() {
852     let fixture = parse_macro(
853         r#"
854          macro_rules! vec {
855             ($($item:expr),*) => {
856                 {
857                     let mut v = Vec::new();
858                     $(
859                         v.push($item);
860                     )*
861                     v
862                 }
863             };
864 }
865 "#,
866     );
867     fixture
868         .assert_expand_items(r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#)
869         .assert_expand_items(
870             r#"vec![1u32,2];"#,
871             r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#,
872         );
873
874     let tree = fixture.expand_expr(r#"vec![1u32,2];"#);
875
876     assert_eq_text!(
877         &format!("{:#?}", tree),
878         r#"BLOCK_EXPR@0..45
879   STMT_LIST@0..45
880     L_CURLY@0..1 "{"
881     LET_STMT@1..20
882       LET_KW@1..4 "let"
883       IDENT_PAT@4..8
884         MUT_KW@4..7 "mut"
885         NAME@7..8
886           IDENT@7..8 "v"
887       EQ@8..9 "="
888       CALL_EXPR@9..19
889         PATH_EXPR@9..17
890           PATH@9..17
891             PATH@9..12
892               PATH_SEGMENT@9..12
893                 NAME_REF@9..12
894                   IDENT@9..12 "Vec"
895             COLON2@12..14 "::"
896             PATH_SEGMENT@14..17
897               NAME_REF@14..17
898                 IDENT@14..17 "new"
899         ARG_LIST@17..19
900           L_PAREN@17..18 "("
901           R_PAREN@18..19 ")"
902       SEMICOLON@19..20 ";"
903     EXPR_STMT@20..33
904       METHOD_CALL_EXPR@20..32
905         PATH_EXPR@20..21
906           PATH@20..21
907             PATH_SEGMENT@20..21
908               NAME_REF@20..21
909                 IDENT@20..21 "v"
910         DOT@21..22 "."
911         NAME_REF@22..26
912           IDENT@22..26 "push"
913         ARG_LIST@26..32
914           L_PAREN@26..27 "("
915           LITERAL@27..31
916             INT_NUMBER@27..31 "1u32"
917           R_PAREN@31..32 ")"
918       SEMICOLON@32..33 ";"
919     EXPR_STMT@33..43
920       METHOD_CALL_EXPR@33..42
921         PATH_EXPR@33..34
922           PATH@33..34
923             PATH_SEGMENT@33..34
924               NAME_REF@33..34
925                 IDENT@33..34 "v"
926         DOT@34..35 "."
927         NAME_REF@35..39
928           IDENT@35..39 "push"
929         ARG_LIST@39..42
930           L_PAREN@39..40 "("
931           LITERAL@40..41
932             INT_NUMBER@40..41 "2"
933           R_PAREN@41..42 ")"
934       SEMICOLON@42..43 ";"
935     PATH_EXPR@43..44
936       PATH@43..44
937         PATH_SEGMENT@43..44
938           NAME_REF@43..44
939             IDENT@43..44 "v"
940     R_CURLY@44..45 "}"
941 "#
942     );
943 }
944
945 #[test]
946 fn test_winapi_struct() {
947     // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366
948
949     parse_macro(
950         r#"
951 macro_rules! STRUCT {
952     ($(#[$attrs:meta])* struct $name:ident {
953         $($field:ident: $ftype:ty,)+
954     }) => (
955         #[repr(C)] #[derive(Copy)] $(#[$attrs])*
956         pub struct $name {
957             $(pub $field: $ftype,)+
958         }
959         impl Clone for $name {
960             #[inline]
961             fn clone(&self) -> $name { *self }
962         }
963         #[cfg(feature = "impl-default")]
964         impl Default for $name {
965             #[inline]
966             fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } }
967         }
968     );
969 }
970 "#,
971     ).
972     // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs
973     assert_expand_items(r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#,
974         "# [repr (C)] # [derive (Copy)] pub struct D3DVSHADERCAPS2_0 {pub Caps : u8 ,} impl Clone for D3DVSHADERCAPS2_0 {# [inline] fn clone (& self) -> D3DVSHADERCAPS2_0 {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DVSHADERCAPS2_0 {# [inline] fn default () -> D3DVSHADERCAPS2_0 {unsafe {$crate :: _core :: mem :: zeroed ()}}}"
975     )
976     .assert_expand_items(r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#,
977         "# [repr (C)] # [derive (Copy)] # [cfg_attr (target_arch = \"x86\" , repr (packed))] pub struct D3DCONTENTPROTECTIONCAPS {pub Caps : u8 ,} impl Clone for D3DCONTENTPROTECTIONCAPS {# [inline] fn clone (& self) -> D3DCONTENTPROTECTIONCAPS {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DCONTENTPROTECTIONCAPS {# [inline] fn default () -> D3DCONTENTPROTECTIONCAPS {unsafe {$crate :: _core :: mem :: zeroed ()}}}"
978     );
979 }
980
981 #[test]
982 fn test_int_base() {
983     parse_macro(
984         r#"
985 macro_rules! int_base {
986     ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
987         #[stable(feature = "rust1", since = "1.0.0")]
988         impl fmt::$Trait for $T {
989             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
990                 $Radix.fmt_int(*self as $U, f)
991             }
992         }
993     }
994 }
995 "#,
996     ).assert_expand_items(r#" int_base!{Binary for isize as usize -> Binary}"#,
997         "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt ::Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}"
998     );
999 }
1000
1001 #[test]
1002 fn test_generate_pattern_iterators() {
1003     // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs
1004     parse_macro(
1005         r#"
1006 macro_rules! generate_pattern_iterators {
1007         { double ended; with $(#[$common_stability_attribute:meta])*,
1008                            $forward_iterator:ident,
1009                            $reverse_iterator:ident, $iterty:ty
1010         } => {
1011             fn foo(){}
1012         }
1013 }
1014 "#,
1015     ).assert_expand_items(
1016         r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str );"#,
1017         "fn foo () {}",
1018     );
1019 }
1020
1021 #[test]
1022 fn test_impl_fn_for_zst() {
1023     // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs
1024     parse_macro(
1025         r#"
1026 macro_rules! impl_fn_for_zst  {
1027         {  $( $( #[$attr: meta] )*
1028         struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
1029             |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
1030 $body: block; )+
1031         } => {
1032            $(
1033             $( #[$attr] )*
1034             struct $Name;
1035
1036             impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
1037                 #[inline]
1038                 extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
1039                     $body
1040                 }
1041             }
1042
1043             impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
1044                 #[inline]
1045                 extern "rust-call" fn call_mut(
1046                     &mut self,
1047                     ($( $arg, )*): ($( $ArgTy, )*)
1048                 ) -> $ReturnTy {
1049                     Fn::call(&*self, ($( $arg, )*))
1050                 }
1051             }
1052
1053             impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
1054                 type Output = $ReturnTy;
1055
1056                 #[inline]
1057                 extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
1058                     Fn::call(&self, ($( $arg, )*))
1059                 }
1060             }
1061         )+
1062 }
1063         }
1064 "#,
1065     ).assert_expand_items(r#"
1066 impl_fn_for_zst !   {
1067      # [ derive ( Clone ) ]
1068      struct   CharEscapeDebugContinue   impl   Fn   =   | c :   char |   ->   char :: EscapeDebug   {
1069          c . escape_debug_ext ( false )
1070      } ;
1071
1072      # [ derive ( Clone ) ]
1073      struct   CharEscapeUnicode   impl   Fn   =   | c :   char |   ->   char :: EscapeUnicode   {
1074          c . escape_unicode ( )
1075      } ;
1076      # [ derive ( Clone ) ]
1077      struct   CharEscapeDefault   impl   Fn   =   | c :   char |   ->   char :: EscapeDefault   {
1078          c . escape_default ( )
1079      } ;
1080  }
1081 "#,
1082         "# [derive (Clone)] struct CharEscapeDebugContinue ; impl Fn < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDebug {{c . escape_debug_ext (false)}}} impl FnMut < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDebugContinue {type Output = char :: EscapeDebug ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeUnicode ; impl Fn < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeUnicode {{c . escape_unicode ()}}} impl FnMut < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeUnicode {type Output = char :: EscapeUnicode ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeDefault ; impl Fn < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDefault {{c . escape_default ()}}} impl FnMut < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDefault {type Output = char :: EscapeDefault ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (& self , (c ,))}}"
1083     );
1084 }
1085
1086 #[test]
1087 fn test_impl_nonzero_fmt() {
1088     // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12
1089     parse_macro(
1090         r#"
1091         macro_rules! impl_nonzero_fmt {
1092             ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
1093                 fn foo () {}
1094             }
1095         }
1096 "#,
1097     ).assert_expand_items(
1098         r#"impl_nonzero_fmt! { # [stable(feature= "nonzero",since="1.28.0")] (Debug,Display,Binary,Octal,LowerHex,UpperHex) for NonZeroU8}"#,
1099         "fn foo () {}",
1100     );
1101 }
1102
1103 #[test]
1104 fn test_cfg_if_items() {
1105     // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986
1106     parse_macro(
1107         r#"
1108         macro_rules! __cfg_if_items {
1109             (($($not:meta,)*) ; ) => {};
1110             (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
1111                  __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
1112             }
1113         }
1114 "#,
1115     ).assert_expand_items(
1116         r#"__cfg_if_items ! { ( rustdoc , ) ; ( ( ) ( # [ cfg ( any ( target_os = "redox" , unix ) ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as unix ; # [ cfg ( windows ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as windows ; # [ cfg ( any ( target_os = "linux" , target_os = "l4re" ) ) ] pub mod linux ; ) ) , }"#,
1117         "__cfg_if_items ! {(rustdoc ,) ;}",
1118     );
1119 }
1120
1121 #[test]
1122 fn test_cfg_if_main() {
1123     // from https://github.com/rust-lang/rust/blob/3d211248393686e0f73851fc7548f6605220fbe1/src/libpanic_unwind/macros.rs#L9
1124     parse_macro(
1125         r#"
1126         macro_rules! cfg_if {
1127             ($(
1128                 if #[cfg($($meta:meta),*)] { $($it:item)* }
1129             ) else * else {
1130                 $($it2:item)*
1131             }) => {
1132                 __cfg_if_items! {
1133                     () ;
1134                     $( ( ($($meta),*) ($($it)*) ), )*
1135                     ( () ($($it2)*) ),
1136                 }
1137             };
1138
1139             // Internal macro to Apply a cfg attribute to a list of items
1140             (@__apply $m:meta, $($it:item)*) => {
1141                 $(#[$m] $it)*
1142             };
1143         }
1144 "#,
1145     ).assert_expand_items(r#"
1146 cfg_if !   {
1147      if   # [ cfg ( target_env   =   "msvc" ) ]   {
1148          // no extra unwinder support needed
1149      }   else   if   # [ cfg ( all ( target_arch   =   "wasm32" ,   not ( target_os   =   "emscripten" ) ) ) ]   {
1150          // no unwinder on the system!
1151      }   else   {
1152          mod   libunwind ;
1153          pub   use   libunwind :: * ;
1154      }
1155  }
1156 "#,
1157         "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}"
1158     ).assert_expand_items(
1159         r#"
1160 cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , }
1161 "#,
1162         "",
1163     );
1164 }
1165
1166 #[test]
1167 fn test_proptest_arbitrary() {
1168     // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16
1169     parse_macro(
1170         r#"
1171 macro_rules! arbitrary {
1172     ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty;
1173         $args: ident => $logic: expr) => {
1174         impl<$($bounds)*> $crate::arbitrary::Arbitrary for $typ {
1175             type Parameters = $params;
1176             type Strategy = $strat;
1177             fn arbitrary_with($args: Self::Parameters) -> Self::Strategy {
1178                 $logic
1179             }
1180         }
1181     };
1182
1183 }"#,
1184     ).assert_expand_items(r#"arbitrary !   ( [ A : Arbitrary ]
1185         Vec < A > ,
1186         VecStrategy < A :: Strategy > ,
1187         RangedParams1 < A :: Parameters > ;
1188         args =>   { let product_unpack !   [ range , a ] = args ; vec ( any_with :: < A >   ( a ) , range ) }
1189     ) ;"#,
1190     "impl <A : Arbitrary > $crate :: arbitrary :: Arbitrary for Vec < A > {type Parameters = RangedParams1 < A :: Parameters > ; type Strategy = VecStrategy < A :: Strategy > ; fn arbitrary_with (args : Self :: Parameters) -> Self :: Strategy {{let product_unpack ! [range , a] = args ; vec (any_with :: < A > (a) , range)}}}"
1191     );
1192 }
1193
1194 #[test]
1195 fn test_old_ridl() {
1196     // This is from winapi 2.8, which do not have a link from github
1197     //
1198     let expanded = parse_macro(
1199         r#"
1200 #[macro_export]
1201 macro_rules! RIDL {
1202     (interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident)
1203         {$(
1204             fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty
1205         ),+}
1206     ) => {
1207         impl $interface {
1208             $(pub unsafe fn $method(&mut self) -> $rtr {
1209                 ((*self.lpVtbl).$method)(self $(,$p)*)
1210             })+
1211         }
1212     };
1213 }"#,
1214     ).expand_tt(r#"
1215     RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) {
1216         fn GetDataSize(&mut self) -> UINT
1217     }}"#);
1218
1219     assert_eq!(expanded.to_string(), "impl ID3D11Asynchronous {pub unsafe fn GetDataSize (& mut self) -> UINT {((* self . lpVtbl) .GetDataSize) (self)}}");
1220 }
1221
1222 #[test]
1223 fn test_quick_error() {
1224     let expanded = parse_macro(
1225         r#"
1226 macro_rules! quick_error {
1227
1228  (SORT [enum $name:ident $( #[$meta:meta] )*]
1229         items [$($( #[$imeta:meta] )*
1230                   => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
1231                                 {$( $ifuncs:tt )*} )* ]
1232         buf [ ]
1233         queue [ ]
1234     ) => {
1235         quick_error!(ENUMINITION [enum $name $( #[$meta] )*]
1236             body []
1237             queue [$(
1238                 $( #[$imeta] )*
1239                 =>
1240                 $iitem: $imode [$( $ivar: $ityp ),*]
1241             )*]
1242         );
1243 };
1244
1245 }
1246 "#,
1247     )
1248     .expand_tt(
1249         r#"
1250 quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [
1251         => One : UNIT [] {}
1252         => Two : TUPLE [s :String] {display ("two: {}" , s) from ()}
1253     ] buf [] queue []) ;
1254 "#,
1255     );
1256
1257     assert_eq!(expanded.to_string(), "quick_error ! (ENUMINITION [enum Wrapped # [derive (Debug)]] body [] queue [=> One : UNIT [] => Two : TUPLE [s : String]]) ;");
1258 }
1259
1260 #[test]
1261 fn test_empty_repeat_vars_in_empty_repeat_vars() {
1262     parse_macro(
1263         r#"
1264 macro_rules! delegate_impl {
1265     ([$self_type:ident, $self_wrap:ty, $self_map:ident]
1266      pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* {
1267
1268         $(
1269         @escape [type $assoc_name_ext:ident]
1270         )*
1271         $(
1272         @section type
1273         $(
1274             $(#[$_assoc_attr:meta])*
1275             type $assoc_name:ident $(: $assoc_bound:ty)*;
1276         )+
1277         )*
1278         $(
1279         @section self
1280         $(
1281             $(#[$_method_attr:meta])*
1282             fn $method_name:ident(self $(: $self_selftype:ty)* $(,$marg:ident : $marg_ty:ty)*) -> $mret:ty;
1283         )+
1284         )*
1285         $(
1286         @section nodelegate
1287         $($tail:tt)*
1288         )*
1289     }) => {
1290         impl<> $name for $self_wrap where $self_type: $name {
1291             $(
1292             $(
1293                 fn $method_name(self $(: $self_selftype)* $(,$marg: $marg_ty)*) -> $mret {
1294                     $self_map!(self).$method_name($($marg),*)
1295                 }
1296             )*
1297             )*
1298         }
1299     }
1300 }
1301 "#,
1302     ).assert_expand_items(
1303         r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#,
1304         "impl <> Data for & \'a mut G where G : Data {}",
1305     );
1306 }
1307
1308 #[test]
1309 fn expr_interpolation() {
1310     let expanded = parse_macro(
1311         r#"
1312         macro_rules! id {
1313             ($expr:expr) => {
1314                 map($expr)
1315             }
1316         }
1317         "#,
1318     )
1319     .expand_expr("id!(x + foo);");
1320
1321     assert_eq!(expanded.to_string(), "map(x+foo)");
1322 }
1323
1324 #[test]
1325 fn test_issue_2520() {
1326     let macro_fixture = parse_macro(
1327         r#"
1328         macro_rules! my_macro {
1329             {
1330                 ( $(
1331                     $( [] $sname:ident : $stype:ty  )?
1332                     $( [$expr:expr] $nname:ident : $ntype:ty  )?
1333                 ),* )
1334             } => {
1335                 Test {
1336                     $(
1337                         $( $sname, )?
1338                     )*
1339                 }
1340             };
1341         }
1342     "#,
1343     );
1344
1345     macro_fixture.assert_expand_items(
1346         r#"my_macro ! {
1347             ([] p1 : u32 , [|_| S0K0] s : S0K0 , [] k0 : i32)
1348         }"#,
1349         "Test {p1 , k0 ,}",
1350     );
1351 }
1352
1353 #[test]
1354 fn test_issue_3861() {
1355     let macro_fixture = parse_macro(
1356         r#"
1357         macro_rules! rgb_color {
1358             ($p:expr, $t: ty) => {
1359                 pub fn new() {
1360                     let _ = 0 as $t << $p;
1361                 }
1362             };
1363         }
1364     "#,
1365     );
1366
1367     macro_fixture.expand_items(r#"rgb_color!(8 + 8, u32);"#);
1368 }
1369
1370 #[test]
1371 fn test_repeat_bad_var() {
1372     // FIXME: the second rule of the macro should be removed and an error about
1373     // `$( $c )+` raised
1374     parse_macro(
1375         r#"
1376         macro_rules! foo {
1377             ($( $b:ident )+) => {
1378                 $( $c )+
1379             };
1380             ($( $b:ident )+) => {
1381                 $( $b )+
1382             }
1383         }
1384     "#,
1385     )
1386     .assert_expand_items("foo!(b0 b1);", "b0 b1");
1387 }
1388
1389 #[test]
1390 fn test_no_space_after_semi_colon() {
1391     let expanded = parse_macro(
1392         r#"
1393         macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) }
1394     "#,
1395     )
1396     .expand_items(r#"with_std! {mod m;mod f;}"#);
1397
1398     let dump = format!("{:#?}", expanded);
1399     assert_eq_text!(
1400         r###"MACRO_ITEMS@0..52
1401   MODULE@0..26
1402     ATTR@0..21
1403       POUND@0..1 "#"
1404       L_BRACK@1..2 "["
1405       META@2..20
1406         PATH@2..5
1407           PATH_SEGMENT@2..5
1408             NAME_REF@2..5
1409               IDENT@2..5 "cfg"
1410         TOKEN_TREE@5..20
1411           L_PAREN@5..6 "("
1412           IDENT@6..13 "feature"
1413           EQ@13..14 "="
1414           STRING@14..19 "\"std\""
1415           R_PAREN@19..20 ")"
1416       R_BRACK@20..21 "]"
1417     MOD_KW@21..24 "mod"
1418     NAME@24..25
1419       IDENT@24..25 "m"
1420     SEMICOLON@25..26 ";"
1421   MODULE@26..52
1422     ATTR@26..47
1423       POUND@26..27 "#"
1424       L_BRACK@27..28 "["
1425       META@28..46
1426         PATH@28..31
1427           PATH_SEGMENT@28..31
1428             NAME_REF@28..31
1429               IDENT@28..31 "cfg"
1430         TOKEN_TREE@31..46
1431           L_PAREN@31..32 "("
1432           IDENT@32..39 "feature"
1433           EQ@39..40 "="
1434           STRING@40..45 "\"std\""
1435           R_PAREN@45..46 ")"
1436       R_BRACK@46..47 "]"
1437     MOD_KW@47..50 "mod"
1438     NAME@50..51
1439       IDENT@50..51 "f"
1440     SEMICOLON@51..52 ";""###,
1441         dump.trim()
1442     );
1443 }
1444
1445 // https://github.com/rust-lang/rust/blob/master/src/test/ui/issues/issue-57597.rs
1446 #[test]
1447 fn test_rustc_issue_57597() {
1448     fn test_error(fixture: &str) {
1449         assert_eq!(parse_macro_error(fixture), ParseError::RepetitionEmptyTokenTree);
1450     }
1451
1452     test_error("macro_rules! foo { ($($($i:ident)?)+) => {}; }");
1453     test_error("macro_rules! foo { ($($($i:ident)?)*) => {}; }");
1454     test_error("macro_rules! foo { ($($($i:ident)?)?) => {}; }");
1455     test_error("macro_rules! foo { ($($($($i:ident)?)?)?) => {}; }");
1456     test_error("macro_rules! foo { ($($($($i:ident)*)?)?) => {}; }");
1457     test_error("macro_rules! foo { ($($($($i:ident)?)*)?) => {}; }");
1458     test_error("macro_rules! foo { ($($($($i:ident)?)?)*) => {}; }");
1459     test_error("macro_rules! foo { ($($($($i:ident)*)*)?) => {}; }");
1460     test_error("macro_rules! foo { ($($($($i:ident)?)*)*) => {}; }");
1461     test_error("macro_rules! foo { ($($($($i:ident)?)*)+) => {}; }");
1462     test_error("macro_rules! foo { ($($($($i:ident)+)?)*) => {}; }");
1463     test_error("macro_rules! foo { ($($($($i:ident)+)*)?) => {}; }");
1464 }
1465
1466 #[test]
1467 fn test_expand_bad_literal() {
1468     parse_macro(
1469         r#"
1470         macro_rules! foo { ($i:literal) => {}; }
1471     "#,
1472     )
1473     .assert_expand_err(r#"foo!(&k");"#, &ExpandError::BindingError("".into()));
1474 }
1475
1476 #[test]
1477 fn test_empty_comments() {
1478     parse_macro(
1479         r#"
1480         macro_rules! one_arg_macro { ($fmt:expr) => (); }
1481     "#,
1482     )
1483     .assert_expand_err(
1484         r#"one_arg_macro!(/**/)"#,
1485         &ExpandError::BindingError("expected Expr".into()),
1486     );
1487 }