diff options
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r-- | crates/ide_completion/src/context.rs | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 9d761aa43..6dc6769df 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -25,9 +25,8 @@ use crate::{ | |||
25 | CompletionConfig, | 25 | CompletionConfig, |
26 | }; | 26 | }; |
27 | 27 | ||
28 | #[derive(Debug, PartialEq, Eq)] | 28 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
29 | pub(crate) enum IsPatOrConst { | 29 | pub(crate) enum PatternRefutability { |
30 | No, | ||
31 | Refutable, | 30 | Refutable, |
32 | Irrefutable, | 31 | Irrefutable, |
33 | } | 32 | } |
@@ -64,7 +63,7 @@ pub(crate) struct CompletionContext<'a> { | |||
64 | pub(super) is_label_ref: bool, | 63 | pub(super) is_label_ref: bool, |
65 | 64 | ||
66 | // potentially set if we are completing a name | 65 | // potentially set if we are completing a name |
67 | pub(super) is_pat_or_const: IsPatOrConst, | 66 | pub(super) is_pat_or_const: Option<PatternRefutability>, |
68 | pub(super) is_param: bool, | 67 | pub(super) is_param: bool, |
69 | 68 | ||
70 | /// FIXME: `ActiveParameter` is string-based, which is very very wrong | 69 | /// FIXME: `ActiveParameter` is string-based, which is very very wrong |
@@ -169,7 +168,7 @@ impl<'a> CompletionContext<'a> { | |||
169 | active_parameter: ActiveParameter::at(db, position), | 168 | active_parameter: ActiveParameter::at(db, position), |
170 | is_label_ref: false, | 169 | is_label_ref: false, |
171 | is_param: false, | 170 | is_param: false, |
172 | is_pat_or_const: IsPatOrConst::No, | 171 | is_pat_or_const: None, |
173 | is_trivial_path: false, | 172 | is_trivial_path: false, |
174 | path_qual: None, | 173 | path_qual: None, |
175 | after_if: false, | 174 | after_if: false, |
@@ -473,19 +472,13 @@ impl<'a> CompletionContext<'a> { | |||
473 | 472 | ||
474 | fn classify_name(&mut self, original_file: &SyntaxNode, name: ast::Name, offset: TextSize) { | 473 | fn classify_name(&mut self, original_file: &SyntaxNode, name: ast::Name, offset: TextSize) { |
475 | if let Some(bind_pat) = name.syntax().parent().and_then(ast::IdentPat::cast) { | 474 | if let Some(bind_pat) = name.syntax().parent().and_then(ast::IdentPat::cast) { |
476 | self.is_pat_or_const = IsPatOrConst::Refutable; | 475 | self.is_pat_or_const = Some(PatternRefutability::Refutable); |
477 | // if any of these is here our bind pat can't be a const pat anymore | 476 | // if any of these is here our bind pat can't be a const pat anymore |
478 | let complex_ident_pat = bind_pat.at_token().is_some() | 477 | let complex_ident_pat = bind_pat.at_token().is_some() |
479 | || bind_pat.ref_token().is_some() | 478 | || bind_pat.ref_token().is_some() |
480 | || bind_pat.mut_token().is_some(); | 479 | || bind_pat.mut_token().is_some(); |
481 | if complex_ident_pat { | 480 | if complex_ident_pat { |
482 | self.is_pat_or_const = IsPatOrConst::No; | 481 | self.is_pat_or_const = None; |
483 | } else if let Some(pat_field) = | ||
484 | bind_pat.syntax().parent().and_then(ast::RecordPatField::cast) | ||
485 | { | ||
486 | if pat_field.name_ref().is_none() { | ||
487 | self.is_pat_or_const = IsPatOrConst::No; | ||
488 | } | ||
489 | } else { | 482 | } else { |
490 | let irrefutable_pat = bind_pat.syntax().ancestors().find_map(|node| { | 483 | let irrefutable_pat = bind_pat.syntax().ancestors().find_map(|node| { |
491 | match_ast! { | 484 | match_ast! { |
@@ -499,19 +492,24 @@ impl<'a> CompletionContext<'a> { | |||
499 | if let Some(Some(pat)) = irrefutable_pat { | 492 | if let Some(Some(pat)) = irrefutable_pat { |
500 | // This check is here since we could be inside a pattern in the initializer expression of the let statement. | 493 | // This check is here since we could be inside a pattern in the initializer expression of the let statement. |
501 | if pat.syntax().text_range().contains_range(bind_pat.syntax().text_range()) { | 494 | if pat.syntax().text_range().contains_range(bind_pat.syntax().text_range()) { |
502 | self.is_pat_or_const = IsPatOrConst::Irrefutable; | 495 | self.is_pat_or_const = Some(PatternRefutability::Irrefutable); |
503 | } | 496 | } |
504 | } | 497 | } |
498 | |||
499 | let is_name_in_field_pat = bind_pat | ||
500 | .syntax() | ||
501 | .parent() | ||
502 | .and_then(ast::RecordPatField::cast) | ||
503 | .map_or(false, |pat_field| pat_field.name_ref().is_none()); | ||
504 | if is_name_in_field_pat { | ||
505 | self.is_pat_or_const = None; | ||
506 | } | ||
505 | } | 507 | } |
506 | 508 | ||
507 | self.fill_impl_def(); | 509 | self.fill_impl_def(); |
508 | } | 510 | } |
509 | if is_node::<ast::Param>(name.syntax()) { | 511 | self.is_param |= is_node::<ast::Param>(name.syntax()); |
510 | self.is_param = true; | 512 | if ast::RecordPatField::for_field_name(&name).is_some() { |
511 | return; | ||
512 | } | ||
513 | // FIXME: remove this (V) duplication and make the check more precise | ||
514 | if name.syntax().ancestors().find_map(ast::RecordPatFieldList::cast).is_some() { | ||
515 | self.record_pat_syntax = | 513 | self.record_pat_syntax = |
516 | self.sema.find_node_at_offset_with_macros(&original_file, offset); | 514 | self.sema.find_node_at_offset_with_macros(&original_file, offset); |
517 | } | 515 | } |
@@ -523,22 +521,20 @@ impl<'a> CompletionContext<'a> { | |||
523 | name_ref: ast::NameRef, | 521 | name_ref: ast::NameRef, |
524 | offset: TextSize, | 522 | offset: TextSize, |
525 | ) { | 523 | ) { |
526 | // FIXME: remove this (^) duplication and make the check more precise | 524 | self.fill_impl_def(); |
527 | if name_ref.syntax().ancestors().find_map(ast::RecordPatFieldList::cast).is_some() { | 525 | if ast::RecordExprField::for_field_name(&name_ref).is_some() { |
526 | self.record_lit_syntax = | ||
527 | self.sema.find_node_at_offset_with_macros(original_file, offset); | ||
528 | } | ||
529 | if ast::RecordPatField::for_field_name_ref(&name_ref).is_some() { | ||
528 | self.record_pat_syntax = | 530 | self.record_pat_syntax = |
529 | self.sema.find_node_at_offset_with_macros(&original_file, offset); | 531 | self.sema.find_node_at_offset_with_macros(&original_file, offset); |
530 | } | 532 | } |
531 | 533 | ||
532 | self.name_ref_syntax = | 534 | self.name_ref_syntax = |
533 | find_node_at_offset(original_file, name_ref.syntax().text_range().start()); | 535 | find_node_at_offset(original_file, name_ref.syntax().text_range().start()); |
534 | let name_range = name_ref.syntax().text_range(); | ||
535 | if ast::RecordExprField::for_field_name(&name_ref).is_some() { | ||
536 | self.record_lit_syntax = | ||
537 | self.sema.find_node_at_offset_with_macros(original_file, offset); | ||
538 | } | ||
539 | |||
540 | self.fill_impl_def(); | ||
541 | 536 | ||
537 | let name_range = name_ref.syntax().text_range(); | ||
542 | let top_node = name_ref | 538 | let top_node = name_ref |
543 | .syntax() | 539 | .syntax() |
544 | .ancestors() | 540 | .ancestors() |