diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2024-06-30 16:54:31 +0200 |
|---|---|---|
| committer | Lukas Wirth <lukastw97@gmail.com> | 2024-06-30 16:56:30 +0200 |
| commit | 45362de42f5143874671c3db82933eea1785d2c2 (patch) | |
| tree | d62cf246b84c12a4a49c3624812f7c07043e25c8 /src/tools/rust-analyzer/crates/proc-macro-api | |
| parent | b1518b262e177b23362a72adf5d3e3ba23cf44fe (diff) | |
Abstract proc-macro-srv protocol format
Diffstat (limited to 'src/tools/rust-analyzer/crates/proc-macro-api')
4 files changed, 51 insertions, 35 deletions
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 00000000000..415845c0bdc --- /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<Option<&'a String>> { + 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 f21411bc814..d7f49013aee 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 49ebedba7dd..fa3ba9bbfcd 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<Option<Self>> { - Ok(match read_json(inp, buf)? { + fn read<R: BufRead>( + from_proto: ProtocolRead<R>, + inp: &mut R, + buf: &mut String, + ) -> io::Result<Option<Self>> { + 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<W: Write>(self, to_proto: ProtocolWrite<W>, 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<Option<&'a String>> { - 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<R: BufRead> = + for<'i, 'buf> fn(inp: &'i mut R, buf: &'buf mut String) -> io::Result<Option<&'buf String>>; +#[allow(type_alias_bounds)] +type ProtocolWrite<W: Write> = 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 3a1a4cfa131..2b1a791827a 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<Response, ServerError> { - 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)), })?; |
