Skip to content

Commit fbc7b76

Browse files
authored
Merge pull request #21669 from Shourya742/2026-02-18-add-span-parent
Implement Span::SpanParent for proc-macro-srv
2 parents 6e0c268 + e13e5c2 commit fbc7b76

6 files changed

Lines changed: 95 additions & 3 deletions

File tree

crates/load-cargo/src/lib.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use ide_db::{
2626
use itertools::Itertools;
2727
use proc_macro_api::{
2828
MacroDylib, ProcMacroClient,
29-
bidirectional_protocol::msg::{SubRequest, SubResponse},
29+
bidirectional_protocol::msg::{ParentSpan, SubRequest, SubResponse},
3030
};
3131
use project_model::{CargoConfig, PackageRoot, ProjectManifest, ProjectWorkspace};
3232
use span::{Span, SpanAnchor, SyntaxContext};
@@ -659,6 +659,44 @@ impl ProcMacroExpander for Expander {
659659
ctx: current_span.ctx.into_u32(),
660660
})
661661
}
662+
SubRequest::SpanParent { file_id, ast_id, start, end, ctx } => {
663+
let span = Span {
664+
range: TextRange::new(TextSize::from(start), TextSize::from(end)),
665+
anchor: SpanAnchor {
666+
file_id: span::EditionedFileId::from_raw(file_id),
667+
ast_id: span::ErasedFileAstId::from_raw(ast_id),
668+
},
669+
// SAFETY: We only receive spans from the server. If someone mess up the communication UB can happen,
670+
// but that will be their problem.
671+
ctx: unsafe { SyntaxContext::from_u32(ctx) },
672+
};
673+
674+
if let Some(macro_call_id) = span.ctx.outer_expn(db) {
675+
let macro_call_loc = db.lookup_intern_macro_call(macro_call_id.into());
676+
677+
let call_site_file = macro_call_loc.kind.file_id();
678+
let call_site_ast_id = macro_call_loc.kind.erased_ast_id();
679+
680+
if let Some(editioned_file_id) = call_site_file.file_id() {
681+
let range = db
682+
.ast_id_map(editioned_file_id.into())
683+
.get_erased(call_site_ast_id)
684+
.text_range();
685+
686+
let parent_span = Some(ParentSpan {
687+
file_id: editioned_file_id.editioned_file_id(db).as_u32(),
688+
ast_id: span::ROOT_ERASED_FILE_AST_ID.into_raw(),
689+
start: u32::from(range.start()),
690+
end: u32::from(range.end()),
691+
ctx: macro_call_loc.ctxt.into_u32(),
692+
});
693+
694+
return Ok(SubResponse::SpanParentResult { parent_span });
695+
}
696+
}
697+
698+
Ok(SubResponse::SpanParentResult { parent_span: None })
699+
}
662700
};
663701
match self.0.expand(
664702
subtree.view(),

crates/proc-macro-api/src/bidirectional_protocol/msg.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub enum SubRequest {
2222
LineColumn { file_id: u32, ast_id: u32, offset: u32 },
2323
ByteRange { file_id: u32, ast_id: u32, start: u32, end: u32 },
2424
SpanSource { file_id: u32, ast_id: u32, start: u32, end: u32, ctx: u32 },
25+
SpanParent { file_id: u32, ast_id: u32, start: u32, end: u32, ctx: u32 },
2526
}
2627

2728
#[derive(Debug, Serialize, Deserialize)]
@@ -50,11 +51,23 @@ pub enum SubResponse {
5051
end: u32,
5152
ctx: u32,
5253
},
54+
SpanParentResult {
55+
parent_span: Option<ParentSpan>,
56+
},
5357
Cancel {
5458
reason: String,
5559
},
5660
}
5761

62+
#[derive(Debug, Serialize, Deserialize)]
63+
pub struct ParentSpan {
64+
pub file_id: u32,
65+
pub ast_id: u32,
66+
pub start: u32,
67+
pub end: u32,
68+
pub ctx: u32,
69+
}
70+
5871
#[derive(Debug, Serialize, Deserialize)]
5972
pub enum BidirectionalMessage {
6073
Request(Request),

crates/proc-macro-srv-cli/src/main_loop.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,40 @@ impl proc_macro_srv::ProcMacroClientInterface for ProcMacroClientHandle<'_> {
309309
other => handle_failure(other),
310310
}
311311
}
312+
313+
fn span_parent(
314+
&mut self,
315+
proc_macro_srv::span::Span { range, anchor, ctx }: proc_macro_srv::span::Span,
316+
) -> Option<proc_macro_srv::span::Span> {
317+
let response = self.roundtrip(bidirectional::SubRequest::SpanParent {
318+
file_id: anchor.file_id.as_u32(),
319+
ast_id: anchor.ast_id.into_raw(),
320+
start: range.start().into(),
321+
end: range.end().into(),
322+
ctx: ctx.into_u32(),
323+
});
324+
325+
match response {
326+
Ok(bidirectional::SubResponse::SpanParentResult { parent_span }) => {
327+
parent_span.map(|bidirectional::ParentSpan { file_id, ast_id, start, end, ctx }| {
328+
proc_macro_srv::span::Span {
329+
range: proc_macro_srv::span::TextRange::new(
330+
proc_macro_srv::span::TextSize::new(start),
331+
proc_macro_srv::span::TextSize::new(end),
332+
),
333+
anchor: proc_macro_srv::span::SpanAnchor {
334+
file_id: proc_macro_srv::span::EditionedFileId::from_raw(file_id),
335+
ast_id: proc_macro_srv::span::ErasedFileAstId::from_raw(ast_id),
336+
},
337+
// SAFETY: spans originate from the server. If the protocol is violated,
338+
// undefined behavior is the caller’s responsibility.
339+
ctx: unsafe { proc_macro_srv::span::SyntaxContext::from_u32(ctx) },
340+
}
341+
})
342+
}
343+
other => handle_failure(other),
344+
}
345+
}
312346
}
313347

314348
fn handle_expand_ra(

crates/proc-macro-srv/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ pub trait ProcMacroClientInterface {
121121

122122
fn byte_range(&mut self, span: Span) -> Range<usize>;
123123
fn span_source(&mut self, span: Span) -> Span;
124+
fn span_parent(&mut self, span: Span) -> Option<Span>;
124125
}
125126

126127
const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024;

crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,10 @@ impl server::Server for RaSpanServer<'_> {
164164
self.callback.as_mut()?.source_text(span)
165165
}
166166

167-
fn span_parent(&mut self, _span: Self::Span) -> Option<Self::Span> {
168-
// FIXME requires db, looks up the parent call site
167+
fn span_parent(&mut self, span: Self::Span) -> Option<Self::Span> {
168+
if let Some(ref mut callback) = self.callback {
169+
return callback.span_parent(span);
170+
}
169171
None
170172
}
171173
fn span_source(&mut self, span: Self::Span) -> Self::Span {

crates/proc-macro-srv/src/tests/utils.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ impl ProcMacroClientInterface for MockCallback<'_> {
146146
fn span_source(&mut self, span: Span) -> Span {
147147
span
148148
}
149+
150+
fn span_parent(&mut self, _span: Span) -> Option<Span> {
151+
None
152+
}
149153
}
150154

151155
pub fn assert_expand_with_callback(

0 commit comments

Comments
 (0)