aboutsummaryrefslogtreecommitdiff
path: root/crates/proc_macro_api
diff options
context:
space:
mode:
Diffstat (limited to 'crates/proc_macro_api')
-rw-r--r--crates/proc_macro_api/Cargo.toml1
-rw-r--r--crates/proc_macro_api/src/lib.rs86
-rw-r--r--crates/proc_macro_api/src/process.rs81
-rw-r--r--crates/proc_macro_api/src/rpc.rs2
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"
17jod-thread = "0.1.1" 17jod-thread = "0.1.1"
18 18
19tt = { path = "../tt", version = "0.0.0" } 19tt = { path = "../tt", version = "0.0.0" }
20base_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
19use base_db::ProcMacro;
19use tt::{SmolStr, Subtree}; 20use tt::{SmolStr, Subtree};
20 21
21use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread}; 22use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread};
@@ -23,7 +24,7 @@ use crate::process::{ProcMacroProcessSrv, ProcMacroProcessThread};
23pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind}; 24pub use rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};
24 25
25#[derive(Debug, Clone)] 26#[derive(Debug, Clone)]
26pub struct ProcMacroProcessExpander { 27struct 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))?;
52enum 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)]
58pub struct ProcMacroClient { 61pub struct ProcMacroClient {
59 kind: ProcMacroClientKind, 62 process: Arc<ProcMacroProcessSrv>,
63 thread: ProcMacroProcessThread,
60} 64}
61 65
62impl ProcMacroClient { 66impl 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
12use crossbeam_channel::{bounded, Receiver, Sender}; 12use crossbeam_channel::{bounded, Receiver, Sender};
13use tt::Subtree;
14 13
15use crate::{ 14use 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)]
21pub(crate) struct ProcMacroProcessSrv { 20pub(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
111fn client_loop(task_rx: Receiver<Task>, mut process: Process) { 89fn 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
148struct Process { 117struct 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)]
23pub enum ProcMacroKind { 23pub enum ProcMacroKind {
24 CustomDerive, 24 CustomDerive,
25 FuncLike, 25 FuncLike,