@@ -18,7 +18,7 @@ use smallvec::{smallvec, SmallVec};
18
18
use syntax:: {
19
19
algo:: skip_trivia_token,
20
20
ast:: { self , HasAttrs , HasGenericParams , HasLoopBody } ,
21
- match_ast, AstNode , Direction , SyntaxNode , SyntaxNodePtr , SyntaxToken , TextRange , TextSize ,
21
+ match_ast, AstNode , Direction , SyntaxNode , SyntaxNodePtr , SyntaxToken , TextSize ,
22
22
} ;
23
23
24
24
use crate :: {
@@ -178,10 +178,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
178
178
self . imp . speculative_expand_attr ( actual_macro_call, speculative_args, token_to_map)
179
179
}
180
180
181
+ /// Descend the token into macrocalls to its first mapped counterpart.
181
182
pub fn descend_into_macros_single ( & self , token : SyntaxToken ) -> SyntaxToken {
182
- self . imp . descend_into_macros ( token) . pop ( ) . unwrap ( )
183
+ self . imp . descend_into_macros_single ( token)
183
184
}
184
185
186
+ /// Descend the token into macrocalls to all its mapped counterparts.
185
187
pub fn descend_into_macros ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
186
188
self . imp . descend_into_macros ( token)
187
189
}
@@ -509,72 +511,102 @@ impl<'db> SemanticsImpl<'db> {
509
511
} ;
510
512
511
513
if first == last {
512
- self . descend_into_macros_impl ( first, |InFile { value, .. } | {
513
- if let Some ( node) = value. ancestors ( ) . find_map ( N :: cast) {
514
- res. push ( node)
515
- }
516
- } ) ;
514
+ self . descend_into_macros_impl (
515
+ first,
516
+ |InFile { value, .. } | {
517
+ if let Some ( node) = value. ancestors ( ) . find_map ( N :: cast) {
518
+ res. push ( node)
519
+ }
520
+ } ,
521
+ false ,
522
+ ) ;
517
523
} else {
518
524
// Descend first and last token, then zip them to look for the node they belong to
519
525
let mut scratch: SmallVec < [ _ ; 1 ] > = smallvec ! [ ] ;
520
- self . descend_into_macros_impl ( first, |token| {
521
- scratch. push ( token) ;
522
- } ) ;
526
+ self . descend_into_macros_impl (
527
+ first,
528
+ |token| {
529
+ scratch. push ( token) ;
530
+ } ,
531
+ false ,
532
+ ) ;
523
533
524
534
let mut scratch = scratch. into_iter ( ) ;
525
- self . descend_into_macros_impl ( last, |InFile { value : last, file_id : last_fid } | {
526
- if let Some ( InFile { value : first, file_id : first_fid } ) = scratch. next ( ) {
527
- if first_fid == last_fid {
528
- if let Some ( p) = first. parent ( ) {
529
- let range = first. text_range ( ) . cover ( last. text_range ( ) ) ;
530
- let node = find_root ( & p)
531
- . covering_element ( range)
532
- . ancestors ( )
533
- . take_while ( |it| it. text_range ( ) == range)
534
- . find_map ( N :: cast) ;
535
- if let Some ( node) = node {
536
- res. push ( node) ;
535
+ self . descend_into_macros_impl (
536
+ last,
537
+ |InFile { value : last, file_id : last_fid } | {
538
+ if let Some ( InFile { value : first, file_id : first_fid } ) = scratch. next ( ) {
539
+ if first_fid == last_fid {
540
+ if let Some ( p) = first. parent ( ) {
541
+ let range = first. text_range ( ) . cover ( last. text_range ( ) ) ;
542
+ let node = find_root ( & p)
543
+ . covering_element ( range)
544
+ . ancestors ( )
545
+ . take_while ( |it| it. text_range ( ) == range)
546
+ . find_map ( N :: cast) ;
547
+ if let Some ( node) = node {
548
+ res. push ( node) ;
549
+ }
537
550
}
538
551
}
539
552
}
540
- }
541
- } ) ;
553
+ } ,
554
+ false ,
555
+ ) ;
542
556
}
543
557
res
544
558
}
545
559
546
560
fn descend_into_macros ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
547
561
let mut res = smallvec ! [ ] ;
548
- self . descend_into_macros_impl ( token, |InFile { value, .. } | res. push ( value) ) ;
562
+ self . descend_into_macros_impl ( token, |InFile { value, .. } | res. push ( value) , false ) ;
549
563
res
550
564
}
551
565
552
- fn descend_into_macros_impl ( & self , token : SyntaxToken , mut f : impl FnMut ( InFile < SyntaxToken > ) ) {
566
+ fn descend_into_macros_single ( & self , token : SyntaxToken ) -> SyntaxToken {
567
+ let mut res = token. clone ( ) ;
568
+ self . descend_into_macros_impl ( token, |InFile { value, .. } | res = value, true ) ;
569
+ res
570
+ }
571
+
572
+ fn descend_into_macros_impl (
573
+ & self ,
574
+ token : SyntaxToken ,
575
+ mut f : impl FnMut ( InFile < SyntaxToken > ) ,
576
+ single : bool ,
577
+ ) {
553
578
let _p = profile:: span ( "descend_into_macros" ) ;
554
579
let parent = match token. parent ( ) {
555
580
Some ( it) => it,
556
581
None => return ,
557
582
} ;
558
583
let sa = self . analyze ( & parent) ;
559
- let mut stack: SmallVec < [ _ ; 1 ] > = smallvec ! [ InFile :: new( sa. file_id, token) ] ;
584
+ let mut stack: SmallVec < [ _ ; 4 ] > = smallvec ! [ InFile :: new( sa. file_id, token) ] ;
560
585
let mut cache = self . expansion_info_cache . borrow_mut ( ) ;
561
586
let mut mcache = self . macro_call_cache . borrow_mut ( ) ;
562
587
563
588
let mut process_expansion_for_token =
564
- |stack : & mut SmallVec < _ > , file_id, item, token : InFile < & _ > | {
565
- let mapped_tokens = cache
566
- . entry ( file_id)
567
- . or_insert_with ( || file_id. expansion_info ( self . db . upcast ( ) ) )
568
- . as_ref ( ) ?
569
- . map_token_down ( self . db . upcast ( ) , item, token) ?;
589
+ |stack : & mut SmallVec < _ > , macro_file, item, token : InFile < & _ > | {
590
+ let expansion_info = cache
591
+ . entry ( macro_file)
592
+ . or_insert_with ( || macro_file. expansion_info ( self . db . upcast ( ) ) )
593
+ . as_ref ( ) ?;
594
+
595
+ {
596
+ let InFile { file_id, value } = expansion_info. expanded ( ) ;
597
+ self . cache ( value, file_id) ;
598
+ }
599
+
600
+ let mut mapped_tokens =
601
+ expansion_info. map_token_down ( self . db . upcast ( ) , item, token) ?;
570
602
571
603
let len = stack. len ( ) ;
572
604
// requeue the tokens we got from mapping our current token down
573
- stack . extend ( mapped_tokens . inspect ( |token| {
574
- if let Some ( parent ) = token . value . parent ( ) {
575
- self . cache ( find_root ( & parent ) , token . file_id ) ;
576
- }
577
- } ) ) ;
605
+ if single {
606
+ stack . extend ( mapped_tokens . next ( ) ) ;
607
+ } else {
608
+ stack . extend ( mapped_tokens ) ;
609
+ }
578
610
// if the length changed we have found a mapping for the token
579
611
( stack. len ( ) != len) . then ( || ( ) )
580
612
} ;
@@ -606,17 +638,15 @@ impl<'db> SemanticsImpl<'db> {
606
638
}
607
639
608
640
// or are we inside a function-like macro call
609
- if let Some ( macro_call) = token. value . ancestors ( ) . find_map ( ast:: MacroCall :: cast) {
610
- let tt = macro_call. token_tree ( ) ?;
611
- let l_delim = match tt. left_delimiter_token ( ) {
612
- Some ( it) => it. text_range ( ) . end ( ) ,
613
- None => tt. syntax ( ) . text_range ( ) . start ( ) ,
614
- } ;
615
- let r_delim = match tt. right_delimiter_token ( ) {
616
- Some ( it) => it. text_range ( ) . start ( ) ,
617
- None => tt. syntax ( ) . text_range ( ) . end ( ) ,
618
- } ;
619
- if !TextRange :: new ( l_delim, r_delim) . contains_range ( token. value . text_range ( ) ) {
641
+ if let Some ( tt) =
642
+ // FIXME replace map.while_some with take_while once stable
643
+ token. value . ancestors ( ) . map ( ast:: TokenTree :: cast) . while_some ( ) . last ( )
644
+ {
645
+ let macro_call = tt. syntax ( ) . parent ( ) . and_then ( ast:: MacroCall :: cast) ?;
646
+ if tt. left_delimiter_token ( ) . map_or ( false , |it| it == token. value ) {
647
+ return None ;
648
+ }
649
+ if tt. right_delimiter_token ( ) . map_or ( false , |it| it == token. value ) {
620
650
return None ;
621
651
}
622
652
0 commit comments