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