aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/context.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-26 22:49:06 +0100
committerGitHub <[email protected]>2021-05-26 22:49:06 +0100
commit7624729d61ac6d810ed77ce6aaf5d3e5b82824fd (patch)
treede41505a55f5f962704658d37f53fb424dd538b5 /crates/ide_completion/src/context.rs
parentb4015b6aaa0dd80f5c85c7ed03e83d0d16042264 (diff)
parent1f897f7319da4852eac53ff765ed4e5b66a31b67 (diff)
Merge #9016
9016: Set `record_pat_syntax` more precisely in CompletionContext r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <[email protected]>
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r--crates/ide_completion/src/context.rs54
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)]
29pub(crate) enum IsPatOrConst { 29pub(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()