]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/macro_expansion_tests/mbe.rs
d17c9131da752bee9d6c073741ddd09d4abac21c
[rust.git] / crates / hir_def / src / macro_expansion_tests / mbe.rs
1 //! Tests specific to declarative macros, aka macros by example. This covers
2 //! both stable `macro_rules!` macros as well as unstable `macro` macros.
3
4 mod tt_conversion;
5 mod matching;
6 mod meta_syntax;
7
8 use expect_test::expect;
9
10 use crate::macro_expansion_tests::check;
11
12 #[test]
13 fn mbe_smoke_test() {
14     check(
15         r#"
16 macro_rules! impl_froms {
17     ($e:ident: $($v:ident),*) => {
18         $(
19             impl From<$v> for $e {
20                 fn from(it: $v) -> $e { $e::$v(it) }
21             }
22         )*
23     }
24 }
25 impl_froms!(TokenTree: Leaf, Subtree);
26 "#,
27         expect![[r#"
28 macro_rules! impl_froms {
29     ($e:ident: $($v:ident),*) => {
30         $(
31             impl From<$v> for $e {
32                 fn from(it: $v) -> $e { $e::$v(it) }
33             }
34         )*
35     }
36 }
37 impl From<Leaf> for TokenTree {
38     fn from(it:Leaf) -> TokenTree {
39         TokenTree::Leaf(it)
40     }
41 }
42 impl From<Subtree> for TokenTree {
43     fn from(it:Subtree) -> TokenTree {
44         TokenTree::Subtree(it)
45     }
46 }
47 "#]],
48     );
49 }
50
51 #[test]
52 fn expansion_does_not_parse_as_expression() {
53     check(
54         r#"
55 macro_rules! stmts {
56     () => { let _ = 0; }
57 }
58
59 fn f() { let _ = stmts!(); }
60 "#,
61         expect![[r#"
62 macro_rules! stmts {
63     () => { let _ = 0; }
64 }
65
66 fn f() { let _ = /* error: could not convert tokens */; }
67 "#]],
68     )
69 }
70
71 #[test]
72 fn wrong_nesting_level() {
73     check(
74         r#"
75 macro_rules! m {
76     ($($i:ident);*) => ($i)
77 }
78 m!{a}
79 "#,
80         expect![[r#"
81 macro_rules! m {
82     ($($i:ident);*) => ($i)
83 }
84 /* error: expected simple binding, found nested binding `i` */
85 "#]],
86     );
87 }
88
89 #[test]
90 fn match_by_first_token_literally() {
91     check(
92         r#"
93 macro_rules! m {
94     ($i:ident) => ( mod $i {} );
95     (= $i:ident) => ( fn $i() {} );
96     (+ $i:ident) => ( struct $i; )
97 }
98 m! { foo }
99 m! { = bar }
100 m! { + Baz }
101 "#,
102         expect![[r#"
103 macro_rules! m {
104     ($i:ident) => ( mod $i {} );
105     (= $i:ident) => ( fn $i() {} );
106     (+ $i:ident) => ( struct $i; )
107 }
108 mod foo {}
109 fn bar() {}
110 struct Baz;
111 "#]],
112     );
113 }
114
115 #[test]
116 fn match_by_last_token_literally() {
117     check(
118         r#"
119 macro_rules! m {
120     ($i:ident) => ( mod $i {} );
121     ($i:ident =) => ( fn $i() {} );
122     ($i:ident +) => ( struct $i; )
123 }
124 m! { foo }
125 m! { bar = }
126 m! { Baz + }
127 "#,
128         expect![[r#"
129 macro_rules! m {
130     ($i:ident) => ( mod $i {} );
131     ($i:ident =) => ( fn $i() {} );
132     ($i:ident +) => ( struct $i; )
133 }
134 mod foo {}
135 fn bar() {}
136 struct Baz;
137 "#]],
138     );
139 }
140
141 #[test]
142 fn match_by_ident() {
143     check(
144         r#"
145 macro_rules! m {
146     ($i:ident) => ( mod $i {} );
147     (spam $i:ident) => ( fn $i() {} );
148     (eggs $i:ident) => ( struct $i; )
149 }
150 m! { foo }
151 m! { spam bar }
152 m! { eggs Baz }
153 "#,
154         expect![[r#"
155 macro_rules! m {
156     ($i:ident) => ( mod $i {} );
157     (spam $i:ident) => ( fn $i() {} );
158     (eggs $i:ident) => ( struct $i; )
159 }
160 mod foo {}
161 fn bar() {}
162 struct Baz;
163 "#]],
164     );
165 }
166
167 #[test]
168 fn match_by_separator_token() {
169     check(
170         r#"
171 macro_rules! m {
172     ($($i:ident),*) => ($(mod $i {} )*);
173     ($($i:ident)#*) => ($(fn $i() {} )*);
174     ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; )
175 }
176
177 m! { foo, bar }
178
179 m! { foo# bar }
180
181 m! { Foo,# Bar }
182 "#,
183         expect![[r##"
184 macro_rules! m {
185     ($($i:ident),*) => ($(mod $i {} )*);
186     ($($i:ident)#*) => ($(fn $i() {} )*);
187     ($i:ident ,# $ j:ident) => ( struct $i; struct $ j; )
188 }
189
190 mod foo {}
191 mod bar {}
192
193 fn foo() {}
194 fn bar() {}
195
196 struct Foo;
197 struct Bar;
198 "##]],
199     );
200 }
201
202 #[test]
203 fn test_match_group_pattern_with_multiple_defs() {
204     check(
205         r#"
206 macro_rules! m {
207     ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
208 }
209 m! { foo, bar }
210 "#,
211         expect![[r#"
212 macro_rules! m {
213     ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } );
214 }
215 impl Bar {
216     fn foo() {}
217     fn bar() {}
218 }
219 "#]],
220     );
221 }
222
223 #[test]
224 fn test_match_group_pattern_with_multiple_statement() {
225     check(
226         r#"
227 macro_rules! m {
228     ($($i:ident),*) => ( fn baz() { $($i ();)* } );
229 }
230 m! { foo, bar }
231 "#,
232         expect![[r#"
233 macro_rules! m {
234     ($($i:ident),*) => ( fn baz() { $($i ();)* } );
235 }
236 fn baz() {
237     foo();
238     bar();
239 }
240 "#]],
241     )
242 }
243
244 #[test]
245 fn test_match_group_pattern_with_multiple_statement_without_semi() {
246     check(
247         r#"
248 macro_rules! m {
249     ($($i:ident),*) => ( fn baz() { $($i() );* } );
250 }
251 m! { foo, bar }
252 "#,
253         expect![[r#"
254 macro_rules! m {
255     ($($i:ident),*) => ( fn baz() { $($i() );* } );
256 }
257 fn baz() {
258     foo();
259     bar()
260 }
261 "#]],
262     )
263 }
264
265 #[test]
266 fn test_match_group_empty_fixed_token() {
267     check(
268         r#"
269 macro_rules! m {
270     ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } );
271 }
272 m!{#abc}
273 "#,
274         expect![[r##"
275 macro_rules! m {
276     ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } );
277 }
278 fn baz() {}
279 "##]],
280     )
281 }
282
283 #[test]
284 fn test_match_group_in_subtree() {
285     check(
286         r#"
287 macro_rules! m {
288     (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } );
289 }
290 m! { fn baz { a b } }
291 "#,
292         expect![[r#"
293 macro_rules! m {
294     (fn $name:ident { $($i:ident)* } ) => ( fn $name() { $($i ();)* } );
295 }
296 fn baz() {
297     a();
298     b();
299 }
300 "#]],
301     )
302 }
303
304 #[test]
305 fn test_expr_order() {
306     check(
307         r#"
308 macro_rules! m {
309     ($ i:expr) => { fn bar() { $ i * 3; } }
310 }
311 // +tree
312 m! { 1 + 2 }
313 "#,
314         expect![[r#"
315 macro_rules! m {
316     ($ i:expr) => { fn bar() { $ i * 3; } }
317 }
318 fn bar() {
319     1+2*3;
320 }
321 // MACRO_ITEMS@0..15
322 //   FN@0..15
323 //     FN_KW@0..2 "fn"
324 //     NAME@2..5
325 //       IDENT@2..5 "bar"
326 //     PARAM_LIST@5..7
327 //       L_PAREN@5..6 "("
328 //       R_PAREN@6..7 ")"
329 //     BLOCK_EXPR@7..15
330 //       STMT_LIST@7..15
331 //         L_CURLY@7..8 "{"
332 //         EXPR_STMT@8..14
333 //           BIN_EXPR@8..13
334 //             BIN_EXPR@8..11
335 //               LITERAL@8..9
336 //                 INT_NUMBER@8..9 "1"
337 //               PLUS@9..10 "+"
338 //               LITERAL@10..11
339 //                 INT_NUMBER@10..11 "2"
340 //             STAR@11..12 "*"
341 //             LITERAL@12..13
342 //               INT_NUMBER@12..13 "3"
343 //           SEMICOLON@13..14 ";"
344 //         R_CURLY@14..15 "}"
345
346 "#]],
347     )
348 }
349
350 #[test]
351 fn test_match_group_with_multichar_sep() {
352     check(
353         r#"
354 macro_rules! m {
355     (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
356 }
357 m! (fn baz { true false } );
358 "#,
359         expect![[r#"
360 macro_rules! m {
361     (fn $name:ident { $($i:literal)* }) => ( fn $name() -> bool { $($i)&&* } );
362 }
363 fn baz() -> bool {
364     true && false
365 }
366 "#]],
367     );
368
369     check(
370         r#"
371 macro_rules! m {
372     (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
373 }
374 m! (fn baz { true && false } );
375 "#,
376         expect![[r#"
377 macro_rules! m {
378     (fn $name:ident { $($i:literal)&&* }) => ( fn $name() -> bool { $($i)&&* } );
379 }
380 fn baz() -> bool {
381     true && false
382 }
383 "#]],
384     );
385 }
386
387 #[test]
388 fn test_match_group_zero_match() {
389     check(
390         r#"
391 macro_rules! m { ( $($i:ident)* ) => (); }
392 m!();
393 "#,
394         expect![[r#"
395 macro_rules! m { ( $($i:ident)* ) => (); }
396
397 "#]],
398     );
399 }
400
401 #[test]
402 fn test_match_group_in_group() {
403     check(
404         r#"
405 macro_rules! m {
406     [ $( ( $($i:ident)* ) )* ] => [ x![$( ( $($i)* ) )*]; ]
407 }
408 m! ( (a b) );
409 "#,
410         expect![[r#"
411 macro_rules! m {
412     [ $( ( $($i:ident)* ) )* ] => [ x![$( ( $($i)* ) )*]; ]
413 }
414 x![(a b)];
415 "#]],
416     )
417 }
418
419 #[test]
420 fn test_expand_to_item_list() {
421     check(
422         r#"
423 macro_rules! structs {
424     ($($i:ident),*) => { $(struct $i { field: u32 } )* }
425 }
426
427 // +tree
428 structs!(Foo, Bar);
429             "#,
430         expect![[r#"
431 macro_rules! structs {
432     ($($i:ident),*) => { $(struct $i { field: u32 } )* }
433 }
434
435 struct Foo {
436     field:u32
437 }
438 struct Bar {
439     field:u32
440 }
441 // MACRO_ITEMS@0..40
442 //   STRUCT@0..20
443 //     STRUCT_KW@0..6 "struct"
444 //     NAME@6..9
445 //       IDENT@6..9 "Foo"
446 //     RECORD_FIELD_LIST@9..20
447 //       L_CURLY@9..10 "{"
448 //       RECORD_FIELD@10..19
449 //         NAME@10..15
450 //           IDENT@10..15 "field"
451 //         COLON@15..16 ":"
452 //         PATH_TYPE@16..19
453 //           PATH@16..19
454 //             PATH_SEGMENT@16..19
455 //               NAME_REF@16..19
456 //                 IDENT@16..19 "u32"
457 //       R_CURLY@19..20 "}"
458 //   STRUCT@20..40
459 //     STRUCT_KW@20..26 "struct"
460 //     NAME@26..29
461 //       IDENT@26..29 "Bar"
462 //     RECORD_FIELD_LIST@29..40
463 //       L_CURLY@29..30 "{"
464 //       RECORD_FIELD@30..39
465 //         NAME@30..35
466 //           IDENT@30..35 "field"
467 //         COLON@35..36 ":"
468 //         PATH_TYPE@36..39
469 //           PATH@36..39
470 //             PATH_SEGMENT@36..39
471 //               NAME_REF@36..39
472 //                 IDENT@36..39 "u32"
473 //       R_CURLY@39..40 "}"
474
475             "#]],
476     );
477 }
478
479 #[test]
480 fn test_two_idents() {
481     check(
482         r#"
483 macro_rules! m {
484     ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
485 }
486 m! { foo, bar }
487 "#,
488         expect![[r#"
489 macro_rules! m {
490     ($i:ident, $j:ident) => { fn foo() { let a = $i; let b = $j; } }
491 }
492 fn foo() {
493     let a = foo;
494     let b = bar;
495 }
496 "#]],
497     );
498 }
499
500 #[test]
501 fn test_tt_to_stmts() {
502     check(
503         r#"
504 macro_rules! m {
505     () => {
506         let a = 0;
507         a = 10 + 1;
508         a
509     }
510 }
511
512 fn f() -> i32 {
513     // +tree
514     m!{}
515 }
516 "#,
517         expect![[r#"
518 macro_rules! m {
519     () => {
520         let a = 0;
521         a = 10 + 1;
522         a
523     }
524 }
525
526 fn f() -> i32 {
527     let a = 0;
528     a = 10+1;
529     a
530 // MACRO_STMTS@0..15
531 //   LET_STMT@0..7
532 //     LET_KW@0..3 "let"
533 //     IDENT_PAT@3..4
534 //       NAME@3..4
535 //         IDENT@3..4 "a"
536 //     EQ@4..5 "="
537 //     LITERAL@5..6
538 //       INT_NUMBER@5..6 "0"
539 //     SEMICOLON@6..7 ";"
540 //   EXPR_STMT@7..14
541 //     BIN_EXPR@7..13
542 //       PATH_EXPR@7..8
543 //         PATH@7..8
544 //           PATH_SEGMENT@7..8
545 //             NAME_REF@7..8
546 //               IDENT@7..8 "a"
547 //       EQ@8..9 "="
548 //       BIN_EXPR@9..13
549 //         LITERAL@9..11
550 //           INT_NUMBER@9..11 "10"
551 //         PLUS@11..12 "+"
552 //         LITERAL@12..13
553 //           INT_NUMBER@12..13 "1"
554 //     SEMICOLON@13..14 ";"
555 //   PATH_EXPR@14..15
556 //     PATH@14..15
557 //       PATH_SEGMENT@14..15
558 //         NAME_REF@14..15
559 //           IDENT@14..15 "a"
560
561 }
562 "#]],
563     );
564 }
565
566 #[test]
567 fn test_match_literal() {
568     check(
569         r#"
570 macro_rules! m {
571     ('(') => { fn l_paren() {} }
572 }
573 m!['('];
574 "#,
575         expect![[r#"
576 macro_rules! m {
577     ('(') => { fn l_paren() {} }
578 }
579 fn l_paren() {}
580 "#]],
581     );
582 }
583
584 #[test]
585 fn test_parse_macro_def_simple() {
586     cov_mark::check!(parse_macro_def_simple);
587     check(
588         r#"
589 macro m($id:ident) { fn $id() {} }
590 m!(bar);
591 "#,
592         expect![[r#"
593 macro m($id:ident) { fn $id() {} }
594 fn bar() {}
595 "#]],
596     );
597 }
598
599 #[test]
600 fn test_parse_macro_def_rules() {
601     cov_mark::check!(parse_macro_def_rules);
602
603     check(
604         r#"
605 macro m {
606     ($id:ident) => { fn $id() {} }
607 }
608 m!(bar);
609 "#,
610         expect![[r#"
611 macro m {
612     ($id:ident) => { fn $id() {} }
613 }
614 fn bar() {}
615 "#]],
616     );
617 }
618
619 #[test]
620 fn test_macro_2_0_panic_2015() {
621     check(
622         r#"
623 macro panic_2015 {
624     () => (),
625     (bar) => (),
626 }
627 panic_2015!(bar);
628 "#,
629         expect![[r#"
630 macro panic_2015 {
631     () => (),
632     (bar) => (),
633 }
634
635 "#]],
636     );
637 }
638
639 #[test]
640 fn test_path() {
641     check(
642         r#"
643 macro_rules! m {
644     ($p:path) => { fn foo() { let a = $p; } }
645 }
646
647 m! { foo }
648
649 m! { bar::<u8>::baz::<u8> }
650 "#,
651         expect![[r#"
652 macro_rules! m {
653     ($p:path) => { fn foo() { let a = $p; } }
654 }
655
656 fn foo() {
657     let a = foo;
658 }
659
660 fn foo() {
661     let a = bar::<u8>::baz::<u8> ;
662 }
663 "#]],
664     );
665 }
666
667 #[test]
668 fn test_two_paths() {
669     check(
670         r#"
671 macro_rules! m {
672     ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
673 }
674 m! { foo, bar }
675 "#,
676         expect![[r#"
677 macro_rules! m {
678     ($i:path, $j:path) => { fn foo() { let a = $ i; let b = $j; } }
679 }
680 fn foo() {
681     let a = foo;
682     let b = bar;
683 }
684 "#]],
685     );
686 }
687
688 #[test]
689 fn test_path_with_path() {
690     check(
691         r#"
692 macro_rules! m {
693     ($p:path) => { fn foo() { let a = $p::bar; } }
694 }
695 m! { foo }
696 "#,
697         expect![[r#"
698 macro_rules! m {
699     ($p:path) => { fn foo() { let a = $p::bar; } }
700 }
701 fn foo() {
702     let a = foo::bar;
703 }
704 "#]],
705     );
706 }
707
708 #[test]
709 fn test_expr() {
710     check(
711         r#"
712 macro_rules! m {
713     ($e:expr) => { fn bar() { $e; } }
714 }
715
716 m! { 2 + 2 * baz(3).quux() }
717 "#,
718         expect![[r#"
719 macro_rules! m {
720     ($e:expr) => { fn bar() { $e; } }
721 }
722
723 fn bar() {
724     2+2*baz(3).quux();
725 }
726 "#]],
727     )
728 }
729
730 #[test]
731 fn test_last_expr() {
732     check(
733         r#"
734 macro_rules! vec {
735     ($($item:expr),*) => {{
736             let mut v = Vec::new();
737             $( v.push($item); )*
738             v
739     }};
740 }
741
742 fn f() {
743     vec![1,2,3];
744 }
745 "#,
746         expect![[r#"
747 macro_rules! vec {
748     ($($item:expr),*) => {{
749             let mut v = Vec::new();
750             $( v.push($item); )*
751             v
752     }};
753 }
754
755 fn f() {
756      {
757         let mut v = Vec::new();
758         v.push(1);
759         v.push(2);
760         v.push(3);
761         v
762     };
763 }
764 "#]],
765     );
766 }
767
768 #[test]
769 fn test_expr_with_attr() {
770     check(
771         r#"
772 macro_rules! m { ($a:expr) => { x!(); } }
773 m!(#[allow(a)]());
774 "#,
775         expect![[r#"
776 macro_rules! m { ($a:expr) => { x!(); } }
777 x!();
778 "#]],
779     )
780 }
781
782 #[test]
783 fn test_ty() {
784     check(
785         r#"
786 macro_rules! m {
787     ($t:ty) => ( fn bar() -> $t {} )
788 }
789 m! { Baz<u8> }
790 "#,
791         expect![[r#"
792 macro_rules! m {
793     ($t:ty) => ( fn bar() -> $t {} )
794 }
795 fn bar() -> Baz<u8> {}
796 "#]],
797     )
798 }
799
800 #[test]
801 fn test_ty_with_complex_type() {
802     check(
803         r#"
804 macro_rules! m {
805     ($t:ty) => ( fn bar() -> $ t {} )
806 }
807
808 m! { &'a Baz<u8> }
809
810 m! { extern "Rust" fn() -> Ret }
811 "#,
812         expect![[r#"
813 macro_rules! m {
814     ($t:ty) => ( fn bar() -> $ t {} )
815 }
816
817 fn bar() -> & 'a Baz<u8> {}
818
819 fn bar() -> extern "Rust"fn() -> Ret {}
820 "#]],
821     );
822 }
823
824 #[test]
825 fn test_pat_() {
826     check(
827         r#"
828 macro_rules! m {
829     ($p:pat) => { fn foo() { let $p; } }
830 }
831 m! { (a, b) }
832 "#,
833         expect![[r#"
834 macro_rules! m {
835     ($p:pat) => { fn foo() { let $p; } }
836 }
837 fn foo() {
838     let (a, b);
839 }
840 "#]],
841     );
842 }
843
844 #[test]
845 fn test_stmt() {
846     check(
847         r#"
848 macro_rules! m {
849     ($s:stmt) => ( fn bar() { $s; } )
850 }
851 m! { 2 }
852 m! { let a = 0 }
853 "#,
854         expect![[r#"
855 macro_rules! m {
856     ($s:stmt) => ( fn bar() { $s; } )
857 }
858 fn bar() {
859     2;
860 }
861 fn bar() {
862     let a = 0;
863 }
864 "#]],
865     )
866 }
867
868 #[test]
869 fn test_single_item() {
870     check(
871         r#"
872 macro_rules! m { ($i:item) => ( $i ) }
873 m! { mod c {} }
874 "#,
875         expect![[r#"
876 macro_rules! m { ($i:item) => ( $i ) }
877 mod c {}
878 "#]],
879     )
880 }
881
882 #[test]
883 fn test_all_items() {
884     check(
885         r#"
886 macro_rules! m { ($($i:item)*) => ($($i )*) }
887 m! {
888     extern crate a;
889     mod b;
890     mod c {}
891     use d;
892     const E: i32 = 0;
893     static F: i32 = 0;
894     impl G {}
895     struct H;
896     enum I { Foo }
897     trait J {}
898     fn h() {}
899     extern {}
900     type T = u8;
901 }
902 "#,
903         expect![[r#"
904 macro_rules! m { ($($i:item)*) => ($($i )*) }
905 extern crate a;
906 mod b;
907 mod c {}
908 use d;
909 const E:i32 = 0;
910 static F:i32 = 0;
911 impl G {}
912 struct H;
913 enum I {
914     Foo
915 }
916 trait J {}
917 fn h() {}
918 extern {}
919 type T = u8;
920 "#]],
921     );
922 }
923
924 #[test]
925 fn test_block() {
926     check(
927         r#"
928 macro_rules! m { ($b:block) => { fn foo() $b } }
929 m! { { 1; } }
930 "#,
931         expect![[r#"
932 macro_rules! m { ($b:block) => { fn foo() $b } }
933 fn foo() {
934     1;
935 }
936 "#]],
937     );
938 }
939
940 #[test]
941 fn test_meta() {
942     check(
943         r#"
944 macro_rules! m {
945     ($m:meta) => ( #[$m] fn bar() {} )
946 }
947 m! { cfg(target_os = "windows") }
948 m! { hello::world }
949 "#,
950         expect![[r##"
951 macro_rules! m {
952     ($m:meta) => ( #[$m] fn bar() {} )
953 }
954 #[cfg(target_os = "windows")] fn bar() {}
955 #[hello::world] fn bar() {}
956 "##]],
957     );
958 }
959
960 #[test]
961 fn test_meta_doc_comments() {
962     cov_mark::check!(test_meta_doc_comments);
963     check(
964         r#"
965 macro_rules! m {
966     ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
967 }
968 m! {
969     /// Single Line Doc 1
970     /**
971         MultiLines Doc
972     */
973 }
974 "#,
975         expect![[r##"
976 macro_rules! m {
977     ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
978 }
979 #[doc = " Single Line Doc 1"]
980 #[doc = "\n        MultiLines Doc\n    "] fn bar() {}
981 "##]],
982     );
983 }
984
985 #[test]
986 fn test_meta_extended_key_value_attributes() {
987     check(
988         r#"
989 macro_rules! m {
990     (#[$m:meta]) => ( #[$m] fn bar() {} )
991 }
992 m! { #[doc = concat!("The `", "bla", "` lang item.")] }
993 "#,
994         expect![[r##"
995 macro_rules! m {
996     (#[$m:meta]) => ( #[$m] fn bar() {} )
997 }
998 #[doc = concat!("The `", "bla", "` lang item.")] fn bar() {}
999 "##]],
1000     );
1001 }
1002
1003 #[test]
1004 fn test_meta_doc_comments_non_latin() {
1005     check(
1006         r#"
1007 macro_rules! m {
1008     ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1009 }
1010 m! {
1011     /// 錦瑟無端五十弦,一弦一柱思華年。
1012     /**
1013         莊生曉夢迷蝴蝶,望帝春心託杜鵑。
1014     */
1015 }
1016 "#,
1017         expect![[r##"
1018 macro_rules! m {
1019     ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} )
1020 }
1021 #[doc = " 錦瑟無端五十弦,一弦一柱思華年。"]
1022 #[doc = "\n        莊生曉夢迷蝴蝶,望帝春心託杜鵑。\n    "] fn bar() {}
1023 "##]],
1024     );
1025 }
1026
1027 #[test]
1028 fn test_meta_doc_comments_escaped_characters() {
1029     check(
1030         r#"
1031 macro_rules! m {
1032     ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1033 }
1034 m! {
1035     /// \ " '
1036 }
1037 "#,
1038         expect![[r##"
1039 macro_rules! m {
1040     ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} )
1041 }
1042 #[doc = " \\ \" \'"] fn bar() {}
1043 "##]],
1044     );
1045 }