Skip to content
47 changes: 47 additions & 0 deletions crates/load-cargo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
8 changes: 8 additions & 0 deletions crates/proc-macro-api/src/bidirectional_protocol/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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,
},
Expand Down
36 changes: 36 additions & 0 deletions crates/proc-macro-srv-cli/src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions crates/proc-macro-srv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
4 changes: 4 additions & 0 deletions crates/proc-macro-srv/src/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down