Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/load-cargo/src/lib.rs2
-rw-r--r--crates/proc-macro-api/src/bidirectional_protocol.rs27
-rw-r--r--crates/proc-macro-api/src/bidirectional_protocol/msg.rs89
-rw-r--r--crates/proc-macro-api/src/process.rs5
-rw-r--r--crates/proc-macro-srv-cli/src/lib.rs22
-rw-r--r--crates/proc-macro-srv-cli/src/main_loop.rs67
-rw-r--r--crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs35
-rw-r--r--crates/proc-macro-srv/src/dylib.rs18
-rw-r--r--crates/proc-macro-srv/src/dylib/proc_macros.rs15
-rw-r--r--crates/proc-macro-srv/src/lib.rs51
-rw-r--r--crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs33
-rw-r--r--crates/proc-macro-srv/src/server_impl/token_id.rs18
-rw-r--r--crates/proc-macro-srv/src/tests/utils.rs40
13 files changed, 290 insertions, 132 deletions
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index d0c34580c4..fd90bc404a 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -724,6 +724,8 @@ impl ProcMacroExpander for Expander {
Ok(SubResponse::SpanParentResult { parent_span: None })
}
+ // FIXME: implement this
+ SubRequest::SpanJoin { .. } => Ok(SubResponse::SpanJoinResult { span: None }),
};
match self.0.expand(
subtree.view(),
diff --git a/crates/proc-macro-api/src/bidirectional_protocol.rs b/crates/proc-macro-api/src/bidirectional_protocol.rs
index ba59cb219b..75c3bf8d35 100644
--- a/crates/proc-macro-api/src/bidirectional_protocol.rs
+++ b/crates/proc-macro-api/src/bidirectional_protocol.rs
@@ -12,8 +12,8 @@ use span::Span;
use crate::{
ProcMacro, ProcMacroKind, ServerError,
bidirectional_protocol::msg::{
- BidirectionalMessage, ExpandMacro, ExpandMacroData, ExpnGlobals, Request, Response,
- SubRequest, SubResponse,
+ ApiVersionCheck, BidirectionalMessage, ExpandMacro, ExpandMacroData, ExpnGlobals,
+ ListMacros, Request, Response, SubRequest, SubResponse,
},
legacy_protocol::{
SpanMode,
@@ -98,7 +98,7 @@ pub(crate) fn version_check(
srv: &ProcMacroServerProcess,
callback: SubCallback<'_>,
) -> Result<u32, ServerError> {
- let request = BidirectionalMessage::Request(Request::ApiVersionCheck {});
+ let request = BidirectionalMessage::Request(Request::ApiVersionCheck(ApiVersionCheck {}));
let response_payload = run_request(srv, request, callback)?;
@@ -135,9 +135,9 @@ pub(crate) fn find_proc_macros(
dylib_path: &AbsPath,
callback: SubCallback<'_>,
) -> Result<Result<Vec<(String, ProcMacroKind)>, String>, ServerError> {
- let request = BidirectionalMessage::Request(Request::ListMacros {
+ let request = BidirectionalMessage::Request(Request::ListMacros(ListMacros {
dylib_path: dylib_path.to_path_buf().into(),
- });
+ }));
let response_payload = run_request(srv, request, callback)?;
@@ -186,25 +186,12 @@ pub(crate) fn expand(
match response_payload {
BidirectionalMessage::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)),
- BidirectionalMessage::Response(Response::ExpandMacroExtended(it)) => Ok(it
.map(|resp| {
- let mut expanded = FlatTree::to_subtree_resolved(
+ 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 }),
diff --git a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs
index ab4bed81e6..e516297f06 100644
--- a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs
+++ b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs
@@ -1,6 +1,8 @@
//! Bidirectional protocol messages
+#![expect(clippy::disallowed_types)]
use std::{
+ collections::{HashMap, HashSet},
io::{self, BufRead, Write},
ops::Range,
};
@@ -16,13 +18,54 @@ use crate::{
#[derive(Debug, Serialize, Deserialize)]
pub enum SubRequest {
- FilePath { file_id: u32 },
- SourceText { file_id: u32, ast_id: u32, start: u32, end: u32 },
- LocalFilePath { file_id: u32 },
- LineColumn { file_id: u32, ast_id: u32, offset: u32 },
- ByteRange { file_id: u32, ast_id: u32, start: u32, end: u32 },
- SpanSource { file_id: u32, ast_id: u32, start: u32, end: u32, ctx: u32 },
- SpanParent { file_id: u32, ast_id: u32, start: u32, end: u32, ctx: u32 },
+ FilePath {
+ file_id: u32,
+ },
+ SourceText {
+ file_id: u32,
+ ast_id: u32,
+ start: u32,
+ end: u32,
+ },
+ LocalFilePath {
+ file_id: u32,
+ },
+ LineColumn {
+ file_id: u32,
+ ast_id: u32,
+ offset: u32,
+ },
+ ByteRange {
+ file_id: u32,
+ ast_id: u32,
+ start: u32,
+ end: u32,
+ },
+ SpanSource {
+ file_id: u32,
+ ast_id: u32,
+ start: u32,
+ end: u32,
+ ctx: u32,
+ },
+ SpanParent {
+ file_id: u32,
+ ast_id: u32,
+ start: u32,
+ end: u32,
+ ctx: u32,
+ },
+ SpanJoin {
+ file_id: u32,
+ ast_id_first: u32,
+ start_first: u32,
+ end_first: u32,
+ ctx_first: u32,
+ ast_id_second: u32,
+ start_second: u32,
+ end_second: u32,
+ ctx_second: u32,
+ },
}
#[derive(Debug, Serialize, Deserialize)]
@@ -54,6 +97,9 @@ pub enum SubResponse {
SpanParentResult {
parent_span: Option<ParentSpan>,
},
+ SpanJoinResult {
+ span: Option<SpanJoin>,
+ },
Cancel {
reason: String,
},
@@ -69,6 +115,15 @@ pub struct ParentSpan {
}
#[derive(Debug, Serialize, Deserialize)]
+pub struct SpanJoin {
+ pub ast_id: u32,
+ pub start: u32,
+ pub end: u32,
+ pub ctx: u32,
+}
+
+#[expect(clippy::large_enum_variant)]
+#[derive(Debug, Serialize, Deserialize)]
pub enum BidirectionalMessage {
Request(Request),
Response(Response),
@@ -78,22 +133,30 @@ pub enum BidirectionalMessage {
#[derive(Debug, Serialize, Deserialize)]
pub enum Request {
- ListMacros { dylib_path: Utf8PathBuf },
+ ListMacros(ListMacros),
ExpandMacro(Box<ExpandMacro>),
- ApiVersionCheck {},
+ ApiVersionCheck(ApiVersionCheck),
SetConfig(ServerConfig),
}
+#[expect(clippy::large_enum_variant)]
#[derive(Debug, Serialize, Deserialize)]
pub enum Response {
ListMacros(Result<Vec<(String, ProcMacroKind)>, String>),
- ExpandMacro(Result<FlatTree, PanicMessage>),
ApiVersionCheck(u32),
SetConfig(ServerConfig),
- ExpandMacroExtended(Result<ExpandMacroExtended, PanicMessage>),
+ ExpandMacro(Result<ExpandMacroResponse, PanicMessage>),
}
#[derive(Debug, Serialize, Deserialize)]
+pub struct ListMacros {
+ pub dylib_path: Utf8PathBuf,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct ApiVersionCheck {}
+
+#[derive(Debug, Serialize, Deserialize)]
pub struct ExpandMacro {
pub lib: Utf8PathBuf,
pub env: Vec<(String, String)>,
@@ -102,9 +165,11 @@ pub struct ExpandMacro {
}
#[derive(Debug, Serialize, Deserialize)]
-pub struct ExpandMacroExtended {
+pub struct ExpandMacroResponse {
pub tree: FlatTree,
pub span_data_table: Vec<u32>,
+ pub tracked_env_vars: HashMap<Box<str>, Option<Box<str>>>,
+ pub tracked_paths: HashSet<Box<str>>,
}
#[derive(Debug, Serialize, Deserialize)]
diff --git a/crates/proc-macro-api/src/process.rs b/crates/proc-macro-api/src/process.rs
index 80e4ed05c3..035c12669c 100644
--- a/crates/proc-macro-api/src/process.rs
+++ b/crates/proc-macro-api/src/process.rs
@@ -240,8 +240,9 @@ impl ProcMacroServerProcess {
/// Enable support for rust-analyzer span mode if the server supports it.
pub(crate) fn rust_analyzer_spans(&self) -> bool {
match self.protocol {
- Protocol::LegacyJson { mode } => mode == SpanMode::RustAnalyzer,
- Protocol::BidirectionalPostcardPrototype { mode } => mode == SpanMode::RustAnalyzer,
+ Protocol::LegacyJson { mode } | Protocol::BidirectionalPostcardPrototype { mode } => {
+ mode == SpanMode::RustAnalyzer
+ }
}
}
diff --git a/crates/proc-macro-srv-cli/src/lib.rs b/crates/proc-macro-srv-cli/src/lib.rs
index 8475c05ae8..3d0e2027b7 100644
--- a/crates/proc-macro-srv-cli/src/lib.rs
+++ b/crates/proc-macro-srv-cli/src/lib.rs
@@ -1,11 +1,11 @@
-//! Library interface for `proc-macro-srv-cli`.
-//!
-//! This module exposes the server main loop and protocol format for integration testing.
-
-#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
-
-#[cfg(feature = "in-rust-tree")]
-extern crate rustc_driver as _;
-
-#[cfg(feature = "sysroot-abi")]
-pub mod main_loop;
+//! Library interface for `proc-macro-srv-cli`.
+//!
+//! This module exposes the server main loop and protocol format for integration testing.
+
+#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
+
+#[cfg(feature = "in-rust-tree")]
+extern crate rustc_driver as _;
+
+#[cfg(feature = "sysroot-abi")]
+pub mod main_loop;
diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs
index c525ed848b..6697b6380d 100644
--- a/crates/proc-macro-srv-cli/src/main_loop.rs
+++ b/crates/proc-macro-srv-cli/src/main_loop.rs
@@ -1,4 +1,5 @@
//! The main loop of the proc-macro server.
+use proc_macro_api::bidirectional_protocol::msg::{ApiVersionCheck, ListMacros};
use proc_macro_api::{
ProtocolFormat, bidirectional_protocol::msg as bidirectional, legacy_protocol::msg as legacy,
version::CURRENT_API_VERSION,
@@ -72,7 +73,7 @@ fn run_new(
match req {
bidirectional::BidirectionalMessage::Request(request) => match request {
- bidirectional::Request::ListMacros { dylib_path } => {
+ bidirectional::Request::ListMacros(ListMacros { dylib_path }) => {
let res = srv.list_macros(&dylib_path).map(|macros| {
macros
.into_iter()
@@ -83,7 +84,7 @@ fn run_new(
send_response(stdout, bidirectional::Response::ListMacros(res))?;
}
- bidirectional::Request::ApiVersionCheck {} => {
+ bidirectional::Request::ApiVersionCheck(ApiVersionCheck {}) => {
send_response(
stdout,
bidirectional::Response::ApiVersionCheck(CURRENT_API_VERSION),
@@ -142,6 +143,7 @@ fn handle_expand_id(
let attributes = attributes
.map(|it| it.to_tokenstream_unresolved::<SpanTrans>(CURRENT_API_VERSION, |_, b| b));
+ let mut tracked_env = Default::default();
let res = srv
.expand(
lib,
@@ -153,11 +155,18 @@ fn handle_expand_id(
def_site,
call_site,
mixed_site,
+ &mut tracked_env,
None,
)
.map(|it| {
legacy::FlatTree::from_tokenstream_raw::<SpanTrans>(it, call_site, CURRENT_API_VERSION)
})
+ .map(|tree| bidirectional::ExpandMacroResponse {
+ tree,
+ span_data_table: vec![],
+ tracked_env_vars: tracked_env.env_vars,
+ tracked_paths: tracked_env.paths,
+ })
.map_err(|e| legacy::PanicMessage(e.into_string().unwrap_or_default()));
send_response(stdout, bidirectional::Response::ExpandMacro(res))
@@ -343,6 +352,46 @@ impl proc_macro_srv::ProcMacroClientInterface for ProcMacroClientHandle<'_> {
other => handle_failure(other),
}
}
+
+ fn span_join(
+ &mut self,
+ first: proc_macro_srv::span::Span,
+ second: proc_macro_srv::span::Span,
+ ) -> Option<proc_macro_srv::span::Span> {
+ assert_eq!(first.anchor.file_id, second.anchor.file_id);
+ let response = self.roundtrip(bidirectional::SubRequest::SpanJoin {
+ file_id: first.anchor.file_id.as_u32(),
+ ast_id_first: first.anchor.ast_id.into_raw(),
+ start_first: first.range.start().into(),
+ end_first: first.range.end().into(),
+ ctx_first: first.ctx.into_u32(),
+ ast_id_second: second.anchor.ast_id.into_raw(),
+ start_second: second.range.start().into(),
+ end_second: second.range.end().into(),
+ ctx_second: second.ctx.into_u32(),
+ });
+
+ match response {
+ Ok(bidirectional::SubResponse::SpanJoinResult { span }) => {
+ span.map(|bidirectional::SpanJoin { ast_id, start, end, ctx }| {
+ proc_macro_srv::span::Span {
+ range: proc_macro_srv::span::TextRange::new(
+ proc_macro_srv::span::TextSize::new(start),
+ proc_macro_srv::span::TextSize::new(end),
+ ),
+ anchor: proc_macro_srv::span::SpanAnchor {
+ file_id: first.anchor.file_id,
+ ast_id: proc_macro_srv::span::ErasedFileAstId::from_raw(ast_id),
+ },
+ // SAFETY: spans originate from the server. If the protocol is violated,
+ // undefined behavior is the caller’s responsibility.
+ ctx: unsafe { proc_macro_srv::span::SyntaxContext::from_u32(ctx) },
+ }
+ })
+ }
+ other => handle_failure(other),
+ }
+ }
}
fn handle_expand_ra(
@@ -383,6 +432,8 @@ fn handle_expand_ra(
})
});
+ let mut tracked_env = Default::default();
+
let res = srv
.expand(
lib,
@@ -394,6 +445,7 @@ fn handle_expand_ra(
def_site,
call_site,
mixed_site,
+ &mut tracked_env,
Some(&mut ProcMacroClientHandle { stdin, stdout, buf }),
)
.map(|it| {
@@ -407,10 +459,15 @@ fn handle_expand_ra(
legacy::serialize_span_data_index_map(&span_data_table),
)
})
- .map(|(tree, span_data_table)| bidirectional::ExpandMacroExtended { tree, span_data_table })
+ .map(|(tree, span_data_table)| bidirectional::ExpandMacroResponse {
+ tree,
+ span_data_table,
+ tracked_env_vars: tracked_env.env_vars,
+ tracked_paths: tracked_env.paths,
+ })
.map_err(|e| legacy::PanicMessage(e.into_string().unwrap_or_default()));
- send_response(stdout, bidirectional::Response::ExpandMacroExtended(res))
+ send_response(stdout, bidirectional::Response::ExpandMacro(res))
}
fn run_old(
@@ -480,6 +537,7 @@ fn run_old(
def_site,
call_site,
mixed_site,
+ &mut Default::default(),
None,
)
.map(|it| {
@@ -522,6 +580,7 @@ fn run_old(
def_site,
call_site,
mixed_site,
+ &mut Default::default(),
None,
)
.map(|it| {
diff --git a/crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs b/crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs
index ba9657a9bb..456b9fd70b 100644
--- a/crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs
+++ b/crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs
@@ -15,7 +15,10 @@ use expect_test::expect;
use proc_macro_api::{
ProtocolFormat::BidirectionalPostcardPrototype,
bidirectional_protocol::{
- msg::{ExpandMacro, ExpandMacroData, ExpnGlobals, Request, Response},
+ msg::{
+ ApiVersionCheck, ExpandMacro, ExpandMacroData, ExpnGlobals, ListMacros, Request,
+ Response,
+ },
reject_subrequests,
},
legacy_protocol::msg::{PanicMessage, ServerConfig, SpanDataIndexMap, SpanMode},
@@ -25,8 +28,12 @@ use proc_macro_api::{
#[test]
fn test_bidi_version_check_bidirectional() {
with_server(BidirectionalPostcardPrototype, |writer, reader| {
- let response =
- request_bidirectional(writer, reader, Request::ApiVersionCheck {}, reject_subrequests);
+ let response = request_bidirectional(
+ writer,
+ reader,
+ Request::ApiVersionCheck(ApiVersionCheck {}),
+ reject_subrequests,
+ );
match response {
Response::ApiVersionCheck(version) => {
@@ -44,7 +51,7 @@ fn test_bidi_list_macros() {
let response = request_bidirectional(
writer,
reader,
- Request::ListMacros { dylib_path },
+ Request::ListMacros(ListMacros { dylib_path }),
&reject_subrequests,
);
@@ -84,7 +91,7 @@ fn test_bidi_list_macros_invalid_path() {
let response = request_bidirectional(
writer,
reader,
- Request::ListMacros { dylib_path: "/nonexistent/path/to/dylib.so".into() },
+ Request::ListMacros(ListMacros { dylib_path: "/nonexistent/path/to/dylib.so".into() }),
reject_subrequests,
);
@@ -168,8 +175,12 @@ fn test_bidi_basic_call_flow() {
with_server(BidirectionalPostcardPrototype, |writer, reader| {
let dylib_path = proc_macro_test_dylib_path();
- let response1 =
- request_bidirectional(writer, reader, Request::ApiVersionCheck {}, reject_subrequests);
+ let response1 = request_bidirectional(
+ writer,
+ reader,
+ Request::ApiVersionCheck(ApiVersionCheck {}),
+ reject_subrequests,
+ );
assert!(matches!(response1, Response::ApiVersionCheck(_)));
let response2 = request_bidirectional(
@@ -183,7 +194,7 @@ fn test_bidi_basic_call_flow() {
let response3 = request_bidirectional(
writer,
reader,
- Request::ListMacros { dylib_path: dylib_path.clone() },
+ Request::ListMacros(ListMacros { dylib_path: dylib_path.clone() }),
reject_subrequests,
);
assert!(matches!(response3, Response::ListMacros(Ok(_))));
@@ -195,8 +206,12 @@ fn test_bidi_expand_nonexistent_macro() {
with_server(BidirectionalPostcardPrototype, |writer, reader| {
let dylib_path = proc_macro_test_dylib_path();
- let version_response =
- request_bidirectional(writer, reader, Request::ApiVersionCheck {}, reject_subrequests);
+ let version_response = request_bidirectional(
+ writer,
+ reader,
+ Request::ApiVersionCheck(ApiVersionCheck {}),
+ reject_subrequests,
+ );
let Response::ApiVersionCheck(version) = version_response else {
panic!("expected version check response");
};
diff --git a/crates/proc-macro-srv/src/dylib.rs b/crates/proc-macro-srv/src/dylib.rs
index 9a65538675..96daa2c462 100644
--- a/crates/proc-macro-srv/src/dylib.rs
+++ b/crates/proc-macro-srv/src/dylib.rs
@@ -12,7 +12,7 @@ use object::Object;
use paths::{Utf8Path, Utf8PathBuf};
use crate::{
- PanicMessage, ProcMacroClientHandle, ProcMacroKind, ProcMacroSrvSpan,
+ PanicMessage, ProcMacroClientHandle, ProcMacroKind, ProcMacroSrvSpan, TrackedEnv,
dylib::proc_macros::ProcMacros, token_stream::TokenStream,
};
@@ -45,14 +45,22 @@ impl Expander {
def_site: S,
call_site: S,
mixed_site: S,
- callback: Option<ProcMacroClientHandle<'_>>,
+ tracked_env: &'a mut TrackedEnv,
+ callback: Option<ProcMacroClientHandle<'a>>,
) -> Result<TokenStream<S>, PanicMessage>
where
<S::Server<'a> as bridge::server::Server>::TokenStream: Default,
{
- self.inner
- .proc_macros
- .expand(macro_name, macro_body, attribute, def_site, call_site, mixed_site, callback)
+ self.inner.proc_macros.expand(
+ macro_name,
+ macro_body,
+ attribute,
+ def_site,
+ call_site,
+ mixed_site,
+ tracked_env,
+ callback,
+ )
}
pub(crate) fn list_macros(&self) -> impl Iterator<Item = (&str, ProcMacroKind)> {
diff --git a/crates/proc-macro-srv/src/dylib/proc_macros.rs b/crates/proc-macro-srv/src/dylib/proc_macros.rs
index cf00be0327..4ed32f8e6c 100644
--- a/crates/proc-macro-srv/src/dylib/proc_macros.rs
+++ b/crates/proc-macro-srv/src/dylib/proc_macros.rs
@@ -1,5 +1,7 @@
//! Proc macro ABI
-use crate::{ProcMacroClientHandle, ProcMacroKind, ProcMacroSrvSpan, token_stream::TokenStream};
+use crate::{
+ ProcMacroClientHandle, ProcMacroKind, ProcMacroSrvSpan, TrackedEnv, token_stream::TokenStream,
+};
use rustc_proc_macro::bridge;
#[repr(transparent)]
@@ -12,7 +14,7 @@ impl From<bridge::PanicMessage> for crate::PanicMessage {
}
impl ProcMacros {
- pub(crate) fn expand<S: ProcMacroSrvSpan>(
+ pub(crate) fn expand<'a, S: ProcMacroSrvSpan>(
&self,
macro_name: &str,
macro_body: TokenStream<S>,
@@ -20,7 +22,8 @@ impl ProcMacros {
def_site: S,
call_site: S,
mixed_site: S,
- callback: Option<ProcMacroClientHandle<'_>>,
+ tracked_env: &'a mut TrackedEnv,
+ callback: Option<ProcMacroClientHandle<'a>>,
) -> Result<TokenStream<S>, crate::PanicMessage> {
let parsed_attributes = attribute.unwrap_or_default();
@@ -31,7 +34,7 @@ impl ProcMacros {
{
let res = client.run(
&bridge::server::SAME_THREAD,
- S::make_server(call_site, def_site, mixed_site, callback),
+ S::make_server(call_site, def_site, mixed_site, tracked_env, callback),
macro_body,
cfg!(debug_assertions),
);
@@ -40,7 +43,7 @@ impl ProcMacros {
bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
let res = client.run(
&bridge::server::SAME_THREAD,
- S::make_server(call_site, def_site, mixed_site, callback),
+ S::make_server(call_site, def_site, mixed_site, tracked_env, callback),
macro_body,
cfg!(debug_assertions),
);
@@ -49,7 +52,7 @@ impl ProcMacros {
bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
let res = client.run(
&bridge::server::SAME_THREAD,
- S::make_server(call_site, def_site, mixed_site, callback),
+ S::make_server(call_site, def_site, mixed_site, tracked_env, callback),
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 0bdc379cb6..a71323d89d 100644
--- a/crates/proc-macro-srv/src/lib.rs
+++ b/crates/proc-macro-srv/src/lib.rs
@@ -13,14 +13,8 @@
#![cfg(feature = "sysroot-abi")]
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)]
-#![allow(
- unreachable_pub,
- internal_features,
- clippy::disallowed_types,
- clippy::print_stderr,
- unused_crate_dependencies,
- unused_features
-)]
+#![expect(unreachable_pub, internal_features, clippy::disallowed_types, clippy::print_stderr)]
+#![allow(unused_features, unused_crate_dependencies)]
#![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)]
#[cfg(not(feature = "in-rust-tree"))]
@@ -41,7 +35,7 @@ mod server_impl;
mod token_stream;
use std::{
- collections::{HashMap, hash_map::Entry},
+ collections::{HashMap, HashSet, hash_map::Entry},
env,
ffi::OsString,
fs,
@@ -52,7 +46,7 @@ use std::{
};
use paths::{Utf8Path, Utf8PathBuf};
-use span::Span;
+use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, Span};
use temp_dir::TempDir;
pub use crate::server_impl::token_id::SpanId;
@@ -123,6 +117,7 @@ pub trait ProcMacroClientInterface {
fn byte_range(&mut self, span: Span) -> Range<usize>;
fn span_source(&mut self, span: Span) -> Span;
fn span_parent(&mut self, span: Span) -> Option<Span>;
+ fn span_join(&mut self, first: Span, second: Span) -> Option<Span>;
}
const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024;
@@ -144,7 +139,7 @@ impl ExpandError {
}
impl ProcMacroSrv<'_> {
- pub fn expand<S: ProcMacroSrvSpan>(
+ pub fn expand<'a, S: ProcMacroSrvSpan + 'a>(
&self,
lib: impl AsRef<Utf8Path>,
env: &[(String, String)],
@@ -155,7 +150,8 @@ impl ProcMacroSrv<'_> {
def_site: S,
call_site: S,
mixed_site: S,
- callback: Option<ProcMacroClientHandle<'_>>,
+ tracked_env: &'a mut TrackedEnv,
+ callback: Option<ProcMacroClientHandle<'a>>,
) -> Result<token_stream::TokenStream<S>, ExpandError> {
let snapped_env = self.env;
let expander = self.expander(lib.as_ref()).map_err(|err| ExpandError::Internal {
@@ -172,13 +168,18 @@ impl ProcMacroSrv<'_> {
.name(macro_name.to_owned())
.spawn_scoped(s, move || {
expander.expand(
- macro_name, macro_body, attribute, def_site, call_site, mixed_site,
+ macro_name,
+ macro_body,
+ attribute,
+ def_site,
+ call_site,
+ mixed_site,
+ tracked_env,
callback,
)
});
match thread.unwrap().join() {
Ok(res) => res.map_err(ExpandError::Panic),
-
Err(payload) => {
if let Some(marker) = payload.downcast_ref::<ProcMacroPanicMarker>() {
return match marker {
@@ -235,6 +236,12 @@ impl ProcMacroSrv<'_> {
}
}
+#[derive(Default)]
+pub struct TrackedEnv {
+ pub env_vars: HashMap<Box<str>, Option<Box<str>>>,
+ pub paths: HashSet<Box<str>>,
+}
+
pub trait ProcMacroSrvSpan: Copy + Send + Sync {
type Server<'a>: rustc_proc_macro::bridge::server::Server<
TokenStream = crate::token_stream::TokenStream<Self>,
@@ -243,6 +250,7 @@ pub trait ProcMacroSrvSpan: Copy + Send + Sync {
call_site: Self,
def_site: Self,
mixed_site: Self,
+ tracked_env: &'a mut TrackedEnv,
callback: Option<ProcMacroClientHandle<'a>>,
) -> Self::Server<'a>;
}
@@ -254,16 +262,10 @@ impl ProcMacroSrvSpan for SpanId {
call_site: Self,
def_site: Self,
mixed_site: Self,
+ _: &'a mut TrackedEnv,
callback: Option<ProcMacroClientHandle<'a>>,
) -> Self::Server<'a> {
- Self::Server {
- call_site,
- def_site,
- mixed_site,
- callback,
- tracked_env_vars: Default::default(),
- tracked_paths: Default::default(),
- }
+ Self::Server { call_site, def_site, mixed_site, callback }
}
}
@@ -273,6 +275,7 @@ impl ProcMacroSrvSpan for Span {
call_site: Self,
def_site: Self,
mixed_site: Self,
+ tracked_env: &'a mut TrackedEnv,
callback: Option<ProcMacroClientHandle<'a>>,
) -> Self::Server<'a> {
Self::Server {
@@ -280,8 +283,8 @@ impl ProcMacroSrvSpan for Span {
def_site,
mixed_site,
callback,
- tracked_env_vars: Default::default(),
- tracked_paths: Default::default(),
+ tracked_env,
+ fixup_id: FIXUP_ERASED_FILE_AST_ID_MARKER,
}
}
}
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 6b6bfcc934..61eb4243f8 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
@@ -4,30 +4,25 @@
//! It is an unfortunate result of how the proc-macro API works that we need to look into the
//! concrete representation of the spans, and as such, RustRover cannot make use of this unless they
//! change their representation to be compatible with rust-analyzer's.
-use std::{
- collections::{HashMap, HashSet},
- ops::{Bound, Range},
-};
+use std::ops::{Bound, Range};
use intern::Symbol;
use rustc_proc_macro::bridge::server;
-use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, Span, TextRange, TextSize};
+use span::{ErasedFileAstId, Span, TextRange, TextSize};
use crate::{
- ProcMacroClientHandle,
+ ProcMacroClientHandle, TrackedEnv,
bridge::{Diagnostic, ExpnGlobals, Literal, TokenTree},
server_impl::literal_from_str,
};
pub struct RaSpanServer<'a> {
- // FIXME: Report this back to the caller to track as dependencies
- pub tracked_env_vars: HashMap<Box<str>, Option<Box<str>>>,
- // FIXME: Report this back to the caller to track as dependencies
- pub tracked_paths: HashSet<Box<str>>,
+ pub tracked_env: &'a mut TrackedEnv,
pub call_site: Span,
pub def_site: Span,
pub mixed_site: Span,
pub callback: Option<ProcMacroClientHandle<'a>>,
+ pub fixup_id: ErasedFileAstId,
}
impl server::Server for RaSpanServer<'_> {
@@ -56,10 +51,10 @@ impl server::Server for RaSpanServer<'_> {
}
fn track_env_var(&mut self, var: &str, value: Option<&str>) {
- self.tracked_env_vars.insert(var.into(), value.map(Into::into));
+ self.tracked_env.env_vars.insert(var.into(), value.map(Into::into));
}
fn track_path(&mut self, path: &str) {
- self.tracked_paths.insert(path.into());
+ self.tracked_env.paths.insert(path.into());
}
fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span>, String> {
@@ -185,16 +180,14 @@ impl server::Server for RaSpanServer<'_> {
fn span_join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
// We can't modify the span range for fixup spans, those are meaningful to fixup, so just
// prefer the non-fixup span.
- if first.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
+ if first.anchor.ast_id == self.fixup_id {
return Some(second);
}
- if second.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
+ if second.anchor.ast_id == self.fixup_id {
return Some(first);
}
- // FIXME: Once we can talk back to the client, implement a "long join" request for anchors
- // that differ in [AstId]s as joining those spans requires resolving the AstIds.
if first.anchor != second.anchor {
- return None;
+ return self.callback.as_mut()?.span_join(first, second);
}
// Differing context, we can't merge these so prefer the one that's root
if first.ctx != second.ctx {
@@ -217,7 +210,7 @@ impl server::Server for RaSpanServer<'_> {
end: Bound<usize>,
) -> Option<Self::Span> {
// We can't modify the span range for fixup spans, those are meaningful to fixup.
- if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
+ if span.anchor.ast_id == self.fixup_id {
return Some(span);
}
let length = span.range.len().into();
@@ -260,7 +253,7 @@ impl server::Server for RaSpanServer<'_> {
fn span_end(&mut self, span: Self::Span) -> Self::Span {
// We can't modify the span range for fixup spans, those are meaningful to fixup.
- if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
+ if span.anchor.ast_id == self.fixup_id {
return span;
}
Span { range: TextRange::empty(span.range.end()), ..span }
@@ -268,7 +261,7 @@ impl server::Server for RaSpanServer<'_> {
fn span_start(&mut self, span: Self::Span) -> Self::Span {
// We can't modify the span range for fixup spans, those are meaningful to fixup.
- if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
+ if span.anchor.ast_id == self.fixup_id {
return span;
}
Span { range: TextRange::empty(span.range.start()), ..span }
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 e1c96095c8..6c393b8bef 100644
--- a/crates/proc-macro-srv/src/server_impl/token_id.rs
+++ b/crates/proc-macro-srv/src/server_impl/token_id.rs
@@ -1,9 +1,6 @@
//! proc-macro server backend based on [`proc_macro_api::msg::SpanId`] as the backing span.
//! This backend is rather inflexible, used by RustRover and older rust-analyzer versions.
-use std::{
- collections::{HashMap, HashSet},
- ops::{Bound, Range},
-};
+use std::ops::{Bound, Range};
use intern::Symbol;
use rustc_proc_macro::bridge::server;
@@ -26,10 +23,6 @@ impl std::fmt::Debug for SpanId {
type Span = SpanId;
pub struct SpanIdServer<'a> {
- // FIXME: Report this back to the caller to track as dependencies
- pub tracked_env_vars: HashMap<Box<str>, Option<Box<str>>>,
- // FIXME: Report this back to the caller to track as dependencies
- pub tracked_paths: HashSet<Box<str>>,
pub call_site: Span,
pub def_site: Span,
pub mixed_site: Span,
@@ -60,12 +53,9 @@ impl server::Server for SpanIdServer<'_> {
fn injected_env_var(&mut self, _: &str) -> Option<std::string::String> {
None
}
- fn track_env_var(&mut self, var: &str, value: Option<&str>) {
- self.tracked_env_vars.insert(var.into(), value.map(Into::into));
- }
- fn track_path(&mut self, path: &str) {
- self.tracked_paths.insert(path.into());
- }
+ fn track_env_var(&mut self, _: &str, _: Option<&str>) {}
+
+ fn track_path(&mut self, _: &str) {}
fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span>, String> {
literal_from_str(s, self.call_site)
diff --git a/crates/proc-macro-srv/src/tests/utils.rs b/crates/proc-macro-srv/src/tests/utils.rs
index 31beca20d6..9da4d90d65 100644
--- a/crates/proc-macro-srv/src/tests/utils.rs
+++ b/crates/proc-macro-srv/src/tests/utils.rs
@@ -62,7 +62,16 @@ fn assert_expand_impl(
let attr_ts_string = attr_ts.as_ref().map(|it| format!("{it:?}"));
let res = expander
- .expand(macro_name, input_ts, attr_ts, def_site, call_site, mixed_site, None)
+ .expand(
+ macro_name,
+ input_ts,
+ attr_ts,
+ def_site,
+ call_site,
+ mixed_site,
+ &mut Default::default(),
+ None,
+ )
.unwrap();
expect.assert_eq(&format!(
"{input_ts_string}{}{}{}",
@@ -94,8 +103,18 @@ fn assert_expand_impl(
let fixture_string = format!("{fixture:?}");
let attr_string = attr.as_ref().map(|it| format!("{it:?}"));
- let res =
- expander.expand(macro_name, fixture, attr, def_site, call_site, mixed_site, None).unwrap();
+ let res = expander
+ .expand(
+ macro_name,
+ fixture,
+ attr,
+ def_site,
+ call_site,
+ mixed_site,
+ &mut Default::default(),
+ None,
+ )
+ .unwrap();
expect_spanned.assert_eq(&format!(
"{fixture_string}{}{}{}",
if attr_string.is_some() { "\n\n" } else { "" },
@@ -150,6 +169,10 @@ impl ProcMacroClientInterface for MockCallback<'_> {
fn span_parent(&mut self, _span: Span) -> Option<Span> {
None
}
+
+ fn span_join(&mut self, _: Span, _: Span) -> Option<Span> {
+ None
+ }
}
pub fn assert_expand_with_callback(
@@ -182,7 +205,16 @@ pub fn assert_expand_with_callback(
let mut callback = MockCallback { text: ra_fixture };
let res = expander
- .expand(macro_name, fixture, None, def_site, call_site, mixed_site, Some(&mut callback))
+ .expand(
+ macro_name,
+ fixture,
+ None,
+ def_site,
+ call_site,
+ mixed_site,
+ &mut Default::default(),
+ Some(&mut callback),
+ )
.unwrap();
expect_spanned.assert_eq(&format!("{res:?}"));
}