Merge pull request #21400 from Veykril/push-kslvlxlpmwwu

internal: Clean up proc-macro-srv callback trait
This commit is contained in:
Lukas Wirth 2026-01-04 10:55:28 +00:00 committed by GitHub
commit 4bfdbb8bba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 58 additions and 61 deletions

View file

@ -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.
///

View file

@ -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,
@ -61,6 +61,9 @@ pub trait ExpandDatabase: RootQueryDb {
#[salsa::lru(1024)]
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;
@ -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

View file

@ -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

View file

@ -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 })
}

View file

@ -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"]

View file

@ -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,

View file

@ -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;

View file

@ -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> {