Unnamed repository; edit this file 'description' to name the repository.
internal: Clean up proc-macro-srv callback trait
Lukas Wirth 4 months ago
parent 13d71e0 · commit 148028b
-rw-r--r--crates/base-db/src/editioned_file_id.rs3
-rw-r--r--crates/hir-expand/src/db.rs14
-rw-r--r--crates/hir-expand/src/lib.rs24
-rw-r--r--crates/load-cargo/src/lib.rs29
-rw-r--r--crates/proc-macro-srv-cli/Cargo.toml1
-rw-r--r--crates/proc-macro-srv-cli/src/main_loop.rs22
-rw-r--r--crates/proc-macro-srv/src/lib.rs7
-rw-r--r--crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs19
8 files changed, 58 insertions, 61 deletions
diff --git a/crates/base-db/src/editioned_file_id.rs b/crates/base-db/src/editioned_file_id.rs
index e2791ffe6f..13fb05d565 100644
--- a/crates/base-db/src/editioned_file_id.rs
+++ b/crates/base-db/src/editioned_file_id.rs
@@ -26,6 +26,9 @@ const _: () = {
krate: Crate,
}
+ // FIXME: This poses an invalidation problem, if one constructs an `EditionedFileId` with a
+ // different crate then whatever the input of a memo used, it will invalidate the memo causing
+ // it to recompute even if the crate is not really used.
/// We like to include the origin crate in an `EditionedFileId` (for use in the item tree),
/// but this poses us a problem.
///
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index 40d44cd1db..51767f87ff 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -9,8 +9,8 @@ use triomphe::Arc;
use crate::{
AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo,
- EagerExpander, EditionedFileId, ExpandError, ExpandResult, ExpandTo, HirFileId, MacroCallId,
- MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
+ EagerExpander, EditionedFileId, ExpandError, ExpandResult, ExpandTo, FileRange, HirFileId,
+ MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
attrs::Meta,
builtin::pseudo_derive_attr_expansion,
cfg_process::attr_macro_input_to_token_tree,
@@ -62,6 +62,9 @@ pub trait ExpandDatabase: RootQueryDb {
fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
#[salsa::transparent]
+ fn resolve_span(&self, span: Span) -> FileRange;
+
+ #[salsa::transparent]
fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode;
/// Implementation for the macro case.
@@ -158,6 +161,13 @@ fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) ->
}
}
+fn resolve_span(db: &dyn ExpandDatabase, Span { range, anchor, ctx: _ }: Span) -> FileRange {
+ let file_id = EditionedFileId::from_span_guess_origin(db, anchor.file_id);
+ let anchor_offset =
+ db.ast_id_map(file_id.into()).get_erased(anchor.ast_id).text_range().start();
+ FileRange { file_id, range: range + anchor_offset }
+}
+
/// This expands the given macro call, but with different arguments. This is
/// used for completion, where we want to see what 'would happen' if we insert a
/// token. The `token_to_map` mapped down into the expansion, with the mapped
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 7b6a6135b3..05541e782e 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -901,11 +901,8 @@ impl ExpansionInfo {
let span = self.exp_map.span_at(token.start());
match &self.arg_map {
SpanMap::RealSpanMap(_) => {
- let file_id =
- EditionedFileId::from_span_guess_origin(db, span.anchor.file_id).into();
- let anchor_offset =
- db.ast_id_map(file_id).get_erased(span.anchor.ast_id).text_range().start();
- InFile { file_id, value: smallvec::smallvec![span.range + anchor_offset] }
+ let range = db.resolve_span(span);
+ InFile { file_id: range.file_id.into(), value: smallvec::smallvec![range.range] }
}
SpanMap::ExpansionSpanMap(arg_map) => {
let Some(arg_node) = &self.arg.value else {
@@ -947,7 +944,7 @@ pub fn map_node_range_up_rooted(
range: TextRange,
) -> Option<FileRange> {
let mut spans = exp_map.spans_for_range(range).filter(|span| span.ctx.is_root());
- let Span { range, anchor, ctx: _ } = spans.next()?;
+ let Span { range, anchor, ctx } = spans.next()?;
let mut start = range.start();
let mut end = range.end();
@@ -958,10 +955,7 @@ pub fn map_node_range_up_rooted(
start = start.min(span.range.start());
end = end.max(span.range.end());
}
- let file_id = EditionedFileId::from_span_guess_origin(db, anchor.file_id);
- let anchor_offset =
- db.ast_id_map(file_id.into()).get_erased(anchor.ast_id).text_range().start();
- Some(FileRange { file_id, range: TextRange::new(start, end) + anchor_offset })
+ Some(db.resolve_span(Span { range: TextRange::new(start, end), anchor, ctx }))
}
/// Maps up the text range out of the expansion hierarchy back into the original file its from.
@@ -984,10 +978,7 @@ pub fn map_node_range_up(
start = start.min(span.range.start());
end = end.max(span.range.end());
}
- let file_id = EditionedFileId::from_span_guess_origin(db, anchor.file_id);
- let anchor_offset =
- db.ast_id_map(file_id.into()).get_erased(anchor.ast_id).text_range().start();
- Some((FileRange { file_id, range: TextRange::new(start, end) + anchor_offset }, ctx))
+ Some((db.resolve_span(Span { range: TextRange::new(start, end), anchor, ctx }), ctx))
}
/// Looks up the span at the given offset.
@@ -997,10 +988,7 @@ pub fn span_for_offset(
offset: TextSize,
) -> (FileRange, SyntaxContext) {
let span = exp_map.span_at(offset);
- let file_id = EditionedFileId::from_span_guess_origin(db, span.anchor.file_id);
- let anchor_offset =
- db.ast_id_map(file_id.into()).get_erased(span.anchor.ast_id).text_range().start();
- (FileRange { file_id, range: span.range + anchor_offset }, span.ctx)
+ (db.resolve_span(span), span.ctx)
}
/// In Rust, macros expand token trees to token trees. When we want to turn a
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index c302e266fe..e8d98b1ce6 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -19,7 +19,7 @@ use hir_expand::{
},
};
use ide_db::{
- ChangeWithProcMacros, EditionedFileId, FxHashMap, RootDatabase,
+ ChangeWithProcMacros, FxHashMap, RootDatabase,
base_db::{CrateGraphBuilder, Env, ProcMacroLoadingError, SourceRoot, SourceRootId},
prime_caches,
};
@@ -32,7 +32,8 @@ use proc_macro_api::{
},
};
use project_model::{CargoConfig, PackageRoot, ProjectManifest, ProjectWorkspace};
-use span::Span;
+use span::{Span, SpanAnchor, SyntaxContext};
+use tt::{TextRange, TextSize};
use vfs::{
AbsPath, AbsPathBuf, FileId, VfsPath,
file_set::FileSetConfig,
@@ -553,20 +554,18 @@ impl ProcMacroExpander for Expander {
Ok(SubResponse::LocalFilePathResult { name })
}
SubRequest::SourceText { file_id, ast_id, start, end } => {
- let raw_file_id = FileId::from_raw(file_id);
- let editioned_file_id = span::EditionedFileId::from_raw(file_id);
let ast_id = span::ErasedFileAstId::from_raw(ast_id);
- let hir_file_id = EditionedFileId::from_span_guess_origin(db, editioned_file_id);
- let anchor_offset = db
- .ast_id_map(hir_expand::HirFileId::FileId(hir_file_id))
- .get_erased(ast_id)
- .text_range()
- .start();
- let anchor_offset = u32::from(anchor_offset);
- let abs_start = start + anchor_offset;
- let abs_end = end + anchor_offset;
- let source = db.file_text(raw_file_id).text(db);
- let text = source.get(abs_start as usize..abs_end as usize).map(ToOwned::to_owned);
+ let editioned_file_id = span::EditionedFileId::from_raw(file_id);
+ let span = Span {
+ range: TextRange::new(TextSize::from(start), TextSize::from(end)),
+ anchor: SpanAnchor { file_id: editioned_file_id, ast_id },
+ ctx: SyntaxContext::root(editioned_file_id.edition()),
+ };
+ let range = db.resolve_span(span);
+ let source = db.file_text(range.file_id.file_id(db)).text(db);
+ let text = source
+ .get(usize::from(range.range.start())..usize::from(range.range.end()))
+ .map(ToOwned::to_owned);
Ok(SubResponse::SourceTextResult { text })
}
diff --git a/crates/proc-macro-srv-cli/Cargo.toml b/crates/proc-macro-srv-cli/Cargo.toml
index 2c6e5a16ee..6b2db0b269 100644
--- a/crates/proc-macro-srv-cli/Cargo.toml
+++ b/crates/proc-macro-srv-cli/Cargo.toml
@@ -18,6 +18,7 @@ clap = {version = "4.5.42", default-features = false, features = ["std"]}
[features]
default = []
+# default = ["sysroot-abi"]
sysroot-abi = ["proc-macro-srv/sysroot-abi", "proc-macro-api/sysroot-abi"]
in-rust-tree = ["proc-macro-srv/in-rust-tree", "sysroot-abi"]
diff --git a/crates/proc-macro-srv-cli/src/main_loop.rs b/crates/proc-macro-srv-cli/src/main_loop.rs
index 4891e07314..b2f4b96bd2 100644
--- a/crates/proc-macro-srv-cli/src/main_loop.rs
+++ b/crates/proc-macro-srv-cli/src/main_loop.rs
@@ -185,8 +185,8 @@ impl<'a, C: Codec> ProcMacroClientHandle<'a, C> {
}
impl<C: Codec> proc_macro_srv::ProcMacroClientInterface for ProcMacroClientHandle<'_, C> {
- fn file(&mut self, file_id: u32) -> String {
- match self.roundtrip(bidirectional::SubRequest::FilePath { file_id }) {
+ fn file(&mut self, file_id: proc_macro_srv::span::FileId) -> String {
+ match self.roundtrip(bidirectional::SubRequest::FilePath { file_id: file_id.index() }) {
Some(bidirectional::BidirectionalMessage::SubResponse(
bidirectional::SubResponse::FilePathResult { name },
)) => name,
@@ -194,9 +194,16 @@ impl<C: Codec> proc_macro_srv::ProcMacroClientInterface for ProcMacroClientHandl
}
}
- fn source_text(&mut self, file_id: u32, ast_id: u32, start: u32, end: u32) -> Option<String> {
- match self.roundtrip(bidirectional::SubRequest::SourceText { file_id, ast_id, start, end })
- {
+ fn source_text(
+ &mut self,
+ proc_macro_srv::span::Span { range, anchor, ctx: _ }: proc_macro_srv::span::Span,
+ ) -> Option<String> {
+ match self.roundtrip(bidirectional::SubRequest::SourceText {
+ file_id: anchor.file_id.as_u32(),
+ ast_id: anchor.ast_id.into_raw(),
+ start: range.start().into(),
+ end: range.end().into(),
+ }) {
Some(bidirectional::BidirectionalMessage::SubResponse(
bidirectional::SubResponse::SourceTextResult { text },
)) => text,
@@ -204,8 +211,9 @@ impl<C: Codec> proc_macro_srv::ProcMacroClientInterface for ProcMacroClientHandl
}
}
- fn local_file(&mut self, file_id: u32) -> Option<String> {
- match self.roundtrip(bidirectional::SubRequest::LocalFilePath { file_id }) {
+ fn local_file(&mut self, file_id: proc_macro_srv::span::FileId) -> Option<String> {
+ match self.roundtrip(bidirectional::SubRequest::LocalFilePath { file_id: file_id.index() })
+ {
Some(bidirectional::BidirectionalMessage::SubResponse(
bidirectional::SubResponse::LocalFilePathResult { name },
)) => name,
diff --git a/crates/proc-macro-srv/src/lib.rs b/crates/proc-macro-srv/src/lib.rs
index d63aea947c..f2d1dfbba4 100644
--- a/crates/proc-macro-srv/src/lib.rs
+++ b/crates/proc-macro-srv/src/lib.rs
@@ -53,6 +53,7 @@ use temp_dir::TempDir;
pub use crate::server_impl::token_id::SpanId;
pub use proc_macro::Delimiter;
+pub use span;
pub use crate::bridge::*;
pub use crate::server_impl::literal_from_str;
@@ -94,9 +95,9 @@ impl<'env> ProcMacroSrv<'env> {
pub type ProcMacroClientHandle<'a> = &'a mut (dyn ProcMacroClientInterface + Sync + Send);
pub trait ProcMacroClientInterface {
- fn file(&mut self, file_id: u32) -> String;
- fn source_text(&mut self, file_id: u32, ast_id: u32, start: u32, end: u32) -> Option<String>;
- fn local_file(&mut self, file_id: u32) -> Option<String>;
+ fn file(&mut self, file_id: span::FileId) -> String;
+ fn source_text(&mut self, span: Span) -> Option<String>;
+ fn local_file(&mut self, file_id: span::FileId) -> Option<String>;
}
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 2ce3b717cb..32725afc55 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
@@ -128,13 +128,10 @@ impl server::Span for RaSpanServer<'_> {
format!("{:?}", span)
}
fn file(&mut self, span: Self::Span) -> String {
- self.callback
- .as_mut()
- .map(|cb| cb.file(span.anchor.file_id.file_id().index()))
- .unwrap_or_default()
+ self.callback.as_mut().map(|cb| cb.file(span.anchor.file_id.file_id())).unwrap_or_default()
}
fn local_file(&mut self, span: Self::Span) -> Option<String> {
- self.callback.as_mut().and_then(|cb| cb.local_file(span.anchor.file_id.file_id().index()))
+ self.callback.as_mut().and_then(|cb| cb.local_file(span.anchor.file_id.file_id()))
}
fn save_span(&mut self, _span: Self::Span) -> usize {
// FIXME, quote is incompatible with third-party tools
@@ -153,17 +150,7 @@ impl server::Span for RaSpanServer<'_> {
/// See PR:
/// https://github.com/rust-lang/rust/pull/55780
fn source_text(&mut self, span: Self::Span) -> Option<String> {
- let file_id = span.anchor.file_id;
- let ast_id = span.anchor.ast_id;
- let start: u32 = span.range.start().into();
- let end: u32 = span.range.end().into();
-
- self.callback.as_mut()?.source_text(
- file_id.file_id().index(),
- ast_id.into_raw(),
- start,
- end,
- )
+ self.callback.as_mut()?.source_text(span)
}
fn parent(&mut self, _span: Self::Span) -> Option<Self::Span> {