@@ -8,12 +8,13 @@ use base_db::{
8
8
use la_arena:: RawIdx ;
9
9
use rustc_hash:: { FxHashMap , FxHashSet } ;
10
10
use smallvec:: SmallVec ;
11
+ use stdx:: never;
11
12
use syntax:: {
12
13
ast:: { self , AstNode , HasLoopBody } ,
13
14
match_ast, SyntaxElement , SyntaxKind , SyntaxNode , TextRange , TextSize ,
14
15
} ;
15
16
use triomphe:: Arc ;
16
- use tt:: Spacing ;
17
+ use tt:: { Spacing , Span } ;
17
18
18
19
use crate :: {
19
20
span:: SpanMapRef ,
@@ -45,19 +46,20 @@ impl SyntaxFixupUndoInfo {
45
46
// replacement -> censor + append
46
47
// append -> insert a fake node, here we need to assemble some dummy span that we can figure out how
47
48
// to remove later
49
+ const FIXUP_DUMMY_FILE : FileId = FileId :: from_raw ( FileId :: MAX_FILE_ID ) ;
50
+ const FIXUP_DUMMY_AST_ID : ErasedFileAstId = ErasedFileAstId :: from_raw ( RawIdx :: from_u32 ( !0 ) ) ;
51
+ const FIXUP_DUMMY_RANGE : TextRange = TextRange :: empty ( TextSize :: new ( 0 ) ) ;
52
+ const FIXUP_DUMMY_RANGE_END : TextSize = TextSize :: new ( !0 ) ;
48
53
49
54
pub ( crate ) fn fixup_syntax ( span_map : SpanMapRef < ' _ > , node : & SyntaxNode ) -> SyntaxFixups {
50
55
let mut append = FxHashMap :: < SyntaxElement , _ > :: default ( ) ;
51
56
let mut remove = FxHashSet :: < SyntaxNode > :: default ( ) ;
52
57
let mut preorder = node. preorder ( ) ;
53
58
let mut original = Vec :: new ( ) ;
54
- let dummy_range = TextRange :: empty ( TextSize :: new ( 0 ) ) ;
59
+ let dummy_range = FIXUP_DUMMY_RANGE ;
55
60
// we use a file id of `FileId(!0)` to signal a fake node, and the text range's start offset as
56
61
// the index into the replacement vec but only if the end points to !0
57
- let dummy_anchor = SpanAnchor {
58
- file_id : FileId :: from_raw ( !0 ) ,
59
- ast_id : ErasedFileAstId :: from_raw ( RawIdx :: from ( !0 ) ) ,
60
- } ;
62
+ let dummy_anchor = SpanAnchor { file_id : FIXUP_DUMMY_FILE , ast_id : FIXUP_DUMMY_AST_ID } ;
61
63
let fake_span = |range| SpanData {
62
64
range : dummy_range,
63
65
anchor : dummy_anchor,
@@ -76,7 +78,7 @@ pub(crate) fn fixup_syntax(span_map: SpanMapRef<'_>, node: &SyntaxNode) -> Synta
76
78
let replacement = Leaf :: Ident ( Ident {
77
79
text : "__ra_fixup" . into ( ) ,
78
80
span : SpanData {
79
- range : TextRange :: new ( TextSize :: new ( idx) , TextSize :: new ( ! 0 ) ) ,
81
+ range : TextRange :: new ( TextSize :: new ( idx) , FIXUP_DUMMY_RANGE_END ) ,
80
82
anchor : dummy_anchor,
81
83
ctx : span_map. span_for_range ( node_range) . ctx ,
82
84
} ,
@@ -299,6 +301,13 @@ fn has_error_to_handle(node: &SyntaxNode) -> bool {
299
301
pub ( crate ) fn reverse_fixups ( tt : & mut Subtree , undo_info : & SyntaxFixupUndoInfo ) {
300
302
let Some ( undo_info) = undo_info. original . as_deref ( ) else { return } ;
301
303
let undo_info = & * * undo_info;
304
+ if never ! (
305
+ tt. delimiter. close. anchor. file_id == FIXUP_DUMMY_FILE
306
+ || tt. delimiter. open. anchor. file_id == FIXUP_DUMMY_FILE
307
+ ) {
308
+ tt. delimiter . close = SpanData :: DUMMY ;
309
+ tt. delimiter . open = SpanData :: DUMMY ;
310
+ }
302
311
reverse_fixups_ ( tt, undo_info) ;
303
312
}
304
313
@@ -310,24 +319,36 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
310
319
. filter ( |tt| match tt {
311
320
tt:: TokenTree :: Leaf ( leaf) => {
312
321
let span = leaf. span ( ) ;
313
- span. anchor . file_id != FileId :: from_raw ( !0 ) || span. range . end ( ) == TextSize :: new ( !0 )
322
+ let is_real_leaf = span. anchor . file_id != FIXUP_DUMMY_FILE ;
323
+ let is_replaced_node = span. range . end ( ) == FIXUP_DUMMY_RANGE_END ;
324
+ is_real_leaf || is_replaced_node
314
325
}
315
326
tt:: TokenTree :: Subtree ( _) => true ,
316
327
} )
317
328
. flat_map ( |tt| match tt {
318
329
tt:: TokenTree :: Subtree ( mut tt) => {
330
+ if tt. delimiter . close . anchor . file_id == FIXUP_DUMMY_FILE
331
+ || tt. delimiter . open . anchor . file_id == FIXUP_DUMMY_FILE
332
+ {
333
+ // Even though fixup never creates subtrees with fixup spans, the old proc-macro server
334
+ // might copy them if the proc-macro asks for it, so we need to filter those out
335
+ // here as well.
336
+ return SmallVec :: new_const ( ) ;
337
+ }
319
338
reverse_fixups_ ( & mut tt, undo_info) ;
320
339
SmallVec :: from_const ( [ tt. into ( ) ] )
321
340
}
322
341
tt:: TokenTree :: Leaf ( leaf) => {
323
- if leaf. span ( ) . anchor . file_id == FileId :: from_raw ( !0 ) {
342
+ if leaf. span ( ) . anchor . file_id == FIXUP_DUMMY_FILE {
343
+ // we have a fake node here, we need to replace it again with the original
324
344
let original = undo_info[ u32:: from ( leaf. span ( ) . range . start ( ) ) as usize ] . clone ( ) ;
325
345
if original. delimiter . kind == tt:: DelimiterKind :: Invisible {
326
346
original. token_trees . into ( )
327
347
} else {
328
348
SmallVec :: from_const ( [ original. into ( ) ] )
329
349
}
330
350
} else {
351
+ // just a normal leaf
331
352
SmallVec :: from_const ( [ leaf. into ( ) ] )
332
353
}
333
354
}
0 commit comments