]> git.lizzy.rs Git - rust.git/blob - crates/proc-macro-srv/src/abis/abi_1_58/mod.rs
41e2e45703d9ae7546e7cb8c960731ece1e3659b
[rust.git] / crates / proc-macro-srv / src / abis / abi_1_58 / mod.rs
1 //! Macro ABI for version 1.58 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 {
21     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 {
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
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                         true,
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                         true,
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                         true,
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
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 }