Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21657 from Shourya742/2026-02-16-add-span-source-implementation
Implement Span::SpanSouce for proc-macro-srv
| -rw-r--r-- | crates/load-cargo/src/lib.rs | 47 | ||||
| -rw-r--r-- | crates/proc-macro-api/src/bidirectional_protocol/msg.rs | 8 | ||||
| -rw-r--r-- | crates/proc-macro-srv-cli/src/main_loop.rs | 36 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/lib.rs | 1 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs | 4 | ||||
| -rw-r--r-- | crates/proc-macro-srv/src/tests/utils.rs | 4 |
6 files changed, 99 insertions, 1 deletions
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index 70a00cf825..654ff4f75b 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -612,6 +612,53 @@ impl ProcMacroExpander for Expander { Ok(SubResponse::ByteRangeResult { range: range.range.into() }) } + SubRequest::SpanSource { file_id, ast_id, start, end, ctx } => { + let span = Span { + range: TextRange::new(TextSize::from(start), TextSize::from(end)), + anchor: SpanAnchor { + file_id: span::EditionedFileId::from_raw(file_id), + ast_id: span::ErasedFileAstId::from_raw(ast_id), + }, + // SAFETY: We only receive spans from the server. If someone mess up the communication UB can happen, + // but that will be their problem. + ctx: unsafe { SyntaxContext::from_u32(ctx) }, + }; + + let mut current_span = span; + let mut current_ctx = span.ctx; + + while let Some(macro_call_id) = current_ctx.outer_expn(db) { + let macro_call_loc = db.lookup_intern_macro_call(macro_call_id.into()); + + let call_site_file = macro_call_loc.kind.file_id(); + + let resolved = db.resolve_span(current_span); + + current_ctx = macro_call_loc.ctxt; + current_span = Span { + range: resolved.range, + anchor: SpanAnchor { + file_id: resolved.file_id.editioned_file_id(db), + ast_id: span::ROOT_ERASED_FILE_AST_ID, + }, + ctx: current_ctx, + }; + + if call_site_file.file_id().is_some() { + break; + } + } + + let resolved = db.resolve_span(current_span); + + Ok(SubResponse::SpanSourceResult { + file_id: resolved.file_id.editioned_file_id(db).as_u32(), + ast_id: span::ROOT_ERASED_FILE_AST_ID.into_raw(), + start: u32::from(resolved.range.start()), + end: u32::from(resolved.range.end()), + ctx: current_span.ctx.into_u32(), + }) + } }; match self.0.expand( subtree.view(), diff --git a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs index 3f0422dc5b..10a8d66677 100644 --- a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs +++ b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs @@ -21,6 +21,7 @@ pub enum SubRequest { 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 }, } #[derive(Debug, Serialize, Deserialize)] @@ -42,6 +43,13 @@ pub enum SubResponse { ByteRangeResult { range: Range<usize>, }, + SpanSourceResult { + file_id: u32, + ast_id: u32, + start: u32, + end: u32, + ctx: u32, + }, Cancel { reason: String, }, diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs index 9be3199a38..2c54b18077 100644 --- a/crates/proc-macro-srv-cli/src/main_loop.rs +++ b/crates/proc-macro-srv-cli/src/main_loop.rs @@ -273,6 +273,42 @@ impl proc_macro_srv::ProcMacroClientInterface for ProcMacroClientHandle<'_> { other => handle_failure(other), } } + + fn span_source( + &mut self, + proc_macro_srv::span::Span { range, anchor, ctx }: proc_macro_srv::span::Span, + ) -> proc_macro_srv::span::Span { + match self.roundtrip(bidirectional::SubRequest::SpanSource { + file_id: anchor.file_id.as_u32(), + ast_id: anchor.ast_id.into_raw(), + start: range.start().into(), + end: range.end().into(), + ctx: ctx.into_u32(), + }) { + Ok(bidirectional::SubResponse::SpanSourceResult { + file_id, + 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: proc_macro_srv::span::EditionedFileId::from_raw(file_id), + ast_id: proc_macro_srv::span::ErasedFileAstId::from_raw(ast_id), + }, + // SAFETY: We only receive spans from the server. If someone mess up the communication UB can happen, + // but that will be their problem. + ctx: unsafe { proc_macro_srv::span::SyntaxContext::from_u32(ctx) }, + } + } + other => handle_failure(other), + } + } } fn handle_expand_ra( diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs index c548dc620a..6b770e440c 100644 --- a/crates/proc-macro-srv/src/lib.rs +++ b/crates/proc-macro-srv/src/lib.rs @@ -120,6 +120,7 @@ pub trait ProcMacroClientInterface { fn line_column(&mut self, span: Span) -> Option<(u32, u32)>; fn byte_range(&mut self, span: Span) -> Range<usize>; + fn span_source(&mut self, span: Span) -> Span; } const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024; 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 c114d52ec3..0890e72c4f 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 @@ -173,7 +173,9 @@ impl server::Server for RaSpanServer<'_> { None } fn span_source(&mut self, span: Self::Span) -> Self::Span { - // FIXME requires db, returns the top level call site + if let Some(ref mut callback) = self.callback { + return callback.span_source(span); + } span } fn span_byte_range(&mut self, span: Self::Span) -> Range<usize> { diff --git a/crates/proc-macro-srv/src/tests/utils.rs b/crates/proc-macro-srv/src/tests/utils.rs index b7c5c4fdd2..28d826d01e 100644 --- a/crates/proc-macro-srv/src/tests/utils.rs +++ b/crates/proc-macro-srv/src/tests/utils.rs @@ -142,6 +142,10 @@ impl ProcMacroClientInterface for MockCallback<'_> { fn byte_range(&mut self, span: Span) -> Range<usize> { Range { start: span.range.start().into(), end: span.range.end().into() } } + + fn span_source(&mut self, span: Span) -> Span { + span + } } pub fn assert_expand_with_callback( |