11//! To make attribute macros work reliably when typing, we need to take care to
22//! fix up syntax errors in the code we're passing to them.
33
4- use la_arena:: RawIdx ;
54use rustc_hash:: { FxHashMap , FxHashSet } ;
65use smallvec:: SmallVec ;
7- use span:: { ErasedFileAstId , FileId , Span , SpanAnchor , SpanData } ;
6+ use span:: { ErasedFileAstId , Span , SpanAnchor , SpanData , FIXUP_ERASED_FILE_AST_ID_MARKER } ;
87use stdx:: never;
98use syntax:: {
109 ast:: { self , AstNode , HasLoopBody } ,
@@ -39,13 +38,11 @@ impl SyntaxFixupUndoInfo {
3938 pub ( crate ) const NONE : Self = SyntaxFixupUndoInfo { original : None } ;
4039}
4140
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 ;
4843const 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`.
4946const FIXUP_DUMMY_RANGE_END : TextSize = TextSize :: new ( !0 ) ;
5047
5148pub ( crate ) fn fixup_syntax (
@@ -58,13 +55,13 @@ pub(crate) fn fixup_syntax(
5855 let mut preorder = node. preorder ( ) ;
5956 let mut original = Vec :: new ( ) ;
6057 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+ }
6865 } ;
6966 while let Some ( event) = preorder. next ( ) {
7067 let syntax:: WalkEvent :: Enter ( node) = event else { continue } ;
@@ -76,12 +73,13 @@ pub(crate) fn fixup_syntax(
7673 let original_tree = mbe:: syntax_node_to_token_tree ( & node, span_map, call_site) ;
7774 let idx = original. len ( ) as u32 ;
7875 original. push ( original_tree) ;
76+ let span = span_map. span_for_range ( node_range) ;
7977 let replacement = Leaf :: Ident ( Ident {
8078 text : "__ra_fixup" . into ( ) ,
8179 span : SpanData {
8280 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 ,
8583 } ,
8684 } ) ;
8785 append. insert ( node. clone ( ) . into ( ) , vec ! [ replacement] ) ;
@@ -304,8 +302,8 @@ pub(crate) fn reverse_fixups(tt: &mut Subtree, undo_info: &SyntaxFixupUndoInfo)
304302 let undo_info = & * * undo_info;
305303 #[ allow( deprecated) ]
306304 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
309307 ) {
310308 tt. delimiter . close = SpanData :: DUMMY ;
311309 tt. delimiter . open = SpanData :: DUMMY ;
@@ -321,16 +319,16 @@ fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
321319 . filter ( |tt| match tt {
322320 tt:: TokenTree :: Leaf ( leaf) => {
323321 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 ;
325323 let is_replaced_node = span. range . end ( ) == FIXUP_DUMMY_RANGE_END ;
326324 is_real_leaf || is_replaced_node
327325 }
328326 tt:: TokenTree :: Subtree ( _) => true ,
329327 } )
330328 . flat_map ( |tt| match tt {
331329 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
334332 {
335333 // Even though fixup never creates subtrees with fixup spans, the old proc-macro server
336334 // 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]) {
341339 SmallVec :: from_const ( [ tt. into ( ) ] )
342340 }
343341 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 {
345343 // we have a fake node here, we need to replace it again with the original
346344 let original = undo_info[ u32:: from ( leaf. span ( ) . range . start ( ) ) as usize ] . clone ( ) ;
347345 if original. delimiter . kind == tt:: DelimiterKind :: Invisible {
0 commit comments