diff options
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r-- | crates/ide_completion/src/context.rs | 34 |
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(); |