@@ -29,6 +29,28 @@ pub(crate) enum PatternRefutability {
2929 Irrefutable ,
3030}
3131
32+ #[ derive( Debug ) ]
33+ pub ( crate ) struct PathCompletionContext {
34+ /// If this is a call with () already there
35+ call_kind : Option < CallKind > ,
36+ /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
37+ pub ( super ) is_trivial_path : bool ,
38+ /// If not a trivial path, the prefix (qualifier).
39+ pub ( super ) path_qual : Option < ast:: Path > ,
40+ pub ( super ) is_path_type : bool ,
41+ pub ( super ) has_type_args : bool ,
42+ /// `true` if we are a statement or a last expr in the block.
43+ pub ( super ) can_be_stmt : bool ,
44+ /// `true` if we expect an expression at the cursor position.
45+ pub ( super ) is_expr : bool ,
46+ }
47+
48+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
49+ pub ( crate ) enum CallKind {
50+ Pat ,
51+ Mac ,
52+ Expr ,
53+ }
3254/// `CompletionContext` is created early during completion to figure out, where
3355/// exactly is the cursor, syntax-wise.
3456#[ derive( Debug ) ]
@@ -68,24 +90,9 @@ pub(crate) struct CompletionContext<'a> {
6890 pub ( super ) prev_sibling : Option < ImmediatePrevSibling > ,
6991 pub ( super ) attribute_under_caret : Option < ast:: Attr > ,
7092
93+ pub ( super ) path_context : Option < PathCompletionContext > ,
7194 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
7295 pub ( super ) active_parameter : Option < ActiveParameter > ,
73- /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
74- pub ( super ) is_trivial_path : bool ,
75- /// If not a trivial path, the prefix (qualifier).
76- pub ( super ) path_qual : Option < ast:: Path > ,
77- /// `true` if we are a statement or a last expr in the block.
78- pub ( super ) can_be_stmt : bool ,
79- /// `true` if we expect an expression at the cursor position.
80- pub ( super ) is_expr : bool ,
81- /// If this is a call (method or function) in particular, i.e. the () are already there.
82- pub ( super ) is_call : bool ,
83- /// Like `is_call`, but for tuple patterns.
84- pub ( super ) is_pattern_call : bool ,
85- /// If this is a macro call, i.e. the () are already there.
86- pub ( super ) is_macro_call : bool ,
87- pub ( super ) is_path_type : bool ,
88- pub ( super ) has_type_args : bool ,
8996 pub ( super ) locals : Vec < ( String , Local ) > ,
9097
9198 pub ( super ) previous_token : Option < SyntaxToken > ,
@@ -149,15 +156,7 @@ impl<'a> CompletionContext<'a> {
149156 is_label_ref : false ,
150157 is_param : false ,
151158 is_pat_or_const : None ,
152- is_trivial_path : false ,
153- path_qual : None ,
154- can_be_stmt : false ,
155- is_expr : false ,
156- is_call : false ,
157- is_pattern_call : false ,
158- is_macro_call : false ,
159- is_path_type : false ,
160- has_type_args : false ,
159+ path_context : None ,
161160 previous_token : None ,
162161 in_loop_body : false ,
163162 completion_location : None ,
@@ -250,14 +249,14 @@ impl<'a> CompletionContext<'a> {
250249 pub ( crate ) fn has_dot_receiver ( & self ) -> bool {
251250 matches ! (
252251 & self . completion_location,
253- Some ( ImmediateLocation :: FieldAccess { receiver, .. } ) | Some ( ImmediateLocation :: MethodCall { receiver } )
252+ Some ( ImmediateLocation :: FieldAccess { receiver, .. } ) | Some ( ImmediateLocation :: MethodCall { receiver, .. } )
254253 if receiver. is_some( )
255254 )
256255 }
257256
258257 pub ( crate ) fn dot_receiver ( & self ) -> Option < & ast:: Expr > {
259258 match & self . completion_location {
260- Some ( ImmediateLocation :: MethodCall { receiver } )
259+ Some ( ImmediateLocation :: MethodCall { receiver, .. } )
261260 | Some ( ImmediateLocation :: FieldAccess { receiver, .. } ) => receiver. as_ref ( ) ,
262261 _ => None ,
263262 }
@@ -275,11 +274,6 @@ impl<'a> CompletionContext<'a> {
275274 matches ! ( self . completion_location, Some ( ImmediateLocation :: ItemList ) )
276275 }
277276
278- // fn expects_value(&self) -> bool {
279- pub ( crate ) fn expects_expression ( & self ) -> bool {
280- self . is_expr
281- }
282-
283277 pub ( crate ) fn has_block_expr_parent ( & self ) -> bool {
284278 matches ! ( self . completion_location, Some ( ImmediateLocation :: BlockExpr ) )
285279 }
@@ -316,6 +310,26 @@ impl<'a> CompletionContext<'a> {
316310 ) || self . attribute_under_caret . is_some ( )
317311 }
318312
313+ pub ( crate ) fn expects_expression ( & self ) -> bool {
314+ self . path_context . as_ref ( ) . map_or ( false , |it| it. is_expr )
315+ }
316+
317+ pub ( crate ) fn path_call_kind ( & self ) -> Option < CallKind > {
318+ self . path_context . as_ref ( ) . and_then ( |it| it. call_kind )
319+ }
320+
321+ pub ( crate ) fn is_trivial_path ( & self ) -> bool {
322+ self . path_context . as_ref ( ) . map_or ( false , |it| it. is_trivial_path )
323+ }
324+
325+ pub ( crate ) fn path_qual ( & self ) -> Option < & ast:: Path > {
326+ self . path_context . as_ref ( ) . and_then ( |it| it. path_qual . as_ref ( ) )
327+ }
328+
329+ pub ( crate ) fn can_be_stmt ( & self ) -> bool {
330+ self . path_context . as_ref ( ) . map_or ( false , |it| it. can_be_stmt )
331+ }
332+
319333 fn fill_impl_def ( & mut self ) {
320334 self . impl_def = self
321335 . sema
@@ -568,22 +582,32 @@ impl<'a> CompletionContext<'a> {
568582 } ;
569583
570584 if let Some ( segment) = ast:: PathSegment :: cast ( parent) {
585+ let path_ctx = self . path_context . get_or_insert ( PathCompletionContext {
586+ call_kind : None ,
587+ is_trivial_path : false ,
588+ path_qual : None ,
589+ has_type_args : false ,
590+ is_path_type : false ,
591+ can_be_stmt : false ,
592+ is_expr : false ,
593+ } ) ;
571594 let path = segment. parent_path ( ) ;
572- self . is_call = path
573- . syntax ( )
574- . parent ( )
575- . and_then ( ast:: PathExpr :: cast)
576- . and_then ( |it| it. syntax ( ) . parent ( ) . and_then ( ast:: CallExpr :: cast) )
577- . is_some ( ) ;
578- self . is_macro_call = path. syntax ( ) . parent ( ) . and_then ( ast:: MacroCall :: cast) . is_some ( ) ;
579- self . is_pattern_call =
580- path. syntax ( ) . parent ( ) . and_then ( ast:: TupleStructPat :: cast) . is_some ( ) ;
581595
582- self . is_path_type = path. syntax ( ) . parent ( ) . and_then ( ast:: PathType :: cast) . is_some ( ) ;
583- self . has_type_args = segment. generic_arg_list ( ) . is_some ( ) ;
596+ if let Some ( p) = path. syntax ( ) . parent ( ) {
597+ path_ctx. call_kind = match_ast ! {
598+ match p {
599+ ast:: PathExpr ( it) => it. syntax( ) . parent( ) . and_then( ast:: CallExpr :: cast) . map( |_| CallKind :: Expr ) ,
600+ ast:: MacroCall ( _it) => Some ( CallKind :: Mac ) ,
601+ ast:: TupleStructPat ( _it) => Some ( CallKind :: Pat ) ,
602+ _ => None
603+ }
604+ } ;
605+ }
606+ path_ctx. is_path_type = path. syntax ( ) . parent ( ) . and_then ( ast:: PathType :: cast) . is_some ( ) ;
607+ path_ctx. has_type_args = segment. generic_arg_list ( ) . is_some ( ) ;
584608
585609 if let Some ( path) = path_or_use_tree_qualifier ( & path) {
586- self . path_qual = path
610+ path_ctx . path_qual = path
587611 . segment ( )
588612 . and_then ( |it| {
589613 find_node_with_range :: < ast:: PathSegment > (
@@ -601,11 +625,11 @@ impl<'a> CompletionContext<'a> {
601625 }
602626 }
603627
604- self . is_trivial_path = true ;
628+ path_ctx . is_trivial_path = true ;
605629
606630 // Find either enclosing expr statement (thing with `;`) or a
607631 // block. If block, check that we are the last expr.
608- self . can_be_stmt = name_ref
632+ path_ctx . can_be_stmt = name_ref
609633 . syntax ( )
610634 . ancestors ( )
611635 . find_map ( |node| {
@@ -621,10 +645,8 @@ impl<'a> CompletionContext<'a> {
621645 None
622646 } )
623647 . unwrap_or ( false ) ;
624- self . is_expr = path. syntax ( ) . parent ( ) . and_then ( ast:: PathExpr :: cast) . is_some ( ) ;
648+ path_ctx . is_expr = path. syntax ( ) . parent ( ) . and_then ( ast:: PathExpr :: cast) . is_some ( ) ;
625649 }
626- self . is_call |=
627- matches ! ( self . completion_location, Some ( ImmediateLocation :: MethodCall { .. } ) ) ;
628650 }
629651}
630652
0 commit comments