diff options
-rw-r--r-- | crates/ra_proc_macro/src/lib.rs | 16 | ||||
-rw-r--r-- | crates/ra_proc_macro/src/process.rs | 57 |
2 files changed, 54 insertions, 19 deletions
diff --git a/crates/ra_proc_macro/src/lib.rs b/crates/ra_proc_macro/src/lib.rs index a0a478dc8..51fbb046a 100644 --- a/crates/ra_proc_macro/src/lib.rs +++ b/crates/ra_proc_macro/src/lib.rs | |||
@@ -9,7 +9,7 @@ mod rpc; | |||
9 | mod process; | 9 | mod process; |
10 | pub mod msg; | 10 | pub mod msg; |
11 | 11 | ||
12 | use process::ProcMacroProcessSrv; | 12 | use process::{ProcMacroProcessSrv, ProcMacroProcessThread}; |
13 | use ra_tt::{SmolStr, Subtree}; | 13 | use ra_tt::{SmolStr, Subtree}; |
14 | use rpc::ProcMacroKind; | 14 | use rpc::ProcMacroKind; |
15 | use std::{ | 15 | use std::{ |
@@ -45,21 +45,23 @@ impl ra_tt::TokenExpander for ProcMacroProcessExpander { | |||
45 | } | 45 | } |
46 | } | 46 | } |
47 | 47 | ||
48 | #[derive(Debug, Clone)] | 48 | #[derive(Debug)] |
49 | enum ProcMacroClientKind { | 49 | enum ProcMacroClientKind { |
50 | Process { process: Arc<ProcMacroProcessSrv> }, | 50 | Process { process: Arc<ProcMacroProcessSrv>, thread: ProcMacroProcessThread }, |
51 | Dummy, | 51 | Dummy, |
52 | } | 52 | } |
53 | 53 | ||
54 | #[derive(Debug, Clone)] | 54 | #[derive(Debug)] |
55 | pub struct ProcMacroClient { | 55 | pub struct ProcMacroClient { |
56 | kind: ProcMacroClientKind, | 56 | kind: ProcMacroClientKind, |
57 | } | 57 | } |
58 | 58 | ||
59 | impl ProcMacroClient { | 59 | impl ProcMacroClient { |
60 | pub fn extern_process(process_path: &Path) -> Result<ProcMacroClient, std::io::Error> { | 60 | pub fn extern_process(process_path: &Path) -> Result<ProcMacroClient, std::io::Error> { |
61 | let process = ProcMacroProcessSrv::run(process_path)?; | 61 | let (thread, process) = ProcMacroProcessSrv::run(process_path)?; |
62 | Ok(ProcMacroClient { kind: ProcMacroClientKind::Process { process: Arc::new(process) } }) | 62 | Ok(ProcMacroClient { |
63 | kind: ProcMacroClientKind::Process { process: Arc::new(process), thread }, | ||
64 | }) | ||
63 | } | 65 | } |
64 | 66 | ||
65 | pub fn dummy() -> ProcMacroClient { | 67 | pub fn dummy() -> ProcMacroClient { |
@@ -72,7 +74,7 @@ impl ProcMacroClient { | |||
72 | ) -> Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)> { | 74 | ) -> Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)> { |
73 | match &self.kind { | 75 | match &self.kind { |
74 | ProcMacroClientKind::Dummy => vec![], | 76 | ProcMacroClientKind::Dummy => vec![], |
75 | ProcMacroClientKind::Process { process } => { | 77 | ProcMacroClientKind::Process { process, .. } => { |
76 | let macros = match process.find_proc_macros(dylib_path) { | 78 | let macros = match process.find_proc_macros(dylib_path) { |
77 | Err(err) => { | 79 | Err(err) => { |
78 | eprintln!("Fail to find proc macro. Error: {:#?}", err); | 80 | eprintln!("Fail to find proc macro. Error: {:#?}", err); |
diff --git a/crates/ra_proc_macro/src/process.rs b/crates/ra_proc_macro/src/process.rs index 6a3fe2e20..d028b365c 100644 --- a/crates/ra_proc_macro/src/process.rs +++ b/crates/ra_proc_macro/src/process.rs | |||
@@ -11,7 +11,7 @@ use std::{ | |||
11 | io::{self, Write}, | 11 | io::{self, Write}, |
12 | path::{Path, PathBuf}, | 12 | path::{Path, PathBuf}, |
13 | process::{Child, Command, Stdio}, | 13 | process::{Child, Command, Stdio}, |
14 | thread::spawn, | 14 | thread::{spawn, JoinHandle}, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | #[derive(Debug, Default)] | 17 | #[derive(Debug, Default)] |
@@ -19,9 +19,15 @@ pub(crate) struct ProcMacroProcessSrv { | |||
19 | inner: Option<Handle>, | 19 | inner: Option<Handle>, |
20 | } | 20 | } |
21 | 21 | ||
22 | struct Task { | 22 | #[derive(Debug)] |
23 | req: Message, | 23 | pub(crate) struct ProcMacroProcessThread { |
24 | result_tx: Sender<Message>, | 24 | handle: Option<JoinHandle<()>>, |
25 | sender: Sender<Task>, | ||
26 | } | ||
27 | |||
28 | enum Task { | ||
29 | Request { req: Message, result_tx: Sender<Message> }, | ||
30 | Close, | ||
25 | } | 31 | } |
26 | 32 | ||
27 | #[derive(Debug)] | 33 | #[derive(Debug)] |
@@ -60,16 +66,33 @@ impl Process { | |||
60 | } | 66 | } |
61 | } | 67 | } |
62 | 68 | ||
69 | impl std::ops::Drop for ProcMacroProcessThread { | ||
70 | fn drop(&mut self) { | ||
71 | if let Some(handle) = self.handle.take() { | ||
72 | let _ = self.sender.send(Task::Close); | ||
73 | |||
74 | // Join the thread, it should finish shortly. We don't really care | ||
75 | // whether it panicked, so it is safe to ignore the result | ||
76 | let _ = handle.join(); | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
63 | impl ProcMacroProcessSrv { | 81 | impl ProcMacroProcessSrv { |
64 | pub fn run(process_path: &Path) -> Result<ProcMacroProcessSrv, io::Error> { | 82 | pub fn run( |
83 | process_path: &Path, | ||
84 | ) -> Result<(ProcMacroProcessThread, ProcMacroProcessSrv), io::Error> { | ||
65 | let process = Process::run(process_path)?; | 85 | let process = Process::run(process_path)?; |
66 | 86 | ||
67 | let (task_tx, task_rx) = bounded(0); | 87 | let (task_tx, task_rx) = bounded(0); |
68 | 88 | let handle = spawn(move || { | |
69 | let _ = spawn(move || { | ||
70 | client_loop(task_rx, process); | 89 | client_loop(task_rx, process); |
71 | }); | 90 | }); |
72 | Ok(ProcMacroProcessSrv { inner: Some(Handle { sender: task_tx }) }) | 91 | |
92 | let srv = ProcMacroProcessSrv { inner: Some(Handle { sender: task_tx.clone() }) }; | ||
93 | let thread = ProcMacroProcessThread { handle: Some(handle), sender: task_tx }; | ||
94 | |||
95 | Ok((thread, srv)) | ||
73 | } | 96 | } |
74 | 97 | ||
75 | pub fn find_proc_macros( | 98 | pub fn find_proc_macros( |
@@ -117,7 +140,12 @@ impl ProcMacroProcessSrv { | |||
117 | 140 | ||
118 | let (result_tx, result_rx) = bounded(0); | 141 | let (result_tx, result_rx) = bounded(0); |
119 | 142 | ||
120 | handle.sender.send(Task { req: req.into(), result_tx }).unwrap(); | 143 | handle.sender.send(Task::Request { req: req.into(), result_tx }).map_err(|err| { |
144 | ra_tt::ExpansionError::Unknown(format!( | ||
145 | "Fail to send task in channel, reason : {:#?} ", | ||
146 | err | ||
147 | )) | ||
148 | })?; | ||
121 | let response = result_rx.recv().unwrap(); | 149 | let response = result_rx.recv().unwrap(); |
122 | 150 | ||
123 | match response { | 151 | match response { |
@@ -155,7 +183,12 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) { | |||
155 | Err(_) => break, | 183 | Err(_) => break, |
156 | }; | 184 | }; |
157 | 185 | ||
158 | let res = match send_message(&mut stdin, &mut stdout, task.req) { | 186 | let (req, result_tx) = match task { |
187 | Task::Request { req, result_tx } => (req, result_tx), | ||
188 | Task::Close => break, | ||
189 | }; | ||
190 | |||
191 | let res = match send_message(&mut stdin, &mut stdout, req) { | ||
159 | Ok(res) => res, | 192 | Ok(res) => res, |
160 | Err(_err) => { | 193 | Err(_err) => { |
161 | let res = Response { | 194 | let res = Response { |
@@ -167,7 +200,7 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) { | |||
167 | data: None, | 200 | data: None, |
168 | }), | 201 | }), |
169 | }; | 202 | }; |
170 | if task.result_tx.send(res.into()).is_err() { | 203 | if result_tx.send(res.into()).is_err() { |
171 | break; | 204 | break; |
172 | } | 205 | } |
173 | // Restart the process | 206 | // Restart the process |
@@ -185,7 +218,7 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) { | |||
185 | }; | 218 | }; |
186 | 219 | ||
187 | if let Some(res) = res { | 220 | if let Some(res) = res { |
188 | if task.result_tx.send(res).is_err() { | 221 | if result_tx.send(res).is_err() { |
189 | break; | 222 | break; |
190 | } | 223 | } |
191 | } | 224 | } |