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
Lukas Wirth 2 months ago
parent 3ad9e7d · parent f8b1895 · commit e538437
-rw-r--r--crates/load-cargo/src/lib.rs47
-rw-r--r--crates/proc-macro-api/src/bidirectional_protocol/msg.rs8
-rw-r--r--crates/proc-macro-srv-cli/src/main_loop.rs36
-rw-r--r--crates/proc-macro-srv/src/lib.rs1
-rw-r--r--crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs4
-rw-r--r--crates/proc-macro-srv/src/tests/utils.rs4
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(