22
33mod source_to_def;
44
5- use std:: { cell:: RefCell , fmt, iter :: successors } ;
5+ use std:: { cell:: RefCell , fmt} ;
66
77use base_db:: { FileId , FileRange } ;
88use hir_def:: {
@@ -14,6 +14,7 @@ use hir_expand::{name::AsName, ExpansionInfo};
1414use hir_ty:: { associated_type_shorthand_candidates, Interner } ;
1515use itertools:: Itertools ;
1616use rustc_hash:: { FxHashMap , FxHashSet } ;
17+ use smallvec:: { smallvec, SmallVec } ;
1718use syntax:: {
1819 algo:: find_node_at_offset,
1920 ast:: { self , GenericParamsOwner , LoopBodyOwner } ,
@@ -166,6 +167,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
166167 }
167168
168169 pub fn descend_into_macros ( & self , token : SyntaxToken ) -> SyntaxToken {
170+ self . imp . descend_into_macros ( token) . pop ( ) . unwrap ( )
171+ }
172+
173+ pub fn descend_into_macros_many ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
169174 self . imp . descend_into_macros ( token)
170175 }
171176
@@ -440,76 +445,83 @@ impl<'db> SemanticsImpl<'db> {
440445 )
441446 }
442447
443- fn descend_into_macros ( & self , token : SyntaxToken ) -> SyntaxToken {
448+ fn descend_into_macros ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
444449 let _p = profile:: span ( "descend_into_macros" ) ;
445450 let parent = match token. parent ( ) {
446451 Some ( it) => it,
447- None => return token,
452+ None => return smallvec ! [ token] ,
448453 } ;
449454 let sa = self . analyze ( & parent) ;
450-
451- let token = successors ( Some ( InFile :: new ( sa. file_id , token) ) , |token| {
455+ let mut queue = vec ! [ InFile :: new( sa. file_id, token) ] ;
456+ let mut res = smallvec ! [ ] ;
457+ while let Some ( token) = queue. pop ( ) {
452458 self . db . unwind_if_cancelled ( ) ;
453459
454- for node in token. value . ancestors ( ) {
455- match_ast ! {
456- match node {
457- ast:: MacroCall ( macro_call) => {
458- let tt = macro_call. token_tree( ) ?;
459- let l_delim = match tt. left_delimiter_token( ) {
460- Some ( it) => it. text_range( ) . end( ) ,
461- None => tt. syntax( ) . text_range( ) . start( )
462- } ;
463- let r_delim = match tt. right_delimiter_token( ) {
464- Some ( it) => it. text_range( ) . start( ) ,
465- None => tt. syntax( ) . text_range( ) . end( )
466- } ;
467- if !TextRange :: new( l_delim, r_delim) . contains_range( token. value. text_range( ) ) {
468- return None ;
469- }
470- let file_id = sa. expand( self . db, token. with_value( & macro_call) ) ?;
471- let token = self
472- . expansion_info_cache
473- . borrow_mut( )
474- . entry( file_id)
475- . or_insert_with( || file_id. expansion_info( self . db. upcast( ) ) )
476- . as_ref( ) ?
477- . map_token_down( self . db. upcast( ) , None , token. as_ref( ) ) ?;
478-
479- if let Some ( parent) = token. value. parent( ) {
480- self . cache( find_root( & parent) , token. file_id) ;
481- }
482-
483- return Some ( token) ;
484- } ,
485- ast:: Item ( item) => {
486- if let Some ( call_id) = self . with_ctx( |ctx| ctx. item_to_macro_call( token. with_value( item. clone( ) ) ) ) {
487- let file_id = call_id. as_file( ) ;
488- let token = self
489- . expansion_info_cache
490- . borrow_mut( )
460+ let mapped = ( || {
461+ for node in token. value . ancestors ( ) {
462+ match_ast ! {
463+ match node {
464+ ast:: MacroCall ( macro_call) => {
465+ let tt = macro_call. token_tree( ) ?;
466+ let l_delim = match tt. left_delimiter_token( ) {
467+ Some ( it) => it. text_range( ) . end( ) ,
468+ None => tt. syntax( ) . text_range( ) . start( )
469+ } ;
470+ let r_delim = match tt. right_delimiter_token( ) {
471+ Some ( it) => it. text_range( ) . start( ) ,
472+ None => tt. syntax( ) . text_range( ) . end( )
473+ } ;
474+ if !TextRange :: new( l_delim, r_delim) . contains_range( token. value. text_range( ) ) {
475+ return None ;
476+ }
477+ let file_id = sa. expand( self . db, token. with_value( & macro_call) ) ?;
478+ let mut cache = self . expansion_info_cache. borrow_mut( ) ;
479+ let tokens = cache
491480 . entry( file_id)
492481 . or_insert_with( || file_id. expansion_info( self . db. upcast( ) ) )
493482 . as_ref( ) ?
494- . map_token_down( self . db. upcast( ) , Some ( item) , token. as_ref( ) ) ?;
495-
496- if let Some ( parent) = token. value. parent( ) {
497- self . cache( find_root( & parent) , token. file_id) ;
483+ . map_token_down( self . db. upcast( ) , None , token. as_ref( ) ) ?;
484+
485+ queue. extend( tokens. inspect( |token| {
486+ if let Some ( parent) = token. value. parent( ) {
487+ self . cache( find_root( & parent) , token. file_id) ;
488+ }
489+ } ) ) ;
490+ return Some ( ( ) ) ;
491+ } ,
492+ ast:: Item ( item) => {
493+ match self . with_ctx( |ctx| ctx. item_to_macro_call( token. with_value( item) ) ) {
494+ Some ( call_id) => {
495+ let file_id = call_id. as_file( ) ;
496+ let mut cache = self . expansion_info_cache. borrow_mut( ) ;
497+ let tokens = cache
498+ . entry( file_id)
499+ . or_insert_with( || file_id. expansion_info( self . db. upcast( ) ) )
500+ . as_ref( ) ?
501+ . map_token_down( self . db. upcast( ) , None , token. as_ref( ) ) ?;
502+
503+ queue. extend( tokens. inspect( |token| {
504+ if let Some ( parent) = token. value. parent( ) {
505+ self . cache( find_root( & parent) , token. file_id) ;
506+ }
507+ } ) ) ;
508+ return Some ( ( ) ) ;
509+ }
510+ None => { }
498511 }
499-
500- return Some ( token) ;
501- }
502- } ,
503- _ => { }
512+ } ,
513+ _ => { }
514+ }
504515 }
505516 }
517+ None
518+ } ) ( ) ;
519+ match mapped {
520+ Some ( ( ) ) => ( ) ,
521+ None => res. push ( token. value ) ,
506522 }
507-
508- None
509- } )
510- . last ( )
511- . unwrap ( ) ;
512- token. value
523+ }
524+ res
513525 }
514526
515527 fn descend_node_at_offset (
@@ -519,8 +531,8 @@ impl<'db> SemanticsImpl<'db> {
519531 ) -> impl Iterator < Item = SyntaxNode > + ' _ {
520532 // Handle macro token cases
521533 node. token_at_offset ( offset)
522- . map ( |token| self . descend_into_macros ( token) )
523- . map ( |it| self . token_ancestors_with_macros ( it) )
534+ . flat_map ( move |token| self . descend_into_macros ( token) )
535+ . map ( move |it| self . token_ancestors_with_macros ( it) )
524536 . flatten ( )
525537 }
526538
0 commit comments