2
2
3
3
mod source_to_def;
4
4
5
- use std:: { cell:: RefCell , fmt, iter, mem, ops} ;
5
+ use std:: {
6
+ cell:: RefCell ,
7
+ fmt, iter, mem,
8
+ ops:: { self , ControlFlow } ,
9
+ } ;
6
10
7
11
use base_db:: { FileId , FileRange } ;
8
12
use either:: Either ;
@@ -39,6 +43,12 @@ use crate::{
39
43
TypeAlias , TypeParam , VariantDef ,
40
44
} ;
41
45
46
+ pub enum DescendPreference {
47
+ SameText ,
48
+ SameKind ,
49
+ None ,
50
+ }
51
+
42
52
#[ derive( Debug , Clone , PartialEq , Eq ) ]
43
53
pub enum PathResolution {
44
54
/// An item
@@ -397,6 +407,7 @@ impl<'db> SemanticsImpl<'db> {
397
407
// This might not be the correct way to do this, but it works for now
398
408
let mut res = smallvec ! [ ] ;
399
409
let tokens = ( || {
410
+ // FIXME: the trivia skipping should not be necessary
400
411
let first = skip_trivia_token ( node. syntax ( ) . first_token ( ) ?, Direction :: Next ) ?;
401
412
let last = skip_trivia_token ( node. syntax ( ) . last_token ( ) ?, Direction :: Prev ) ?;
402
413
Some ( ( first, last) )
@@ -407,18 +418,19 @@ impl<'db> SemanticsImpl<'db> {
407
418
} ;
408
419
409
420
if first == last {
421
+ // node is just the token, so descend the token
410
422
self . descend_into_macros_impl ( first, 0 . into ( ) , & mut |InFile { value, .. } | {
411
423
if let Some ( node) = value. parent_ancestors ( ) . find_map ( N :: cast) {
412
424
res. push ( node)
413
425
}
414
- false
426
+ ControlFlow :: Continue ( ( ) )
415
427
} ) ;
416
428
} else {
417
429
// Descend first and last token, then zip them to look for the node they belong to
418
430
let mut scratch: SmallVec < [ _ ; 1 ] > = smallvec ! [ ] ;
419
431
self . descend_into_macros_impl ( first, 0 . into ( ) , & mut |token| {
420
432
scratch. push ( token) ;
421
- false
433
+ ControlFlow :: Continue ( ( ) )
422
434
} ) ;
423
435
424
436
let mut scratch = scratch. into_iter ( ) ;
@@ -441,7 +453,7 @@ impl<'db> SemanticsImpl<'db> {
441
453
}
442
454
}
443
455
}
444
- false
456
+ ControlFlow :: Continue ( ( ) )
445
457
} ,
446
458
) ;
447
459
}
@@ -453,78 +465,92 @@ impl<'db> SemanticsImpl<'db> {
453
465
/// be considered for the mapping in case of inline format args.
454
466
pub fn descend_into_macros (
455
467
& self ,
468
+ mode : DescendPreference ,
456
469
token : SyntaxToken ,
457
470
offset : TextSize ,
458
471
) -> 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
+ } ;
476
489
let mut res = smallvec ! [ ] ;
477
490
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 {
479
502
res. push ( value) ;
480
503
}
481
- false
504
+ ControlFlow :: Continue ( ( ) )
482
505
} ) ;
483
506
if res. is_empty ( ) {
484
507
res. push ( token) ;
485
508
}
486
509
res
487
510
}
488
511
489
- pub fn descend_into_macros_with_kind_preference (
512
+ pub fn descend_into_macros_single (
490
513
& self ,
514
+ mode : DescendPreference ,
491
515
token : SyntaxToken ,
492
516
offset : TextSize ,
493
517
) -> SyntaxToken {
518
+ enum Dp < ' t > {
519
+ SameText ( & ' t str ) ,
520
+ SameKind ( SyntaxKind ) ,
521
+ None ,
522
+ }
494
523
let fetch_kind = |token : & SyntaxToken | match token. parent ( ) {
495
524
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,
499
526
_ => token. kind ( ) ,
500
527
} ,
501
528
None => token. kind ( ) ,
502
529
} ;
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 ( ) ;
505
536
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 )
512
544
}
513
- false
545
+ Dp :: None => true ,
546
+ } ;
547
+ if is_a_match {
548
+ res = value;
549
+ ControlFlow :: Break ( ( ) )
550
+ } else {
551
+ ControlFlow :: Continue ( ( ) )
514
552
}
515
553
} ) ;
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
- } ) ;
528
554
res
529
555
}
530
556
@@ -535,7 +561,7 @@ impl<'db> SemanticsImpl<'db> {
535
561
// FIXME: We might want this to be Option<TextSize> to be able to opt out of subrange
536
562
// mapping, specifically for node downmapping
537
563
_offset : TextSize ,
538
- f : & mut dyn FnMut ( InFile < SyntaxToken > ) -> bool ,
564
+ f : & mut dyn FnMut ( InFile < SyntaxToken > ) -> ControlFlow < ( ) > ,
539
565
) {
540
566
// FIXME: Clean this up
541
567
let _p = profile:: span ( "descend_into_macros" ) ;
@@ -560,25 +586,24 @@ impl<'db> SemanticsImpl<'db> {
560
586
let def_map = sa. resolver . def_map ( ) ;
561
587
let mut stack: SmallVec < [ _ ; 4 ] > = smallvec ! [ InFile :: new( sa. file_id, token) ] ;
562
588
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 ( ) ) ) ;
568
593
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
+ }
573
598
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 ( ) ;
576
601
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
+ } ;
582
607
583
608
// Remap the next token in the queue into a macro call its in, if it is not being remapped
584
609
// 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> {
598
623
} ) ;
599
624
if let Some ( call_id) = containing_attribute_macro_call {
600
625
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) ;
602
627
}
603
628
604
629
// Then check for token trees, that means we are either in a function-like macro or
@@ -624,7 +649,7 @@ impl<'db> SemanticsImpl<'db> {
624
649
it
625
650
}
626
651
} ;
627
- process_expansion_for_token ( & mut stack, file_id, token . as_ref ( ) )
652
+ process_expansion_for_token ( & mut stack, file_id)
628
653
} else if let Some ( meta) = ast:: Meta :: cast ( parent) {
629
654
// attribute we failed expansion for earlier, this might be a derive invocation
630
655
// or derive helper attribute
@@ -646,11 +671,7 @@ impl<'db> SemanticsImpl<'db> {
646
671
Some ( call_id) => {
647
672
// resolved to a derive
648
673
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) ;
654
675
}
655
676
None => Some ( adt) ,
656
677
}
@@ -682,11 +703,8 @@ impl<'db> SemanticsImpl<'db> {
682
703
def_map. derive_helpers_in_scope ( InFile :: new ( token. file_id , id) ) ?;
683
704
let mut res = None ;
684
705
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 ( ) ) ) ;
690
708
}
691
709
res
692
710
} else {
@@ -695,7 +713,7 @@ impl<'db> SemanticsImpl<'db> {
695
713
} ) ( )
696
714
. is_none ( ) ;
697
715
698
- if was_not_remapped && f ( token) {
716
+ if was_not_remapped && f ( token) . is_break ( ) {
699
717
break ;
700
718
}
701
719
}
@@ -711,7 +729,7 @@ impl<'db> SemanticsImpl<'db> {
711
729
offset : TextSize ,
712
730
) -> impl Iterator < Item = impl Iterator < Item = SyntaxNode > + ' _ > + ' _ {
713
731
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) )
715
733
. map ( |descendants| {
716
734
descendants. into_iter ( ) . map ( move |it| self . token_ancestors_with_macros ( it) )
717
735
} )
0 commit comments