@@ -12,13 +12,13 @@ pub mod legacy_protocol {
12
12
mod process;
13
13
14
14
use paths:: { AbsPath , AbsPathBuf } ;
15
- use span:: Span ;
15
+ use span:: { ErasedFileAstId , FIXUP_ERASED_FILE_AST_ID_MARKER , Span } ;
16
16
use std:: { fmt, io, sync:: Arc , time:: SystemTime } ;
17
17
18
18
use crate :: {
19
19
legacy_protocol:: msg:: {
20
- ExpandMacro , ExpandMacroData , ExpnGlobals , FlatTree , HAS_GLOBAL_SPANS , PanicMessage ,
21
- RUST_ANALYZER_SPAN_SUPPORT , Request , Response , SpanDataIndexMap ,
20
+ ExpandMacro , ExpandMacroData , ExpnGlobals , FlatTree , HAS_GLOBAL_SPANS , HASHED_AST_ID ,
21
+ PanicMessage , RUST_ANALYZER_SPAN_SUPPORT , Request , Response , SpanDataIndexMap ,
22
22
deserialize_span_data_index_map, flat:: serialize_span_data_index_map,
23
23
} ,
24
24
process:: ProcMacroServerProcess ,
@@ -161,6 +161,38 @@ impl ProcMacro {
161
161
self . kind
162
162
}
163
163
164
+ fn needs_fixup_change ( & self ) -> bool {
165
+ let version = self . process . version ( ) ;
166
+ ( RUST_ANALYZER_SPAN_SUPPORT ..HASHED_AST_ID ) . contains ( & version)
167
+ }
168
+
169
+ /// On some server versions, the fixup ast id is different than ours. So change it to match.
170
+ fn change_fixup_to_match_old_server ( & self , tt : & mut tt:: TopSubtree < Span > ) {
171
+ const OLD_FIXUP_AST_ID : ErasedFileAstId = ErasedFileAstId :: from_raw ( !0 - 1 ) ;
172
+ let change_ast_id = |ast_id : & mut ErasedFileAstId | {
173
+ if * ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER {
174
+ * ast_id = OLD_FIXUP_AST_ID ;
175
+ } else if * ast_id == OLD_FIXUP_AST_ID {
176
+ // Swap between them, that means no collision plus the change can be reversed by doing itself.
177
+ * ast_id = FIXUP_ERASED_FILE_AST_ID_MARKER ;
178
+ }
179
+ } ;
180
+
181
+ for tt in & mut tt. 0 {
182
+ match tt {
183
+ tt:: TokenTree :: Leaf ( tt:: Leaf :: Ident ( tt:: Ident { span, .. } ) )
184
+ | tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( tt:: Literal { span, .. } ) )
185
+ | tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( tt:: Punct { span, .. } ) ) => {
186
+ change_ast_id ( & mut span. anchor . ast_id ) ;
187
+ }
188
+ tt:: TokenTree :: Subtree ( subtree) => {
189
+ change_ast_id ( & mut subtree. delimiter . open . anchor . ast_id ) ;
190
+ change_ast_id ( & mut subtree. delimiter . close . anchor . ast_id ) ;
191
+ }
192
+ }
193
+ }
194
+ }
195
+
164
196
/// Expands the procedural macro by sending an expansion request to the server.
165
197
/// This includes span information and environmental context.
166
198
pub fn expand (
@@ -173,6 +205,20 @@ impl ProcMacro {
173
205
mixed_site : Span ,
174
206
current_dir : String ,
175
207
) -> Result < Result < tt:: TopSubtree < Span > , PanicMessage > , ServerError > {
208
+ let ( mut subtree, mut attr) = ( subtree, attr) ;
209
+ let ( mut subtree_changed, mut attr_changed) ;
210
+ if self . needs_fixup_change ( ) {
211
+ subtree_changed = tt:: TopSubtree :: from_subtree ( subtree) ;
212
+ self . change_fixup_to_match_old_server ( & mut subtree_changed) ;
213
+ subtree = subtree_changed. view ( ) ;
214
+
215
+ if let Some ( attr) = & mut attr {
216
+ attr_changed = tt:: TopSubtree :: from_subtree ( * attr) ;
217
+ self . change_fixup_to_match_old_server ( & mut attr_changed) ;
218
+ * attr = attr_changed. view ( ) ;
219
+ }
220
+ }
221
+
176
222
let version = self . process . version ( ) ;
177
223
178
224
let mut span_data_table = SpanDataIndexMap :: default ( ) ;
@@ -205,15 +251,23 @@ impl ProcMacro {
205
251
let response = self . process . send_task ( Request :: ExpandMacro ( Box :: new ( task) ) ) ?;
206
252
207
253
match response {
208
- Response :: ExpandMacro ( it) => {
209
- Ok ( it. map ( |tree| FlatTree :: to_subtree_resolved ( tree, version, & span_data_table) ) )
210
- }
254
+ Response :: ExpandMacro ( it) => Ok ( it. map ( |tree| {
255
+ let mut expanded = FlatTree :: to_subtree_resolved ( tree, version, & span_data_table) ;
256
+ if self . needs_fixup_change ( ) {
257
+ self . change_fixup_to_match_old_server ( & mut expanded) ;
258
+ }
259
+ expanded
260
+ } ) ) ,
211
261
Response :: ExpandMacroExtended ( it) => Ok ( it. map ( |resp| {
212
- FlatTree :: to_subtree_resolved (
262
+ let mut expanded = FlatTree :: to_subtree_resolved (
213
263
resp. tree ,
214
264
version,
215
265
& deserialize_span_data_index_map ( & resp. span_data_table ) ,
216
- )
266
+ ) ;
267
+ if self . needs_fixup_change ( ) {
268
+ self . change_fixup_to_match_old_server ( & mut expanded) ;
269
+ }
270
+ expanded
217
271
} ) ) ,
218
272
_ => Err ( ServerError { message : "unexpected response" . to_owned ( ) , io : None } ) ,
219
273
}
0 commit comments