From 376bca919ea6a2b33ed0f232e357df5ce0f645c4 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 27 Nov 2025 18:56:47 +0530 Subject: [PATCH 1/7] Add bidirectional messaging proc-macro-srv --- Cargo.lock | 3 + .../hir-def/src/macro_expansion_tests/mod.rs | 3 +- crates/hir-expand/src/proc_macro.rs | 4 +- crates/load-cargo/src/lib.rs | 6 +- crates/proc-macro-api/Cargo.toml | 1 + .../src/bidirectional_protocol.rs | 296 +++++++++++++++++ .../src/bidirectional_protocol/msg.rs | 114 +++++++ crates/proc-macro-api/src/legacy_protocol.rs | 23 +- .../proc-macro-api/src/legacy_protocol/msg.rs | 2 +- crates/proc-macro-api/src/lib.rs | 11 +- crates/proc-macro-api/src/process.rs | 173 +++++++--- crates/proc-macro-api/src/transport.rs | 3 + .../src/{ => transport}/codec.rs | 5 +- .../codec}/json.rs | 6 +- .../codec}/postcard.rs | 6 +- .../src/{ => transport}/framing.rs | 4 +- crates/proc-macro-srv-cli/Cargo.toml | 1 + crates/proc-macro-srv-cli/src/main.rs | 6 + crates/proc-macro-srv-cli/src/main_loop.rs | 309 +++++++++++++++++- crates/proc-macro-srv/Cargo.toml | 1 + crates/proc-macro-srv/src/dylib.rs | 26 ++ .../proc-macro-srv/src/dylib/proc_macros.rs | 77 ++++- crates/proc-macro-srv/src/lib.rs | 86 ++++- .../src/server_impl/rust_analyzer_span.rs | 24 +- .../src/server_impl/token_id.rs | 4 + crates/test-fixture/src/lib.rs | 10 + 26 files changed, 1112 insertions(+), 92 deletions(-) create mode 100644 crates/proc-macro-api/src/bidirectional_protocol.rs create mode 100644 crates/proc-macro-api/src/bidirectional_protocol/msg.rs create mode 100644 crates/proc-macro-api/src/transport.rs rename crates/proc-macro-api/src/{ => transport}/codec.rs (76%) rename crates/proc-macro-api/src/{legacy_protocol => transport/codec}/json.rs (89%) rename crates/proc-macro-api/src/{legacy_protocol => transport/codec}/postcard.rs (84%) rename crates/proc-macro-api/src/{ => transport}/framing.rs (63%) diff --git a/Cargo.lock b/Cargo.lock index efe56cb7f61c..060a62b112b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1836,6 +1836,7 @@ dependencies = [ name = "proc-macro-api" version = "0.0.0" dependencies = [ + "base-db", "indexmap", "intern", "paths", @@ -1856,6 +1857,7 @@ dependencies = [ name = "proc-macro-srv" version = "0.0.0" dependencies = [ + "crossbeam-channel", "expect-test", "intern", "libc", @@ -1874,6 +1876,7 @@ name = "proc-macro-srv-cli" version = "0.0.0" dependencies = [ "clap", + "crossbeam-channel", "postcard", "proc-macro-api", "proc-macro-srv", diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 78af976e1b13..07cad9695b61 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -16,7 +16,7 @@ mod proc_macros; use std::{any::TypeId, iter, ops::Range, sync}; -use base_db::RootQueryDb; +use base_db::{RootQueryDb, SourceDatabase}; use expect_test::Expect; use hir_expand::{ AstId, InFile, MacroCallId, MacroCallKind, MacroKind, @@ -374,6 +374,7 @@ struct IdentityWhenValidProcMacroExpander; impl ProcMacroExpander for IdentityWhenValidProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &base_db::Env, diff --git a/crates/hir-expand/src/proc_macro.rs b/crates/hir-expand/src/proc_macro.rs index f97d721dfa88..d2614aa5f149 100644 --- a/crates/hir-expand/src/proc_macro.rs +++ b/crates/hir-expand/src/proc_macro.rs @@ -4,7 +4,7 @@ use core::fmt; use std::any::Any; use std::{panic::RefUnwindSafe, sync}; -use base_db::{Crate, CrateBuilderId, CratesIdMap, Env, ProcMacroLoadingError}; +use base_db::{Crate, CrateBuilderId, CratesIdMap, Env, ProcMacroLoadingError, SourceDatabase}; use intern::Symbol; use rustc_hash::FxHashMap; use span::Span; @@ -25,6 +25,7 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + Any { /// [`ProcMacroKind::Attr`]), environment variables, and span information. fn expand( &self, + db: &dyn SourceDatabase, subtree: &tt::TopSubtree, attrs: Option<&tt::TopSubtree>, env: &Env, @@ -309,6 +310,7 @@ impl CustomProcMacroExpander { let current_dir = calling_crate.data(db).proc_macro_cwd.to_string(); match proc_macro.expander.expand( + db, tt, attr_arg, env, diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index 28fbfecfde80..e043e4ac7634 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -17,7 +17,9 @@ use hir_expand::proc_macro::{ }; use ide_db::{ ChangeWithProcMacros, FxHashMap, RootDatabase, - base_db::{CrateGraphBuilder, Env, ProcMacroLoadingError, SourceRoot, SourceRootId}, + base_db::{ + CrateGraphBuilder, Env, ProcMacroLoadingError, SourceDatabase, SourceRoot, SourceRootId, + }, prime_caches, }; use itertools::Itertools; @@ -522,6 +524,7 @@ struct Expander(proc_macro_api::ProcMacro); impl ProcMacroExpander for Expander { fn expand( &self, + db: &dyn SourceDatabase, subtree: &tt::TopSubtree, attrs: Option<&tt::TopSubtree>, env: &Env, @@ -531,6 +534,7 @@ impl ProcMacroExpander for Expander { current_dir: String, ) -> Result, ProcMacroExpansionError> { match self.0.expand( + db, subtree.view(), attrs.map(|attrs| attrs.view()), env.clone().into(), diff --git a/crates/proc-macro-api/Cargo.toml b/crates/proc-macro-api/Cargo.toml index 4de1a3e5dd7d..7e56d68964ce 100644 --- a/crates/proc-macro-api/Cargo.toml +++ b/crates/proc-macro-api/Cargo.toml @@ -19,6 +19,7 @@ serde_json = { workspace = true, features = ["unbounded_depth"] } tracing.workspace = true rustc-hash.workspace = true indexmap.workspace = true +base-db.workspace = true # local deps paths = { workspace = true, features = ["serde1"] } diff --git a/crates/proc-macro-api/src/bidirectional_protocol.rs b/crates/proc-macro-api/src/bidirectional_protocol.rs new file mode 100644 index 000000000000..246f70a10196 --- /dev/null +++ b/crates/proc-macro-api/src/bidirectional_protocol.rs @@ -0,0 +1,296 @@ +//! Bidirectional protocol methods + +use std::{ + io::{self, BufRead, Write}, + sync::Arc, +}; + +use base_db::SourceDatabase; +use paths::AbsPath; +use span::{FileId, Span}; + +use crate::{ + Codec, ProcMacro, ProcMacroKind, ServerError, + bidirectional_protocol::msg::{ + Envelope, ExpandMacro, ExpandMacroData, ExpnGlobals, Kind, Payload, Request, RequestId, + Response, SubRequest, SubResponse, + }, + legacy_protocol::{ + SpanMode, + msg::{ + FlatTree, ServerConfig, SpanDataIndexMap, deserialize_span_data_index_map, + serialize_span_data_index_map, + }, + }, + process::ProcMacroServerProcess, + transport::codec::{json::JsonProtocol, postcard::PostcardProtocol}, + version, +}; + +pub mod msg; + +pub trait ClientCallbacks { + fn handle_sub_request(&mut self, id: u64, req: SubRequest) -> Result; +} + +pub fn run_conversation( + writer: &mut dyn Write, + reader: &mut dyn BufRead, + buf: &mut C::Buf, + id: RequestId, + initial: Payload, + callbacks: &mut dyn ClientCallbacks, +) -> Result { + let msg = Envelope { id, kind: Kind::Request, payload: initial }; + let encoded = C::encode(&msg).map_err(wrap_encode)?; + C::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 Some(b) = maybe_buf else { + return Err(ServerError { + message: "proc-macro server closed the stream".into(), + io: Some(Arc::new(io::Error::new(io::ErrorKind::UnexpectedEof, "closed"))), + }); + }; + + let msg: Envelope = C::decode(b).map_err(wrap_decode)?; + + if msg.id != id { + return Err(ServerError { + message: format!("unexpected message id {}, expected {}", msg.id, id), + io: None, + }); + } + + match (msg.kind, msg.payload) { + (Kind::SubRequest, Payload::SubRequest(sr)) => { + let resp = callbacks.handle_sub_request(id, sr)?; + let reply = + Envelope { id, kind: Kind::SubResponse, payload: Payload::SubResponse(resp) }; + let encoded = C::encode(&reply).map_err(wrap_encode)?; + C::write(writer, &encoded).map_err(wrap_io("failed to write sub-response"))?; + } + (Kind::Response, payload) => { + return Ok(payload); + } + (kind, payload) => { + return Err(ServerError { + message: format!( + "unexpected message kind {:?} with payload {:?}", + kind, payload + ), + io: None, + }); + } + } + } +} + +fn wrap_io(msg: &'static str) -> impl Fn(io::Error) -> ServerError { + move |err| ServerError { message: msg.into(), io: Some(Arc::new(err)) } +} + +fn wrap_encode(err: io::Error) -> ServerError { + ServerError { message: "failed to encode message".into(), io: Some(Arc::new(err)) } +} + +fn wrap_decode(err: io::Error) -> ServerError { + ServerError { message: "failed to decode message".into(), io: Some(Arc::new(err)) } +} + +pub(crate) fn version_check(srv: &ProcMacroServerProcess) -> Result { + let request = Payload::Request(Request::ApiVersionCheck {}); + + struct NoCallbacks; + impl ClientCallbacks for NoCallbacks { + fn handle_sub_request( + &mut self, + _id: u64, + _req: SubRequest, + ) -> Result { + Err(ServerError { message: "sub-request not supported here".into(), io: None }) + } + } + + let mut callbacks = NoCallbacks; + + let response_payload = + run_bidirectional(srv, (0, Kind::Request, request).into(), &mut callbacks)?; + + match response_payload { + Payload::Response(Response::ApiVersionCheck(version)) => Ok(version), + other => { + Err(ServerError { message: format!("unexpected response: {:?}", other), io: None }) + } + } +} + +/// Enable support for rust-analyzer span mode if the server supports it. +pub(crate) fn enable_rust_analyzer_spans( + srv: &ProcMacroServerProcess, +) -> Result { + let request = + Payload::Request(Request::SetConfig(ServerConfig { span_mode: SpanMode::RustAnalyzer })); + + struct NoCallbacks; + impl ClientCallbacks for NoCallbacks { + fn handle_sub_request( + &mut self, + _id: u64, + _req: SubRequest, + ) -> Result { + Err(ServerError { message: "sub-request not supported here".into(), io: None }) + } + } + + let mut callbacks = NoCallbacks; + + let response_payload = + run_bidirectional(srv, (0, Kind::Request, request).into(), &mut callbacks)?; + + match response_payload { + Payload::Response(Response::SetConfig(ServerConfig { span_mode })) => Ok(span_mode), + _ => Err(ServerError { message: "unexpected response".to_owned(), io: None }), + } +} + +/// Finds proc-macros in a given dynamic library. +pub(crate) fn find_proc_macros( + srv: &ProcMacroServerProcess, + dylib_path: &AbsPath, +) -> Result, String>, ServerError> { + let request = + Payload::Request(Request::ListMacros { dylib_path: dylib_path.to_path_buf().into() }); + + struct NoCallbacks; + impl ClientCallbacks for NoCallbacks { + fn handle_sub_request( + &mut self, + _id: u64, + _req: SubRequest, + ) -> Result { + Err(ServerError { message: "sub-request not supported here".into(), io: None }) + } + } + + let mut callbacks = NoCallbacks; + + let response_payload = + run_bidirectional(srv, (0, Kind::Request, request).into(), &mut callbacks)?; + + match response_payload { + Payload::Response(Response::ListMacros(it)) => Ok(it), + _ => Err(ServerError { message: "unexpected response".to_owned(), io: None }), + } +} + +pub(crate) fn expand( + proc_macro: &ProcMacro, + db: &dyn SourceDatabase, + subtree: tt::SubtreeView<'_, Span>, + attr: Option>, + env: Vec<(String, String)>, + def_site: Span, + call_site: Span, + mixed_site: Span, + current_dir: String, +) -> Result>, String>, crate::ServerError> +{ + let version = proc_macro.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; + let mixed_site = span_data_table.insert_full(mixed_site).0; + let task = Payload::Request(Request::ExpandMacro(Box::new(ExpandMacro { + data: ExpandMacroData { + macro_body: FlatTree::from_subtree(subtree, version, &mut span_data_table), + 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() { + serialize_span_data_index_map(&span_data_table) + } else { + Vec::new() + }, + }, + lib: proc_macro.dylib_path.to_path_buf().into(), + env, + current_dir: Some(current_dir), + }))); + + struct Callbacks<'de> { + db: &'de dyn SourceDatabase, + } + impl<'db> ClientCallbacks for Callbacks<'db> { + fn handle_sub_request( + &mut self, + _id: u64, + req: SubRequest, + ) -> Result { + match req { + SubRequest::SourceText { file_id, start, end } => { + let file = FileId::from_raw(file_id); + let text = self.db.file_text(file).text(self.db); + + let slice = text.get(start as usize..end as usize).map(|s| s.to_owned()); + + Ok(SubResponse::SourceTextResult { text: slice }) + } + } + } + } + + let mut callbacks = Callbacks { db }; + + let response_payload = + run_bidirectional(&proc_macro.process, (0, Kind::Request, task).into(), &mut callbacks)?; + + match response_payload { + Payload::Response(Response::ExpandMacro(it)) => Ok(it + .map(|tree| { + let mut expanded = FlatTree::to_subtree_resolved(tree, version, &span_data_table); + if proc_macro.needs_fixup_change() { + proc_macro.change_fixup_to_match_old_server(&mut expanded); + } + expanded + }) + .map_err(|msg| msg.0)), + Payload::Response(Response::ExpandMacroExtended(it)) => Ok(it + .map(|resp| { + let mut expanded = FlatTree::to_subtree_resolved( + resp.tree, + version, + &deserialize_span_data_index_map(&resp.span_data_table), + ); + if proc_macro.needs_fixup_change() { + proc_macro.change_fixup_to_match_old_server(&mut expanded); + } + expanded + }) + .map_err(|msg| msg.0)), + _ => Err(ServerError { message: "unexpected response".to_owned(), io: None }), + } +} + +fn run_bidirectional( + srv: &ProcMacroServerProcess, + msg: Envelope, + callbacks: &mut dyn ClientCallbacks, +) -> Result { + if let Some(server_error) = srv.exited() { + return Err(server_error.clone()); + } + + if srv.use_postcard() { + srv.run_bidirectional::(msg.id, msg.payload, callbacks) + } else { + srv.run_bidirectional::(msg.id, msg.payload, callbacks) + } +} diff --git a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs new file mode 100644 index 000000000000..7aed3ae1e607 --- /dev/null +++ b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs @@ -0,0 +1,114 @@ +//! Bidirectional protocol messages + +use paths::Utf8PathBuf; +use serde::{Deserialize, Serialize}; + +use crate::{ + ProcMacroKind, + legacy_protocol::msg::{FlatTree, Message, PanicMessage, ServerConfig}, +}; + +pub type RequestId = u64; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Envelope { + pub id: RequestId, + pub kind: Kind, + pub payload: Payload, +} + +impl From<(RequestId, Kind, Payload)> for Envelope { + fn from(value: (RequestId, Kind, Payload)) -> Self { + Envelope { id: value.0, kind: value.1, payload: value.2 } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] +pub enum Kind { + Request, + Response, + SubRequest, + SubResponse, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum SubRequest { + SourceText { file_id: u32, start: u32, end: u32 }, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum SubResponse { + SourceTextResult { text: Option }, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum Payload { + Request(Request), + Response(Response), + SubRequest(SubRequest), + SubResponse(SubResponse), +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum Request { + ListMacros { dylib_path: Utf8PathBuf }, + ExpandMacro(Box), + ApiVersionCheck {}, + SetConfig(ServerConfig), +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum Response { + ListMacros(Result, String>), + ExpandMacro(Result), + ApiVersionCheck(u32), + SetConfig(ServerConfig), + ExpandMacroExtended(Result), +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ExpandMacro { + pub lib: Utf8PathBuf, + pub env: Vec<(String, String)>, + pub current_dir: Option, + #[serde(flatten)] + pub data: ExpandMacroData, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ExpandMacroExtended { + pub tree: FlatTree, + pub span_data_table: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ExpandMacroData { + pub macro_body: FlatTree, + pub macro_name: String, + pub attributes: Option, + #[serde(skip_serializing_if = "ExpnGlobals::skip_serializing_if")] + #[serde(default)] + pub has_global_spans: ExpnGlobals, + + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + pub span_data_table: Vec, +} + +#[derive(Clone, Copy, Default, Debug, Serialize, Deserialize)] +pub struct ExpnGlobals { + #[serde(skip_serializing)] + #[serde(default)] + pub serialize: bool, + pub def_site: usize, + pub call_site: usize, + pub mixed_site: usize, +} + +impl ExpnGlobals { + fn skip_serializing_if(&self) -> bool { + !self.serialize + } +} + +impl Message for Envelope {} diff --git a/crates/proc-macro-api/src/legacy_protocol.rs b/crates/proc-macro-api/src/legacy_protocol.rs index c2b132ddcc1d..81a9f391812c 100644 --- a/crates/proc-macro-api/src/legacy_protocol.rs +++ b/crates/proc-macro-api/src/legacy_protocol.rs @@ -1,30 +1,26 @@ //! The initial proc-macro-srv protocol, soon to be deprecated. -pub mod json; pub mod msg; -pub mod postcard; use std::{ io::{BufRead, Write}, sync::Arc, }; +use base_db::SourceDatabase; use paths::AbsPath; use span::Span; use crate::{ ProcMacro, ProcMacroKind, ServerError, - codec::Codec, - legacy_protocol::{ - json::JsonProtocol, - msg::{ - ExpandMacro, ExpandMacroData, ExpnGlobals, FlatTree, Message, Request, Response, - ServerConfig, SpanDataIndexMap, deserialize_span_data_index_map, - flat::serialize_span_data_index_map, - }, - postcard::PostcardProtocol, + legacy_protocol::msg::{ + ExpandMacro, ExpandMacroData, ExpnGlobals, FlatTree, Message, Request, Response, + ServerConfig, SpanDataIndexMap, deserialize_span_data_index_map, + flat::serialize_span_data_index_map, }, process::ProcMacroServerProcess, + transport::codec::Codec, + transport::codec::{json::JsonProtocol, postcard::PostcardProtocol}, version, }; @@ -82,6 +78,7 @@ pub(crate) fn find_proc_macros( pub(crate) fn expand( proc_macro: &ProcMacro, + _db: &dyn SourceDatabase, subtree: tt::SubtreeView<'_, Span>, attr: Option>, env: Vec<(String, String)>, @@ -155,9 +152,9 @@ fn send_task(srv: &ProcMacroServerProcess, req: Request) -> Result, req) + srv.send_task::<_, _, PostcardProtocol>(send_request::, req) } else { - srv.send_task(send_request::, req) + srv.send_task::<_, _, JsonProtocol>(send_request::, req) } } diff --git a/crates/proc-macro-api/src/legacy_protocol/msg.rs b/crates/proc-macro-api/src/legacy_protocol/msg.rs index a6e228d977db..0ebb0e9f93d5 100644 --- a/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -8,7 +8,7 @@ use paths::Utf8PathBuf; use serde::de::DeserializeOwned; use serde_derive::{Deserialize, Serialize}; -use crate::{ProcMacroKind, codec::Codec}; +use crate::{Codec, ProcMacroKind}; /// Represents requests sent from the client to the proc-macro-srv. #[derive(Debug, Serialize, Deserialize)] diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs index 85b250eddfd4..7b9b5b39ab1c 100644 --- a/crates/proc-macro-api/src/lib.rs +++ b/crates/proc-macro-api/src/lib.rs @@ -16,18 +16,19 @@ #[cfg(feature = "in-rust-tree")] extern crate rustc_driver as _; -mod codec; -mod framing; +pub mod bidirectional_protocol; pub mod legacy_protocol; mod process; +pub mod transport; +use base_db::SourceDatabase; use paths::{AbsPath, AbsPathBuf}; use semver::Version; use span::{ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, Span}; use std::{fmt, io, sync::Arc, time::SystemTime}; -pub use crate::codec::Codec; use crate::process::ProcMacroServerProcess; +pub use crate::transport::codec::Codec; /// The versions of the server protocol pub mod version { @@ -218,6 +219,7 @@ impl ProcMacro { /// This includes span information and environmental context. pub fn expand( &self, + db: &dyn SourceDatabase, subtree: tt::SubtreeView<'_, Span>, attr: Option>, env: Vec<(String, String)>, @@ -240,7 +242,8 @@ impl ProcMacro { } } - legacy_protocol::expand( + self.process.expand( + db, self, subtree, attr, diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs index d6a8d27bfc42..39d954855187 100644 --- a/crates/proc-macro-api/src/process.rs +++ b/crates/proc-macro-api/src/process.rs @@ -7,12 +7,18 @@ use std::{ sync::{Arc, Mutex, OnceLock}, }; +use base_db::SourceDatabase; use paths::AbsPath; use semver::Version; +use span::Span; use stdx::JodChild; use crate::{ - ProcMacroKind, ServerError, + Codec, ProcMacro, ProcMacroKind, ServerError, + bidirectional_protocol::{ + self, ClientCallbacks, + msg::{Payload, RequestId}, + }, legacy_protocol::{self, SpanMode}, version, }; @@ -33,6 +39,8 @@ pub(crate) struct ProcMacroServerProcess { pub(crate) enum Protocol { LegacyJson { mode: SpanMode }, LegacyPostcard { mode: SpanMode }, + NewPostcard { mode: SpanMode }, + NewJson { mode: SpanMode }, } /// Maintains the state of the proc-macro server process. @@ -62,6 +70,8 @@ impl ProcMacroServerProcess { && has_working_format_flag { &[ + (Some("postcard-new"), Protocol::NewPostcard { mode: SpanMode::Id }), + (Some("json-new"), Protocol::NewJson { mode: SpanMode::Id }), (Some("postcard-legacy"), Protocol::LegacyPostcard { mode: SpanMode::Id }), (Some("json-legacy"), Protocol::LegacyJson { mode: SpanMode::Id }), ] @@ -105,9 +115,10 @@ impl ProcMacroServerProcess { && let Ok(new_mode) = srv.enable_rust_analyzer_spans() { match &mut srv.protocol { - Protocol::LegacyJson { mode } | Protocol::LegacyPostcard { mode } => { - *mode = new_mode - } + Protocol::LegacyJson { mode } + | Protocol::LegacyPostcard { mode } + | Protocol::NewJson { mode } + | Protocol::NewPostcard { mode } => *mode = new_mode, } } tracing::info!("Proc-macro server protocol: {:?}", srv.protocol); @@ -143,22 +154,32 @@ impl ProcMacroServerProcess { match self.protocol { Protocol::LegacyJson { mode } => mode == SpanMode::RustAnalyzer, Protocol::LegacyPostcard { mode } => mode == SpanMode::RustAnalyzer, + Protocol::NewJson { mode } => mode == SpanMode::RustAnalyzer, + Protocol::NewPostcard { mode } => mode == SpanMode::RustAnalyzer, } } /// Checks the API version of the running proc-macro server. fn version_check(&self) -> Result { match self.protocol { - Protocol::LegacyJson { .. } => legacy_protocol::version_check(self), - Protocol::LegacyPostcard { .. } => legacy_protocol::version_check(self), + Protocol::LegacyJson { .. } | Protocol::LegacyPostcard { .. } => { + legacy_protocol::version_check(self) + } + Protocol::NewJson { .. } | Protocol::NewPostcard { .. } => { + bidirectional_protocol::version_check(self) + } } } /// Enable support for rust-analyzer span mode if the server supports it. fn enable_rust_analyzer_spans(&self) -> Result { match self.protocol { - Protocol::LegacyJson { .. } => legacy_protocol::enable_rust_analyzer_spans(self), - Protocol::LegacyPostcard { .. } => legacy_protocol::enable_rust_analyzer_spans(self), + Protocol::LegacyJson { .. } | Protocol::LegacyPostcard { .. } => { + legacy_protocol::enable_rust_analyzer_spans(self) + } + Protocol::NewJson { .. } | Protocol::NewPostcard { .. } => { + bidirectional_protocol::enable_rust_analyzer_spans(self) + } } } @@ -168,28 +189,69 @@ impl ProcMacroServerProcess { dylib_path: &AbsPath, ) -> Result, String>, ServerError> { match self.protocol { - Protocol::LegacyJson { .. } => legacy_protocol::find_proc_macros(self, dylib_path), - Protocol::LegacyPostcard { .. } => legacy_protocol::find_proc_macros(self, dylib_path), + Protocol::LegacyJson { .. } | Protocol::LegacyPostcard { .. } => { + legacy_protocol::find_proc_macros(self, dylib_path) + } + Protocol::NewJson { .. } | Protocol::NewPostcard { .. } => { + bidirectional_protocol::find_proc_macros(self, dylib_path) + } + } + } + + pub(crate) fn expand( + &self, + db: &dyn SourceDatabase, + proc_macro: &ProcMacro, + subtree: tt::SubtreeView<'_, Span>, + attr: Option>, + env: Vec<(String, String)>, + def_site: Span, + call_site: Span, + mixed_site: Span, + current_dir: String, + ) -> Result, String>, ServerError> { + match self.protocol { + Protocol::LegacyJson { .. } | Protocol::LegacyPostcard { .. } => { + legacy_protocol::expand( + proc_macro, + db, + subtree, + attr, + env, + def_site, + call_site, + mixed_site, + current_dir, + ) + } + Protocol::NewJson { .. } | Protocol::NewPostcard { .. } => { + bidirectional_protocol::expand( + proc_macro, + db, + subtree, + attr, + env, + def_site, + call_site, + mixed_site, + current_dir, + ) + } } } - pub(crate) fn send_task( + pub(crate) fn send_task( &self, - serialize_req: impl FnOnce( + send: impl FnOnce( &mut dyn Write, &mut dyn BufRead, Request, - &mut Buf, + &mut C::Buf, ) -> Result, ServerError>, req: Request, - ) -> Result - where - Buf: Default, - { - let state = &mut *self.state.lock().unwrap(); - let mut buf = Buf::default(); - serialize_req(&mut state.stdin, &mut state.stdout, req, &mut buf) - .and_then(|res| { + ) -> Result { + self.with_locked_io::(|writer, reader, buf| { + send(writer, reader, req, buf).and_then(|res| { res.ok_or_else(|| { let message = "proc-macro server did not respond with data".to_owned(); ServerError { @@ -201,33 +263,54 @@ impl ProcMacroServerProcess { } }) }) - .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, - }; - // `AssertUnwindSafe` is fine here, we already correct initialized - // server_error at this point. - self.exited.get_or_init(|| AssertUnwindSafe(server_error)).0.clone() + }) + } + + pub(crate) fn with_locked_io( + &self, + f: impl FnOnce(&mut dyn Write, &mut dyn BufRead, &mut C::Buf) -> Result, + ) -> Result { + let state = &mut *self.state.lock().unwrap(); + let mut buf = C::Buf::default(); + + f(&mut state.stdin, &mut state.stdout, &mut buf).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 } - }) + } else { + e + } + }) + } + + pub(crate) fn run_bidirectional( + &self, + id: RequestId, + initial: Payload, + callbacks: &mut dyn ClientCallbacks, + ) -> Result { + self.with_locked_io::(|writer, reader, buf| { + bidirectional_protocol::run_conversation::( + writer, reader, buf, id, initial, callbacks, + ) + }) } } diff --git a/crates/proc-macro-api/src/transport.rs b/crates/proc-macro-api/src/transport.rs new file mode 100644 index 000000000000..b7a1d8f7322c --- /dev/null +++ b/crates/proc-macro-api/src/transport.rs @@ -0,0 +1,3 @@ +//! Contains construct for transport of messages. +pub mod codec; +pub mod framing; diff --git a/crates/proc-macro-api/src/codec.rs b/crates/proc-macro-api/src/transport/codec.rs similarity index 76% rename from crates/proc-macro-api/src/codec.rs rename to crates/proc-macro-api/src/transport/codec.rs index baccaa6be4c2..c9afad260a56 100644 --- a/crates/proc-macro-api/src/codec.rs +++ b/crates/proc-macro-api/src/transport/codec.rs @@ -4,7 +4,10 @@ use std::io; use serde::de::DeserializeOwned; -use crate::framing::Framing; +use crate::transport::framing::Framing; + +pub mod json; +pub mod postcard; pub trait Codec: Framing { fn encode(msg: &T) -> io::Result; diff --git a/crates/proc-macro-api/src/legacy_protocol/json.rs b/crates/proc-macro-api/src/transport/codec/json.rs similarity index 89% rename from crates/proc-macro-api/src/legacy_protocol/json.rs rename to crates/proc-macro-api/src/transport/codec/json.rs index 1359c0568402..96db802e0bfd 100644 --- a/crates/proc-macro-api/src/legacy_protocol/json.rs +++ b/crates/proc-macro-api/src/transport/codec/json.rs @@ -3,14 +3,14 @@ use std::io::{self, BufRead, Write}; use serde::{Serialize, de::DeserializeOwned}; -use crate::{codec::Codec, framing::Framing}; +use crate::{Codec, transport::framing::Framing}; pub struct JsonProtocol; impl Framing for JsonProtocol { type Buf = String; - fn read<'a, R: BufRead>( + fn read<'a, R: BufRead + ?Sized>( inp: &mut R, buf: &'a mut String, ) -> io::Result> { @@ -35,7 +35,7 @@ impl Framing for JsonProtocol { } } - fn write(out: &mut W, buf: &String) -> io::Result<()> { + fn write(out: &mut W, buf: &String) -> io::Result<()> { tracing::debug!("> {}", buf); out.write_all(buf.as_bytes())?; out.write_all(b"\n")?; diff --git a/crates/proc-macro-api/src/legacy_protocol/postcard.rs b/crates/proc-macro-api/src/transport/codec/postcard.rs similarity index 84% rename from crates/proc-macro-api/src/legacy_protocol/postcard.rs rename to crates/proc-macro-api/src/transport/codec/postcard.rs index c28a9bfe3a1a..6f5319e75b37 100644 --- a/crates/proc-macro-api/src/legacy_protocol/postcard.rs +++ b/crates/proc-macro-api/src/transport/codec/postcard.rs @@ -4,14 +4,14 @@ use std::io::{self, BufRead, Write}; use serde::{Serialize, de::DeserializeOwned}; -use crate::{codec::Codec, framing::Framing}; +use crate::{Codec, transport::framing::Framing}; pub struct PostcardProtocol; impl Framing for PostcardProtocol { type Buf = Vec; - fn read<'a, R: BufRead>( + fn read<'a, R: BufRead + ?Sized>( inp: &mut R, buf: &'a mut Vec, ) -> io::Result>> { @@ -23,7 +23,7 @@ impl Framing for PostcardProtocol { Ok(Some(buf)) } - fn write(out: &mut W, buf: &Vec) -> io::Result<()> { + fn write(out: &mut W, buf: &Vec) -> io::Result<()> { out.write_all(buf)?; out.flush() } diff --git a/crates/proc-macro-api/src/framing.rs b/crates/proc-macro-api/src/transport/framing.rs similarity index 63% rename from crates/proc-macro-api/src/framing.rs rename to crates/proc-macro-api/src/transport/framing.rs index a1e6fc05ca11..2a11eb19c365 100644 --- a/crates/proc-macro-api/src/framing.rs +++ b/crates/proc-macro-api/src/transport/framing.rs @@ -5,10 +5,10 @@ use std::io::{self, BufRead, Write}; pub trait Framing { type Buf: Default; - fn read<'a, R: BufRead>( + fn read<'a, R: BufRead + ?Sized>( inp: &mut R, buf: &'a mut Self::Buf, ) -> io::Result>; - fn write(out: &mut W, buf: &Self::Buf) -> io::Result<()>; + fn write(out: &mut W, buf: &Self::Buf) -> io::Result<()>; } diff --git a/crates/proc-macro-srv-cli/Cargo.toml b/crates/proc-macro-srv-cli/Cargo.toml index aa153897fa96..298592ee4763 100644 --- a/crates/proc-macro-srv-cli/Cargo.toml +++ b/crates/proc-macro-srv-cli/Cargo.toml @@ -15,6 +15,7 @@ proc-macro-srv.workspace = true proc-macro-api.workspace = true tt.workspace = true postcard.workspace = true +crossbeam-channel.workspace = true clap = {version = "4.5.42", default-features = false, features = ["std"]} [features] diff --git a/crates/proc-macro-srv-cli/src/main.rs b/crates/proc-macro-srv-cli/src/main.rs index 813ac339a91d..d3dae0494fe4 100644 --- a/crates/proc-macro-srv-cli/src/main.rs +++ b/crates/proc-macro-srv-cli/src/main.rs @@ -52,6 +52,8 @@ fn main() -> std::io::Result<()> { enum ProtocolFormat { JsonLegacy, PostcardLegacy, + JsonNew, + PostcardNew, } impl ValueEnum for ProtocolFormat { @@ -65,12 +67,16 @@ impl ValueEnum for ProtocolFormat { ProtocolFormat::PostcardLegacy => { Some(clap::builder::PossibleValue::new("postcard-legacy")) } + ProtocolFormat::JsonNew => Some(clap::builder::PossibleValue::new("json-new")), + ProtocolFormat::PostcardNew => Some(clap::builder::PossibleValue::new("postcard-new")), } } fn from_str(input: &str, _ignore_case: bool) -> Result { match input { "json-legacy" => Ok(ProtocolFormat::JsonLegacy), "postcard-legacy" => Ok(ProtocolFormat::PostcardLegacy), + "postcard-new" => Ok(ProtocolFormat::PostcardNew), + "json-new" => Ok(ProtocolFormat::JsonNew), _ => Err(format!("unknown protocol format: {input}")), } } diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs index df54f38cbccb..e543260964fb 100644 --- a/crates/proc-macro-srv-cli/src/main_loop.rs +++ b/crates/proc-macro-srv-cli/src/main_loop.rs @@ -1,16 +1,16 @@ //! The main loop of the proc-macro server. use std::io; +use crossbeam_channel::unbounded; +use proc_macro_api::bidirectional_protocol::msg::Request; use proc_macro_api::{ Codec, - legacy_protocol::{ - json::JsonProtocol, - msg::{ - self, ExpandMacroData, ExpnGlobals, Message, SpanMode, SpanTransformer, - deserialize_span_data_index_map, serialize_span_data_index_map, - }, - postcard::PostcardProtocol, + bidirectional_protocol::msg::{Envelope, Kind, Payload}, + legacy_protocol::msg::{ + self, ExpandMacroData, ExpnGlobals, Message, SpanMode, SpanTransformer, + deserialize_span_data_index_map, serialize_span_data_index_map, }, + transport::codec::{json::JsonProtocol, postcard::PostcardProtocol}, version::CURRENT_API_VERSION, }; use proc_macro_srv::{EnvSnapshot, SpanId}; @@ -39,9 +39,280 @@ pub(crate) fn run(format: ProtocolFormat) -> io::Result<()> { match format { ProtocolFormat::JsonLegacy => run_::(), ProtocolFormat::PostcardLegacy => run_::(), + ProtocolFormat::JsonNew => run_new::(), + ProtocolFormat::PostcardNew => run_new::(), } } +fn run_new() -> io::Result<()> { + fn macro_kind_to_api(kind: proc_macro_srv::ProcMacroKind) -> proc_macro_api::ProcMacroKind { + match kind { + proc_macro_srv::ProcMacroKind::CustomDerive => { + proc_macro_api::ProcMacroKind::CustomDerive + } + proc_macro_srv::ProcMacroKind::Bang => proc_macro_api::ProcMacroKind::Bang, + proc_macro_srv::ProcMacroKind::Attr => proc_macro_api::ProcMacroKind::Attr, + } + } + + let mut buf = C::Buf::default(); + let mut stdin = io::stdin().lock(); + let mut stdout = io::stdout().lock(); + + let env_snapshot = EnvSnapshot::default(); + let srv = proc_macro_srv::ProcMacroSrv::new(&env_snapshot); + + let mut span_mode = SpanMode::Id; + + 'outer: loop { + let req_opt = Envelope::read::<_, C>(&mut stdin, &mut buf)?; + let Some(req) = req_opt else { + break 'outer; + }; + + match (req.kind, req.payload) { + (Kind::Request, Payload::Request(request)) => match request { + Request::ListMacros { dylib_path } => { + let res = srv.list_macros(&dylib_path).map(|macros| { + macros + .into_iter() + .map(|(name, kind)| (name, macro_kind_to_api(kind))) + .collect() + }); + + let resp_env = Envelope { + id: req.id, + kind: Kind::Response, + payload: Payload::Response( + proc_macro_api::bidirectional_protocol::msg::Response::ListMacros(res), + ), + }; + + resp_env.write::<_, C>(&mut stdout)?; + } + + Request::ApiVersionCheck {} => { + let resp_env = Envelope { + id: req.id, + kind: Kind::Response, + payload: Payload::Response( + proc_macro_api::bidirectional_protocol::msg::Response::ApiVersionCheck( + CURRENT_API_VERSION, + ), + ), + }; + resp_env.write::<_, C>(&mut stdout)?; + } + + Request::SetConfig(config) => { + span_mode = config.span_mode; + let resp_env = Envelope { + id: req.id, + kind: Kind::Response, + payload: Payload::Response( + proc_macro_api::bidirectional_protocol::msg::Response::SetConfig( + config, + ), + ), + }; + resp_env.write::<_, C>(&mut stdout)?; + } + + Request::ExpandMacro(task) => { + let proc_macro_api::bidirectional_protocol::msg::ExpandMacro { + lib, + env, + current_dir, + data: + proc_macro_api::bidirectional_protocol::msg::ExpandMacroData { + macro_body, + macro_name, + attributes, + has_global_spans: + proc_macro_api::bidirectional_protocol::msg::ExpnGlobals { + serialize: _, + def_site, + call_site, + mixed_site, + }, + span_data_table, + }, + } = *task; + + match span_mode { + SpanMode::Id => { + let def_site = SpanId(def_site as u32); + let call_site = SpanId(call_site as u32); + let mixed_site = SpanId(mixed_site as u32); + + let macro_body = macro_body.to_tokenstream_unresolved::( + CURRENT_API_VERSION, + |_, b| b, + ); + let attributes = attributes.map(|it| { + it.to_tokenstream_unresolved::( + CURRENT_API_VERSION, + |_, b| b, + ) + }); + + let res = srv + .expand( + lib, + &env, + current_dir, + ¯o_name, + macro_body, + attributes, + def_site, + call_site, + mixed_site, + ) + .map(|it| { + msg::FlatTree::from_tokenstream_raw::( + it, + call_site, + CURRENT_API_VERSION, + ) + }) + .map_err(|e| e.into_string().unwrap_or_default()) + .map_err(msg::PanicMessage); + + let resp_env = Envelope { + id: req.id, + kind: Kind::Response, + payload: Payload::Response(proc_macro_api::bidirectional_protocol::msg::Response::ExpandMacro(res)), + }; + + resp_env.write::<_, C>(&mut stdout)?; + } + + SpanMode::RustAnalyzer => { + let mut span_data_table = + deserialize_span_data_index_map(&span_data_table); + + let def_site_span = span_data_table[def_site]; + let call_site_span = span_data_table[call_site]; + let mixed_site_span = span_data_table[mixed_site]; + + let macro_body_ts = macro_body.to_tokenstream_resolved( + CURRENT_API_VERSION, + &span_data_table, + |a, b| srv.join_spans(a, b).unwrap_or(b), + ); + let attributes_ts = attributes.map(|it| { + it.to_tokenstream_resolved( + CURRENT_API_VERSION, + &span_data_table, + |a, b| srv.join_spans(a, b).unwrap_or(b), + ) + }); + + let (subreq_tx, subreq_rx) = unbounded::(); + let (subresp_tx, subresp_rx) = + unbounded::(); + let (result_tx, result_rx) = crossbeam_channel::bounded(1); + + std::thread::scope(|scope| { + let srv_ref = &srv; + + scope.spawn({ + let lib = lib.clone(); + let env = env.clone(); + let current_dir = current_dir.clone(); + let macro_name = macro_name.clone(); + move || { + let res = srv_ref + .expand_with_channels( + lib, + &env, + current_dir, + ¯o_name, + macro_body_ts, + attributes_ts, + def_site_span, + call_site_span, + mixed_site_span, + subresp_rx, + subreq_tx, + ) + .map(|it| { + ( + msg::FlatTree::from_tokenstream( + it, + CURRENT_API_VERSION, + call_site_span, + &mut span_data_table, + ), + serialize_span_data_index_map(&span_data_table), + ) + }) + .map(|(tree, span_data_table)| { + proc_macro_api::bidirectional_protocol::msg::ExpandMacroExtended { tree, span_data_table } + }) + .map_err(|e| e.into_string().unwrap_or_default()) + .map_err(msg::PanicMessage); + let _ = result_tx.send(res); + } + }); + + loop { + if let Ok(res) = result_rx.try_recv() { + let resp_env = Envelope { + id: req.id, + kind: Kind::Response, + payload: Payload::Response( + proc_macro_api::bidirectional_protocol::msg::Response::ExpandMacroExtended(res), + ), + }; + resp_env.write::<_, C>(&mut stdout).unwrap(); + break; + } + + let subreq = match subreq_rx.recv() { + Ok(r) => r, + Err(_) => { + break; + } + }; + + let sub_env = Envelope { + id: req.id, + kind: Kind::SubRequest, + payload: Payload::SubRequest(from_srv_req(subreq)), + }; + sub_env.write::<_, C>(&mut stdout).unwrap(); + + let resp_opt = + Envelope::read::<_, C>(&mut stdin, &mut buf).unwrap(); + let resp = match resp_opt { + Some(env) => env, + None => { + break; + } + }; + + match (resp.kind, resp.payload) { + (Kind::SubResponse, Payload::SubResponse(subresp)) => { + let _ = subresp_tx.send(from_client_res(subresp)); + } + _ => { + break; + } + } + } + }); + } + } + } + }, + _ => {} + } + } + + Ok(()) +} + fn run_() -> io::Result<()> { fn macro_kind_to_api(kind: proc_macro_srv::ProcMacroKind) -> proc_macro_api::ProcMacroKind { match kind { @@ -178,3 +449,27 @@ fn run_() -> io::Result<()> { Ok(()) } + +fn from_srv_req( + value: proc_macro_srv::SubRequest, +) -> proc_macro_api::bidirectional_protocol::msg::SubRequest { + match value { + proc_macro_srv::SubRequest::SourceText { file_id, start, end } => { + proc_macro_api::bidirectional_protocol::msg::SubRequest::SourceText { + file_id: file_id.file_id().index(), + start, + end, + } + } + } +} + +fn from_client_res( + value: proc_macro_api::bidirectional_protocol::msg::SubResponse, +) -> proc_macro_srv::SubResponse { + match value { + proc_macro_api::bidirectional_protocol::msg::SubResponse::SourceTextResult { text } => { + proc_macro_srv::SubResponse::SourceTextResult { text } + } + } +} diff --git a/crates/proc-macro-srv/Cargo.toml b/crates/proc-macro-srv/Cargo.toml index 361017178409..b2abda0bfd7f 100644 --- a/crates/proc-macro-srv/Cargo.toml +++ b/crates/proc-macro-srv/Cargo.toml @@ -22,6 +22,7 @@ paths.workspace = true # span = {workspace = true, default-features = false} does not work span = { path = "../span", version = "0.0.0", default-features = false} intern.workspace = true +crossbeam-channel.workspace = true ra-ap-rustc_lexer.workspace = true diff --git a/crates/proc-macro-srv/src/dylib.rs b/crates/proc-macro-srv/src/dylib.rs index 03433197b779..ba089c9549d3 100644 --- a/crates/proc-macro-srv/src/dylib.rs +++ b/crates/proc-macro-srv/src/dylib.rs @@ -54,6 +54,32 @@ impl Expander { .expand(macro_name, macro_body, attribute, def_site, call_site, mixed_site) } + pub(crate) fn expand_with_channels( + &self, + macro_name: &str, + macro_body: crate::token_stream::TokenStream, + attribute: Option>, + def_site: S, + call_site: S, + mixed_site: S, + cli_to_server: crossbeam_channel::Receiver, + server_to_cli: crossbeam_channel::Sender, + ) -> Result, crate::PanicMessage> + where + ::TokenStream: Default, + { + self.inner.proc_macros.expand_with_channels( + macro_name, + macro_body, + attribute, + def_site, + call_site, + mixed_site, + cli_to_server, + server_to_cli, + ) + } + pub(crate) fn list_macros(&self) -> impl Iterator { self.inner.proc_macros.list_macros() } diff --git a/crates/proc-macro-srv/src/dylib/proc_macros.rs b/crates/proc-macro-srv/src/dylib/proc_macros.rs index c879c7609d91..5b6f1cf2f332 100644 --- a/crates/proc-macro-srv/src/dylib/proc_macros.rs +++ b/crates/proc-macro-srv/src/dylib/proc_macros.rs @@ -1,5 +1,4 @@ //! Proc macro ABI - use proc_macro::bridge; use crate::{ProcMacroKind, ProcMacroSrvSpan, token_stream::TokenStream}; @@ -32,7 +31,65 @@ impl ProcMacros { { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site), + S::make_server(call_site, def_site, mixed_site, None, None), + macro_body, + cfg!(debug_assertions), + ); + return res.map_err(crate::PanicMessage::from); + } + bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { + let res = client.run( + &bridge::server::SameThread, + S::make_server(call_site, def_site, mixed_site, None, None), + macro_body, + cfg!(debug_assertions), + ); + return res.map_err(crate::PanicMessage::from); + } + bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { + let res = client.run( + &bridge::server::SameThread, + S::make_server(call_site, def_site, mixed_site, None, None), + parsed_attributes, + macro_body, + cfg!(debug_assertions), + ); + return res.map_err(crate::PanicMessage::from); + } + _ => continue, + } + } + + Err(bridge::PanicMessage::String(format!("proc-macro `{macro_name}` is missing")).into()) + } + + pub(crate) fn expand_with_channels( + &self, + macro_name: &str, + macro_body: TokenStream, + attribute: Option>, + def_site: S, + call_site: S, + mixed_site: S, + cli_to_server: crossbeam_channel::Receiver, + server_to_cli: crossbeam_channel::Sender, + ) -> Result, crate::PanicMessage> { + let parsed_attributes = attribute.unwrap_or_default(); + + for proc_macro in &self.0 { + match proc_macro { + bridge::client::ProcMacro::CustomDerive { trait_name, client, .. } + if *trait_name == macro_name => + { + let res = client.run( + &bridge::server::SameThread, + S::make_server( + call_site, + def_site, + mixed_site, + Some(cli_to_server), + Some(server_to_cli), + ), macro_body, cfg!(debug_assertions), ); @@ -41,7 +98,13 @@ impl ProcMacros { bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site), + S::make_server( + call_site, + def_site, + mixed_site, + Some(cli_to_server), + Some(server_to_cli), + ), macro_body, cfg!(debug_assertions), ); @@ -50,7 +113,13 @@ impl ProcMacros { bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { let res = client.run( &bridge::server::SameThread, - S::make_server(call_site, def_site, mixed_site), + S::make_server( + call_site, + def_site, + mixed_site, + Some(cli_to_server), + Some(server_to_cli), + ), parsed_attributes, macro_body, cfg!(debug_assertions), diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index 93319df824c0..f369ab93a2a3 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -47,7 +47,7 @@ use std::{ }; use paths::{Utf8Path, Utf8PathBuf}; -use span::Span; +use span::{EditionedFileId, Span}; use temp_dir::TempDir; pub use crate::server_impl::token_id::SpanId; @@ -91,6 +91,14 @@ impl<'env> ProcMacroSrv<'env> { } } +pub enum SubRequest { + SourceText { file_id: EditionedFileId, start: u32, end: u32 }, +} + +pub enum SubResponse { + SourceTextResult { text: Option }, +} + const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024; impl ProcMacroSrv<'_> { @@ -133,6 +141,53 @@ impl ProcMacroSrv<'_> { result } + pub fn expand_with_channels( + &self, + lib: impl AsRef, + env: &[(String, String)], + current_dir: Option>, + macro_name: &str, + macro_body: token_stream::TokenStream, + attribute: Option>, + def_site: S, + call_site: S, + mixed_site: S, + cli_to_server: crossbeam_channel::Receiver, + server_to_cli: crossbeam_channel::Sender, + ) -> Result, PanicMessage> { + let snapped_env = self.env; + let expander = self.expander(lib.as_ref()).map_err(|err| PanicMessage { + message: Some(format!("failed to load macro: {err}")), + })?; + + let prev_env = EnvChange::apply(snapped_env, env, current_dir.as_ref().map(<_>::as_ref)); + + let result = thread::scope(|s| { + let thread = thread::Builder::new() + .stack_size(EXPANDER_STACK_SIZE) + .name(macro_name.to_owned()) + .spawn_scoped(s, move || { + expander.expand_with_channels( + macro_name, + macro_body, + attribute, + def_site, + call_site, + mixed_site, + cli_to_server, + server_to_cli, + ) + }); + match thread.unwrap().join() { + Ok(res) => res, + Err(e) => std::panic::resume_unwind(e), + } + }); + prev_env.rollback(); + + result + } + pub fn list_macros( &self, dylib_path: &Utf8Path, @@ -170,31 +225,54 @@ impl ProcMacroSrv<'_> { pub trait ProcMacroSrvSpan: Copy + Send + Sync { type Server: proc_macro::bridge::server::Server>; - fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server; + fn make_server( + call_site: Self, + def_site: Self, + mixed_site: Self, + cli_to_server: Option>, + server_to_cli: Option>, + ) -> Self::Server; } impl ProcMacroSrvSpan for SpanId { type Server = server_impl::token_id::SpanIdServer; - fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { + fn make_server( + call_site: Self, + def_site: Self, + mixed_site: Self, + cli_to_server: Option>, + server_to_cli: Option>, + ) -> Self::Server { Self::Server { call_site, def_site, mixed_site, + cli_to_server, + server_to_cli, tracked_env_vars: Default::default(), tracked_paths: Default::default(), } } } + impl ProcMacroSrvSpan for Span { type Server = server_impl::rust_analyzer_span::RaSpanServer; - fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { + fn make_server( + call_site: Self, + def_site: Self, + mixed_site: Self, + cli_to_server: Option>, + server_to_cli: Option>, + ) -> Self::Server { Self::Server { call_site, def_site, mixed_site, tracked_env_vars: Default::default(), tracked_paths: Default::default(), + cli_to_server, + server_to_cli, } } } diff --git a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 7c685c2da734..1a8f6d6730f7 100644 --- a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -14,6 +14,7 @@ use proc_macro::bridge::server; use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, Span, TextRange, TextSize}; use crate::{ + SubRequest, SubResponse, bridge::{Diagnostic, ExpnGlobals, Literal, TokenTree}, server_impl::literal_from_str, }; @@ -28,6 +29,8 @@ pub struct RaSpanServer { pub call_site: Span, pub def_site: Span, pub mixed_site: Span, + pub cli_to_server: Option>, + pub server_to_cli: Option>, } impl server::Types for RaSpanServer { @@ -149,9 +152,26 @@ impl server::Span for RaSpanServer { /// /// See PR: /// https://github.com/rust-lang/rust/pull/55780 - fn source_text(&mut self, _span: Self::Span) -> Option { + fn source_text(&mut self, span: Self::Span) -> Option { // FIXME requires db, needs special handling wrt fixup spans - None + if self.server_to_cli.is_some() && self.cli_to_server.is_some() { + let file_id = span.anchor.file_id; + let start: u32 = span.range.start().into(); + let end: u32 = span.range.end().into(); + let _ = self.server_to_cli.clone().unwrap().send(SubRequest::SourceText { + file_id, + start, + end, + }); + self.cli_to_server + .clone() + .unwrap() + .recv() + .and_then(|SubResponse::SourceTextResult { text }| Ok(text)) + .expect("REASON") + } else { + None + } } fn parent(&mut self, _span: Self::Span) -> Option { diff --git a/crates/proc-macro-srv/src/server_impl/token_id.rs b/crates/proc-macro-srv/src/server_impl/token_id.rs index 5ac263b9d5f6..268042b3bc07 100644 --- a/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/crates/proc-macro-srv/src/server_impl/token_id.rs @@ -9,6 +9,7 @@ use intern::Symbol; use proc_macro::bridge::server; use crate::{ + SubRequest, SubResponse, bridge::{Diagnostic, ExpnGlobals, Literal, TokenTree}, server_impl::literal_from_str, }; @@ -34,6 +35,8 @@ pub struct SpanIdServer { pub call_site: Span, pub def_site: Span, pub mixed_site: Span, + pub cli_to_server: Option>, + pub server_to_cli: Option>, } impl server::Types for SpanIdServer { @@ -139,6 +142,7 @@ impl server::Span for SpanIdServer { /// See PR: /// https://github.com/rust-lang/rust/pull/55780 fn source_text(&mut self, _span: Self::Span) -> Option { + // FIXME requires db, needs special handling wrt fixup spans None } diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index 5e8b250c24a0..e08a65c39204 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -732,6 +732,7 @@ struct IdentityProcMacroExpander; impl ProcMacroExpander for IdentityProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -754,6 +755,7 @@ struct Issue18089ProcMacroExpander; impl ProcMacroExpander for Issue18089ProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -789,6 +791,7 @@ struct AttributeInputReplaceProcMacroExpander; impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, _: &TopSubtree, attrs: Option<&TopSubtree>, _: &Env, @@ -812,6 +815,7 @@ struct Issue18840ProcMacroExpander; impl ProcMacroExpander for Issue18840ProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, fn_: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -847,6 +851,7 @@ struct MirrorProcMacroExpander; impl ProcMacroExpander for MirrorProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, input: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -885,6 +890,7 @@ struct ShortenProcMacroExpander; impl ProcMacroExpander for ShortenProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, input: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -927,6 +933,7 @@ struct Issue17479ProcMacroExpander; impl ProcMacroExpander for Issue17479ProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -956,6 +963,7 @@ struct Issue18898ProcMacroExpander; impl ProcMacroExpander for Issue18898ProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -1011,6 +1019,7 @@ struct DisallowCfgProcMacroExpander; impl ProcMacroExpander for DisallowCfgProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _: Option<&TopSubtree>, _: &Env, @@ -1042,6 +1051,7 @@ struct GenerateSuffixedTypeProcMacroExpander; impl ProcMacroExpander for GenerateSuffixedTypeProcMacroExpander { fn expand( &self, + _: &dyn SourceDatabase, subtree: &TopSubtree, _attrs: Option<&TopSubtree>, _env: &Env, From 80705fb3907fe29111d11f1f37fa52b181745387 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Mon, 15 Dec 2025 20:02:26 +0530 Subject: [PATCH 2/7] remove salsa dependency check on proc_macro_srv_cli --- .github/workflows/ci.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5975272d871a..623200aea032 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -71,9 +71,6 @@ jobs: - name: Test run: cargo test --features sysroot-abi -p proc-macro-srv -p proc-macro-srv-cli -p proc-macro-api -- --quiet - - name: Check salsa dependency - run: "! (cargo tree -p proc-macro-srv-cli | grep -q salsa)" - rust: if: github.repository == 'rust-lang/rust-analyzer' name: Rust From 178d6ce761ebff096d18eb45f0e3d67550d8945c Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Mon, 15 Dec 2025 20:16:51 +0530 Subject: [PATCH 3/7] make json-new as default protocol choice for proc-macro-srv-cli --- crates/proc-macro-srv-cli/src/main.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/proc-macro-srv-cli/src/main.rs b/crates/proc-macro-srv-cli/src/main.rs index d3dae0494fe4..c9134b402dfa 100644 --- a/crates/proc-macro-srv-cli/src/main.rs +++ b/crates/proc-macro-srv-cli/src/main.rs @@ -31,7 +31,7 @@ fn main() -> std::io::Result<()> { clap::Arg::new("format") .long("format") .action(clap::ArgAction::Set) - .default_value("json-legacy") + .default_value("json-new") .value_parser(clap::builder::EnumValueParser::::new()), clap::Arg::new("version") .long("version") @@ -58,7 +58,12 @@ enum ProtocolFormat { impl ValueEnum for ProtocolFormat { fn value_variants<'a>() -> &'a [Self] { - &[ProtocolFormat::JsonLegacy, ProtocolFormat::PostcardLegacy] + &[ + ProtocolFormat::JsonLegacy, + ProtocolFormat::PostcardLegacy, + ProtocolFormat::JsonNew, + ProtocolFormat::PostcardNew, + ] } fn to_possible_value(&self) -> Option { From 28a3b808c4af775ce97611e2cb9c5b73f5eaf034 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 18 Dec 2025 10:10:23 +0530 Subject: [PATCH 4/7] add request id to requests --- .../src/bidirectional_protocol.rs | 50 ++++++------------- crates/proc-macro-api/src/process.rs | 11 +++- .../src/server_impl/rust_analyzer_span.rs | 9 ++-- 3 files changed, 29 insertions(+), 41 deletions(-) diff --git a/crates/proc-macro-api/src/bidirectional_protocol.rs b/crates/proc-macro-api/src/bidirectional_protocol.rs index 246f70a10196..728f0f707d71 100644 --- a/crates/proc-macro-api/src/bidirectional_protocol.rs +++ b/crates/proc-macro-api/src/bidirectional_protocol.rs @@ -30,7 +30,7 @@ use crate::{ pub mod msg; pub trait ClientCallbacks { - fn handle_sub_request(&mut self, id: u64, req: SubRequest) -> Result; + fn handle_sub_request(&mut self, req: SubRequest) -> Result; } pub fn run_conversation( @@ -65,7 +65,7 @@ pub fn run_conversation( match (msg.kind, msg.payload) { (Kind::SubRequest, Payload::SubRequest(sr)) => { - let resp = callbacks.handle_sub_request(id, sr)?; + let resp = callbacks.handle_sub_request(sr)?; let reply = Envelope { id, kind: Kind::SubResponse, payload: Payload::SubResponse(resp) }; let encoded = C::encode(&reply).map_err(wrap_encode)?; @@ -104,19 +104,14 @@ pub(crate) fn version_check(srv: &ProcMacroServerProcess) -> Result Result { + fn handle_sub_request(&mut self, _req: SubRequest) -> Result { Err(ServerError { message: "sub-request not supported here".into(), io: None }) } } let mut callbacks = NoCallbacks; - let response_payload = - run_bidirectional(srv, (0, Kind::Request, request).into(), &mut callbacks)?; + let response_payload = run_request(srv, request, &mut callbacks)?; match response_payload { Payload::Response(Response::ApiVersionCheck(version)) => Ok(version), @@ -135,19 +130,14 @@ pub(crate) fn enable_rust_analyzer_spans( struct NoCallbacks; impl ClientCallbacks for NoCallbacks { - fn handle_sub_request( - &mut self, - _id: u64, - _req: SubRequest, - ) -> Result { + fn handle_sub_request(&mut self, _req: SubRequest) -> Result { Err(ServerError { message: "sub-request not supported here".into(), io: None }) } } let mut callbacks = NoCallbacks; - let response_payload = - run_bidirectional(srv, (0, Kind::Request, request).into(), &mut callbacks)?; + let response_payload = run_request(srv, request, &mut callbacks)?; match response_payload { Payload::Response(Response::SetConfig(ServerConfig { span_mode })) => Ok(span_mode), @@ -165,19 +155,14 @@ pub(crate) fn find_proc_macros( struct NoCallbacks; impl ClientCallbacks for NoCallbacks { - fn handle_sub_request( - &mut self, - _id: u64, - _req: SubRequest, - ) -> Result { + fn handle_sub_request(&mut self, _req: SubRequest) -> Result { Err(ServerError { message: "sub-request not supported here".into(), io: None }) } } let mut callbacks = NoCallbacks; - let response_payload = - run_bidirectional(srv, (0, Kind::Request, request).into(), &mut callbacks)?; + let response_payload = run_request(srv, request, &mut callbacks)?; match response_payload { Payload::Response(Response::ListMacros(it)) => Ok(it), @@ -229,11 +214,7 @@ pub(crate) fn expand( db: &'de dyn SourceDatabase, } impl<'db> ClientCallbacks for Callbacks<'db> { - fn handle_sub_request( - &mut self, - _id: u64, - req: SubRequest, - ) -> Result { + fn handle_sub_request(&mut self, req: SubRequest) -> Result { match req { SubRequest::SourceText { file_id, start, end } => { let file = FileId::from_raw(file_id); @@ -249,8 +230,7 @@ pub(crate) fn expand( let mut callbacks = Callbacks { db }; - let response_payload = - run_bidirectional(&proc_macro.process, (0, Kind::Request, task).into(), &mut callbacks)?; + let response_payload = run_request(&proc_macro.process, task, &mut callbacks)?; match response_payload { Payload::Response(Response::ExpandMacro(it)) => Ok(it @@ -279,18 +259,20 @@ pub(crate) fn expand( } } -fn run_bidirectional( +fn run_request( srv: &ProcMacroServerProcess, - msg: Envelope, + msg: Payload, callbacks: &mut dyn ClientCallbacks, ) -> Result { if let Some(server_error) = srv.exited() { return Err(server_error.clone()); } + let id = srv.request_id(); + if srv.use_postcard() { - srv.run_bidirectional::(msg.id, msg.payload, callbacks) + srv.run_bidirectional::(id, msg, callbacks) } else { - srv.run_bidirectional::(msg.id, msg.payload, callbacks) + srv.run_bidirectional::(id, msg, callbacks) } } diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs index 39d954855187..723fc928ff66 100644 --- a/crates/proc-macro-api/src/process.rs +++ b/crates/proc-macro-api/src/process.rs @@ -4,7 +4,10 @@ use std::{ io::{self, BufRead, BufReader, Read, Write}, panic::AssertUnwindSafe, process::{Child, ChildStdin, ChildStdout, Command, Stdio}, - sync::{Arc, Mutex, OnceLock}, + sync::{ + Arc, Mutex, OnceLock, + atomic::{AtomicU64, Ordering}, + }, }; use base_db::SourceDatabase; @@ -33,6 +36,7 @@ pub(crate) struct ProcMacroServerProcess { protocol: Protocol, /// Populated when the server exits. exited: OnceLock>, + next_request_id: AtomicU64, } #[derive(Debug, Clone)] @@ -90,6 +94,7 @@ impl ProcMacroServerProcess { version: 0, protocol: protocol.clone(), exited: OnceLock::new(), + next_request_id: AtomicU64::new(1), }) }; let mut srv = create_srv()?; @@ -312,6 +317,10 @@ impl ProcMacroServerProcess { ) }) } + + pub(crate) fn request_id(&self) -> RequestId { + self.next_request_id.fetch_add(1, Ordering::Relaxed) + } } /// Manages the execution of the proc-macro server process. diff --git a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 1a8f6d6730f7..cccb74429dd6 100644 --- a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -163,12 +163,9 @@ impl server::Span for RaSpanServer { start, end, }); - self.cli_to_server - .clone() - .unwrap() - .recv() - .and_then(|SubResponse::SourceTextResult { text }| Ok(text)) - .expect("REASON") + match self.cli_to_server.as_ref()?.recv().ok()? { + SubResponse::SourceTextResult { text } => text, + } } else { None } From 57fdf52eccf00fe95f79251b8fe6fbf5817c7ea3 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 18 Dec 2025 14:05:45 +0530 Subject: [PATCH 5/7] refactor the main loop in proc_macro-srv-cli --- crates/proc-macro-srv-cli/src/main_loop.rs | 458 +++++++++++---------- 1 file changed, 247 insertions(+), 211 deletions(-) diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs index e543260964fb..aec971c776e2 100644 --- a/crates/proc-macro-srv-cli/src/main_loop.rs +++ b/crates/proc-macro-srv-cli/src/main_loop.rs @@ -80,236 +80,254 @@ fn run_new() -> io::Result<()> { .collect() }); - let resp_env = Envelope { - id: req.id, - kind: Kind::Response, - payload: Payload::Response( - proc_macro_api::bidirectional_protocol::msg::Response::ListMacros(res), - ), - }; - - resp_env.write::<_, C>(&mut stdout)?; + send_response::<_, C>( + &mut stdout, + req.id, + proc_macro_api::bidirectional_protocol::msg::Response::ListMacros(res), + )?; } Request::ApiVersionCheck {} => { - let resp_env = Envelope { - id: req.id, - kind: Kind::Response, - payload: Payload::Response( - proc_macro_api::bidirectional_protocol::msg::Response::ApiVersionCheck( - CURRENT_API_VERSION, - ), + send_response::<_, C>( + &mut stdout, + req.id, + proc_macro_api::bidirectional_protocol::msg::Response::ApiVersionCheck( + CURRENT_API_VERSION, ), - }; - resp_env.write::<_, C>(&mut stdout)?; + )?; } Request::SetConfig(config) => { span_mode = config.span_mode; - let resp_env = Envelope { - id: req.id, - kind: Kind::Response, - payload: Payload::Response( - proc_macro_api::bidirectional_protocol::msg::Response::SetConfig( - config, - ), - ), - }; - resp_env.write::<_, C>(&mut stdout)?; + send_response::<_, C>( + &mut stdout, + req.id, + proc_macro_api::bidirectional_protocol::msg::Response::SetConfig(config), + )?; } - Request::ExpandMacro(task) => { - let proc_macro_api::bidirectional_protocol::msg::ExpandMacro { + handle_expand::<_, _, C>( + &srv, + &mut stdin, + &mut stdout, + &mut buf, + req.id, + span_mode, + *task, + )?; + } + }, + _ => continue, + } + } + + Ok(()) +} + +fn handle_expand( + srv: &proc_macro_srv::ProcMacroSrv<'_>, + stdin: &mut R, + stdout: &mut W, + buf: &mut C::Buf, + req_id: u64, + span_mode: SpanMode, + task: proc_macro_api::bidirectional_protocol::msg::ExpandMacro, +) -> io::Result<()> { + match span_mode { + SpanMode::Id => handle_expand_id::<_, C>(srv, stdout, req_id, task), + SpanMode::RustAnalyzer => { + handle_expand_ra::<_, _, C>(srv, stdin, stdout, buf, req_id, task) + } + } +} + +fn handle_expand_id( + srv: &proc_macro_srv::ProcMacroSrv<'_>, + stdout: &mut W, + req_id: u64, + task: proc_macro_api::bidirectional_protocol::msg::ExpandMacro, +) -> io::Result<()> { + let proc_macro_api::bidirectional_protocol::msg::ExpandMacro { lib, env, current_dir, data } = + task; + let proc_macro_api::bidirectional_protocol::msg::ExpandMacroData { + macro_body, + macro_name, + attributes, + has_global_spans: + proc_macro_api::bidirectional_protocol::msg::ExpnGlobals { + def_site, + call_site, + mixed_site, + .. + }, + .. + } = data; + + let def_site = SpanId(def_site as u32); + let call_site = SpanId(call_site as u32); + let mixed_site = SpanId(mixed_site as u32); + + let macro_body = + macro_body.to_tokenstream_unresolved::(CURRENT_API_VERSION, |_, b| b); + let attributes = attributes + .map(|it| it.to_tokenstream_unresolved::(CURRENT_API_VERSION, |_, b| b)); + + let res = srv + .expand( + lib, + &env, + current_dir, + ¯o_name, + macro_body, + attributes, + def_site, + call_site, + mixed_site, + ) + .map(|it| { + msg::FlatTree::from_tokenstream_raw::(it, call_site, CURRENT_API_VERSION) + }) + .map_err(|e| msg::PanicMessage(e.into_string().unwrap_or_default())); + + send_response::<_, C>( + stdout, + req_id, + proc_macro_api::bidirectional_protocol::msg::Response::ExpandMacro(res), + ) +} + +fn handle_expand_ra( + srv: &proc_macro_srv::ProcMacroSrv<'_>, + stdin: &mut R, + stdout: &mut W, + buf: &mut C::Buf, + req_id: u64, + task: proc_macro_api::bidirectional_protocol::msg::ExpandMacro, +) -> io::Result<()> { + let proc_macro_api::bidirectional_protocol::msg::ExpandMacro { + lib, + env, + current_dir, + data: + proc_macro_api::bidirectional_protocol::msg::ExpandMacroData { + macro_body, + macro_name, + attributes, + has_global_spans: + proc_macro_api::bidirectional_protocol::msg::ExpnGlobals { + serialize: _, + def_site, + call_site, + mixed_site, + }, + span_data_table, + }, + } = task; + + let mut span_data_table = deserialize_span_data_index_map(&span_data_table); + + let def_site_span = span_data_table[def_site]; + let call_site_span = span_data_table[call_site]; + let mixed_site_span = span_data_table[mixed_site]; + + let macro_body_ts = + macro_body.to_tokenstream_resolved(CURRENT_API_VERSION, &span_data_table, |a, b| { + srv.join_spans(a, b).unwrap_or(b) + }); + let attributes_ts = attributes.map(|it| { + it.to_tokenstream_resolved(CURRENT_API_VERSION, &span_data_table, |a, b| { + srv.join_spans(a, b).unwrap_or(b) + }) + }); + + let (subreq_tx, subreq_rx) = unbounded::(); + let (subresp_tx, subresp_rx) = unbounded::(); + let (result_tx, result_rx) = crossbeam_channel::bounded(1); + + std::thread::scope(|scope| { + let srv_ref = &srv; + + scope.spawn({ + let lib = lib.clone(); + let env = env.clone(); + let current_dir = current_dir.clone(); + let macro_name = macro_name.clone(); + move || { + let res = srv_ref + .expand_with_channels( lib, - env, + &env, current_dir, - data: - proc_macro_api::bidirectional_protocol::msg::ExpandMacroData { - macro_body, - macro_name, - attributes, - has_global_spans: - proc_macro_api::bidirectional_protocol::msg::ExpnGlobals { - serialize: _, - def_site, - call_site, - mixed_site, - }, - span_data_table, - }, - } = *task; - - match span_mode { - SpanMode::Id => { - let def_site = SpanId(def_site as u32); - let call_site = SpanId(call_site as u32); - let mixed_site = SpanId(mixed_site as u32); - - let macro_body = macro_body.to_tokenstream_unresolved::( + ¯o_name, + macro_body_ts, + attributes_ts, + def_site_span, + call_site_span, + mixed_site_span, + subresp_rx, + subreq_tx, + ) + .map(|it| { + ( + msg::FlatTree::from_tokenstream( + it, CURRENT_API_VERSION, - |_, b| b, - ); - let attributes = attributes.map(|it| { - it.to_tokenstream_unresolved::( - CURRENT_API_VERSION, - |_, b| b, - ) - }); - - let res = srv - .expand( - lib, - &env, - current_dir, - ¯o_name, - macro_body, - attributes, - def_site, - call_site, - mixed_site, - ) - .map(|it| { - msg::FlatTree::from_tokenstream_raw::( - it, - call_site, - CURRENT_API_VERSION, - ) - }) - .map_err(|e| e.into_string().unwrap_or_default()) - .map_err(msg::PanicMessage); - - let resp_env = Envelope { - id: req.id, - kind: Kind::Response, - payload: Payload::Response(proc_macro_api::bidirectional_protocol::msg::Response::ExpandMacro(res)), - }; - - resp_env.write::<_, C>(&mut stdout)?; + call_site_span, + &mut span_data_table, + ), + serialize_span_data_index_map(&span_data_table), + ) + }) + .map(|(tree, span_data_table)| { + proc_macro_api::bidirectional_protocol::msg::ExpandMacroExtended { + tree, + span_data_table, } + }) + .map_err(|e| e.into_string().unwrap_or_default()) + .map_err(msg::PanicMessage); + let _ = result_tx.send(res); + } + }); + + loop { + if let Ok(res) = result_rx.try_recv() { + send_response::<_, C>( + stdout, + req_id, + proc_macro_api::bidirectional_protocol::msg::Response::ExpandMacroExtended(res), + ) + .unwrap(); + break; + } - SpanMode::RustAnalyzer => { - let mut span_data_table = - deserialize_span_data_index_map(&span_data_table); + let subreq = match subreq_rx.recv() { + Ok(r) => r, + Err(_) => { + break; + } + }; - let def_site_span = span_data_table[def_site]; - let call_site_span = span_data_table[call_site]; - let mixed_site_span = span_data_table[mixed_site]; + send_subrequest::<_, C>(stdout, req_id, from_srv_req(subreq)).unwrap(); - let macro_body_ts = macro_body.to_tokenstream_resolved( - CURRENT_API_VERSION, - &span_data_table, - |a, b| srv.join_spans(a, b).unwrap_or(b), - ); - let attributes_ts = attributes.map(|it| { - it.to_tokenstream_resolved( - CURRENT_API_VERSION, - &span_data_table, - |a, b| srv.join_spans(a, b).unwrap_or(b), - ) - }); - - let (subreq_tx, subreq_rx) = unbounded::(); - let (subresp_tx, subresp_rx) = - unbounded::(); - let (result_tx, result_rx) = crossbeam_channel::bounded(1); - - std::thread::scope(|scope| { - let srv_ref = &srv; - - scope.spawn({ - let lib = lib.clone(); - let env = env.clone(); - let current_dir = current_dir.clone(); - let macro_name = macro_name.clone(); - move || { - let res = srv_ref - .expand_with_channels( - lib, - &env, - current_dir, - ¯o_name, - macro_body_ts, - attributes_ts, - def_site_span, - call_site_span, - mixed_site_span, - subresp_rx, - subreq_tx, - ) - .map(|it| { - ( - msg::FlatTree::from_tokenstream( - it, - CURRENT_API_VERSION, - call_site_span, - &mut span_data_table, - ), - serialize_span_data_index_map(&span_data_table), - ) - }) - .map(|(tree, span_data_table)| { - proc_macro_api::bidirectional_protocol::msg::ExpandMacroExtended { tree, span_data_table } - }) - .map_err(|e| e.into_string().unwrap_or_default()) - .map_err(msg::PanicMessage); - let _ = result_tx.send(res); - } - }); - - loop { - if let Ok(res) = result_rx.try_recv() { - let resp_env = Envelope { - id: req.id, - kind: Kind::Response, - payload: Payload::Response( - proc_macro_api::bidirectional_protocol::msg::Response::ExpandMacroExtended(res), - ), - }; - resp_env.write::<_, C>(&mut stdout).unwrap(); - break; - } - - let subreq = match subreq_rx.recv() { - Ok(r) => r, - Err(_) => { - break; - } - }; - - let sub_env = Envelope { - id: req.id, - kind: Kind::SubRequest, - payload: Payload::SubRequest(from_srv_req(subreq)), - }; - sub_env.write::<_, C>(&mut stdout).unwrap(); - - let resp_opt = - Envelope::read::<_, C>(&mut stdin, &mut buf).unwrap(); - let resp = match resp_opt { - Some(env) => env, - None => { - break; - } - }; - - match (resp.kind, resp.payload) { - (Kind::SubResponse, Payload::SubResponse(subresp)) => { - let _ = subresp_tx.send(from_client_res(subresp)); - } - _ => { - break; - } - } - } - }); - } - } + let resp_opt = Envelope::read::<_, C>(stdin, buf).unwrap(); + let resp = match resp_opt { + Some(env) => env, + None => { + break; } - }, - _ => {} - } - } + }; + match (resp.kind, resp.payload) { + (Kind::SubResponse, Payload::SubResponse(subresp)) => { + let _ = subresp_tx.send(from_client_res(subresp)); + } + _ => { + break; + } + } + } + }); Ok(()) } @@ -473,3 +491,21 @@ fn from_client_res( } } } + +fn send_response( + stdout: &mut W, + id: u64, + resp: proc_macro_api::bidirectional_protocol::msg::Response, +) -> io::Result<()> { + let resp = Envelope { id, kind: Kind::Response, payload: Payload::Response(resp) }; + resp.write::(stdout) +} + +fn send_subrequest( + stdout: &mut W, + id: u64, + resp: proc_macro_api::bidirectional_protocol::msg::SubRequest, +) -> io::Result<()> { + let resp = Envelope { id, kind: Kind::SubRequest, payload: Payload::SubRequest(resp) }; + resp.write::(stdout) +} From 58f2e178661863be683ea79d27c1c387d67b8c24 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 18 Dec 2025 14:25:15 +0530 Subject: [PATCH 6/7] make imports proper --- crates/proc-macro-srv-cli/src/main_loop.rs | 253 ++++++++++----------- 1 file changed, 120 insertions(+), 133 deletions(-) diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs index aec971c776e2..1ad73d4daac2 100644 --- a/crates/proc-macro-srv-cli/src/main_loop.rs +++ b/crates/proc-macro-srv-cli/src/main_loop.rs @@ -2,23 +2,22 @@ use std::io; use crossbeam_channel::unbounded; -use proc_macro_api::bidirectional_protocol::msg::Request; use proc_macro_api::{ Codec, - bidirectional_protocol::msg::{Envelope, Kind, Payload}, - legacy_protocol::msg::{ - self, ExpandMacroData, ExpnGlobals, Message, SpanMode, SpanTransformer, - deserialize_span_data_index_map, serialize_span_data_index_map, - }, + bidirectional_protocol::msg as bidirectional, + legacy_protocol::msg as legacy, transport::codec::{json::JsonProtocol, postcard::PostcardProtocol}, version::CURRENT_API_VERSION, }; + +use legacy::Message; + use proc_macro_srv::{EnvSnapshot, SpanId}; use crate::ProtocolFormat; struct SpanTrans; -impl SpanTransformer for SpanTrans { +impl legacy::SpanTransformer for SpanTrans { type Table = (); type Span = SpanId; fn token_id_of( @@ -62,61 +61,61 @@ fn run_new() -> io::Result<()> { let env_snapshot = EnvSnapshot::default(); let srv = proc_macro_srv::ProcMacroSrv::new(&env_snapshot); - let mut span_mode = SpanMode::Id; + let mut span_mode = legacy::SpanMode::Id; 'outer: loop { - let req_opt = Envelope::read::<_, C>(&mut stdin, &mut buf)?; + let req_opt = bidirectional::Envelope::read::<_, C>(&mut stdin, &mut buf)?; let Some(req) = req_opt else { break 'outer; }; match (req.kind, req.payload) { - (Kind::Request, Payload::Request(request)) => match request { - Request::ListMacros { dylib_path } => { - let res = srv.list_macros(&dylib_path).map(|macros| { - macros - .into_iter() - .map(|(name, kind)| (name, macro_kind_to_api(kind))) - .collect() - }); - - send_response::<_, C>( - &mut stdout, - req.id, - proc_macro_api::bidirectional_protocol::msg::Response::ListMacros(res), - )?; - } - - Request::ApiVersionCheck {} => { - send_response::<_, C>( - &mut stdout, - req.id, - proc_macro_api::bidirectional_protocol::msg::Response::ApiVersionCheck( - CURRENT_API_VERSION, - ), - )?; - } + (bidirectional::Kind::Request, bidirectional::Payload::Request(request)) => { + match request { + bidirectional::Request::ListMacros { dylib_path } => { + let res = srv.list_macros(&dylib_path).map(|macros| { + macros + .into_iter() + .map(|(name, kind)| (name, macro_kind_to_api(kind))) + .collect() + }); - Request::SetConfig(config) => { - span_mode = config.span_mode; - send_response::<_, C>( - &mut stdout, - req.id, - proc_macro_api::bidirectional_protocol::msg::Response::SetConfig(config), - )?; - } - Request::ExpandMacro(task) => { - handle_expand::<_, _, C>( - &srv, - &mut stdin, - &mut stdout, - &mut buf, - req.id, - span_mode, - *task, - )?; + send_response::<_, C>( + &mut stdout, + req.id, + bidirectional::Response::ListMacros(res), + )?; + } + + bidirectional::Request::ApiVersionCheck {} => { + send_response::<_, C>( + &mut stdout, + req.id, + bidirectional::Response::ApiVersionCheck(CURRENT_API_VERSION), + )?; + } + + bidirectional::Request::SetConfig(config) => { + span_mode = config.span_mode; + send_response::<_, C>( + &mut stdout, + req.id, + bidirectional::Response::SetConfig(config), + )?; + } + bidirectional::Request::ExpandMacro(task) => { + handle_expand::<_, _, C>( + &srv, + &mut stdin, + &mut stdout, + &mut buf, + req.id, + span_mode, + *task, + )?; + } } - }, + } _ => continue, } } @@ -130,12 +129,12 @@ fn handle_expand( stdout: &mut W, buf: &mut C::Buf, req_id: u64, - span_mode: SpanMode, - task: proc_macro_api::bidirectional_protocol::msg::ExpandMacro, + span_mode: legacy::SpanMode, + task: bidirectional::ExpandMacro, ) -> io::Result<()> { match span_mode { - SpanMode::Id => handle_expand_id::<_, C>(srv, stdout, req_id, task), - SpanMode::RustAnalyzer => { + legacy::SpanMode::Id => handle_expand_id::<_, C>(srv, stdout, req_id, task), + legacy::SpanMode::RustAnalyzer => { handle_expand_ra::<_, _, C>(srv, stdin, stdout, buf, req_id, task) } } @@ -145,21 +144,14 @@ fn handle_expand_id( srv: &proc_macro_srv::ProcMacroSrv<'_>, stdout: &mut W, req_id: u64, - task: proc_macro_api::bidirectional_protocol::msg::ExpandMacro, + task: bidirectional::ExpandMacro, ) -> io::Result<()> { - let proc_macro_api::bidirectional_protocol::msg::ExpandMacro { lib, env, current_dir, data } = - task; - let proc_macro_api::bidirectional_protocol::msg::ExpandMacroData { + let bidirectional::ExpandMacro { lib, env, current_dir, data } = task; + let bidirectional::ExpandMacroData { macro_body, macro_name, attributes, - has_global_spans: - proc_macro_api::bidirectional_protocol::msg::ExpnGlobals { - def_site, - call_site, - mixed_site, - .. - }, + has_global_spans: bidirectional::ExpnGlobals { def_site, call_site, mixed_site, .. }, .. } = data; @@ -185,15 +177,11 @@ fn handle_expand_id( mixed_site, ) .map(|it| { - msg::FlatTree::from_tokenstream_raw::(it, call_site, CURRENT_API_VERSION) + legacy::FlatTree::from_tokenstream_raw::(it, call_site, CURRENT_API_VERSION) }) - .map_err(|e| msg::PanicMessage(e.into_string().unwrap_or_default())); + .map_err(|e| legacy::PanicMessage(e.into_string().unwrap_or_default())); - send_response::<_, C>( - stdout, - req_id, - proc_macro_api::bidirectional_protocol::msg::Response::ExpandMacro(res), - ) + send_response::<_, C>(stdout, req_id, bidirectional::Response::ExpandMacro(res)) } fn handle_expand_ra( @@ -202,29 +190,24 @@ fn handle_expand_ra( stdout: &mut W, buf: &mut C::Buf, req_id: u64, - task: proc_macro_api::bidirectional_protocol::msg::ExpandMacro, + task: bidirectional::ExpandMacro, ) -> io::Result<()> { - let proc_macro_api::bidirectional_protocol::msg::ExpandMacro { + let bidirectional::ExpandMacro { lib, env, current_dir, data: - proc_macro_api::bidirectional_protocol::msg::ExpandMacroData { + bidirectional::ExpandMacroData { macro_body, macro_name, attributes, has_global_spans: - proc_macro_api::bidirectional_protocol::msg::ExpnGlobals { - serialize: _, - def_site, - call_site, - mixed_site, - }, + bidirectional::ExpnGlobals { serialize: _, def_site, call_site, mixed_site }, span_data_table, }, } = task; - let mut span_data_table = deserialize_span_data_index_map(&span_data_table); + let mut span_data_table = legacy::deserialize_span_data_index_map(&span_data_table); let def_site_span = span_data_table[def_site]; let call_site_span = span_data_table[call_site]; @@ -269,23 +252,21 @@ fn handle_expand_ra( ) .map(|it| { ( - msg::FlatTree::from_tokenstream( + legacy::FlatTree::from_tokenstream( it, CURRENT_API_VERSION, call_site_span, &mut span_data_table, ), - serialize_span_data_index_map(&span_data_table), + legacy::serialize_span_data_index_map(&span_data_table), ) }) - .map(|(tree, span_data_table)| { - proc_macro_api::bidirectional_protocol::msg::ExpandMacroExtended { - tree, - span_data_table, - } + .map(|(tree, span_data_table)| bidirectional::ExpandMacroExtended { + tree, + span_data_table, }) .map_err(|e| e.into_string().unwrap_or_default()) - .map_err(msg::PanicMessage); + .map_err(legacy::PanicMessage); let _ = result_tx.send(res); } }); @@ -295,7 +276,7 @@ fn handle_expand_ra( send_response::<_, C>( stdout, req_id, - proc_macro_api::bidirectional_protocol::msg::Response::ExpandMacroExtended(res), + bidirectional::Response::ExpandMacroExtended(res), ) .unwrap(); break; @@ -310,7 +291,7 @@ fn handle_expand_ra( send_subrequest::<_, C>(stdout, req_id, from_srv_req(subreq)).unwrap(); - let resp_opt = Envelope::read::<_, C>(stdin, buf).unwrap(); + let resp_opt = bidirectional::Envelope::read::<_, C>(stdin, buf).unwrap(); let resp = match resp_opt { Some(env) => env, None => { @@ -319,7 +300,10 @@ fn handle_expand_ra( }; match (resp.kind, resp.payload) { - (Kind::SubResponse, Payload::SubResponse(subresp)) => { + ( + bidirectional::Kind::SubResponse, + bidirectional::Payload::SubResponse(subresp), + ) => { let _ = subresp_tx.send(from_client_res(subresp)); } _ => { @@ -343,38 +327,38 @@ fn run_() -> io::Result<()> { } let mut buf = C::Buf::default(); - let mut read_request = || msg::Request::read::<_, C>(&mut io::stdin().lock(), &mut buf); - let write_response = |msg: msg::Response| msg.write::<_, C>(&mut io::stdout().lock()); + let mut read_request = || legacy::Request::read::<_, C>(&mut io::stdin().lock(), &mut buf); + let write_response = |msg: legacy::Response| msg.write::<_, C>(&mut io::stdout().lock()); let env = EnvSnapshot::default(); let srv = proc_macro_srv::ProcMacroSrv::new(&env); - let mut span_mode = SpanMode::Id; + let mut span_mode = legacy::SpanMode::Id; while let Some(req) = read_request()? { let res = match req { - msg::Request::ListMacros { dylib_path } => { - msg::Response::ListMacros(srv.list_macros(&dylib_path).map(|macros| { + legacy::Request::ListMacros { dylib_path } => { + legacy::Response::ListMacros(srv.list_macros(&dylib_path).map(|macros| { macros.into_iter().map(|(name, kind)| (name, macro_kind_to_api(kind))).collect() })) } - msg::Request::ExpandMacro(task) => { - let msg::ExpandMacro { + legacy::Request::ExpandMacro(task) => { + let legacy::ExpandMacro { lib, env, current_dir, data: - ExpandMacroData { + legacy::ExpandMacroData { macro_body, macro_name, attributes, has_global_spans: - ExpnGlobals { serialize: _, def_site, call_site, mixed_site }, + legacy::ExpnGlobals { serialize: _, def_site, call_site, mixed_site }, span_data_table, }, } = *task; match span_mode { - SpanMode::Id => msg::Response::ExpandMacro({ + legacy::SpanMode::Id => legacy::Response::ExpandMacro({ let def_site = SpanId(def_site as u32); let call_site = SpanId(call_site as u32); let mixed_site = SpanId(mixed_site as u32); @@ -397,17 +381,18 @@ fn run_() -> io::Result<()> { mixed_site, ) .map(|it| { - msg::FlatTree::from_tokenstream_raw::( + legacy::FlatTree::from_tokenstream_raw::( it, call_site, CURRENT_API_VERSION, ) }) .map_err(|e| e.into_string().unwrap_or_default()) - .map_err(msg::PanicMessage) + .map_err(legacy::PanicMessage) }), - SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended({ - let mut span_data_table = deserialize_span_data_index_map(&span_data_table); + legacy::SpanMode::RustAnalyzer => legacy::Response::ExpandMacroExtended({ + let mut span_data_table = + legacy::deserialize_span_data_index_map(&span_data_table); let def_site = span_data_table[def_site]; let call_site = span_data_table[call_site]; @@ -438,28 +423,30 @@ fn run_() -> io::Result<()> { ) .map(|it| { ( - msg::FlatTree::from_tokenstream( + legacy::FlatTree::from_tokenstream( it, CURRENT_API_VERSION, call_site, &mut span_data_table, ), - serialize_span_data_index_map(&span_data_table), + legacy::serialize_span_data_index_map(&span_data_table), ) }) - .map(|(tree, span_data_table)| msg::ExpandMacroExtended { + .map(|(tree, span_data_table)| legacy::ExpandMacroExtended { tree, span_data_table, }) .map_err(|e| e.into_string().unwrap_or_default()) - .map_err(msg::PanicMessage) + .map_err(legacy::PanicMessage) }), } } - msg::Request::ApiVersionCheck {} => msg::Response::ApiVersionCheck(CURRENT_API_VERSION), - msg::Request::SetConfig(config) => { + legacy::Request::ApiVersionCheck {} => { + legacy::Response::ApiVersionCheck(CURRENT_API_VERSION) + } + legacy::Request::SetConfig(config) => { span_mode = config.span_mode; - msg::Response::SetConfig(config) + legacy::Response::SetConfig(config) } }; write_response(res)? @@ -468,25 +455,17 @@ fn run_() -> io::Result<()> { Ok(()) } -fn from_srv_req( - value: proc_macro_srv::SubRequest, -) -> proc_macro_api::bidirectional_protocol::msg::SubRequest { +fn from_srv_req(value: proc_macro_srv::SubRequest) -> bidirectional::SubRequest { match value { proc_macro_srv::SubRequest::SourceText { file_id, start, end } => { - proc_macro_api::bidirectional_protocol::msg::SubRequest::SourceText { - file_id: file_id.file_id().index(), - start, - end, - } + bidirectional::SubRequest::SourceText { file_id: file_id.file_id().index(), start, end } } } } -fn from_client_res( - value: proc_macro_api::bidirectional_protocol::msg::SubResponse, -) -> proc_macro_srv::SubResponse { +fn from_client_res(value: bidirectional::SubResponse) -> proc_macro_srv::SubResponse { match value { - proc_macro_api::bidirectional_protocol::msg::SubResponse::SourceTextResult { text } => { + bidirectional::SubResponse::SourceTextResult { text } => { proc_macro_srv::SubResponse::SourceTextResult { text } } } @@ -495,17 +474,25 @@ fn from_client_res( fn send_response( stdout: &mut W, id: u64, - resp: proc_macro_api::bidirectional_protocol::msg::Response, + resp: bidirectional::Response, ) -> io::Result<()> { - let resp = Envelope { id, kind: Kind::Response, payload: Payload::Response(resp) }; + let resp = bidirectional::Envelope { + id, + kind: bidirectional::Kind::Response, + payload: bidirectional::Payload::Response(resp), + }; resp.write::(stdout) } fn send_subrequest( stdout: &mut W, id: u64, - resp: proc_macro_api::bidirectional_protocol::msg::SubRequest, + resp: bidirectional::SubRequest, ) -> io::Result<()> { - let resp = Envelope { id, kind: Kind::SubRequest, payload: Payload::SubRequest(resp) }; + let resp = bidirectional::Envelope { + id, + kind: bidirectional::Kind::SubRequest, + payload: bidirectional::Payload::SubRequest(resp), + }; resp.write::(stdout) } From 19e816d3bf945e0dbfd8b5db9032c0b291d4e890 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 18 Dec 2025 14:34:57 +0530 Subject: [PATCH 7/7] change request id to u32 to make powerpc happy --- .../proc-macro-api/src/bidirectional_protocol/msg.rs | 2 +- crates/proc-macro-api/src/process.rs | 6 +++--- crates/proc-macro-srv-cli/src/main_loop.rs | 11 ++++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs index 7aed3ae1e607..796573385c3c 100644 --- a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs +++ b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs @@ -8,7 +8,7 @@ use crate::{ legacy_protocol::msg::{FlatTree, Message, PanicMessage, ServerConfig}, }; -pub type RequestId = u64; +pub type RequestId = u32; #[derive(Debug, Serialize, Deserialize)] pub struct Envelope { diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs index 723fc928ff66..bb4599c53272 100644 --- a/crates/proc-macro-api/src/process.rs +++ b/crates/proc-macro-api/src/process.rs @@ -6,7 +6,7 @@ use std::{ process::{Child, ChildStdin, ChildStdout, Command, Stdio}, sync::{ Arc, Mutex, OnceLock, - atomic::{AtomicU64, Ordering}, + atomic::{AtomicU32, Ordering}, }, }; @@ -36,7 +36,7 @@ pub(crate) struct ProcMacroServerProcess { protocol: Protocol, /// Populated when the server exits. exited: OnceLock>, - next_request_id: AtomicU64, + next_request_id: AtomicU32, } #[derive(Debug, Clone)] @@ -94,7 +94,7 @@ impl ProcMacroServerProcess { version: 0, protocol: protocol.clone(), exited: OnceLock::new(), - next_request_id: AtomicU64::new(1), + next_request_id: AtomicU32::new(1), }) }; let mut srv = create_srv()?; diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs index 1ad73d4daac2..dc828a87de13 100644 --- a/crates/proc-macro-srv-cli/src/main_loop.rs +++ b/crates/proc-macro-srv-cli/src/main_loop.rs @@ -10,6 +10,7 @@ use proc_macro_api::{ version::CURRENT_API_VERSION, }; +use bidirectional::RequestId; use legacy::Message; use proc_macro_srv::{EnvSnapshot, SpanId}; @@ -128,7 +129,7 @@ fn handle_expand( stdin: &mut R, stdout: &mut W, buf: &mut C::Buf, - req_id: u64, + req_id: RequestId, span_mode: legacy::SpanMode, task: bidirectional::ExpandMacro, ) -> io::Result<()> { @@ -143,7 +144,7 @@ fn handle_expand( fn handle_expand_id( srv: &proc_macro_srv::ProcMacroSrv<'_>, stdout: &mut W, - req_id: u64, + req_id: RequestId, task: bidirectional::ExpandMacro, ) -> io::Result<()> { let bidirectional::ExpandMacro { lib, env, current_dir, data } = task; @@ -189,7 +190,7 @@ fn handle_expand_ra( stdin: &mut R, stdout: &mut W, buf: &mut C::Buf, - req_id: u64, + req_id: RequestId, task: bidirectional::ExpandMacro, ) -> io::Result<()> { let bidirectional::ExpandMacro { @@ -473,7 +474,7 @@ fn from_client_res(value: bidirectional::SubResponse) -> proc_macro_srv::SubResp fn send_response( stdout: &mut W, - id: u64, + id: u32, resp: bidirectional::Response, ) -> io::Result<()> { let resp = bidirectional::Envelope { @@ -486,7 +487,7 @@ fn send_response( fn send_subrequest( stdout: &mut W, - id: u64, + id: u32, resp: bidirectional::SubRequest, ) -> io::Result<()> { let resp = bidirectional::Envelope {