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