22
33mod source_to_def;
44
5- use std:: { cell:: RefCell , fmt, iter, mem, ops} ;
5+ use std:: {
6+ cell:: RefCell ,
7+ fmt, iter, mem,
8+ ops:: { self , ControlFlow } ,
9+ } ;
610
711use base_db:: { FileId , FileRange } ;
812use either:: Either ;
@@ -39,6 +43,12 @@ use crate::{
3943 TypeAlias , TypeParam , VariantDef ,
4044} ;
4145
46+ pub enum DescendPreference {
47+ SameText ,
48+ SameKind ,
49+ None ,
50+ }
51+
4252#[ derive( Debug , Clone , PartialEq , Eq ) ]
4353pub enum PathResolution {
4454 /// An item
@@ -397,6 +407,7 @@ impl<'db> SemanticsImpl<'db> {
397407 // This might not be the correct way to do this, but it works for now
398408 let mut res = smallvec ! [ ] ;
399409 let tokens = ( || {
410+ // FIXME: the trivia skipping should not be necessary
400411 let first = skip_trivia_token ( node. syntax ( ) . first_token ( ) ?, Direction :: Next ) ?;
401412 let last = skip_trivia_token ( node. syntax ( ) . last_token ( ) ?, Direction :: Prev ) ?;
402413 Some ( ( first, last) )
@@ -407,18 +418,19 @@ impl<'db> SemanticsImpl<'db> {
407418 } ;
408419
409420 if first == last {
421+ // node is just the token, so descend the token
410422 self . descend_into_macros_impl ( first, 0 . into ( ) , & mut |InFile { value, .. } | {
411423 if let Some ( node) = value. parent_ancestors ( ) . find_map ( N :: cast) {
412424 res. push ( node)
413425 }
414- false
426+ ControlFlow :: Continue ( ( ) )
415427 } ) ;
416428 } else {
417429 // Descend first and last token, then zip them to look for the node they belong to
418430 let mut scratch: SmallVec < [ _ ; 1 ] > = smallvec ! [ ] ;
419431 self . descend_into_macros_impl ( first, 0 . into ( ) , & mut |token| {
420432 scratch. push ( token) ;
421- false
433+ ControlFlow :: Continue ( ( ) )
422434 } ) ;
423435
424436 let mut scratch = scratch. into_iter ( ) ;
@@ -441,7 +453,7 @@ impl<'db> SemanticsImpl<'db> {
441453 }
442454 }
443455 }
444- false
456+ ControlFlow :: Continue ( ( ) )
445457 } ,
446458 ) ;
447459 }
@@ -453,78 +465,92 @@ impl<'db> SemanticsImpl<'db> {
453465 /// be considered for the mapping in case of inline format args.
454466 pub fn descend_into_macros (
455467 & self ,
468+ mode : DescendPreference ,
456469 token : SyntaxToken ,
457470 offset : TextSize ,
458471 ) -> SmallVec < [ SyntaxToken ; 1 ] > {
459- let mut res = smallvec ! [ ] ;
460- self . descend_into_macros_impl ( token , offset , & mut | InFile { value , .. } | {
461- res . push ( value ) ;
462- false
463- } ) ;
464- res
465- }
466-
467- /// Descend the token into macrocalls to all its mapped counterparts that have the same text as the input token.
468- ///
469- /// Returns the original non descended token if none of the mapped counterparts have the same text.
470- pub fn descend_into_macros_with_same_text (
471- & self ,
472- token : SyntaxToken ,
473- offset : TextSize ,
474- ) -> SmallVec < [ SyntaxToken ; 1 ] > {
475- let text = token . text ( ) ;
472+ enum Dp < ' t > {
473+ SameText ( & ' t str ) ,
474+ SameKind ( SyntaxKind ) ,
475+ None ,
476+ }
477+ let fetch_kind = | token : & SyntaxToken | match token . parent ( ) {
478+ Some ( node ) => match node . kind ( ) {
479+ kind @ ( SyntaxKind :: NAME | SyntaxKind :: NAME_REF ) => kind ,
480+ _ => token. kind ( ) ,
481+ } ,
482+ None => token . kind ( ) ,
483+ } ;
484+ let mode = match mode {
485+ DescendPreference :: SameText => Dp :: SameText ( token . text ( ) ) ,
486+ DescendPreference :: SameKind => Dp :: SameKind ( fetch_kind ( & token ) ) ,
487+ DescendPreference :: None => Dp :: None ,
488+ } ;
476489 let mut res = smallvec ! [ ] ;
477490 self . descend_into_macros_impl ( token. clone ( ) , offset, & mut |InFile { value, .. } | {
478- if value. text ( ) == text {
491+ let is_a_match = match mode {
492+ Dp :: SameText ( text) => value. text ( ) == text,
493+ Dp :: SameKind ( preferred_kind) => {
494+ let kind = fetch_kind ( & value) ;
495+ kind == preferred_kind
496+ // special case for derive macros
497+ || ( preferred_kind == SyntaxKind :: IDENT && kind == SyntaxKind :: NAME_REF )
498+ }
499+ Dp :: None => true ,
500+ } ;
501+ if is_a_match {
479502 res. push ( value) ;
480503 }
481- false
504+ ControlFlow :: Continue ( ( ) )
482505 } ) ;
483506 if res. is_empty ( ) {
484507 res. push ( token) ;
485508 }
486509 res
487510 }
488511
489- pub fn descend_into_macros_with_kind_preference (
512+ pub fn descend_into_macros_single (
490513 & self ,
514+ mode : DescendPreference ,
491515 token : SyntaxToken ,
492516 offset : TextSize ,
493517 ) -> SyntaxToken {
518+ enum Dp < ' t > {
519+ SameText ( & ' t str ) ,
520+ SameKind ( SyntaxKind ) ,
521+ None ,
522+ }
494523 let fetch_kind = |token : & SyntaxToken | match token. parent ( ) {
495524 Some ( node) => match node. kind ( ) {
496- kind @ ( SyntaxKind :: NAME | SyntaxKind :: NAME_REF ) => {
497- node. parent ( ) . map_or ( kind, |it| it. kind ( ) )
498- }
525+ kind @ ( SyntaxKind :: NAME | SyntaxKind :: NAME_REF ) => kind,
499526 _ => token. kind ( ) ,
500527 } ,
501528 None => token. kind ( ) ,
502529 } ;
503- let preferred_kind = fetch_kind ( & token) ;
504- let mut res = None ;
530+ let mode = match mode {
531+ DescendPreference :: SameText => Dp :: SameText ( token. text ( ) ) ,
532+ DescendPreference :: SameKind => Dp :: SameKind ( fetch_kind ( & token) ) ,
533+ DescendPreference :: None => Dp :: None ,
534+ } ;
535+ let mut res = token. clone ( ) ;
505536 self . descend_into_macros_impl ( token. clone ( ) , offset, & mut |InFile { value, .. } | {
506- if fetch_kind ( & value) == preferred_kind {
507- res = Some ( value) ;
508- true
509- } else {
510- if let None = res {
511- res = Some ( value)
537+ let is_a_match = match mode {
538+ Dp :: SameText ( text) => value. text ( ) == text,
539+ Dp :: SameKind ( preferred_kind) => {
540+ let kind = fetch_kind ( & value) ;
541+ kind == preferred_kind
542+ // special case for derive macros
543+ || ( preferred_kind == SyntaxKind :: IDENT && kind == SyntaxKind :: NAME_REF )
512544 }
513- false
545+ Dp :: None => true ,
546+ } ;
547+ if is_a_match {
548+ res = value;
549+ ControlFlow :: Break ( ( ) )
550+ } else {
551+ ControlFlow :: Continue ( ( ) )
514552 }
515553 } ) ;
516- res. unwrap_or ( token)
517- }
518-
519- /// Descend the token into its macro call if it is part of one, returning the token in the
520- /// expansion that it is associated with. If `offset` points into the token's range, it will
521- /// be considered for the mapping in case of inline format args.
522- pub fn descend_into_macros_single ( & self , token : SyntaxToken , offset : TextSize ) -> SyntaxToken {
523- let mut res = token. clone ( ) ;
524- self . descend_into_macros_impl ( token, offset, & mut |InFile { value, .. } | {
525- res = value;
526- true
527- } ) ;
528554 res
529555 }
530556
@@ -535,7 +561,7 @@ impl<'db> SemanticsImpl<'db> {
535561 // FIXME: We might want this to be Option<TextSize> to be able to opt out of subrange
536562 // mapping, specifically for node downmapping
537563 _offset : TextSize ,
538- f : & mut dyn FnMut ( InFile < SyntaxToken > ) -> bool ,
564+ f : & mut dyn FnMut ( InFile < SyntaxToken > ) -> ControlFlow < ( ) > ,
539565 ) {
540566 // FIXME: Clean this up
541567 let _p = profile:: span ( "descend_into_macros" ) ;
@@ -560,25 +586,24 @@ impl<'db> SemanticsImpl<'db> {
560586 let def_map = sa. resolver . def_map ( ) ;
561587 let mut stack: SmallVec < [ _ ; 4 ] > = smallvec ! [ InFile :: new( sa. file_id, token) ] ;
562588
563- let mut process_expansion_for_token =
564- |stack : & mut SmallVec < _ > , macro_file, _token : InFile < & _ > | {
565- let expansion_info = cache
566- . entry ( macro_file)
567- . or_insert_with ( || macro_file. expansion_info ( self . db . upcast ( ) ) ) ;
589+ let mut process_expansion_for_token = |stack : & mut SmallVec < _ > , macro_file| {
590+ let expansion_info = cache
591+ . entry ( macro_file)
592+ . or_insert_with ( || macro_file. expansion_info ( self . db . upcast ( ) ) ) ;
568593
569- {
570- let InFile { file_id, value } = expansion_info. expanded ( ) ;
571- self . cache ( value, file_id) ;
572- }
594+ {
595+ let InFile { file_id, value } = expansion_info. expanded ( ) ;
596+ self . cache ( value, file_id) ;
597+ }
573598
574- let mapped_tokens = expansion_info. map_range_down ( span, None ) ?;
575- let len = stack. len ( ) ;
599+ let mapped_tokens = expansion_info. map_range_down ( span) ?;
600+ let len = stack. len ( ) ;
576601
577- // requeue the tokens we got from mapping our current token down
578- stack. extend ( mapped_tokens. map ( Into :: into) ) ;
579- // if the length changed we have found a mapping for the token
580- ( stack. len ( ) != len) . then_some ( ( ) )
581- } ;
602+ // requeue the tokens we got from mapping our current token down
603+ stack. extend ( mapped_tokens. map ( Into :: into) ) ;
604+ // if the length changed we have found a mapping for the token
605+ ( stack. len ( ) != len) . then_some ( ( ) )
606+ } ;
582607
583608 // Remap the next token in the queue into a macro call its in, if it is not being remapped
584609 // either due to not being in a macro-call or because its unused push it into the result vec,
@@ -598,7 +623,7 @@ impl<'db> SemanticsImpl<'db> {
598623 } ) ;
599624 if let Some ( call_id) = containing_attribute_macro_call {
600625 let file_id = call_id. as_macro_file ( ) ;
601- return process_expansion_for_token ( & mut stack, file_id, token . as_ref ( ) ) ;
626+ return process_expansion_for_token ( & mut stack, file_id) ;
602627 }
603628
604629 // Then check for token trees, that means we are either in a function-like macro or
@@ -624,7 +649,7 @@ impl<'db> SemanticsImpl<'db> {
624649 it
625650 }
626651 } ;
627- process_expansion_for_token ( & mut stack, file_id, token . as_ref ( ) )
652+ process_expansion_for_token ( & mut stack, file_id)
628653 } else if let Some ( meta) = ast:: Meta :: cast ( parent) {
629654 // attribute we failed expansion for earlier, this might be a derive invocation
630655 // or derive helper attribute
@@ -646,11 +671,7 @@ impl<'db> SemanticsImpl<'db> {
646671 Some ( call_id) => {
647672 // resolved to a derive
648673 let file_id = call_id. as_macro_file ( ) ;
649- return process_expansion_for_token (
650- & mut stack,
651- file_id,
652- token. as_ref ( ) ,
653- ) ;
674+ return process_expansion_for_token ( & mut stack, file_id) ;
654675 }
655676 None => Some ( adt) ,
656677 }
@@ -682,11 +703,8 @@ impl<'db> SemanticsImpl<'db> {
682703 def_map. derive_helpers_in_scope ( InFile :: new ( token. file_id , id) ) ?;
683704 let mut res = None ;
684705 for ( .., derive) in helpers. iter ( ) . filter ( |( helper, ..) | * helper == attr_name) {
685- res = res. or ( process_expansion_for_token (
686- & mut stack,
687- derive. as_macro_file ( ) ,
688- token. as_ref ( ) ,
689- ) ) ;
706+ res =
707+ res. or ( process_expansion_for_token ( & mut stack, derive. as_macro_file ( ) ) ) ;
690708 }
691709 res
692710 } else {
@@ -695,7 +713,7 @@ impl<'db> SemanticsImpl<'db> {
695713 } ) ( )
696714 . is_none ( ) ;
697715
698- if was_not_remapped && f ( token) {
716+ if was_not_remapped && f ( token) . is_break ( ) {
699717 break ;
700718 }
701719 }
@@ -711,7 +729,7 @@ impl<'db> SemanticsImpl<'db> {
711729 offset : TextSize ,
712730 ) -> impl Iterator < Item = impl Iterator < Item = SyntaxNode > + ' _ > + ' _ {
713731 node. token_at_offset ( offset)
714- . map ( move |token| self . descend_into_macros ( token, offset) )
732+ . map ( move |token| self . descend_into_macros ( DescendPreference :: None , token, offset) )
715733 . map ( |descendants| {
716734 descendants. into_iter ( ) . map ( move |it| self . token_ancestors_with_macros ( it) )
717735 } )
0 commit comments