1
1
//! To make attribute macros work reliably when typing, we need to take care to
2
2
//! fix up syntax errors in the code we're passing to them.
3
3
4
- use la_arena:: RawIdx ;
5
4
use rustc_hash:: { FxHashMap , FxHashSet } ;
6
5
use smallvec:: SmallVec ;
7
- use span:: { ErasedFileAstId , FileId , Span , SpanAnchor , SpanData } ;
6
+ use span:: { ErasedFileAstId , Span , SpanAnchor , SpanData , FIXUP_ERASED_FILE_AST_ID_MARKER } ;
8
7
use stdx:: never;
9
8
use syntax:: {
10
9
ast:: { self , AstNode , HasLoopBody } ,
@@ -39,13 +38,11 @@ impl SyntaxFixupUndoInfo {
39
38
pub ( crate ) const NONE : Self = SyntaxFixupUndoInfo { original : None } ;
40
39
}
41
40
42
- // censoring -> just don't convert the node
43
- // replacement -> censor + append
44
- // append -> insert a fake node, here we need to assemble some dummy span that we can figure out how
45
- // to remove later
46
- const FIXUP_DUMMY_FILE : FileId = FileId :: from_raw ( FileId :: MAX_FILE_ID ) ;
47
- const FIXUP_DUMMY_AST_ID : ErasedFileAstId = ErasedFileAstId :: from_raw ( RawIdx :: from_u32 ( !0 ) ) ;
41
+ // We mark spans with `FIXUP_DUMMY_AST_ID` to indicate that they are fake.
42
+ const FIXUP_DUMMY_AST_ID : ErasedFileAstId = FIXUP_ERASED_FILE_AST_ID_MARKER ;
48
43
const FIXUP_DUMMY_RANGE : TextRange = TextRange :: empty ( TextSize :: new ( 0 ) ) ;
44
+ // If the fake span has this range end, that means that the range start is an index into the
45
+ // `original` list in `SyntaxFixupUndoInfo`.
49
46
const FIXUP_DUMMY_RANGE_END : TextSize = TextSize :: new ( !0 ) ;
50
47
51
48
pub ( crate ) fn fixup_syntax (
@@ -58,13 +55,13 @@ pub(crate) fn fixup_syntax(
58
55
let mut preorder = node. preorder ( ) ;
59
56
let mut original = Vec :: new ( ) ;
60
57
let dummy_range = FIXUP_DUMMY_RANGE ;
61
- // we use a file id of `FileId(!0)` to signal a fake node, and the text range's start offset as
62
- // the index into the replacement vec but only if the end points to !0
63
- let dummy_anchor = SpanAnchor { file_id : FIXUP_DUMMY_FILE , ast_id : FIXUP_DUMMY_AST_ID } ;
64
- let fake_span = |range| SpanData {
65
- range : dummy_range ,
66
- anchor : dummy_anchor ,
67
- ctx : span_map . span_for_range ( range ) . ctx ,
58
+ let fake_span = | range| {
59
+ let span = span_map . span_for_range ( range ) ;
60
+ SpanData {
61
+ range : dummy_range ,
62
+ anchor : SpanAnchor { ast_id : FIXUP_DUMMY_AST_ID , ..span . anchor } ,
63
+ ctx : span . ctx ,
64
+ }
68
65
} ;
69
66
while let Some ( event) = preorder. next ( ) {
70
67
let syntax:: WalkEvent :: Enter ( node) = event else { continue } ;
@@ -76,12 +73,13 @@ pub(crate) fn fixup_syntax(
76
73
let original_tree = mbe:: syntax_node_to_token_tree ( & node, span_map, call_site) ;
77
74
let idx = original. len ( ) as u32 ;
78
75
original. push ( original_tree) ;
76
+ let span = span_map. span_for_range ( node_range) ;
79
77
let replacement = Leaf :: Ident ( Ident {
80
78
text : "__ra_fixup" . into ( ) ,
81
79
span : SpanData {
82
80
range : TextRange :: new ( TextSize :: new ( idx) , FIXUP_DUMMY_RANGE_END ) ,
83
- anchor : dummy_anchor ,
84
- ctx : span_map . span_for_range ( node_range ) . ctx ,
81
+ anchor : SpanAnchor { ast_id : FIXUP_DUMMY_AST_ID , ..span . anchor } ,
82
+ ctx : span . ctx ,
85
83
} ,
86
84
} ) ;
87
85
append. insert ( node. clone ( ) . into ( ) , vec ! [ replacement] ) ;
@@ -304,8 +302,8 @@ pub(crate) fn reverse_fixups(tt: &mut Subtree, undo_info: &SyntaxFixupUndoInfo)
304
302
let undo_info = & * * undo_info;
305
303
#[ allow( deprecated) ]
306
304
if never ! (
307
- tt. delimiter. close. anchor. file_id == FIXUP_DUMMY_FILE
308
- || tt. delimiter. open. anchor. file_id == FIXUP_DUMMY_FILE
305
+ tt. delimiter. close. anchor. ast_id == FIXUP_DUMMY_AST_ID
306
+ || tt. delimiter. open. anchor. ast_id == FIXUP_DUMMY_AST_ID
309
307
) {
310
308
tt. delimiter . close = SpanData :: DUMMY ;
311
309
tt. delimiter . open = SpanData :: DUMMY ;
@@ -321,16 +319,16 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
321
319
. filter ( |tt| match tt {
322
320
tt:: TokenTree :: Leaf ( leaf) => {
323
321
let span = leaf. span ( ) ;
324
- let is_real_leaf = span. anchor . file_id != FIXUP_DUMMY_FILE ;
322
+ let is_real_leaf = span. anchor . ast_id != FIXUP_DUMMY_AST_ID ;
325
323
let is_replaced_node = span. range . end ( ) == FIXUP_DUMMY_RANGE_END ;
326
324
is_real_leaf || is_replaced_node
327
325
}
328
326
tt:: TokenTree :: Subtree ( _) => true ,
329
327
} )
330
328
. flat_map ( |tt| match tt {
331
329
tt:: TokenTree :: Subtree ( mut tt) => {
332
- if tt. delimiter . close . anchor . file_id == FIXUP_DUMMY_FILE
333
- || tt. delimiter . open . anchor . file_id == FIXUP_DUMMY_FILE
330
+ if tt. delimiter . close . anchor . ast_id == FIXUP_DUMMY_AST_ID
331
+ || tt. delimiter . open . anchor . ast_id == FIXUP_DUMMY_AST_ID
334
332
{
335
333
// Even though fixup never creates subtrees with fixup spans, the old proc-macro server
336
334
// might copy them if the proc-macro asks for it, so we need to filter those out
@@ -341,7 +339,7 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
341
339
SmallVec :: from_const ( [ tt. into ( ) ] )
342
340
}
343
341
tt:: TokenTree :: Leaf ( leaf) => {
344
- if leaf. span ( ) . anchor . file_id == FIXUP_DUMMY_FILE {
342
+ if leaf. span ( ) . anchor . ast_id == FIXUP_DUMMY_AST_ID {
345
343
// we have a fake node here, we need to replace it again with the original
346
344
let original = undo_info[ u32:: from ( leaf. span ( ) . range . start ( ) ) as usize ] . clone ( ) ;
347
345
if original. delimiter . kind == tt:: DelimiterKind :: Invisible {
0 commit comments