@@ -29,6 +29,28 @@ pub(crate) enum PatternRefutability {
29
29
Irrefutable ,
30
30
}
31
31
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
+ }
32
54
/// `CompletionContext` is created early during completion to figure out, where
33
55
/// exactly is the cursor, syntax-wise.
34
56
#[ derive( Debug ) ]
@@ -68,24 +90,9 @@ pub(crate) struct CompletionContext<'a> {
68
90
pub ( super ) prev_sibling : Option < ImmediatePrevSibling > ,
69
91
pub ( super ) attribute_under_caret : Option < ast:: Attr > ,
70
92
93
+ pub ( super ) path_context : Option < PathCompletionContext > ,
71
94
/// FIXME: `ActiveParameter` is string-based, which is very very wrong
72
95
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 ,
89
96
pub ( super ) locals : Vec < ( String , Local ) > ,
90
97
91
98
pub ( super ) previous_token : Option < SyntaxToken > ,
@@ -149,15 +156,7 @@ impl<'a> CompletionContext<'a> {
149
156
is_label_ref : false ,
150
157
is_param : false ,
151
158
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 ,
161
160
previous_token : None ,
162
161
in_loop_body : false ,
163
162
completion_location : None ,
@@ -250,14 +249,14 @@ impl<'a> CompletionContext<'a> {
250
249
pub ( crate ) fn has_dot_receiver ( & self ) -> bool {
251
250
matches ! (
252
251
& self . completion_location,
253
- Some ( ImmediateLocation :: FieldAccess { receiver, .. } ) | Some ( ImmediateLocation :: MethodCall { receiver } )
252
+ Some ( ImmediateLocation :: FieldAccess { receiver, .. } ) | Some ( ImmediateLocation :: MethodCall { receiver, .. } )
254
253
if receiver. is_some( )
255
254
)
256
255
}
257
256
258
257
pub ( crate ) fn dot_receiver ( & self ) -> Option < & ast:: Expr > {
259
258
match & self . completion_location {
260
- Some ( ImmediateLocation :: MethodCall { receiver } )
259
+ Some ( ImmediateLocation :: MethodCall { receiver, .. } )
261
260
| Some ( ImmediateLocation :: FieldAccess { receiver, .. } ) => receiver. as_ref ( ) ,
262
261
_ => None ,
263
262
}
@@ -275,11 +274,6 @@ impl<'a> CompletionContext<'a> {
275
274
matches ! ( self . completion_location, Some ( ImmediateLocation :: ItemList ) )
276
275
}
277
276
278
- // fn expects_value(&self) -> bool {
279
- pub ( crate ) fn expects_expression ( & self ) -> bool {
280
- self . is_expr
281
- }
282
-
283
277
pub ( crate ) fn has_block_expr_parent ( & self ) -> bool {
284
278
matches ! ( self . completion_location, Some ( ImmediateLocation :: BlockExpr ) )
285
279
}
@@ -316,6 +310,26 @@ impl<'a> CompletionContext<'a> {
316
310
) || self . attribute_under_caret . is_some ( )
317
311
}
318
312
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
+
319
333
fn fill_impl_def ( & mut self ) {
320
334
self . impl_def = self
321
335
. sema
@@ -568,22 +582,32 @@ impl<'a> CompletionContext<'a> {
568
582
} ;
569
583
570
584
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
+ } ) ;
571
594
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 ( ) ;
581
595
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 ( ) ;
584
608
585
609
if let Some ( path) = path_or_use_tree_qualifier ( & path) {
586
- self . path_qual = path
610
+ path_ctx . path_qual = path
587
611
. segment ( )
588
612
. and_then ( |it| {
589
613
find_node_with_range :: < ast:: PathSegment > (
@@ -601,11 +625,11 @@ impl<'a> CompletionContext<'a> {
601
625
}
602
626
}
603
627
604
- self . is_trivial_path = true ;
628
+ path_ctx . is_trivial_path = true ;
605
629
606
630
// Find either enclosing expr statement (thing with `;`) or a
607
631
// 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
609
633
. syntax ( )
610
634
. ancestors ( )
611
635
. find_map ( |node| {
@@ -621,10 +645,8 @@ impl<'a> CompletionContext<'a> {
621
645
None
622
646
} )
623
647
. 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 ( ) ;
625
649
}
626
- self . is_call |=
627
- matches ! ( self . completion_location, Some ( ImmediateLocation :: MethodCall { .. } ) ) ;
628
650
}
629
651
}
630
652
0 commit comments