Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/load-cargo/src/lib.rs40
-rw-r--r--crates/proc-macro-api/src/bidirectional_protocol/msg.rs13
-rw-r--r--crates/proc-macro-srv-cli/src/main_loop.rs34
-rw-r--r--crates/proc-macro-srv/src/lib.rs1
-rw-r--r--crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs6
-rw-r--r--crates/proc-macro-srv/src/tests/utils.rs4
6 files changed, 95 insertions, 3 deletions
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index 654ff4f75b..b8ce3a8da4 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -26,7 +26,7 @@ use ide_db::{
use itertools::Itertools;
use proc_macro_api::{
MacroDylib, ProcMacroClient,
- bidirectional_protocol::msg::{SubRequest, SubResponse},
+ bidirectional_protocol::msg::{ParentSpan, SubRequest, SubResponse},
};
use project_model::{CargoConfig, PackageRoot, ProjectManifest, ProjectWorkspace};
use span::{Span, SpanAnchor, SyntaxContext};
@@ -659,6 +659,44 @@ impl ProcMacroExpander for Expander {
ctx: current_span.ctx.into_u32(),
})
}
+ SubRequest::SpanParent { 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) },
+ };
+
+ if let Some(macro_call_id) = span.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 call_site_ast_id = macro_call_loc.kind.erased_ast_id();
+
+ if let Some(editioned_file_id) = call_site_file.file_id() {
+ let range = db
+ .ast_id_map(editioned_file_id.into())
+ .get_erased(call_site_ast_id)
+ .text_range();
+
+ let parent_span = Some(ParentSpan {
+ file_id: editioned_file_id.editioned_file_id(db).as_u32(),
+ ast_id: span::ROOT_ERASED_FILE_AST_ID.into_raw(),
+ start: u32::from(range.start()),
+ end: u32::from(range.end()),
+ ctx: macro_call_loc.ctxt.into_u32(),
+ });
+
+ return Ok(SubResponse::SpanParentResult { parent_span });
+ }
+ }
+
+ Ok(SubResponse::SpanParentResult { parent_span: None })
+ }
};
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 10a8d66677..ab4bed81e6 100644
--- a/crates/proc-macro-api/src/bidirectional_protocol/msg.rs
+++ b/crates/proc-macro-api/src/bidirectional_protocol/msg.rs
@@ -22,6 +22,7 @@ pub enum SubRequest {
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 },
}
#[derive(Debug, Serialize, Deserialize)]
@@ -50,12 +51,24 @@ pub enum SubResponse {
end: u32,
ctx: u32,
},
+ SpanParentResult {
+ parent_span: Option<ParentSpan>,
+ },
Cancel {
reason: String,
},
}
#[derive(Debug, Serialize, Deserialize)]
+pub struct ParentSpan {
+ pub file_id: u32,
+ pub ast_id: u32,
+ pub start: u32,
+ pub end: u32,
+ pub ctx: u32,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
pub enum BidirectionalMessage {
Request(Request),
Response(Response),
diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs
index 2c54b18077..c525ed848b 100644
--- a/crates/proc-macro-srv-cli/src/main_loop.rs
+++ b/crates/proc-macro-srv-cli/src/main_loop.rs
@@ -309,6 +309,40 @@ impl proc_macro_srv::ProcMacroClientInterface for ProcMacroClientHandle<'_> {
other => handle_failure(other),
}
}
+
+ fn span_parent(
+ &mut self,
+ proc_macro_srv::span::Span { range, anchor, ctx }: proc_macro_srv::span::Span,
+ ) -> Option<proc_macro_srv::span::Span> {
+ let response = self.roundtrip(bidirectional::SubRequest::SpanParent {
+ 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(),
+ });
+
+ match response {
+ Ok(bidirectional::SubResponse::SpanParentResult { parent_span }) => {
+ parent_span.map(|bidirectional::ParentSpan { 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: 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(
diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs
index 6b770e440c..65de804404 100644
--- a/crates/proc-macro-srv/src/lib.rs
+++ b/crates/proc-macro-srv/src/lib.rs
@@ -121,6 +121,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>;
}
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 5eb16c37ac..6b6bfcc934 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
@@ -164,8 +164,10 @@ impl server::Server for RaSpanServer<'_> {
self.callback.as_mut()?.source_text(span)
}
- fn span_parent(&mut self, _span: Self::Span) -> Option<Self::Span> {
- // FIXME requires db, looks up the parent call site
+ fn span_parent(&mut self, span: Self::Span) -> Option<Self::Span> {
+ if let Some(ref mut callback) = self.callback {
+ return callback.span_parent(span);
+ }
None
}
fn span_source(&mut self, span: Self::Span) -> Self::Span {
diff --git a/crates/proc-macro-srv/src/tests/utils.rs b/crates/proc-macro-srv/src/tests/utils.rs
index 28d826d01e..31beca20d6 100644
--- a/crates/proc-macro-srv/src/tests/utils.rs
+++ b/crates/proc-macro-srv/src/tests/utils.rs
@@ -146,6 +146,10 @@ impl ProcMacroClientInterface for MockCallback<'_> {
fn span_source(&mut self, span: Span) -> Span {
span
}
+
+ fn span_parent(&mut self, _span: Span) -> Option<Span> {
+ None
+ }
}
pub fn assert_expand_with_callback(