@@ -8,12 +8,13 @@ use base_db::{
88use la_arena:: RawIdx ;
99use rustc_hash:: { FxHashMap , FxHashSet } ;
1010use smallvec:: SmallVec ;
11+ use stdx:: never;
1112use syntax:: {
1213 ast:: { self , AstNode , HasLoopBody } ,
1314 match_ast, SyntaxElement , SyntaxKind , SyntaxNode , TextRange , TextSize ,
1415} ;
1516use triomphe:: Arc ;
16- use tt:: Spacing ;
17+ use tt:: { Spacing , Span } ;
1718
1819use crate :: {
1920 span:: SpanMapRef ,
@@ -45,19 +46,20 @@ impl SyntaxFixupUndoInfo {
4546// replacement -> censor + append
4647// append -> insert a fake node, here we need to assemble some dummy span that we can figure out how
4748// 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 ) ;
4853
4954pub ( crate ) fn fixup_syntax ( span_map : SpanMapRef < ' _ > , node : & SyntaxNode ) -> SyntaxFixups {
5055 let mut append = FxHashMap :: < SyntaxElement , _ > :: default ( ) ;
5156 let mut remove = FxHashSet :: < SyntaxNode > :: default ( ) ;
5257 let mut preorder = node. preorder ( ) ;
5358 let mut original = Vec :: new ( ) ;
54- let dummy_range = TextRange :: empty ( TextSize :: new ( 0 ) ) ;
59+ let dummy_range = FIXUP_DUMMY_RANGE ;
5560 // we use a file id of `FileId(!0)` to signal a fake node, and the text range's start offset as
5661 // 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 } ;
6163 let fake_span = |range| SpanData {
6264 range : dummy_range,
6365 anchor : dummy_anchor,
@@ -76,7 +78,7 @@ pub(crate) fn fixup_syntax(span_map: SpanMapRef<'_>, node: &SyntaxNode) -> Synta
7678 let replacement = Leaf :: Ident ( Ident {
7779 text : "__ra_fixup" . into ( ) ,
7880 span : SpanData {
79- range : TextRange :: new ( TextSize :: new ( idx) , TextSize :: new ( ! 0 ) ) ,
81+ range : TextRange :: new ( TextSize :: new ( idx) , FIXUP_DUMMY_RANGE_END ) ,
8082 anchor : dummy_anchor,
8183 ctx : span_map. span_for_range ( node_range) . ctx ,
8284 } ,
@@ -299,6 +301,13 @@ fn has_error_to_handle(node: &SyntaxNode) -> bool {
299301pub ( crate ) fn reverse_fixups ( tt : & mut Subtree , undo_info : & SyntaxFixupUndoInfo ) {
300302 let Some ( undo_info) = undo_info. original . as_deref ( ) else { return } ;
301303 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+ }
302311 reverse_fixups_ ( tt, undo_info) ;
303312}
304313
@@ -310,24 +319,36 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
310319 . filter ( |tt| match tt {
311320 tt:: TokenTree :: Leaf ( leaf) => {
312321 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
314325 }
315326 tt:: TokenTree :: Subtree ( _) => true ,
316327 } )
317328 . flat_map ( |tt| match tt {
318329 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+ }
319338 reverse_fixups_ ( & mut tt, undo_info) ;
320339 SmallVec :: from_const ( [ tt. into ( ) ] )
321340 }
322341 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
324344 let original = undo_info[ u32:: from ( leaf. span ( ) . range . start ( ) ) as usize ] . clone ( ) ;
325345 if original. delimiter . kind == tt:: DelimiterKind :: Invisible {
326346 original. token_trees . into ( )
327347 } else {
328348 SmallVec :: from_const ( [ original. into ( ) ] )
329349 }
330350 } else {
351+ // just a normal leaf
331352 SmallVec :: from_const ( [ leaf. into ( ) ] )
332353 }
333354 }
0 commit comments