@@ -18,7 +18,7 @@ use smallvec::{smallvec, SmallVec};
1818use syntax:: {
1919 algo:: skip_trivia_token,
2020 ast:: { self , HasAttrs , HasGenericParams , HasLoopBody } ,
21- match_ast, AstNode , Direction , SyntaxNode , SyntaxNodePtr , SyntaxToken , TextRange , TextSize ,
21+ match_ast, AstNode , Direction , SyntaxNode , SyntaxNodePtr , SyntaxToken , TextSize ,
2222} ;
2323
2424use crate :: {
@@ -178,10 +178,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
178178 self . imp . speculative_expand_attr ( actual_macro_call, speculative_args, token_to_map)
179179 }
180180
181+ /// Descend the token into macrocalls to its first mapped counterpart.
181182 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)
183184 }
184185
186+ /// Descend the token into macrocalls to all its mapped counterparts.
185187 pub fn descend_into_macros ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
186188 self . imp . descend_into_macros ( token)
187189 }
@@ -509,72 +511,102 @@ impl<'db> SemanticsImpl<'db> {
509511 } ;
510512
511513 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+ ) ;
517523 } else {
518524 // Descend first and last token, then zip them to look for the node they belong to
519525 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+ ) ;
523533
524534 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+ }
537550 }
538551 }
539552 }
540- }
541- } ) ;
553+ } ,
554+ false ,
555+ ) ;
542556 }
543557 res
544558 }
545559
546560 fn descend_into_macros ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
547561 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 ) ;
549563 res
550564 }
551565
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+ ) {
553578 let _p = profile:: span ( "descend_into_macros" ) ;
554579 let parent = match token. parent ( ) {
555580 Some ( it) => it,
556581 None => return ,
557582 } ;
558583 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) ] ;
560585 let mut cache = self . expansion_info_cache . borrow_mut ( ) ;
561586 let mut mcache = self . macro_call_cache . borrow_mut ( ) ;
562587
563588 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) ?;
570602
571603 let len = stack. len ( ) ;
572604 // 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+ }
578610 // if the length changed we have found a mapping for the token
579611 ( stack. len ( ) != len) . then ( || ( ) )
580612 } ;
@@ -606,17 +638,15 @@ impl<'db> SemanticsImpl<'db> {
606638 }
607639
608640 // 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 ) {
620650 return None ;
621651 }
622652
0 commit comments