aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r--crates/ide_completion/src/context.rs34
1 files changed, 31 insertions, 3 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index a60b8b09d..4c2b31084 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -41,12 +41,15 @@ pub(crate) struct CompletionContext<'a> {
41 pub(super) expected_name: Option<NameOrNameRef>, 41 pub(super) expected_name: Option<NameOrNameRef>,
42 pub(super) expected_type: Option<Type>, 42 pub(super) expected_type: Option<Type>,
43 pub(super) name_ref_syntax: Option<ast::NameRef>, 43 pub(super) name_ref_syntax: Option<ast::NameRef>,
44 pub(super) lifetime_syntax: Option<ast::Lifetime>,
45 pub(super) lifetime_param_syntax: Option<ast::LifetimeParam>,
44 pub(super) function_syntax: Option<ast::Fn>, 46 pub(super) function_syntax: Option<ast::Fn>,
45 pub(super) use_item_syntax: Option<ast::Use>, 47 pub(super) use_item_syntax: Option<ast::Use>,
46 pub(super) record_lit_syntax: Option<ast::RecordExpr>, 48 pub(super) record_lit_syntax: Option<ast::RecordExpr>,
47 pub(super) record_pat_syntax: Option<ast::RecordPat>, 49 pub(super) record_pat_syntax: Option<ast::RecordPat>,
48 pub(super) record_field_syntax: Option<ast::RecordExprField>, 50 pub(super) record_field_syntax: Option<ast::RecordExprField>,
49 pub(super) impl_def: Option<ast::Impl>, 51 pub(super) impl_def: Option<ast::Impl>,
52 pub(super) lifetime_allowed: bool,
50 /// FIXME: `ActiveParameter` is string-based, which is very very wrong 53 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
51 pub(super) active_parameter: Option<ActiveParameter>, 54 pub(super) active_parameter: Option<ActiveParameter>,
52 pub(super) is_param: bool, 55 pub(super) is_param: bool,
@@ -139,9 +142,12 @@ impl<'a> CompletionContext<'a> {
139 original_token, 142 original_token,
140 token, 143 token,
141 krate, 144 krate,
145 lifetime_allowed: false,
142 expected_name: None, 146 expected_name: None,
143 expected_type: None, 147 expected_type: None,
144 name_ref_syntax: None, 148 name_ref_syntax: None,
149 lifetime_syntax: None,
150 lifetime_param_syntax: None,
145 function_syntax: None, 151 function_syntax: None,
146 use_item_syntax: None, 152 use_item_syntax: None,
147 record_lit_syntax: None, 153 record_lit_syntax: None,
@@ -244,7 +250,7 @@ impl<'a> CompletionContext<'a> {
244 pub(crate) fn source_range(&self) -> TextRange { 250 pub(crate) fn source_range(&self) -> TextRange {
245 // check kind of macro-expanded token, but use range of original token 251 // check kind of macro-expanded token, but use range of original token
246 let kind = self.token.kind(); 252 let kind = self.token.kind();
247 if kind == IDENT || kind == UNDERSCORE || kind.is_keyword() { 253 if kind == IDENT || kind == LIFETIME_IDENT || kind == UNDERSCORE || kind.is_keyword() {
248 cov_mark::hit!(completes_if_prefix_is_keyword); 254 cov_mark::hit!(completes_if_prefix_is_keyword);
249 self.original_token.text_range() 255 self.original_token.text_range()
250 } else { 256 } else {
@@ -390,6 +396,11 @@ impl<'a> CompletionContext<'a> {
390 self.expected_name = expected_name; 396 self.expected_name = expected_name;
391 self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); 397 self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset);
392 398
399 if let Some(lifetime) = find_node_at_offset::<ast::Lifetime>(&file_with_fake_ident, offset)
400 {
401 self.classify_lifetime(original_file, lifetime, offset);
402 }
403
393 // First, let's try to complete a reference to some declaration. 404 // First, let's try to complete a reference to some declaration.
394 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&file_with_fake_ident, offset) { 405 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&file_with_fake_ident, offset) {
395 // Special case, `trait T { fn foo(i_am_a_name_ref) {} }`. 406 // Special case, `trait T { fn foo(i_am_a_name_ref) {} }`.
@@ -449,6 +460,23 @@ impl<'a> CompletionContext<'a> {
449 } 460 }
450 } 461 }
451 462
463 fn classify_lifetime(
464 &mut self,
465 original_file: &SyntaxNode,
466 lifetime: ast::Lifetime,
467 offset: TextSize,
468 ) {
469 self.lifetime_syntax =
470 find_node_at_offset(original_file, lifetime.syntax().text_range().start());
471 if lifetime.syntax().parent().map_or(false, |p| p.kind() != syntax::SyntaxKind::ERROR) {
472 self.lifetime_allowed = true;
473 }
474 if let Some(_) = lifetime.syntax().parent().and_then(ast::LifetimeParam::cast) {
475 self.lifetime_param_syntax =
476 self.sema.find_node_at_offset_with_macros(original_file, offset);
477 }
478 }
479
452 fn classify_name_ref( 480 fn classify_name_ref(
453 &mut self, 481 &mut self,
454 original_file: &SyntaxNode, 482 original_file: &SyntaxNode,
@@ -456,11 +484,11 @@ impl<'a> CompletionContext<'a> {
456 offset: TextSize, 484 offset: TextSize,
457 ) { 485 ) {
458 self.name_ref_syntax = 486 self.name_ref_syntax =
459 find_node_at_offset(&original_file, name_ref.syntax().text_range().start()); 487 find_node_at_offset(original_file, name_ref.syntax().text_range().start());
460 let name_range = name_ref.syntax().text_range(); 488 let name_range = name_ref.syntax().text_range();
461 if ast::RecordExprField::for_field_name(&name_ref).is_some() { 489 if ast::RecordExprField::for_field_name(&name_ref).is_some() {
462 self.record_lit_syntax = 490 self.record_lit_syntax =
463 self.sema.find_node_at_offset_with_macros(&original_file, offset); 491 self.sema.find_node_at_offset_with_macros(original_file, offset);
464 } 492 }
465 493
466 self.fill_impl_def(); 494 self.fill_impl_def();