diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/json.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/json.rs new file mode 100644 index 000000000000..415845c0bdc7 --- /dev/null +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/json.rs @@ -0,0 +1,34 @@ +use std::io::{self, BufRead, Write}; + +pub fn read_json<'a>( + inp: &mut impl BufRead, + buf: &'a mut String, +) -> io::Result> { + loop { + buf.clear(); + + inp.read_line(buf)?; + buf.pop(); // Remove trailing '\n' + + if buf.is_empty() { + return Ok(None); + } + + // Some ill behaved macro try to use stdout for debugging + // We ignore it here + if !buf.starts_with('{') { + tracing::error!("proc-macro tried to print : {}", buf); + continue; + } + + return Ok(Some(buf)); + } +} + +pub fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { + tracing::debug!("> {}", msg); + out.write_all(msg.as_bytes())?; + out.write_all(b"\n")?; + out.flush()?; + Ok(()) +} diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index f21411bc8143..d7f49013aee1 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -5,6 +5,7 @@ //! is used to provide basic infrastructure for communication between two //! processes: Client (RA itself), Server (the external program) +pub mod json; pub mod msg; mod process; diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs index 49ebedba7ddf..fa3ba9bbfcd7 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs @@ -122,8 +122,12 @@ impl ExpnGlobals { } pub trait Message: Serialize + DeserializeOwned { - fn read(inp: &mut impl BufRead, buf: &mut String) -> io::Result> { - Ok(match read_json(inp, buf)? { + fn read( + from_proto: ProtocolRead, + inp: &mut R, + buf: &mut String, + ) -> io::Result> { + Ok(match from_proto(inp, buf)? { None => None, Some(text) => { let mut deserializer = serde_json::Deserializer::from_str(text); @@ -134,44 +138,20 @@ pub trait Message: Serialize + DeserializeOwned { } }) } - fn write(self, out: &mut impl Write) -> io::Result<()> { + fn write(self, to_proto: ProtocolWrite, out: &mut W) -> io::Result<()> { let text = serde_json::to_string(&self)?; - write_json(out, &text) + to_proto(out, &text) } } impl Message for Request {} impl Message for Response {} -fn read_json<'a>(inp: &mut impl BufRead, buf: &'a mut String) -> io::Result> { - loop { - buf.clear(); - - inp.read_line(buf)?; - buf.pop(); // Remove trailing '\n' - - if buf.is_empty() { - return Ok(None); - } - - // Some ill behaved macro try to use stdout for debugging - // We ignore it here - if !buf.starts_with('{') { - tracing::error!("proc-macro tried to print : {}", buf); - continue; - } - - return Ok(Some(buf)); - } -} - -fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { - tracing::debug!("> {}", msg); - out.write_all(msg.as_bytes())?; - out.write_all(b"\n")?; - out.flush()?; - Ok(()) -} +#[allow(type_alias_bounds)] +type ProtocolRead = + for<'i, 'buf> fn(inp: &'i mut R, buf: &'buf mut String) -> io::Result>; +#[allow(type_alias_bounds)] +type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) -> io::Result<()>; #[cfg(test)] mod tests { diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs index 3a1a4cfa131b..2b1a791827a7 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs @@ -10,6 +10,7 @@ use paths::AbsPath; use stdx::JodChild; use crate::{ + json::{read_json, write_json}, msg::{Message, Request, Response, SpanMode, CURRENT_API_VERSION, RUST_ANALYZER_SPAN_SUPPORT}, ProcMacroKind, ServerError, }; @@ -201,11 +202,11 @@ fn send_request( req: Request, buf: &mut String, ) -> Result { - req.write(&mut writer).map_err(|err| ServerError { + req.write(write_json, &mut writer).map_err(|err| ServerError { message: "failed to write request".into(), io: Some(Arc::new(err)), })?; - let res = Response::read(&mut reader, buf).map_err(|err| ServerError { + let res = Response::read(read_json, &mut reader, buf).map_err(|err| ServerError { message: "failed to read response".into(), io: Some(Arc::new(err)), })?; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs index 407c1969cbd7..174f9c524621 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs @@ -6,6 +6,8 @@ #[cfg(feature = "in-rust-tree")] extern crate rustc_driver as _; +use proc_macro_api::json::{read_json, write_json}; + use std::io; fn main() -> std::io::Result<()> { @@ -30,9 +32,10 @@ fn run() -> io::Result<()> { eprintln!("{err}"); use proc_macro_api::msg::{self, Message}; - let read_request = |buf: &mut String| msg::Request::read(&mut io::stdin().lock(), buf); + let read_request = + |buf: &mut String| msg::Request::read(read_json, &mut io::stdin().lock(), buf); - let write_response = |msg: msg::Response| msg.write(&mut io::stdout().lock()); + let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock()); let mut buf = String::new(); @@ -61,9 +64,10 @@ fn run() -> io::Result<()> { use proc_macro_api::msg::{self, Message}; use proc_macro_srv::EnvSnapshot; - let read_request = |buf: &mut String| msg::Request::read(&mut io::stdin().lock(), buf); + let read_request = + |buf: &mut String| msg::Request::read(read_json, &mut io::stdin().lock(), buf); - let write_response = |msg: msg::Response| msg.write(&mut io::stdout().lock()); + let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock()); let env = EnvSnapshot::new(); let mut srv = proc_macro_srv::ProcMacroSrv::new(&env); diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs index c2309cb3d116..78ae4574c409 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs @@ -142,6 +142,7 @@ impl Drop for Expander { fn drop(&mut self) { #[cfg(windows)] std::fs::remove_file(&self.path).ok(); + _ = self.path; } }