diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-28 22:21:37 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-05-28 22:21:37 +0100 |
commit | 7869b01b702d1f12acb03ac131b6eb90ad82e9bb (patch) | |
tree | e6d76df5212db7589ef8dc6583b32d6c64871a33 /crates/ide_completion/src/context.rs | |
parent | d5f7b2e52a41a7d3b841f4d0e2225eb703f6a50a (diff) | |
parent | e42c448077ca2b7675320da3c5294bf4bebaedeb (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.rs | 49 |
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 | ||
18 | use crate::{ | 18 | use 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)] | ||
33 | pub(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()) { |