diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-30 20:37:29 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-05-30 20:37:29 +0100 |
commit | 92b9e5ef3c03d51713ff5fa32cd58bdf97701b5e (patch) | |
tree | 8e9cd674d600cfff5d9523c7a017456742ba444c /crates/ide_completion/src/context.rs | |
parent | 088b67079675af3d559dd3572520e3dc62d982ee (diff) | |
parent | 5660408f0a5b62bcc31258678e65078378109c94 (diff) |
Merge #9068
9068: Move more `CompletinoContext` fields to `ImmediateLocation` 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 | 99 |
1 files changed, 35 insertions, 64 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 8d6440cb2..7c46c815d 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -18,7 +18,7 @@ use text_edit::Indel; | |||
18 | use crate::{ | 18 | use crate::{ |
19 | patterns::{ | 19 | patterns::{ |
20 | determine_location, determine_prev_sibling, for_is_prev2, 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, ImmediatePrevSibling, | 21 | is_in_loop_body, previous_token, ImmediateLocation, ImmediatePrevSibling, |
22 | }, | 22 | }, |
23 | CompletionConfig, | 23 | CompletionConfig, |
24 | }; | 24 | }; |
@@ -54,11 +54,6 @@ pub(crate) struct CompletionContext<'a> { | |||
54 | /// The parent impl of the cursor position if it exists. | 54 | /// The parent impl of the cursor position if it exists. |
55 | pub(super) impl_def: Option<ast::Impl>, | 55 | pub(super) impl_def: Option<ast::Impl>, |
56 | 56 | ||
57 | /// RecordExpr the token is a field of | ||
58 | pub(super) record_lit_syntax: Option<ast::RecordExpr>, | ||
59 | /// RecordPat the token is a field of | ||
60 | pub(super) record_pat_syntax: Option<ast::RecordPat>, | ||
61 | |||
62 | // potentially set if we are completing a lifetime | 57 | // potentially set if we are completing a lifetime |
63 | pub(super) lifetime_syntax: Option<ast::Lifetime>, | 58 | pub(super) lifetime_syntax: Option<ast::Lifetime>, |
64 | pub(super) lifetime_param_syntax: Option<ast::LifetimeParam>, | 59 | pub(super) lifetime_param_syntax: Option<ast::LifetimeParam>, |
@@ -71,6 +66,7 @@ pub(crate) struct CompletionContext<'a> { | |||
71 | 66 | ||
72 | pub(super) completion_location: Option<ImmediateLocation>, | 67 | pub(super) completion_location: Option<ImmediateLocation>, |
73 | pub(super) prev_sibling: Option<ImmediatePrevSibling>, | 68 | pub(super) prev_sibling: Option<ImmediatePrevSibling>, |
69 | pub(super) attribute_under_caret: Option<ast::Attr>, | ||
74 | 70 | ||
75 | /// FIXME: `ActiveParameter` is string-based, which is very very wrong | 71 | /// FIXME: `ActiveParameter` is string-based, which is very very wrong |
76 | pub(super) active_parameter: Option<ActiveParameter>, | 72 | pub(super) active_parameter: Option<ActiveParameter>, |
@@ -95,14 +91,10 @@ pub(crate) struct CompletionContext<'a> { | |||
95 | pub(super) is_macro_call: bool, | 91 | pub(super) is_macro_call: bool, |
96 | pub(super) is_path_type: bool, | 92 | pub(super) is_path_type: bool, |
97 | pub(super) has_type_args: bool, | 93 | pub(super) has_type_args: bool, |
98 | pub(super) attribute_under_caret: Option<ast::Attr>, | ||
99 | pub(super) mod_declaration_under_caret: Option<ast::Module>, | ||
100 | pub(super) locals: Vec<(String, Local)>, | 94 | pub(super) locals: Vec<(String, Local)>, |
101 | 95 | ||
102 | // keyword patterns | ||
103 | pub(super) previous_token: Option<SyntaxToken>, | 96 | pub(super) previous_token: Option<SyntaxToken>, |
104 | pub(super) in_loop_body: bool, | 97 | pub(super) in_loop_body: bool, |
105 | pub(super) is_match_arm: bool, | ||
106 | pub(super) incomplete_let: bool, | 98 | pub(super) incomplete_let: bool, |
107 | 99 | ||
108 | no_completion_required: bool, | 100 | no_completion_required: bool, |
@@ -157,8 +149,6 @@ impl<'a> CompletionContext<'a> { | |||
157 | lifetime_param_syntax: None, | 149 | lifetime_param_syntax: None, |
158 | function_def: None, | 150 | function_def: None, |
159 | use_item_syntax: None, | 151 | use_item_syntax: None, |
160 | record_lit_syntax: None, | ||
161 | record_pat_syntax: None, | ||
162 | impl_def: None, | 152 | impl_def: None, |
163 | active_parameter: ActiveParameter::at(db, position), | 153 | active_parameter: ActiveParameter::at(db, position), |
164 | is_label_ref: false, | 154 | is_label_ref: false, |
@@ -176,15 +166,13 @@ impl<'a> CompletionContext<'a> { | |||
176 | is_macro_call: false, | 166 | is_macro_call: false, |
177 | is_path_type: false, | 167 | is_path_type: false, |
178 | has_type_args: false, | 168 | has_type_args: false, |
179 | attribute_under_caret: None, | ||
180 | mod_declaration_under_caret: None, | ||
181 | previous_token: None, | 169 | previous_token: None, |
182 | in_loop_body: false, | 170 | in_loop_body: false, |
183 | completion_location: None, | 171 | completion_location: None, |
184 | prev_sibling: None, | 172 | prev_sibling: None, |
185 | is_match_arm: false, | ||
186 | no_completion_required: false, | 173 | no_completion_required: false, |
187 | incomplete_let: false, | 174 | incomplete_let: false, |
175 | attribute_under_caret: None, | ||
188 | locals, | 176 | locals, |
189 | }; | 177 | }; |
190 | 178 | ||
@@ -227,7 +215,6 @@ impl<'a> CompletionContext<'a> { | |||
227 | break; | 215 | break; |
228 | } | 216 | } |
229 | } | 217 | } |
230 | ctx.fill_keyword_patterns(&speculative_file, offset); | ||
231 | ctx.fill(&original_file, speculative_file, offset); | 218 | ctx.fill(&original_file, speculative_file, offset); |
232 | Some(ctx) | 219 | Some(ctx) |
233 | } | 220 | } |
@@ -311,31 +298,13 @@ impl<'a> CompletionContext<'a> { | |||
311 | } | 298 | } |
312 | 299 | ||
313 | pub(crate) fn is_path_disallowed(&self) -> bool { | 300 | pub(crate) fn is_path_disallowed(&self) -> bool { |
314 | self.record_lit_syntax.is_some() | 301 | matches!( |
315 | || self.record_pat_syntax.is_some() | 302 | self.completion_location, |
316 | || self.attribute_under_caret.is_some() | 303 | Some(ImmediateLocation::Attribute(_)) |
317 | || self.mod_declaration_under_caret.is_some() | 304 | | Some(ImmediateLocation::ModDeclaration(_)) |
318 | } | 305 | | Some(ImmediateLocation::RecordPat(_)) |
319 | 306 | | Some(ImmediateLocation::RecordExpr(_)) | |
320 | fn fill_keyword_patterns(&mut self, file_with_fake_ident: &SyntaxNode, offset: TextSize) { | 307 | ) || self.attribute_under_caret.is_some() |
321 | let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap(); | ||
322 | let syntax_element = NodeOrToken::Token(fake_ident_token); | ||
323 | self.previous_token = previous_token(syntax_element.clone()); | ||
324 | self.in_loop_body = is_in_loop_body(syntax_element.clone()); | ||
325 | self.is_match_arm = is_match_arm(syntax_element.clone()); | ||
326 | |||
327 | self.mod_declaration_under_caret = | ||
328 | find_node_at_offset::<ast::Module>(&file_with_fake_ident, offset) | ||
329 | .filter(|module| module.item_list().is_none()); | ||
330 | self.incomplete_let = | ||
331 | syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| { | ||
332 | it.syntax().text_range().end() == syntax_element.text_range().end() | ||
333 | }); | ||
334 | |||
335 | let inside_impl_trait_block = inside_impl_trait_block(syntax_element.clone()); | ||
336 | let fn_is_prev = self.previous_token_is(T![fn]); | ||
337 | let for_is_prev2 = for_is_prev2(syntax_element.clone()); | ||
338 | self.no_completion_required = (fn_is_prev && !inside_impl_trait_block) || for_is_prev2; | ||
339 | } | 308 | } |
340 | 309 | ||
341 | fn fill_impl_def(&mut self) { | 310 | fn fill_impl_def(&mut self) { |
@@ -453,25 +422,43 @@ impl<'a> CompletionContext<'a> { | |||
453 | file_with_fake_ident: SyntaxNode, | 422 | file_with_fake_ident: SyntaxNode, |
454 | offset: TextSize, | 423 | offset: TextSize, |
455 | ) { | 424 | ) { |
425 | let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap(); | ||
426 | let syntax_element = NodeOrToken::Token(fake_ident_token); | ||
427 | self.previous_token = previous_token(syntax_element.clone()); | ||
428 | self.attribute_under_caret = syntax_element.ancestors().find_map(ast::Attr::cast); | ||
429 | self.no_completion_required = { | ||
430 | let inside_impl_trait_block = inside_impl_trait_block(syntax_element.clone()); | ||
431 | let fn_is_prev = self.previous_token_is(T![fn]); | ||
432 | let for_is_prev2 = for_is_prev2(syntax_element.clone()); | ||
433 | (fn_is_prev && !inside_impl_trait_block) || for_is_prev2 | ||
434 | }; | ||
435 | self.in_loop_body = is_in_loop_body(syntax_element.clone()); | ||
436 | |||
437 | self.incomplete_let = | ||
438 | syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| { | ||
439 | it.syntax().text_range().end() == syntax_element.text_range().end() | ||
440 | }); | ||
441 | |||
456 | let (expected_type, expected_name) = self.expected_type_and_name(); | 442 | let (expected_type, expected_name) = self.expected_type_and_name(); |
457 | self.expected_type = expected_type; | 443 | self.expected_type = expected_type; |
458 | self.expected_name = expected_name; | 444 | self.expected_name = expected_name; |
459 | self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); | 445 | |
460 | let name_like = match find_node_at_offset(&&file_with_fake_ident, offset) { | 446 | let name_like = match find_node_at_offset(&&file_with_fake_ident, offset) { |
461 | Some(it) => it, | 447 | Some(it) => it, |
462 | None => return, | 448 | None => return, |
463 | }; | 449 | }; |
464 | self.completion_location = determine_location(&name_like); | 450 | self.completion_location = |
451 | determine_location(&self.sema, original_file, offset, &name_like); | ||
465 | self.prev_sibling = determine_prev_sibling(&name_like); | 452 | self.prev_sibling = determine_prev_sibling(&name_like); |
466 | match name_like { | 453 | match name_like { |
467 | ast::NameLike::Lifetime(lifetime) => { | 454 | ast::NameLike::Lifetime(lifetime) => { |
468 | self.classify_lifetime(original_file, lifetime, offset); | 455 | self.classify_lifetime(original_file, lifetime, offset); |
469 | } | 456 | } |
470 | ast::NameLike::NameRef(name_ref) => { | 457 | ast::NameLike::NameRef(name_ref) => { |
471 | self.classify_name_ref(original_file, name_ref, offset); | 458 | self.classify_name_ref(original_file, name_ref); |
472 | } | 459 | } |
473 | ast::NameLike::Name(name) => { | 460 | ast::NameLike::Name(name) => { |
474 | self.classify_name(original_file, name, offset); | 461 | self.classify_name(name); |
475 | } | 462 | } |
476 | } | 463 | } |
477 | } | 464 | } |
@@ -505,7 +492,7 @@ impl<'a> CompletionContext<'a> { | |||
505 | } | 492 | } |
506 | } | 493 | } |
507 | 494 | ||
508 | fn classify_name(&mut self, original_file: &SyntaxNode, name: ast::Name, offset: TextSize) { | 495 | fn classify_name(&mut self, name: ast::Name) { |
509 | if let Some(bind_pat) = name.syntax().parent().and_then(ast::IdentPat::cast) { | 496 | if let Some(bind_pat) = name.syntax().parent().and_then(ast::IdentPat::cast) { |
510 | self.is_pat_or_const = Some(PatternRefutability::Refutable); | 497 | self.is_pat_or_const = Some(PatternRefutability::Refutable); |
511 | // if any of these is here our bind pat can't be a const pat anymore | 498 | // if any of these is here our bind pat can't be a const pat anymore |
@@ -543,28 +530,12 @@ impl<'a> CompletionContext<'a> { | |||
543 | 530 | ||
544 | self.fill_impl_def(); | 531 | self.fill_impl_def(); |
545 | } | 532 | } |
533 | |||
546 | self.is_param |= is_node::<ast::Param>(name.syntax()); | 534 | self.is_param |= is_node::<ast::Param>(name.syntax()); |
547 | if ast::RecordPatField::for_field_name(&name).is_some() { | ||
548 | self.record_pat_syntax = | ||
549 | self.sema.find_node_at_offset_with_macros(&original_file, offset); | ||
550 | } | ||
551 | } | 535 | } |
552 | 536 | ||
553 | fn classify_name_ref( | 537 | fn classify_name_ref(&mut self, original_file: &SyntaxNode, name_ref: ast::NameRef) { |
554 | &mut self, | ||
555 | original_file: &SyntaxNode, | ||
556 | name_ref: ast::NameRef, | ||
557 | offset: TextSize, | ||
558 | ) { | ||
559 | self.fill_impl_def(); | 538 | self.fill_impl_def(); |
560 | if ast::RecordExprField::for_field_name(&name_ref).is_some() { | ||
561 | self.record_lit_syntax = | ||
562 | self.sema.find_node_at_offset_with_macros(original_file, offset); | ||
563 | } | ||
564 | if ast::RecordPatField::for_field_name_ref(&name_ref).is_some() { | ||
565 | self.record_pat_syntax = | ||
566 | self.sema.find_node_at_offset_with_macros(&original_file, offset); | ||
567 | } | ||
568 | 539 | ||
569 | self.name_ref_syntax = | 540 | self.name_ref_syntax = |
570 | find_node_at_offset(original_file, name_ref.syntax().text_range().start()); | 541 | find_node_at_offset(original_file, name_ref.syntax().text_range().start()); |