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-28 22:21:37 +0100
committerGitHub <[email protected]>2021-05-28 22:21:37 +0100
commit7869b01b702d1f12acb03ac131b6eb90ad82e9bb (patch)
treee6d76df5212db7589ef8dc6583b32d6c64871a33 /crates/ide_completion/src/context.rs
parentd5f7b2e52a41a7d3b841f4d0e2225eb703f6a50a (diff)
parente42c448077ca2b7675320da3c5294bf4bebaedeb (diff)
Merge #9041
9041: internal: Implement prev sibling determination for `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.rs49
1 files changed, 18 insertions, 31 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 923e35dbb..8d6440cb2 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -17,8 +17,8 @@ use text_edit::Indel;
17 17
18use crate::{ 18use crate::{
19 patterns::{ 19 patterns::{
20 determine_location, for_is_prev2, has_prev_sibling, inside_impl_trait_block, 20 determine_location, determine_prev_sibling, for_is_prev2, inside_impl_trait_block,
21 is_in_loop_body, is_match_arm, previous_token, ImmediateLocation, 21 is_in_loop_body, is_match_arm, previous_token, ImmediateLocation, ImmediatePrevSibling,
22 }, 22 },
23 CompletionConfig, 23 CompletionConfig,
24}; 24};
@@ -29,12 +29,6 @@ pub(crate) enum PatternRefutability {
29 Irrefutable, 29 Irrefutable,
30} 30}
31 31
32#[derive(Copy, Clone, Debug, PartialEq, Eq)]
33pub(crate) enum PrevSibling {
34 Trait,
35 Impl,
36}
37
38/// `CompletionContext` is created early during completion to figure out, where 32/// `CompletionContext` is created early during completion to figure out, where
39/// exactly is the cursor, syntax-wise. 33/// exactly is the cursor, syntax-wise.
40#[derive(Debug)] 34#[derive(Debug)]
@@ -76,6 +70,7 @@ pub(crate) struct CompletionContext<'a> {
76 pub(super) is_param: bool, 70 pub(super) is_param: bool,
77 71
78 pub(super) completion_location: Option<ImmediateLocation>, 72 pub(super) completion_location: Option<ImmediateLocation>,
73 pub(super) prev_sibling: Option<ImmediatePrevSibling>,
79 74
80 /// FIXME: `ActiveParameter` is string-based, which is very very wrong 75 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
81 pub(super) active_parameter: Option<ActiveParameter>, 76 pub(super) active_parameter: Option<ActiveParameter>,
@@ -83,7 +78,6 @@ pub(crate) struct CompletionContext<'a> {
83 pub(super) is_trivial_path: bool, 78 pub(super) is_trivial_path: bool,
84 /// If not a trivial path, the prefix (qualifier). 79 /// If not a trivial path, the prefix (qualifier).
85 pub(super) path_qual: Option<ast::Path>, 80 pub(super) path_qual: Option<ast::Path>,
86 pub(super) after_if: bool,
87 /// `true` if we are a statement or a last expr in the block. 81 /// `true` if we are a statement or a last expr in the block.
88 pub(super) can_be_stmt: bool, 82 pub(super) can_be_stmt: bool,
89 /// `true` if we expect an expression at the cursor position. 83 /// `true` if we expect an expression at the cursor position.
@@ -107,7 +101,6 @@ pub(crate) struct CompletionContext<'a> {
107 101
108 // keyword patterns 102 // keyword patterns
109 pub(super) previous_token: Option<SyntaxToken>, 103 pub(super) previous_token: Option<SyntaxToken>,
110 pub(super) prev_sibling: Option<PrevSibling>,
111 pub(super) in_loop_body: bool, 104 pub(super) in_loop_body: bool,
112 pub(super) is_match_arm: bool, 105 pub(super) is_match_arm: bool,
113 pub(super) incomplete_let: bool, 106 pub(super) incomplete_let: bool,
@@ -173,7 +166,6 @@ impl<'a> CompletionContext<'a> {
173 is_pat_or_const: None, 166 is_pat_or_const: None,
174 is_trivial_path: false, 167 is_trivial_path: false,
175 path_qual: None, 168 path_qual: None,
176 after_if: false,
177 can_be_stmt: false, 169 can_be_stmt: false,
178 is_expr: false, 170 is_expr: false,
179 is_new_item: false, 171 is_new_item: false,
@@ -288,6 +280,10 @@ impl<'a> CompletionContext<'a> {
288 matches!(self.completion_location, Some(ImmediateLocation::ItemList)) 280 matches!(self.completion_location, Some(ImmediateLocation::ItemList))
289 } 281 }
290 282
283 pub(crate) fn expects_expression(&self) -> bool {
284 self.is_expr
285 }
286
291 pub(crate) fn has_block_expr_parent(&self) -> bool { 287 pub(crate) fn has_block_expr_parent(&self) -> bool {
292 matches!(self.completion_location, Some(ImmediateLocation::BlockExpr)) 288 matches!(self.completion_location, Some(ImmediateLocation::BlockExpr))
293 } 289 }
@@ -304,7 +300,14 @@ impl<'a> CompletionContext<'a> {
304 } 300 }
305 301
306 pub(crate) fn has_impl_or_trait_prev_sibling(&self) -> bool { 302 pub(crate) fn has_impl_or_trait_prev_sibling(&self) -> bool {
307 self.prev_sibling.is_some() 303 matches!(
304 self.prev_sibling,
305 Some(ImmediatePrevSibling::ImplDefType) | Some(ImmediatePrevSibling::TraitDefName)
306 )
307 }
308
309 pub(crate) fn after_if(&self) -> bool {
310 matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr))
308 } 311 }
309 312
310 pub(crate) fn is_path_disallowed(&self) -> bool { 313 pub(crate) fn is_path_disallowed(&self) -> bool {
@@ -316,15 +319,10 @@ impl<'a> CompletionContext<'a> {
316 319
317 fn fill_keyword_patterns(&mut self, file_with_fake_ident: &SyntaxNode, offset: TextSize) { 320 fn fill_keyword_patterns(&mut self, file_with_fake_ident: &SyntaxNode, offset: TextSize) {
318 let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap(); 321 let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap();
319 let syntax_element = NodeOrToken::Token(fake_ident_token.clone()); 322 let syntax_element = NodeOrToken::Token(fake_ident_token);
320 self.previous_token = previous_token(syntax_element.clone()); 323 self.previous_token = previous_token(syntax_element.clone());
321 self.in_loop_body = is_in_loop_body(syntax_element.clone()); 324 self.in_loop_body = is_in_loop_body(syntax_element.clone());
322 self.is_match_arm = is_match_arm(syntax_element.clone()); 325 self.is_match_arm = is_match_arm(syntax_element.clone());
323 if has_prev_sibling(syntax_element.clone(), IMPL) {
324 self.prev_sibling = Some(PrevSibling::Impl)
325 } else if has_prev_sibling(syntax_element.clone(), TRAIT) {
326 self.prev_sibling = Some(PrevSibling::Trait)
327 }
328 326
329 self.mod_declaration_under_caret = 327 self.mod_declaration_under_caret =
330 find_node_at_offset::<ast::Module>(&file_with_fake_ident, offset) 328 find_node_at_offset::<ast::Module>(&file_with_fake_ident, offset)
@@ -338,8 +336,6 @@ impl<'a> CompletionContext<'a> {
338 let fn_is_prev = self.previous_token_is(T![fn]); 336 let fn_is_prev = self.previous_token_is(T![fn]);
339 let for_is_prev2 = for_is_prev2(syntax_element.clone()); 337 let for_is_prev2 = for_is_prev2(syntax_element.clone());
340 self.no_completion_required = (fn_is_prev && !inside_impl_trait_block) || for_is_prev2; 338 self.no_completion_required = (fn_is_prev && !inside_impl_trait_block) || for_is_prev2;
341
342 self.completion_location = determine_location(fake_ident_token);
343 } 339 }
344 340
345 fn fill_impl_def(&mut self) { 341 fn fill_impl_def(&mut self) {
@@ -465,6 +461,8 @@ impl<'a> CompletionContext<'a> {
465 Some(it) => it, 461 Some(it) => it,
466 None => return, 462 None => return,
467 }; 463 };
464 self.completion_location = determine_location(&name_like);
465 self.prev_sibling = determine_prev_sibling(&name_like);
468 match name_like { 466 match name_like {
469 ast::NameLike::Lifetime(lifetime) => { 467 ast::NameLike::Lifetime(lifetime) => {
470 self.classify_lifetime(original_file, lifetime, offset); 468 self.classify_lifetime(original_file, lifetime, offset);
@@ -653,17 +651,6 @@ impl<'a> CompletionContext<'a> {
653 }) 651 })
654 .unwrap_or(false); 652 .unwrap_or(false);
655 self.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some(); 653 self.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some();
656
657 if let Some(off) = name_ref.syntax().text_range().start().checked_sub(2.into()) {
658 if let Some(if_expr) =
659 self.sema.find_node_at_offset_with_macros::<ast::IfExpr>(original_file, off)
660 {
661 if if_expr.syntax().text_range().end() < name_ref.syntax().text_range().start()
662 {
663 self.after_if = true;
664 }
665 }
666 }
667 } 654 }
668 655
669 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { 656 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {