Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/proc-macro-api/src/lib.rs')
-rw-r--r--crates/proc-macro-api/src/lib.rs70
1 files changed, 62 insertions, 8 deletions
diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs
index 25c30b6db4..516c7418bd 100644
--- a/crates/proc-macro-api/src/lib.rs
+++ b/crates/proc-macro-api/src/lib.rs
@@ -12,13 +12,13 @@ pub mod legacy_protocol {
mod process;
use paths::{AbsPath, AbsPathBuf};
-use span::Span;
+use span::{ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, Span};
use std::{fmt, io, sync::Arc, time::SystemTime};
use crate::{
legacy_protocol::msg::{
- ExpandMacro, ExpandMacroData, ExpnGlobals, FlatTree, HAS_GLOBAL_SPANS, PanicMessage,
- RUST_ANALYZER_SPAN_SUPPORT, Request, Response, SpanDataIndexMap,
+ ExpandMacro, ExpandMacroData, ExpnGlobals, FlatTree, HAS_GLOBAL_SPANS, HASHED_AST_ID,
+ PanicMessage, RUST_ANALYZER_SPAN_SUPPORT, Request, Response, SpanDataIndexMap,
deserialize_span_data_index_map, flat::serialize_span_data_index_map,
},
process::ProcMacroServerProcess,
@@ -161,6 +161,38 @@ impl ProcMacro {
self.kind
}
+ fn needs_fixup_change(&self) -> bool {
+ let version = self.process.version();
+ (RUST_ANALYZER_SPAN_SUPPORT..HASHED_AST_ID).contains(&version)
+ }
+
+ /// On some server versions, the fixup ast id is different than ours. So change it to match.
+ fn change_fixup_to_match_old_server(&self, tt: &mut tt::TopSubtree<Span>) {
+ const OLD_FIXUP_AST_ID: ErasedFileAstId = ErasedFileAstId::from_raw(!0 - 1);
+ let change_ast_id = |ast_id: &mut ErasedFileAstId| {
+ if *ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
+ *ast_id = OLD_FIXUP_AST_ID;
+ } else if *ast_id == OLD_FIXUP_AST_ID {
+ // Swap between them, that means no collision plus the change can be reversed by doing itself.
+ *ast_id = FIXUP_ERASED_FILE_AST_ID_MARKER;
+ }
+ };
+
+ for tt in &mut tt.0 {
+ match tt {
+ tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { span, .. }))
+ | tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { span, .. }))
+ | tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { span, .. })) => {
+ change_ast_id(&mut span.anchor.ast_id);
+ }
+ tt::TokenTree::Subtree(subtree) => {
+ change_ast_id(&mut subtree.delimiter.open.anchor.ast_id);
+ change_ast_id(&mut subtree.delimiter.close.anchor.ast_id);
+ }
+ }
+ }
+ }
+
/// Expands the procedural macro by sending an expansion request to the server.
/// This includes span information and environmental context.
pub fn expand(
@@ -173,6 +205,20 @@ impl ProcMacro {
mixed_site: Span,
current_dir: String,
) -> Result<Result<tt::TopSubtree<Span>, PanicMessage>, ServerError> {
+ let (mut subtree, mut attr) = (subtree, attr);
+ let (mut subtree_changed, mut attr_changed);
+ if self.needs_fixup_change() {
+ subtree_changed = tt::TopSubtree::from_subtree(subtree);
+ self.change_fixup_to_match_old_server(&mut subtree_changed);
+ subtree = subtree_changed.view();
+
+ if let Some(attr) = &mut attr {
+ attr_changed = tt::TopSubtree::from_subtree(*attr);
+ self.change_fixup_to_match_old_server(&mut attr_changed);
+ *attr = attr_changed.view();
+ }
+ }
+
let version = self.process.version();
let mut span_data_table = SpanDataIndexMap::default();
@@ -205,15 +251,23 @@ impl ProcMacro {
let response = self.process.send_task(Request::ExpandMacro(Box::new(task)))?;
match response {
- Response::ExpandMacro(it) => {
- Ok(it.map(|tree| FlatTree::to_subtree_resolved(tree, version, &span_data_table)))
- }
+ Response::ExpandMacro(it) => Ok(it.map(|tree| {
+ let mut expanded = FlatTree::to_subtree_resolved(tree, version, &span_data_table);
+ if self.needs_fixup_change() {
+ self.change_fixup_to_match_old_server(&mut expanded);
+ }
+ expanded
+ })),
Response::ExpandMacroExtended(it) => Ok(it.map(|resp| {
- FlatTree::to_subtree_resolved(
+ let mut expanded = FlatTree::to_subtree_resolved(
resp.tree,
version,
&deserialize_span_data_index_map(&resp.span_data_table),
- )
+ );
+ if self.needs_fixup_change() {
+ self.change_fixup_to_match_old_server(&mut expanded);
+ }
+ expanded
})),
_ => Err(ServerError { message: "unexpected response".to_owned(), io: None }),
}