Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22420 from Veykril/veykril/push-vpqmplstnrxx
Cleanup bidirection proc-macro-srv protocol a bit
| -rw-r--r-- | crates/load-cargo/src/lib.rs | 2 | ||||
| -rw-r--r-- | crates/proc-macro-api/src/bidirectional_protocol.rs | 27 | ||||
| -rw-r--r-- | crates/proc-macro-api/src/bidirectional_protocol/msg.rs | 89 | ||||
| -rw-r--r-- | crates/proc-macro-api/src/process.rs | 5 | ||||
| -rw-r--r-- | crates/proc-macro-srv-cli/src/lib.rs | 22 | ||||
| -rw-r--r-- | crates/proc-macro-srv-cli/src/main_loop.rs | 67 | ||||
| -rw-r--r-- | crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs | 35 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/dylib.rs | 18 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/dylib/proc_macros.rs | 15 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/lib.rs | 51 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs | 33 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/server_impl/token_id.rs | 18 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/tests/utils.rs | 40 |
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:?}")); } |