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