1 //! Macro ABI for version 1.55 of rustc 2 3 #[allow(dead_code)] 4 #[doc(hidden)] 5 mod proc_macro; 6 7 #[allow(dead_code)] 8 #[doc(hidden)] 9 mod rustc_server; 10 11 use libloading::Library; 12 use proc_macro_api::ProcMacroKind; 13 14 use super::PanicMessage; 15 16 pub(crate) struct Abi { 17 exported_macros: Vec<proc_macro::bridge::client::ProcMacro>, 18 } 19 20 impl From<proc_macro::bridge::PanicMessage> for PanicMessage { from(p: proc_macro::bridge::PanicMessage) -> Self21 fn from(p: proc_macro::bridge::PanicMessage) -> Self { 22 Self { message: p.as_str().map(|s| s.to_string()) } 23 } 24 } 25 26 impl Abi { from_lib(lib: &Library, symbol_name: String) -> Result<Abi, libloading::Error>27 pub unsafe fn from_lib(lib: &Library, symbol_name: String) -> Result<Abi, libloading::Error> { 28 let macros: libloading::Symbol<&&[proc_macro::bridge::client::ProcMacro]> = 29 lib.get(symbol_name.as_bytes())?; 30 Ok(Self { exported_macros: macros.to_vec() }) 31 } 32 expand( &self, macro_name: &str, macro_body: &tt::Subtree, attributes: Option<&tt::Subtree>, ) -> Result<tt::Subtree, PanicMessage>33 pub fn expand( 34 &self, 35 macro_name: &str, 36 macro_body: &tt::Subtree, 37 attributes: Option<&tt::Subtree>, 38 ) -> Result<tt::Subtree, PanicMessage> { 39 let parsed_body = rustc_server::TokenStream::with_subtree(macro_body.clone()); 40 41 let parsed_attributes = attributes.map_or(rustc_server::TokenStream::new(), |attr| { 42 rustc_server::TokenStream::with_subtree(attr.clone()) 43 }); 44 45 for proc_macro in &self.exported_macros { 46 match proc_macro { 47 proc_macro::bridge::client::ProcMacro::CustomDerive { 48 trait_name, client, .. 49 } if *trait_name == macro_name => { 50 let res = client.run( 51 &proc_macro::bridge::server::SameThread, 52 rustc_server::Rustc::default(), 53 parsed_body, 54 false, 55 ); 56 return res.map(|it| it.into_subtree()).map_err(PanicMessage::from); 57 } 58 proc_macro::bridge::client::ProcMacro::Bang { name, client } 59 if *name == macro_name => 60 { 61 let res = client.run( 62 &proc_macro::bridge::server::SameThread, 63 rustc_server::Rustc::default(), 64 parsed_body, 65 false, 66 ); 67 return res.map(|it| it.into_subtree()).map_err(PanicMessage::from); 68 } 69 proc_macro::bridge::client::ProcMacro::Attr { name, client } 70 if *name == macro_name => 71 { 72 let res = client.run( 73 &proc_macro::bridge::server::SameThread, 74 rustc_server::Rustc::default(), 75 parsed_attributes, 76 parsed_body, 77 false, 78 ); 79 return res.map(|it| it.into_subtree()).map_err(PanicMessage::from); 80 } 81 _ => continue, 82 } 83 } 84 85 Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into()) 86 } 87 list_macros(&self) -> Vec<(String, ProcMacroKind)>88 pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> { 89 self.exported_macros 90 .iter() 91 .map(|proc_macro| match proc_macro { 92 proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => { 93 (trait_name.to_string(), ProcMacroKind::CustomDerive) 94 } 95 proc_macro::bridge::client::ProcMacro::Bang { name, .. } => { 96 (name.to_string(), ProcMacroKind::FuncLike) 97 } 98 proc_macro::bridge::client::ProcMacro::Attr { name, .. } => { 99 (name.to_string(), ProcMacroKind::Attr) 100 } 101 }) 102 .collect() 103 } 104 } 105