@@ -38,12 +38,15 @@ pub(crate) struct CompletionContext<'a> {
3838 pub ( super ) expected_name : Option < String > ,
3939 pub ( super ) expected_type : Option < Type > ,
4040 pub ( super ) name_ref_syntax : Option < ast:: NameRef > ,
41+ pub ( super ) lifetime_syntax : Option < ast:: Lifetime > ,
42+ pub ( super ) lifetime_param_syntax : Option < ast:: LifetimeParam > ,
4143 pub ( super ) function_syntax : Option < ast:: Fn > ,
4244 pub ( super ) use_item_syntax : Option < ast:: Use > ,
4345 pub ( super ) record_lit_syntax : Option < ast:: RecordExpr > ,
4446 pub ( super ) record_pat_syntax : Option < ast:: RecordPat > ,
4547 pub ( super ) record_field_syntax : Option < ast:: RecordExprField > ,
4648 pub ( super ) impl_def : Option < ast:: Impl > ,
49+ pub ( super ) lifetime_allowed : bool ,
4750 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
4851 pub ( super ) active_parameter : Option < ActiveParameter > ,
4952 pub ( super ) is_param : bool ,
@@ -136,9 +139,12 @@ impl<'a> CompletionContext<'a> {
136139 original_token,
137140 token,
138141 krate,
142+ lifetime_allowed : false ,
139143 expected_name : None ,
140144 expected_type : None ,
141145 name_ref_syntax : None ,
146+ lifetime_syntax : None ,
147+ lifetime_param_syntax : None ,
142148 function_syntax : None ,
143149 use_item_syntax : None ,
144150 record_lit_syntax : None ,
@@ -241,7 +247,7 @@ impl<'a> CompletionContext<'a> {
241247 pub ( crate ) fn source_range ( & self ) -> TextRange {
242248 // check kind of macro-expanded token, but use range of original token
243249 let kind = self . token . kind ( ) ;
244- if kind == IDENT || kind == UNDERSCORE || kind. is_keyword ( ) {
250+ if kind == IDENT || kind == LIFETIME_IDENT || kind == UNDERSCORE || kind. is_keyword ( ) {
245251 cov_mark:: hit!( completes_if_prefix_is_keyword) ;
246252 self . original_token . text_range ( )
247253 } else {
@@ -386,6 +392,11 @@ impl<'a> CompletionContext<'a> {
386392 self . expected_name = expected. 1 ;
387393 self . attribute_under_caret = find_node_at_offset ( & file_with_fake_ident, offset) ;
388394
395+ if let Some ( lifetime) = find_node_at_offset :: < ast:: Lifetime > ( & file_with_fake_ident, offset)
396+ {
397+ self . classify_lifetime ( original_file, lifetime, offset) ;
398+ }
399+
389400 // First, let's try to complete a reference to some declaration.
390401 if let Some ( name_ref) = find_node_at_offset :: < ast:: NameRef > ( & file_with_fake_ident, offset) {
391402 // Special case, `trait T { fn foo(i_am_a_name_ref) {} }`.
@@ -445,18 +456,35 @@ impl<'a> CompletionContext<'a> {
445456 }
446457 }
447458
459+ fn classify_lifetime (
460+ & mut self ,
461+ original_file : & SyntaxNode ,
462+ lifetime : ast:: Lifetime ,
463+ offset : TextSize ,
464+ ) {
465+ self . lifetime_syntax =
466+ find_node_at_offset ( original_file, lifetime. syntax ( ) . text_range ( ) . start ( ) ) ;
467+ if lifetime. syntax ( ) . parent ( ) . map_or ( false , |p| p. kind ( ) != syntax:: SyntaxKind :: ERROR ) {
468+ self . lifetime_allowed = true ;
469+ }
470+ if let Some ( _) = lifetime. syntax ( ) . parent ( ) . and_then ( ast:: LifetimeParam :: cast) {
471+ self . lifetime_param_syntax =
472+ self . sema . find_node_at_offset_with_macros ( original_file, offset) ;
473+ }
474+ }
475+
448476 fn classify_name_ref (
449477 & mut self ,
450478 original_file : & SyntaxNode ,
451479 name_ref : ast:: NameRef ,
452480 offset : TextSize ,
453481 ) {
454482 self . name_ref_syntax =
455- find_node_at_offset ( & original_file, name_ref. syntax ( ) . text_range ( ) . start ( ) ) ;
483+ find_node_at_offset ( original_file, name_ref. syntax ( ) . text_range ( ) . start ( ) ) ;
456484 let name_range = name_ref. syntax ( ) . text_range ( ) ;
457485 if ast:: RecordExprField :: for_field_name ( & name_ref) . is_some ( ) {
458486 self . record_lit_syntax =
459- self . sema . find_node_at_offset_with_macros ( & original_file, offset) ;
487+ self . sema . find_node_at_offset_with_macros ( original_file, offset) ;
460488 }
461489
462490 self . fill_impl_def ( ) ;
0 commit comments