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