diff options
Diffstat (limited to 'crates/proc_macro_api')
-rw-r--r-- | crates/proc_macro_api/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/proc_macro_api/src/lib.rs | 86 | ||||
-rw-r--r-- | crates/proc_macro_api/src/process.rs | 81 | ||||
-rw-r--r-- | crates/proc_macro_api/src/rpc.rs | 2 |
4 files changed, 62 insertions, 108 deletions
diff --git a/crates/proc_macro_api/Cargo.toml b/crates/proc_macro_api/Cargo.toml index 3863e5189..1af2bbca7 100644 --- a/crates/proc_macro_api/Cargo.toml +++ b/crates/proc_macro_api/Cargo.toml | |||
@@ -17,3 +17,4 @@ crossbeam-channel = "0.5.0" | |||
17 | jod-thread = "0.1.1" | 17 | jod-thread = "0.1.1" |
18 | 18 | ||
19 | tt = { path = "../tt", version = "0.0.0" } | 19 | tt = { path = "../tt", version = "0.0.0" } |
20 | base_db = { path = "../base_db", version = "0.0.0" } | ||
diff --git a/crates/proc_macro_api/src/lib.rs b/crates/proc_macro_api/src/lib.rs index d5e87cf7d..0d061fd53 100644 --- a/crates/proc_macro_api/src/lib.rs +++ b/crates/proc_macro_api/src/lib.rs | |||
@@ -16,6 +16,7 @@ use std::{ | |||
16 | sync::Arc, | 16 | sync::Arc, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | use base_db::ProcMacro; | ||
19 | use tt::{SmolStr, Subtree}; | 20 | use tt::{SmolStr, Subtree}; |
20 | 21 | ||
21 | use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread}; | 22 | use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread}; |
@@ -23,7 +24,7 @@ use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread}; | |||
23 | pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}; | 24 | pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}; |
24 | 25 | ||
25 | #[derive(Debug, Clone)] | 26 | #[derive(Debug, Clone)] |
26 | pub struct ProcMacroProcessExpander { | 27 | struct ProcMacroProcessExpander { |
27 | process: Arc<ProcMacroProcessSrv>, | 28 | process: Arc<ProcMacroProcessSrv>, |
28 | dylib_path: PathBuf, | 29 | dylib_path: PathBuf, |
29 | name: SmolStr, | 30 | name: SmolStr, |
@@ -42,21 +43,24 @@ impl tt::TokenExpander for ProcMacroProcessExpander { | |||
42 | fn expand( | 43 | fn expand( |
43 | &self, | 44 | &self, |
44 | subtree: &Subtree, | 45 | subtree: &Subtree, |
45 | _attr: Option<&Subtree>, | 46 | attr: Option<&Subtree>, |
46 | ) -> Result<Subtree, tt::ExpansionError> { | 47 | ) -> Result<Subtree, tt::ExpansionError> { |
47 | self.process.custom_derive(&self.dylib_path, subtree, &self.name) | 48 | let task = ExpansionTask { |
48 | } | 49 | macro_body: subtree.clone(), |
49 | } | 50 | macro_name: self.name.to_string(), |
51 | attributes: attr.cloned(), | ||
52 | lib: self.dylib_path.to_path_buf(), | ||
53 | }; | ||
50 | 54 | ||
51 | #[derive(Debug)] | 55 | let result: ExpansionResult = self.process.send_task(msg::Request::ExpansionMacro(task))?; |
52 | enum ProcMacroClientKind { | 56 | Ok(result.expansion) |
53 | Process { process: Arc<ProcMacroProcessSrv>, thread: ProcMacroProcessThread }, | 57 | } |
54 | Dummy, | ||
55 | } | 58 | } |
56 | 59 | ||
57 | #[derive(Debug)] | 60 | #[derive(Debug)] |
58 | pub struct ProcMacroClient { | 61 | pub struct ProcMacroClient { |
59 | kind: ProcMacroClientKind, | 62 | process: Arc<ProcMacroProcessSrv>, |
63 | thread: ProcMacroProcessThread, | ||
60 | } | 64 | } |
61 | 65 | ||
62 | impl ProcMacroClient { | 66 | impl ProcMacroClient { |
@@ -65,47 +69,35 @@ impl ProcMacroClient { | |||
65 | args: impl IntoIterator<Item = impl AsRef<OsStr>>, | 69 | args: impl IntoIterator<Item = impl AsRef<OsStr>>, |
66 | ) -> io::Result<ProcMacroClient> { | 70 | ) -> io::Result<ProcMacroClient> { |
67 | let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?; | 71 | let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?; |
68 | Ok(ProcMacroClient { | 72 | Ok(ProcMacroClient { process: Arc::new(process), thread }) |
69 | kind: ProcMacroClientKind::Process { process: Arc::new(process), thread }, | ||
70 | }) | ||
71 | } | 73 | } |
72 | 74 | ||
73 | pub fn dummy() -> ProcMacroClient { | 75 | pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<ProcMacro> { |
74 | ProcMacroClient { kind: ProcMacroClientKind::Dummy } | 76 | let macros = match self.process.find_proc_macros(dylib_path) { |
75 | } | 77 | Err(err) => { |
78 | eprintln!("Failed to find proc macros. Error: {:#?}", err); | ||
79 | return vec![]; | ||
80 | } | ||
81 | Ok(macros) => macros, | ||
82 | }; | ||
76 | 83 | ||
77 | pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<(SmolStr, Arc<dyn tt::TokenExpander>)> { | 84 | macros |
78 | match &self.kind { | 85 | .into_iter() |
79 | ProcMacroClientKind::Dummy => vec![], | 86 | .map(|(name, kind)| { |
80 | ProcMacroClientKind::Process { process, .. } => { | 87 | let name = SmolStr::new(&name); |
81 | let macros = match process.find_proc_macros(dylib_path) { | 88 | let kind = match kind { |
82 | Err(err) => { | 89 | ProcMacroKind::CustomDerive => base_db::ProcMacroKind::CustomDerive, |
83 | eprintln!("Failed to find proc macros. Error: {:#?}", err); | 90 | ProcMacroKind::FuncLike => base_db::ProcMacroKind::FuncLike, |
84 | return vec![]; | 91 | ProcMacroKind::Attr => base_db::ProcMacroKind::Attr, |
85 | } | ||
86 | Ok(macros) => macros, | ||
87 | }; | 92 | }; |
93 | let expander: Arc<dyn tt::TokenExpander> = Arc::new(ProcMacroProcessExpander { | ||
94 | process: self.process.clone(), | ||
95 | name: name.clone(), | ||
96 | dylib_path: dylib_path.into(), | ||
97 | }); | ||
88 | 98 | ||
89 | macros | 99 | ProcMacro { name, kind, expander } |
90 | .into_iter() | 100 | }) |
91 | .filter_map(|(name, kind)| { | 101 | .collect() |
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 | } | 102 | } |
111 | } | 103 | } |
diff --git a/crates/proc_macro_api/src/process.rs b/crates/proc_macro_api/src/process.rs index 907cb3db7..d68723ada 100644 --- a/crates/proc_macro_api/src/process.rs +++ b/crates/proc_macro_api/src/process.rs | |||
@@ -10,16 +10,15 @@ use std::{ | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crossbeam_channel::{bounded, Receiver, Sender}; | 12 | use crossbeam_channel::{bounded, Receiver, Sender}; |
13 | use tt::Subtree; | ||
14 | 13 | ||
15 | use crate::{ | 14 | use crate::{ |
16 | msg::{ErrorCode, Message, Request, Response, ResponseError}, | 15 | msg::{ErrorCode, Message, Request, Response, ResponseError}, |
17 | rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}, | 16 | rpc::{ListMacrosResult, ListMacrosTask, ProcMacroKind}, |
18 | }; | 17 | }; |
19 | 18 | ||
20 | #[derive(Debug, Default)] | 19 | #[derive(Debug, Default)] |
21 | pub(crate) struct ProcMacroProcessSrv { | 20 | pub(crate) struct ProcMacroProcessSrv { |
22 | inner: Option<Weak<Sender<Task>>>, | 21 | inner: Weak<Sender<Task>>, |
23 | } | 22 | } |
24 | 23 | ||
25 | #[derive(Debug)] | 24 | #[derive(Debug)] |
@@ -42,7 +41,7 @@ impl ProcMacroProcessSrv { | |||
42 | }); | 41 | }); |
43 | 42 | ||
44 | let task_tx = Arc::new(task_tx); | 43 | let task_tx = Arc::new(task_tx); |
45 | let srv = ProcMacroProcessSrv { inner: Some(Arc::downgrade(&task_tx)) }; | 44 | let srv = ProcMacroProcessSrv { inner: Arc::downgrade(&task_tx) }; |
46 | let thread = ProcMacroProcessThread { handle, sender: task_tx }; | 45 | let thread = ProcMacroProcessThread { handle, sender: task_tx }; |
47 | 46 | ||
48 | Ok((thread, srv)) | 47 | Ok((thread, srv)) |
@@ -58,43 +57,22 @@ impl ProcMacroProcessSrv { | |||
58 | Ok(result.macros) | 57 | Ok(result.macros) |
59 | } | 58 | } |
60 | 59 | ||
61 | pub(crate) fn custom_derive( | ||
62 | &self, | ||
63 | dylib_path: &Path, | ||
64 | subtree: &Subtree, | ||
65 | derive_name: &str, | ||
66 | ) -> Result<Subtree, tt::ExpansionError> { | ||
67 | let task = ExpansionTask { | ||
68 | macro_body: subtree.clone(), | ||
69 | macro_name: derive_name.to_string(), | ||
70 | attributes: None, | ||
71 | lib: dylib_path.to_path_buf(), | ||
72 | }; | ||
73 | |||
74 | let result: ExpansionResult = self.send_task(Request::ExpansionMacro(task))?; | ||
75 | Ok(result.expansion) | ||
76 | } | ||
77 | |||
78 | pub(crate) fn send_task<R>(&self, req: Request) -> Result<R, tt::ExpansionError> | 60 | pub(crate) fn send_task<R>(&self, req: Request) -> Result<R, tt::ExpansionError> |
79 | where | 61 | where |
80 | R: TryFrom<Response, Error = &'static str>, | 62 | R: TryFrom<Response, Error = &'static str>, |
81 | { | 63 | { |
82 | let sender = match &self.inner { | ||
83 | None => return Err(tt::ExpansionError::Unknown("No sender is found.".to_string())), | ||
84 | Some(it) => it, | ||
85 | }; | ||
86 | |||
87 | let (result_tx, result_rx) = bounded(0); | 64 | let (result_tx, result_rx) = bounded(0); |
88 | let sender = match sender.upgrade() { | 65 | let sender = match self.inner.upgrade() { |
89 | None => { | 66 | None => return Err(tt::ExpansionError::Unknown("proc macro process is closed".into())), |
90 | return Err(tt::ExpansionError::Unknown("Proc macro process is closed.".into())) | ||
91 | } | ||
92 | Some(it) => it, | 67 | Some(it) => it, |
93 | }; | 68 | }; |
94 | sender.send(Task { req, result_tx }).unwrap(); | 69 | sender |
70 | .send(Task { req, result_tx }) | ||
71 | .map_err(|_| tt::ExpansionError::Unknown("proc macro server crashed".into()))?; | ||
72 | |||
95 | let res = result_rx | 73 | let res = result_rx |
96 | .recv() | 74 | .recv() |
97 | .map_err(|_| tt::ExpansionError::Unknown("Proc macro thread is closed.".into()))?; | 75 | .map_err(|_| tt::ExpansionError::Unknown("proc macro server crashed".into()))?; |
98 | 76 | ||
99 | match res { | 77 | match res { |
100 | Some(Response::Error(err)) => { | 78 | Some(Response::Error(err)) => { |
@@ -109,32 +87,23 @@ impl ProcMacroProcessSrv { | |||
109 | } | 87 | } |
110 | 88 | ||
111 | fn client_loop(task_rx: Receiver<Task>, mut process: Process) { | 89 | fn client_loop(task_rx: Receiver<Task>, mut process: Process) { |
112 | let (mut stdin, mut stdout) = match process.stdio() { | 90 | let (mut stdin, mut stdout) = process.stdio().expect("couldn't access child stdio"); |
113 | None => return, | ||
114 | Some(it) => it, | ||
115 | }; | ||
116 | |||
117 | for task in task_rx { | ||
118 | let Task { req, result_tx } = task; | ||
119 | 91 | ||
92 | for Task { req, result_tx } in task_rx { | ||
120 | match send_request(&mut stdin, &mut stdout, req) { | 93 | match send_request(&mut stdin, &mut stdout, req) { |
121 | Ok(res) => result_tx.send(res).unwrap(), | 94 | Ok(res) => result_tx.send(res).unwrap(), |
122 | Err(_err) => { | 95 | Err(_err) => { |
96 | log::error!( | ||
97 | "proc macro server crashed, server process state: {:?}", | ||
98 | process.child.try_wait() | ||
99 | ); | ||
123 | let res = Response::Error(ResponseError { | 100 | let res = Response::Error(ResponseError { |
124 | code: ErrorCode::ServerErrorEnd, | 101 | code: ErrorCode::ServerErrorEnd, |
125 | message: "Server closed".into(), | 102 | message: "proc macro server crashed".into(), |
126 | }); | 103 | }); |
127 | result_tx.send(res.into()).unwrap(); | 104 | result_tx.send(res.into()).unwrap(); |
128 | // Restart the process | 105 | // Exit the thread. |
129 | if process.restart().is_err() { | 106 | break; |
130 | break; | ||
131 | } | ||
132 | let stdio = match process.stdio() { | ||
133 | None => break, | ||
134 | Some(it) => it, | ||
135 | }; | ||
136 | stdin = stdio.0; | ||
137 | stdout = stdio.1; | ||
138 | } | 107 | } |
139 | } | 108 | } |
140 | } | 109 | } |
@@ -146,8 +115,6 @@ struct Task { | |||
146 | } | 115 | } |
147 | 116 | ||
148 | struct Process { | 117 | struct Process { |
149 | path: PathBuf, | ||
150 | args: Vec<OsString>, | ||
151 | child: Child, | 118 | child: Child, |
152 | } | 119 | } |
153 | 120 | ||
@@ -162,15 +129,9 @@ impl Process { | |||
162 | path: PathBuf, | 129 | path: PathBuf, |
163 | args: impl IntoIterator<Item = impl AsRef<OsStr>>, | 130 | args: impl IntoIterator<Item = impl AsRef<OsStr>>, |
164 | ) -> io::Result<Process> { | 131 | ) -> io::Result<Process> { |
165 | let args = args.into_iter().map(|s| s.as_ref().into()).collect(); | 132 | let args: Vec<OsString> = args.into_iter().map(|s| s.as_ref().into()).collect(); |
166 | let child = mk_child(&path, &args)?; | 133 | let child = mk_child(&path, &args)?; |
167 | Ok(Process { path, args, child }) | 134 | Ok(Process { child }) |
168 | } | ||
169 | |||
170 | fn restart(&mut self) -> io::Result<()> { | ||
171 | let _ = self.child.kill(); | ||
172 | self.child = mk_child(&self.path, &self.args)?; | ||
173 | Ok(()) | ||
174 | } | 135 | } |
175 | 136 | ||
176 | fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> { | 137 | fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> { |
diff --git a/crates/proc_macro_api/src/rpc.rs b/crates/proc_macro_api/src/rpc.rs index 203109ca4..b85f92eea 100644 --- a/crates/proc_macro_api/src/rpc.rs +++ b/crates/proc_macro_api/src/rpc.rs | |||
@@ -19,7 +19,7 @@ pub struct ListMacrosTask { | |||
19 | pub lib: PathBuf, | 19 | pub lib: PathBuf, |
20 | } | 20 | } |
21 | 21 | ||
22 | #[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] | 22 | #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] |
23 | pub enum ProcMacroKind { | 23 | pub enum ProcMacroKind { |
24 | CustomDerive, | 24 | CustomDerive, |
25 | FuncLike, | 25 | FuncLike, |