aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/lib.rs')
-rw-r--r--crates/ra_mbe/src/lib.rs110
1 files changed, 87 insertions, 23 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index d2115bd67..9aad08db9 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -214,14 +214,15 @@ impl_froms!(TokenTree: Leaf, Subtree);
214 let tree = token_tree_to_macro_items(&expanded); 214 let tree = token_tree_to_macro_items(&expanded);
215 215
216 // Eat all white space by parse it back and forth 216 // Eat all white space by parse it back and forth
217 let expansion = ast::SourceFile::parse(expansion); 217 // Because $crate will seperate in two token , will do some special treatment here
218 let expansion = expansion.replace("$crate", "C_C__C");
219 let expansion = ast::SourceFile::parse(&expansion);
218 let expansion = syntax_node_to_token_tree(expansion.syntax()).unwrap().0; 220 let expansion = syntax_node_to_token_tree(expansion.syntax()).unwrap().0;
219 let file = token_tree_to_macro_items(&expansion); 221 let file = token_tree_to_macro_items(&expansion);
222 let file = file.unwrap().syntax().debug_dump().trim().to_string();
223 let file = file.replace("C_C__C", "$crate");
220 224
221 assert_eq!( 225 assert_eq!(tree.unwrap().syntax().debug_dump().trim(), file,);
222 tree.unwrap().syntax().debug_dump().trim(),
223 file.unwrap().syntax().debug_dump().trim()
224 );
225 } 226 }
226 227
227 #[test] 228 #[test]
@@ -348,7 +349,36 @@ impl_froms!(TokenTree: Leaf, Subtree);
348 } 349 }
349 350
350 #[test] 351 #[test]
351 fn expand_to_item_list() { 352 fn test_match_group_empty_fixed_token() {
353 let rules = create_rules(
354 r#"
355 macro_rules! foo {
356 ($ ($ i:ident)* #abc) => ( fn baz { $ (
357 $ i ();
358 )*} );
359 }
360"#,
361 );
362
363 assert_expansion(&rules, "foo! {#abc}", "fn baz {}");
364 }
365
366 #[test]
367 fn test_match_group_in_subtree() {
368 let rules = create_rules(
369 r#"
370 macro_rules! foo {
371 (fn $name:ident {$($i:ident)*} ) => ( fn $name() { $ (
372 $ i ();
373 )*} );
374 }"#,
375 );
376
377 assert_expansion(&rules, "foo! {fn baz {a b} }", "fn baz () {a () ; b () ;}");
378 }
379
380 #[test]
381 fn test_expand_to_item_list() {
352 let rules = create_rules( 382 let rules = create_rules(
353 " 383 "
354 macro_rules! structs { 384 macro_rules! structs {
@@ -401,7 +431,7 @@ MACRO_ITEMS@[0; 40)
401 } 431 }
402 432
403 #[test] 433 #[test]
404 fn expand_literals_to_token_tree() { 434 fn test_expand_literals_to_token_tree() {
405 fn to_subtree(tt: &tt::TokenTree) -> &tt::Subtree { 435 fn to_subtree(tt: &tt::TokenTree) -> &tt::Subtree {
406 if let tt::TokenTree::Subtree(subtree) = tt { 436 if let tt::TokenTree::Subtree(subtree) = tt {
407 return &subtree; 437 return &subtree;
@@ -763,30 +793,29 @@ MACRO_ITEMS@[0; 40)
763 ); 793 );
764 } 794 }
765 795
766 // #[test] 796 #[test]
767 // fn test_tt_block() { 797 // fn test_tt_block() {
768 // let rules = create_rules( 798 // let rules = create_rules(
769 // r#" 799 // r#"
770 // macro_rules! foo { 800 // macro_rules! foo {
771 // ($ i:tt) => { fn foo() $ i } 801 // ($ i:tt) => { fn foo() $ i }
772 // } 802 // }
773 // "#, 803 // "#,
774 // ); 804 // );
775 // assert_expansion(&rules, r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#); 805 // assert_expansion(&rules, r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#);
776 // } 806 // }
777 807
778 // #[test] 808 // #[test]
779 // fn test_tt_group() { 809 // fn test_tt_group() {
780 // let rules = create_rules( 810 // let rules = create_rules(
781 // r#" 811 // r#"
782 // macro_rules! foo { 812 // macro_rules! foo {
783 // ($($ i:tt)*) => { $($ i)* } 813 // ($($ i:tt)*) => { $($ i)* }
784 // } 814 // }
785 // "#, 815 // "#,
786 // ); 816 // );
787 // assert_expansion(&rules, r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); 817 // assert_expansion(&rules, r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#);
788 // } 818 // }
789
790 #[test] 819 #[test]
791 fn test_lifetime() { 820 fn test_lifetime() {
792 let rules = create_rules( 821 let rules = create_rules(
@@ -822,4 +851,39 @@ MACRO_ITEMS@[0; 40)
822 ); 851 );
823 assert_expansion(&rules, r#"foo!(pub foo);"#, r#"pub fn foo () {}"#); 852 assert_expansion(&rules, r#"foo!(pub foo);"#, r#"pub fn foo () {}"#);
824 } 853 }
854
855 // The following tests are based on real world situations
856 #[test]
857 fn test_winapi_struct() {
858 // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366
859
860 let rules = create_rules(
861 r#"
862macro_rules! STRUCT {
863 ($(#[$attrs:meta])* struct $name:ident {
864 $($field:ident: $ftype:ty,)+
865 }) => (
866 #[repr(C)] #[derive(Copy)] $(#[$attrs])*
867 pub struct $name {
868 $(pub $field: $ftype,)+
869 }
870 impl Clone for $name {
871 #[inline]
872 fn clone(&self) -> $name { *self }
873 }
874 #[cfg(feature = "impl-default")]
875 impl Default for $name {
876 #[inline]
877 fn default() -> $name { unsafe { $crate::_core::mem::zeroed() } }
878 }
879 );
880}
881"#,
882 );
883 // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs
884 assert_expansion(&rules, r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#,
885 "# [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 ()}}}");
886 assert_expansion(&rules, r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#,
887 "# [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 ()}}}");
888 }
825} 889}