@@ -54,6 +54,12 @@ pub(crate) struct PathCompletionContext {
54
54
pub ( super ) in_loop_body : bool ,
55
55
}
56
56
57
+ #[ derive( Debug ) ]
58
+ pub ( super ) struct PatternContext {
59
+ pub ( super ) refutability : PatternRefutability ,
60
+ pub ( super ) is_param : Option < ParamKind > ,
61
+ }
62
+
57
63
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
58
64
pub ( crate ) enum CallKind {
59
65
Pat ,
@@ -95,15 +101,12 @@ pub(crate) struct CompletionContext<'a> {
95
101
pub ( super ) lifetime_allowed : bool ,
96
102
pub ( super ) is_label_ref : bool ,
97
103
98
- // potentially set if we are completing a name
99
- pub ( super ) is_pat_or_const : Option < PatternRefutability > ,
100
- pub ( super ) is_param : Option < ParamKind > ,
101
-
102
104
pub ( super ) completion_location : Option < ImmediateLocation > ,
103
105
pub ( super ) prev_sibling : Option < ImmediatePrevSibling > ,
104
106
pub ( super ) attribute_under_caret : Option < ast:: Attr > ,
105
107
pub ( super ) previous_token : Option < SyntaxToken > ,
106
108
109
+ pub ( super ) pattern_ctx : Option < PatternContext > ,
107
110
pub ( super ) path_context : Option < PathCompletionContext > ,
108
111
pub ( super ) active_parameter : Option < ActiveParameter > ,
109
112
pub ( super ) locals : Vec < ( String , Local ) > ,
@@ -163,8 +166,7 @@ impl<'a> CompletionContext<'a> {
163
166
lifetime_param_syntax : None ,
164
167
lifetime_allowed : false ,
165
168
is_label_ref : false ,
166
- is_pat_or_const : None ,
167
- is_param : None ,
169
+ pattern_ctx : None ,
168
170
completion_location : None ,
169
171
prev_sibling : None ,
170
172
attribute_under_caret : None ,
@@ -642,50 +644,51 @@ impl<'a> CompletionContext<'a> {
642
644
}
643
645
644
646
fn classify_name ( & mut self , name : ast:: Name ) {
645
- if let Some ( bind_pat) = name. syntax ( ) . parent ( ) . and_then ( ast:: IdentPat :: cast) {
646
- self . is_pat_or_const = Some ( PatternRefutability :: Refutable ) ;
647
- if !bind_pat. is_simple_ident ( ) {
648
- self . is_pat_or_const = None ;
649
- } else {
650
- let irrefutable_pat = bind_pat. syntax ( ) . ancestors ( ) . find_map ( |node| {
651
- match_ast ! {
652
- match node {
653
- ast:: LetStmt ( it) => Some ( it. pat( ) ) ,
654
- ast:: Param ( it) => Some ( it. pat( ) ) ,
655
- _ => None ,
656
- }
657
- }
658
- } ) ;
659
- if let Some ( Some ( pat) ) = irrefutable_pat {
660
- // This check is here since we could be inside a pattern in the initializer expression of the let statement.
661
- if pat. syntax ( ) . text_range ( ) . contains_range ( bind_pat. syntax ( ) . text_range ( ) ) {
662
- self . is_pat_or_const = Some ( PatternRefutability :: Irrefutable ) ;
663
- }
664
- }
647
+ self . fill_impl_def ( ) ;
665
648
666
- let is_name_in_field_pat = bind_pat
649
+ if let Some ( bind_pat) = name. syntax ( ) . parent ( ) . and_then ( ast:: IdentPat :: cast) {
650
+ let is_name_in_field_pat = bind_pat
651
+ . syntax ( )
652
+ . parent ( )
653
+ . and_then ( ast:: RecordPatField :: cast)
654
+ . map_or ( false , |pat_field| pat_field. name_ref ( ) . is_none ( ) ) ;
655
+ if is_name_in_field_pat {
656
+ return ;
657
+ }
658
+ if bind_pat. is_simple_ident ( ) {
659
+ let mut is_param = None ;
660
+ let refutability = bind_pat
667
661
. syntax ( )
668
- . parent ( )
669
- . and_then ( ast:: RecordPatField :: cast)
670
- . map_or ( false , |pat_field| pat_field. name_ref ( ) . is_none ( ) ) ;
671
- if is_name_in_field_pat {
672
- self . is_pat_or_const = None ;
673
- }
662
+ . ancestors ( )
663
+ . skip_while ( |it| ast:: Pat :: can_cast ( it. kind ( ) ) )
664
+ . next ( )
665
+ . map_or ( PatternRefutability :: Irrefutable , |node| {
666
+ match_ast ! {
667
+ match node {
668
+ ast:: LetStmt ( __) => PatternRefutability :: Irrefutable ,
669
+ ast:: Param ( param) => {
670
+ let is_closure_param = param
671
+ . syntax( )
672
+ . ancestors( )
673
+ . nth( 2 )
674
+ . and_then( ast:: ClosureExpr :: cast)
675
+ . is_some( ) ;
676
+ is_param = Some ( if is_closure_param {
677
+ ParamKind :: Closure
678
+ } else {
679
+ ParamKind :: Function
680
+ } ) ;
681
+ PatternRefutability :: Irrefutable
682
+ } ,
683
+ ast:: MatchArm ( __) => PatternRefutability :: Refutable ,
684
+ ast:: Condition ( __) => PatternRefutability :: Refutable ,
685
+ ast:: ForExpr ( __) => PatternRefutability :: Irrefutable ,
686
+ _ => PatternRefutability :: Irrefutable ,
687
+ }
688
+ }
689
+ } ) ;
690
+ self . pattern_ctx = Some ( PatternContext { refutability, is_param } ) ;
674
691
}
675
-
676
- self . fill_impl_def ( ) ;
677
- }
678
-
679
- if let Some ( param) = name
680
- . syntax ( )
681
- . ancestors ( )
682
- . find_map ( ast:: Param :: cast)
683
- . filter ( |it| it. syntax ( ) . text_range ( ) == name. syntax ( ) . text_range ( ) )
684
- {
685
- let is_closure_param =
686
- param. syntax ( ) . ancestors ( ) . nth ( 2 ) . and_then ( ast:: ClosureExpr :: cast) . is_some ( ) ;
687
- self . is_param =
688
- Some ( if is_closure_param { ParamKind :: Closure } else { ParamKind :: Function } ) ;
689
692
}
690
693
}
691
694
0 commit comments