Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/proc-macro-api/src/process.rs')
-rw-r--r--crates/proc-macro-api/src/process.rs64
1 files changed, 63 insertions, 1 deletions
diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs
index fe274a027a..95b12d0b24 100644
--- a/crates/proc-macro-api/src/process.rs
+++ b/crates/proc-macro-api/src/process.rs
@@ -31,6 +31,7 @@ pub(crate) struct ProcMacroServerProcess {
#[derive(Debug)]
enum Protocol {
LegacyJson { mode: SpanMode },
+ Postcard { mode: SpanMode },
}
/// Maintains the state of the proc-macro server process.
@@ -82,7 +83,11 @@ impl ProcMacroServerProcess {
if srv.version >= version::RUST_ANALYZER_SPAN_SUPPORT
&& let Ok(mode) = srv.enable_rust_analyzer_spans()
{
- srv.protocol = Protocol::LegacyJson { mode };
+ if srv.version >= version::POSTCARD_WIRE {
+ srv.protocol = Protocol::Postcard { mode };
+ } else {
+ srv.protocol = Protocol::LegacyJson { mode };
+ }
}
tracing::info!("Proc-macro server protocol: {:?}", srv.protocol);
Ok(srv)
@@ -99,6 +104,10 @@ impl ProcMacroServerProcess {
self.exited.get().map(|it| &it.0)
}
+ pub(crate) fn use_postcard(&self) -> bool {
+ matches!(self.protocol, Protocol::Postcard { .. })
+ }
+
/// Retrieves the API version of the proc-macro server.
pub(crate) fn version(&self) -> u32 {
self.version
@@ -108,6 +117,7 @@ impl ProcMacroServerProcess {
pub(crate) fn rust_analyzer_spans(&self) -> bool {
match self.protocol {
Protocol::LegacyJson { mode } => mode == SpanMode::RustAnalyzer,
+ Protocol::Postcard { mode } => mode == SpanMode::RustAnalyzer,
}
}
@@ -115,6 +125,7 @@ impl ProcMacroServerProcess {
fn version_check(&self) -> Result<u32, ServerError> {
match self.protocol {
Protocol::LegacyJson { .. } => legacy_protocol::version_check(self),
+ Protocol::Postcard { .. } => legacy_protocol::version_check(self),
}
}
@@ -122,6 +133,7 @@ impl ProcMacroServerProcess {
fn enable_rust_analyzer_spans(&self) -> Result<SpanMode, ServerError> {
match self.protocol {
Protocol::LegacyJson { .. } => legacy_protocol::enable_rust_analyzer_spans(self),
+ Protocol::Postcard { .. } => legacy_protocol::enable_rust_analyzer_spans(self),
}
}
@@ -132,6 +144,7 @@ impl ProcMacroServerProcess {
) -> Result<Result<Vec<(String, ProcMacroKind)>, String>, ServerError> {
match self.protocol {
Protocol::LegacyJson { .. } => legacy_protocol::find_proc_macros(self, dylib_path),
+ Protocol::Postcard { .. } => legacy_protocol::find_proc_macros(self, dylib_path),
}
}
@@ -188,6 +201,55 @@ impl ProcMacroServerProcess {
}
})
}
+
+ pub(crate) fn send_task_bin<Request, Response>(
+ &self,
+ serialize_req: impl FnOnce(
+ &mut dyn Write,
+ &mut dyn BufRead,
+ Request,
+ &mut Vec<u8>,
+ ) -> Result<Option<Response>, ServerError>,
+ req: Request,
+ ) -> Result<Response, ServerError> {
+ let state = &mut *self.state.lock().unwrap();
+ let mut buf = Vec::<u8>::new();
+ serialize_req(&mut state.stdin, &mut state.stdout, req, &mut buf)
+ .and_then(|res| {
+ res.ok_or_else(|| ServerError {
+ message: "proc-macro server did not respond with data".to_owned(),
+ io: Some(Arc::new(io::Error::new(
+ io::ErrorKind::BrokenPipe,
+ "proc-macro server did not respond with data",
+ ))),
+ })
+ })
+ .map_err(|e| {
+ if e.io.as_ref().map(|it| it.kind()) == Some(io::ErrorKind::BrokenPipe) {
+ match state.process.child.try_wait() {
+ Ok(None) | Err(_) => e,
+ Ok(Some(status)) => {
+ let mut msg = String::new();
+ if !status.success()
+ && let Some(stderr) = state.process.child.stderr.as_mut()
+ {
+ _ = stderr.read_to_string(&mut msg);
+ }
+ let server_error = ServerError {
+ message: format!(
+ "proc-macro server exited with {status}{}{msg}",
+ if msg.is_empty() { "" } else { ": " }
+ ),
+ io: None,
+ };
+ self.exited.get_or_init(|| AssertUnwindSafe(server_error)).0.clone()
+ }
+ }
+ } else {
+ e
+ }
+ })
+ }
}
/// Manages the execution of the proc-macro server process.