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 6d57da06a..3c31de9ad 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -38,12 +38,15 @@ pub(crate) struct CompletionContext<'a> { | |||
38 | pub(super) expected_name: Option<String>, | 38 | pub(super) expected_name: Option<String>, |
39 | pub(super) expected_type: Option<Type>, | 39 | pub(super) expected_type: Option<Type>, |
40 | pub(super) name_ref_syntax: Option<ast::NameRef>, | 40 | 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>, | ||
41 | pub(super) function_syntax: Option<ast::Fn>, | 43 | pub(super) function_syntax: Option<ast::Fn>, |
42 | pub(super) use_item_syntax: Option<ast::Use>, | 44 | pub(super) use_item_syntax: Option<ast::Use>, |
43 | pub(super) record_lit_syntax: Option<ast::RecordExpr>, | 45 | pub(super) record_lit_syntax: Option<ast::RecordExpr>, |
44 | pub(super) record_pat_syntax: Option<ast::RecordPat>, | 46 | pub(super) record_pat_syntax: Option<ast::RecordPat>, |
45 | pub(super) record_field_syntax: Option<ast::RecordExprField>, | 47 | pub(super) record_field_syntax: Option<ast::RecordExprField>, |
46 | pub(super) impl_def: Option<ast::Impl>, | 48 | pub(super) impl_def: Option<ast::Impl>, |
49 | pub(super) lifetime_allowed: bool, | ||
47 | /// FIXME: `ActiveParameter` is string-based, which is very very wrong | 50 | /// FIXME: `ActiveParameter` is string-based, which is very very wrong |
48 | pub(super) active_parameter: Option<ActiveParameter>, | 51 | pub(super) active_parameter: Option<ActiveParameter>, |
49 | pub(super) is_param: bool, | 52 | pub(super) is_param: bool, |
@@ -136,9 +139,12 @@ impl<'a> CompletionContext<'a> { | |||
136 | original_token, | 139 | original_token, |
137 | token, | 140 | token, |
138 | krate, | 141 | krate, |
142 | lifetime_allowed: false, | ||
139 | expected_name: None, | 143 | expected_name: None, |
140 | expected_type: None, | 144 | expected_type: None, |
141 | name_ref_syntax: None, | 145 | name_ref_syntax: None, |
146 | lifetime_syntax: None, | ||
147 | lifetime_param_syntax: None, | ||
142 | function_syntax: None, | 148 | function_syntax: None, |
143 | use_item_syntax: None, | 149 | use_item_syntax: None, |
144 | record_lit_syntax: None, | 150 | record_lit_syntax: None, |
@@ -241,7 +247,7 @@ impl<'a> CompletionContext<'a> { | |||
241 | pub(crate) fn source_range(&self) -> TextRange { | 247 | pub(crate) fn source_range(&self) -> TextRange { |
242 | // check kind of macro-expanded token, but use range of original token | 248 | // check kind of macro-expanded token, but use range of original token |
243 | let kind = self.token.kind(); | 249 | 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() { |
245 | cov_mark::hit!(completes_if_prefix_is_keyword); | 251 | cov_mark::hit!(completes_if_prefix_is_keyword); |
246 | self.original_token.text_range() | 252 | self.original_token.text_range() |
247 | } else { | 253 | } else { |
@@ -386,6 +392,11 @@ impl<'a> CompletionContext<'a> { | |||
386 | self.expected_name = expected.1; | 392 | self.expected_name = expected.1; |
387 | self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); | 393 | self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); |
388 | 394 | ||
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 | |||
389 | // First, let's try to complete a reference to some declaration. | 400 | // First, let's try to complete a reference to some declaration. |
390 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&file_with_fake_ident, offset) { | 401 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&file_with_fake_ident, offset) { |
391 | // Special case, `trait T { fn foo(i_am_a_name_ref) {} }`. | 402 | // Special case, `trait T { fn foo(i_am_a_name_ref) {} }`. |
@@ -445,6 +456,23 @@ impl<'a> CompletionContext<'a> { | |||
445 | } | 456 | } |
446 | } | 457 | } |
447 | 458 | ||
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 | |||
448 | fn classify_name_ref( | 476 | fn classify_name_ref( |
449 | &mut self, | 477 | &mut self, |
450 | original_file: &SyntaxNode, | 478 | original_file: &SyntaxNode, |
@@ -452,11 +480,11 @@ impl<'a> CompletionContext<'a> { | |||
452 | offset: TextSize, | 480 | offset: TextSize, |
453 | ) { | 481 | ) { |
454 | self.name_ref_syntax = | 482 | 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()); |
456 | let name_range = name_ref.syntax().text_range(); | 484 | let name_range = name_ref.syntax().text_range(); |
457 | if ast::RecordExprField::for_field_name(&name_ref).is_some() { | 485 | if ast::RecordExprField::for_field_name(&name_ref).is_some() { |
458 | self.record_lit_syntax = | 486 | 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); |
460 | } | 488 | } |
461 | 489 | ||
462 | self.fill_impl_def(); | 490 | self.fill_impl_def(); |