@@ -54,6 +54,12 @@ pub(crate) struct PathCompletionContext {
5454 pub ( super ) in_loop_body : bool ,
5555}
5656
57+ #[ derive( Debug ) ]
58+ pub ( super ) struct PatternContext {
59+ pub ( super ) refutability : PatternRefutability ,
60+ pub ( super ) is_param : Option < ParamKind > ,
61+ }
62+
5763#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
5864pub ( crate ) enum CallKind {
5965 Pat ,
@@ -95,15 +101,12 @@ pub(crate) struct CompletionContext<'a> {
95101 pub ( super ) lifetime_allowed : bool ,
96102 pub ( super ) is_label_ref : bool ,
97103
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-
102104 pub ( super ) completion_location : Option < ImmediateLocation > ,
103105 pub ( super ) prev_sibling : Option < ImmediatePrevSibling > ,
104106 pub ( super ) attribute_under_caret : Option < ast:: Attr > ,
105107 pub ( super ) previous_token : Option < SyntaxToken > ,
106108
109+ pub ( super ) pattern_ctx : Option < PatternContext > ,
107110 pub ( super ) path_context : Option < PathCompletionContext > ,
108111 pub ( super ) active_parameter : Option < ActiveParameter > ,
109112 pub ( super ) locals : Vec < ( String , Local ) > ,
@@ -163,8 +166,7 @@ impl<'a> CompletionContext<'a> {
163166 lifetime_param_syntax : None ,
164167 lifetime_allowed : false ,
165168 is_label_ref : false ,
166- is_pat_or_const : None ,
167- is_param : None ,
169+ pattern_ctx : None ,
168170 completion_location : None ,
169171 prev_sibling : None ,
170172 attribute_under_caret : None ,
@@ -642,50 +644,51 @@ impl<'a> CompletionContext<'a> {
642644 }
643645
644646 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 ( ) ;
665648
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
667661 . 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 } ) ;
674691 }
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 } ) ;
689692 }
690693 }
691694
0 commit comments