]> git.lizzy.rs Git - rust.git/blob - crates/proc_macro_srv/src/abis/abi_1_47/mod.rs
Introduce proc_macro_srv::abis, impl 1.47 and 1.55
[rust.git] / crates / proc_macro_srv / src / abis / abi_1_47 / mod.rs
1 //! Macro ABI for version 1.47 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 use libloading::Library;
11
12 use proc_macro_api::ProcMacroKind;
13
14 use super::PanicMessage;
15
16 pub use rustc_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 = rustc_server::TokenStream::with_subtree(macro_body.clone());
42
43         let parsed_attributes = attributes.map_or(rustc_server::TokenStream::new(), |attr| {
44             rustc_server::TokenStream::with_subtree(attr.clone())
45         });
46
47         for proc_macro in &self.exported_macros {
48             match proc_macro {
49                 proc_macro::bridge::client::ProcMacro::CustomDerive {
50                     trait_name, client, ..
51                 } if *trait_name == macro_name => {
52                     let res = client.run(
53                         &proc_macro::bridge::server::SameThread,
54                         rustc_server::Rustc::default(),
55                         parsed_body,
56                         false,
57                     );
58                     return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
59                 }
60                 proc_macro::bridge::client::ProcMacro::Bang { name, client }
61                     if *name == macro_name =>
62                 {
63                     let res = client.run(
64                         &proc_macro::bridge::server::SameThread,
65                         rustc_server::Rustc::default(),
66                         parsed_body,
67                         false,
68                     );
69                     return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
70                 }
71                 proc_macro::bridge::client::ProcMacro::Attr { name, client }
72                     if *name == macro_name =>
73                 {
74                     let res = client.run(
75                         &proc_macro::bridge::server::SameThread,
76                         rustc_server::Rustc::default(),
77                         parsed_attributes,
78                         parsed_body,
79                         false,
80                     );
81                     return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
82                 }
83                 _ => continue,
84             }
85         }
86
87         Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into())
88     }
89
90     pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
91         self.exported_macros
92             .iter()
93             .map(|proc_macro| match proc_macro {
94                 proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
95                     (trait_name.to_string(), ProcMacroKind::CustomDerive)
96                 }
97                 proc_macro::bridge::client::ProcMacro::Bang { name, .. } => {
98                     (name.to_string(), ProcMacroKind::FuncLike)
99                 }
100                 proc_macro::bridge::client::ProcMacro::Attr { name, .. } => {
101                     (name.to_string(), ProcMacroKind::Attr)
102                 }
103             })
104             .collect()
105     }
106 }