@@ -544,38 +544,54 @@ impl<'db> SemanticsImpl<'db> {
544
544
let sa = self . analyze ( & parent) ;
545
545
let mut queue = vec ! [ InFile :: new( sa. file_id, token) ] ;
546
546
let mut cache = self . expansion_info_cache . borrow_mut ( ) ;
547
+
548
+ let mut process_expansion_for_token =
549
+ |queue : & mut Vec < _ > , file_id, item, token : InFile < & _ > | {
550
+ let mapped_tokens = cache
551
+ . entry ( file_id)
552
+ . or_insert_with ( || file_id. expansion_info ( self . db . upcast ( ) ) )
553
+ . as_ref ( ) ?
554
+ . map_token_down ( self . db . upcast ( ) , item, token) ?;
555
+
556
+ let len = queue. len ( ) ;
557
+ // requeue the tokens we got from mapping our current token down
558
+ queue. extend ( mapped_tokens. inspect ( |token| {
559
+ if let Some ( parent) = token. value . parent ( ) {
560
+ self . cache ( find_root ( & parent) , token. file_id ) ;
561
+ }
562
+ } ) ) ;
563
+ // if the length changed we have found a mapping for the token
564
+ ( queue. len ( ) != len) . then ( || ( ) )
565
+ } ;
566
+
547
567
// Remap the next token in the queue into a macro call its in, if it is not being remapped
548
568
// either due to not being in a macro-call or because its unused push it into the result vec,
549
569
// otherwise push the remapped tokens back into the queue as they can potentially be remapped again.
550
570
while let Some ( token) = queue. pop ( ) {
551
571
self . db . unwind_if_cancelled ( ) ;
552
572
let was_not_remapped = ( || {
553
- if let Some ( ( call_id, item) ) = token
554
- . value
555
- . ancestors ( )
556
- . filter_map ( ast:: Item :: cast)
557
- . filter_map ( |item| {
558
- self . with_ctx ( |ctx| ctx. item_to_macro_call ( token. with_value ( item. clone ( ) ) ) )
559
- . zip ( Some ( item) )
560
- } )
561
- . last ( )
562
- {
573
+ // are we inside an attribute macro call
574
+ let containing_attribute_macro_call = self . with_ctx ( |ctx| {
575
+ token
576
+ . value
577
+ . ancestors ( )
578
+ . filter_map ( ast:: Item :: cast)
579
+ . filter_map ( |item| {
580
+ Some ( ( ctx. item_to_macro_call ( token. with_value ( item. clone ( ) ) ) ?, item) )
581
+ } )
582
+ . last ( )
583
+ } ) ;
584
+ if let Some ( ( call_id, item) ) = containing_attribute_macro_call {
563
585
let file_id = call_id. as_file ( ) ;
564
- let tokens = cache
565
- . entry ( file_id)
566
- . or_insert_with ( || file_id. expansion_info ( self . db . upcast ( ) ) )
567
- . as_ref ( ) ?
568
- . map_token_down ( self . db . upcast ( ) , Some ( item) , token. as_ref ( ) ) ?;
569
-
570
- let len = queue. len ( ) ;
571
- queue. extend ( tokens. inspect ( |token| {
572
- if let Some ( parent) = token. value . parent ( ) {
573
- self . cache ( find_root ( & parent) , token. file_id ) ;
574
- }
575
- } ) ) ;
576
- return ( queue. len ( ) != len) . then ( || ( ) ) ;
586
+ return process_expansion_for_token (
587
+ & mut queue,
588
+ file_id,
589
+ Some ( item) ,
590
+ token. as_ref ( ) ,
591
+ ) ;
577
592
}
578
593
594
+ // or are we inside a function-like macro call
579
595
if let Some ( macro_call) = token. value . ancestors ( ) . find_map ( ast:: MacroCall :: cast) {
580
596
let tt = macro_call. token_tree ( ) ?;
581
597
let l_delim = match tt. left_delimiter_token ( ) {
@@ -589,21 +605,12 @@ impl<'db> SemanticsImpl<'db> {
589
605
if !TextRange :: new ( l_delim, r_delim) . contains_range ( token. value . text_range ( ) ) {
590
606
return None ;
591
607
}
608
+
592
609
let file_id = sa. expand ( self . db , token. with_value ( & macro_call) ) ?;
593
- let tokens = cache
594
- . entry ( file_id)
595
- . or_insert_with ( || file_id. expansion_info ( self . db . upcast ( ) ) )
596
- . as_ref ( ) ?
597
- . map_token_down ( self . db . upcast ( ) , None , token. as_ref ( ) ) ?;
598
-
599
- let len = queue. len ( ) ;
600
- queue. extend ( tokens. inspect ( |token| {
601
- if let Some ( parent) = token. value . parent ( ) {
602
- self . cache ( find_root ( & parent) , token. file_id ) ;
603
- }
604
- } ) ) ;
605
- return ( queue. len ( ) != len) . then ( || ( ) ) ;
610
+ return process_expansion_for_token ( & mut queue, file_id, None , token. as_ref ( ) ) ;
606
611
}
612
+
613
+ // outside of a macro invocation so this is a "final" token
607
614
None
608
615
} ) ( )
609
616
. is_none ( ) ;
0 commit comments