Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/proc-macro-api/src/bidirectional_protocol.rs')
| -rw-r--r-- | crates/proc-macro-api/src/bidirectional_protocol.rs | 62 |
1 files changed, 31 insertions, 31 deletions
diff --git a/crates/proc-macro-api/src/bidirectional_protocol.rs b/crates/proc-macro-api/src/bidirectional_protocol.rs index e44723a6a3..ba59cb219b 100644 --- a/crates/proc-macro-api/src/bidirectional_protocol.rs +++ b/crates/proc-macro-api/src/bidirectional_protocol.rs @@ -2,6 +2,7 @@ use std::{ io::{self, BufRead, Write}, + panic::{AssertUnwindSafe, catch_unwind}, sync::Arc, }; @@ -9,7 +10,7 @@ use paths::AbsPath; use span::Span; use crate::{ - Codec, ProcMacro, ProcMacroKind, ServerError, + ProcMacro, ProcMacroKind, ServerError, bidirectional_protocol::msg::{ BidirectionalMessage, ExpandMacro, ExpandMacroData, ExpnGlobals, Request, Response, SubRequest, SubResponse, @@ -22,26 +23,25 @@ use crate::{ }, }, process::ProcMacroServerProcess, - transport::codec::postcard::PostcardProtocol, - version, + transport::postcard, }; pub mod msg; -pub type SubCallback<'a> = &'a mut dyn FnMut(SubRequest) -> Result<SubResponse, ServerError>; +pub type SubCallback<'a> = &'a dyn Fn(SubRequest) -> Result<SubResponse, ServerError>; -pub fn run_conversation<C: Codec>( +pub fn run_conversation( writer: &mut dyn Write, reader: &mut dyn BufRead, - buf: &mut C::Buf, + buf: &mut Vec<u8>, msg: BidirectionalMessage, callback: SubCallback<'_>, ) -> Result<BidirectionalMessage, ServerError> { - let encoded = C::encode(&msg).map_err(wrap_encode)?; - C::write(writer, &encoded).map_err(wrap_io("failed to write initial request"))?; + let encoded = postcard::encode(&msg).map_err(wrap_encode)?; + postcard::write(writer, &encoded).map_err(wrap_io("failed to write initial request"))?; loop { - let maybe_buf = C::read(reader, buf).map_err(wrap_io("failed to read message"))?; + let maybe_buf = postcard::read(reader, buf).map_err(wrap_io("failed to read message"))?; let Some(b) = maybe_buf else { return Err(ServerError { message: "proc-macro server closed the stream".into(), @@ -49,17 +49,28 @@ pub fn run_conversation<C: Codec>( }); }; - let msg: BidirectionalMessage = C::decode(b).map_err(wrap_decode)?; + let msg: BidirectionalMessage = postcard::decode(b).map_err(wrap_decode)?; match msg { BidirectionalMessage::Response(response) => { return Ok(BidirectionalMessage::Response(response)); } BidirectionalMessage::SubRequest(sr) => { - let resp = callback(sr)?; - let reply = BidirectionalMessage::SubResponse(resp); - let encoded = C::encode(&reply).map_err(wrap_encode)?; - C::write(writer, &encoded).map_err(wrap_io("failed to write sub-response"))?; + // TODO: Avoid `AssertUnwindSafe` by making the callback `UnwindSafe` once `ExpandDatabase` + // becomes unwind-safe (currently blocked by `parking_lot::RwLock` in the VFS). + let resp = match catch_unwind(AssertUnwindSafe(|| callback(sr))) { + Ok(Ok(resp)) => BidirectionalMessage::SubResponse(resp), + Ok(Err(err)) => BidirectionalMessage::SubResponse(SubResponse::Cancel { + reason: err.to_string(), + }), + Err(_) => BidirectionalMessage::SubResponse(SubResponse::Cancel { + reason: "callback panicked or was cancelled".into(), + }), + }; + + let encoded = postcard::encode(&resp).map_err(wrap_encode)?; + postcard::write(writer, &encoded) + .map_err(wrap_io("failed to write sub-response"))?; } _ => { return Err(ServerError { @@ -138,6 +149,7 @@ pub(crate) fn find_proc_macros( pub(crate) fn expand( proc_macro: &ProcMacro, + process: &ProcMacroServerProcess, subtree: tt::SubtreeView<'_>, attr: Option<tt::SubtreeView<'_>>, env: Vec<(String, String)>, @@ -147,7 +159,7 @@ pub(crate) fn expand( current_dir: String, callback: SubCallback<'_>, ) -> Result<Result<tt::TopSubtree, String>, crate::ServerError> { - let version = proc_macro.process.version(); + let version = process.version(); let mut span_data_table = SpanDataIndexMap::default(); let def_site = span_data_table.insert_full(def_site).0; let call_site = span_data_table.insert_full(call_site).0; @@ -158,13 +170,8 @@ pub(crate) fn expand( macro_name: proc_macro.name.to_string(), attributes: attr .map(|subtree| FlatTree::from_subtree(subtree, version, &mut span_data_table)), - has_global_spans: ExpnGlobals { - serialize: version >= version::HAS_GLOBAL_SPANS, - def_site, - call_site, - mixed_site, - }, - span_data_table: if proc_macro.process.rust_analyzer_spans() { + has_global_spans: ExpnGlobals { def_site, call_site, mixed_site }, + span_data_table: if process.rust_analyzer_spans() { serialize_span_data_index_map(&span_data_table) } else { Vec::new() @@ -175,7 +182,7 @@ pub(crate) fn expand( current_dir: Some(current_dir), }))); - let response_payload = run_request(&proc_macro.process, task, callback)?; + let response_payload = run_request(process, task, callback)?; match response_payload { BidirectionalMessage::Response(Response::ExpandMacro(it)) => Ok(it @@ -212,14 +219,7 @@ fn run_request( if let Some(err) = srv.exited() { return Err(err.clone()); } - - match srv.use_postcard() { - true => srv.run_bidirectional::<PostcardProtocol>(msg, callback), - false => Err(ServerError { - message: "bidirectional messaging does not support JSON".to_owned(), - io: None, - }), - } + srv.run_bidirectional(msg, callback) } pub fn reject_subrequests(req: SubRequest) -> Result<SubResponse, ServerError> { |