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