aboutsummaryrefslogtreecommitdiff
path: root/crates/proc_macro_api/src/lib.rs
diff options
context:
space:
mode:
authorZac Pullar-Strecker <[email protected]>2020-08-24 10:19:53 +0100
committerZac Pullar-Strecker <[email protected]>2020-08-24 10:20:13 +0100
commit7bbca7a1b3f9293d2f5cc5745199bc5f8396f2f0 (patch)
treebdb47765991cb973b2cd5481a088fac636bd326c /crates/proc_macro_api/src/lib.rs
parentca464650eeaca6195891199a93f4f76cf3e7e697 (diff)
parente65d48d1fb3d4d91d9dc1148a7a836ff5c9a3c87 (diff)
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Diffstat (limited to 'crates/proc_macro_api/src/lib.rs')
-rw-r--r--crates/proc_macro_api/src/lib.rs111
1 files changed, 111 insertions, 0 deletions
diff --git a/crates/proc_macro_api/src/lib.rs b/crates/proc_macro_api/src/lib.rs
new file mode 100644
index 000000000..d5e87cf7d
--- /dev/null
+++ b/crates/proc_macro_api/src/lib.rs
@@ -0,0 +1,111 @@
1//! Client-side Proc-Macro crate
2//!
3//! We separate proc-macro expanding logic to an extern program to allow
4//! different implementations (e.g. wasm or dylib loading). And this crate
5//! is used to provide basic infrastructure for communication between two
6//! processes: Client (RA itself), Server (the external program)
7
8mod rpc;
9mod process;
10pub mod msg;
11
12use std::{
13 ffi::OsStr,
14 io,
15 path::{Path, PathBuf},
16 sync::Arc,
17};
18
19use tt::{SmolStr, Subtree};
20
21use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread};
22
23pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};
24
25#[derive(Debug, Clone)]
26pub struct ProcMacroProcessExpander {
27 process: Arc<ProcMacroProcessSrv>,
28 dylib_path: PathBuf,
29 name: SmolStr,
30}
31
32impl Eq for ProcMacroProcessExpander {}
33impl PartialEq for ProcMacroProcessExpander {
34 fn eq(&self, other: &Self) -> bool {
35 self.name == other.name
36 && self.dylib_path == other.dylib_path
37 && Arc::ptr_eq(&self.process, &other.process)
38 }
39}
40
41impl tt::TokenExpander for ProcMacroProcessExpander {
42 fn expand(
43 &self,
44 subtree: &Subtree,
45 _attr: Option<&Subtree>,
46 ) -> Result<Subtree, tt::ExpansionError> {
47 self.process.custom_derive(&self.dylib_path, subtree, &self.name)
48 }
49}
50
51#[derive(Debug)]
52enum ProcMacroClientKind {
53 Process { process: Arc<ProcMacroProcessSrv>, thread: ProcMacroProcessThread },
54 Dummy,
55}
56
57#[derive(Debug)]
58pub struct ProcMacroClient {
59 kind: ProcMacroClientKind,
60}
61
62impl ProcMacroClient {
63 pub fn extern_process(
64 process_path: PathBuf,
65 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
66 ) -> io::Result<ProcMacroClient> {
67 let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?;
68 Ok(ProcMacroClient {
69 kind: ProcMacroClientKind::Process { process: Arc::new(process), thread },
70 })
71 }
72
73 pub fn dummy() -> ProcMacroClient {
74 ProcMacroClient { kind: ProcMacroClientKind::Dummy }
75 }
76
77 pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<(SmolStr, Arc<dyn tt::TokenExpander>)> {
78 match &self.kind {
79 ProcMacroClientKind::Dummy => vec![],
80 ProcMacroClientKind::Process { process, .. } => {
81 let macros = match process.find_proc_macros(dylib_path) {
82 Err(err) => {
83 eprintln!("Failed to find proc macros. Error: {:#?}", err);
84 return vec![];
85 }
86 Ok(macros) => macros,
87 };
88
89 macros
90 .into_iter()
91 .filter_map(|(name, kind)| {
92 match kind {
93 ProcMacroKind::CustomDerive | ProcMacroKind::FuncLike => {
94 let name = SmolStr::new(&name);
95 let expander: Arc<dyn tt::TokenExpander> =
96 Arc::new(ProcMacroProcessExpander {
97 process: process.clone(),
98 name: name.clone(),
99 dylib_path: dylib_path.into(),
100 });
101 Some((name, expander))
102 }
103 // FIXME: Attribute macro are currently unsupported.
104 ProcMacroKind::Attr => None,
105 }
106 })
107 .collect()
108 }
109 }
110 }
111}