Skip to content

Commit 6d8b7ab

Browse files
bors[bot]Veykril
andauthored
Merge #9018
9018: Collapse more CompletionContext booleans into enums r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents d6ed315 + dfe3a0d commit 6d8b7ab

File tree

6 files changed

+140
-114
lines changed

6 files changed

+140
-114
lines changed

crates/ide_completion/src/completions/flyimport.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
114114
|| ctx.attribute_under_caret.is_some()
115115
|| ctx.mod_declaration_under_caret.is_some()
116116
|| ctx.record_lit_syntax.is_some()
117-
|| ctx.has_trait_parent
118-
|| ctx.has_impl_parent
117+
|| ctx.has_impl_or_trait_parent()
119118
{
120119
return None;
121120
}

crates/ide_completion/src/completions/keyword.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,34 +49,35 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
4949
return;
5050
}
5151

52-
let has_trait_or_impl_parent = ctx.has_impl_parent || ctx.has_trait_parent;
53-
if ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling {
52+
let has_trait_or_impl_parent = ctx.has_impl_or_trait_parent();
53+
let has_block_expr_parent = ctx.has_block_expr_parent();
54+
let has_item_list_parent = ctx.has_item_list_parent();
55+
if ctx.has_impl_or_trait_prev_sibling() {
5456
add_keyword(ctx, acc, "where", "where ");
5557
return;
5658
}
5759
if ctx.previous_token_is(T![unsafe]) {
58-
if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent {
60+
if has_item_list_parent || has_block_expr_parent {
5961
add_keyword(ctx, acc, "fn", "fn $1($2) {\n $0\n}")
6062
}
6163

62-
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
64+
if has_item_list_parent || has_block_expr_parent {
6365
add_keyword(ctx, acc, "trait", "trait $1 {\n $0\n}");
6466
add_keyword(ctx, acc, "impl", "impl $1 {\n $0\n}");
6567
}
6668

6769
return;
6870
}
69-
if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent
70-
{
71+
if has_item_list_parent || has_trait_or_impl_parent || has_block_expr_parent {
7172
add_keyword(ctx, acc, "fn", "fn $1($2) {\n $0\n}");
7273
}
73-
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
74+
if has_item_list_parent || has_block_expr_parent {
7475
add_keyword(ctx, acc, "use", "use ");
7576
add_keyword(ctx, acc, "impl", "impl $1 {\n $0\n}");
7677
add_keyword(ctx, acc, "trait", "trait $1 {\n $0\n}");
7778
}
7879

79-
if ctx.has_item_list_or_source_file_parent {
80+
if has_item_list_parent {
8081
add_keyword(ctx, acc, "enum", "enum $1 {\n $0\n}");
8182
add_keyword(ctx, acc, "struct", "struct $0");
8283
add_keyword(ctx, acc, "union", "union $1 {\n $0\n}");
@@ -92,35 +93,31 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
9293
add_keyword(ctx, acc, "for", "for $1 in $2 {\n $0\n}");
9394
}
9495

95-
if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || ctx.block_expr_parent {
96+
if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || has_block_expr_parent {
9697
add_keyword(ctx, acc, "let", "let ");
9798
}
9899

99100
if ctx.after_if {
100101
add_keyword(ctx, acc, "else", "else {\n $0\n}");
101102
add_keyword(ctx, acc, "else if", "else if $1 {\n $0\n}");
102103
}
103-
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
104+
if has_item_list_parent || has_block_expr_parent {
104105
add_keyword(ctx, acc, "mod", "mod $0");
105106
}
106-
if ctx.bind_pat_parent || ctx.ref_pat_parent {
107+
if ctx.has_ident_or_ref_pat_parent() {
107108
add_keyword(ctx, acc, "mut", "mut ");
108109
}
109-
if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent
110-
{
110+
if has_item_list_parent || has_trait_or_impl_parent || has_block_expr_parent {
111111
add_keyword(ctx, acc, "const", "const ");
112112
add_keyword(ctx, acc, "type", "type ");
113113
}
114-
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
114+
if has_item_list_parent || has_block_expr_parent {
115115
add_keyword(ctx, acc, "static", "static ");
116116
};
117-
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
117+
if has_item_list_parent || has_block_expr_parent {
118118
add_keyword(ctx, acc, "extern", "extern ");
119119
}
120-
if ctx.has_item_list_or_source_file_parent
121-
|| has_trait_or_impl_parent
122-
|| ctx.block_expr_parent
123-
|| ctx.is_match_arm
120+
if has_item_list_parent || has_trait_or_impl_parent || has_block_expr_parent || ctx.is_match_arm
124121
{
125122
add_keyword(ctx, acc, "unsafe", "unsafe ");
126123
}
@@ -133,15 +130,15 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
133130
add_keyword(ctx, acc, "break", "break");
134131
}
135132
}
136-
if ctx.has_item_list_or_source_file_parent || ctx.has_impl_parent | ctx.has_field_list_parent {
133+
if has_item_list_parent || ctx.has_impl_parent() || ctx.has_field_list_parent() {
137134
add_keyword(ctx, acc, "pub(crate)", "pub(crate) ");
138135
add_keyword(ctx, acc, "pub", "pub ");
139136
}
140137

141138
if !ctx.is_trivial_path {
142139
return;
143140
}
144-
let fn_def = match &ctx.function_syntax {
141+
let fn_def = match &ctx.function_def {
145142
Some(it) => it,
146143
None => return,
147144
};

crates/ide_completion/src/completions/snippet.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str)
1414
}
1515

1616
pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
17-
if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) {
17+
if !(ctx.is_trivial_path && ctx.function_def.is_some()) {
1818
return;
1919
}
2020
let cap = match ctx.config.snippet_cap {

crates/ide_completion/src/completions/unqualified_path.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
1313
|| ctx.record_pat_syntax.is_some()
1414
|| ctx.attribute_under_caret.is_some()
1515
|| ctx.mod_declaration_under_caret.is_some()
16-
|| ctx.has_impl_parent
17-
|| ctx.has_trait_parent
16+
|| ctx.has_impl_or_trait_parent()
1817
{
1918
return;
2019
}

crates/ide_completion/src/context.rs

Lines changed: 96 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ use text_edit::Indel;
1818
use crate::{
1919
patterns::{
2020
for_is_prev2, has_bind_pat_parent, has_block_expr_parent, has_field_list_parent,
21-
has_impl_as_prev_sibling, has_impl_parent, has_item_list_or_source_file_parent,
22-
has_ref_parent, has_trait_as_prev_sibling, has_trait_parent, inside_impl_trait_block,
23-
is_in_loop_body, is_match_arm, previous_token,
21+
has_impl_parent, has_item_list_or_source_file_parent, has_prev_sibling, has_ref_parent,
22+
has_trait_parent, inside_impl_trait_block, is_in_loop_body, is_match_arm, previous_token,
2423
},
2524
CompletionConfig,
2625
};
@@ -31,6 +30,24 @@ pub(crate) enum PatternRefutability {
3130
Irrefutable,
3231
}
3332

33+
/// Direct parent container of the cursor position
34+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
35+
pub(crate) enum ImmediateLocation {
36+
Impl,
37+
Trait,
38+
RecordFieldList,
39+
RefPatOrExpr,
40+
IdentPat,
41+
BlockExpr,
42+
ItemList,
43+
}
44+
45+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
46+
pub(crate) enum PrevSibling {
47+
Trait,
48+
Impl,
49+
}
50+
3451
/// `CompletionContext` is created early during completion to figure out, where
3552
/// exactly is the cursor, syntax-wise.
3653
#[derive(Debug)]
@@ -48,14 +65,19 @@ pub(crate) struct CompletionContext<'a> {
4865
pub(super) expected_name: Option<NameOrNameRef>,
4966
pub(super) expected_type: Option<Type>,
5067
pub(super) name_ref_syntax: Option<ast::NameRef>,
51-
pub(super) function_syntax: Option<ast::Fn>,
68+
5269
pub(super) use_item_syntax: Option<ast::Use>,
53-
pub(super) record_lit_syntax: Option<ast::RecordExpr>,
54-
pub(super) record_pat_syntax: Option<ast::RecordPat>,
55-
pub(super) record_field_syntax: Option<ast::RecordExprField>,
70+
71+
/// The parent function of the cursor position if it exists.
72+
pub(super) function_def: Option<ast::Fn>,
5673
/// The parent impl of the cursor position if it exists.
5774
pub(super) impl_def: Option<ast::Impl>,
5875

76+
/// RecordExpr the token is a field of
77+
pub(super) record_lit_syntax: Option<ast::RecordExpr>,
78+
/// RecordPat the token is a field of
79+
pub(super) record_pat_syntax: Option<ast::RecordPat>,
80+
5981
// potentially set if we are completing a lifetime
6082
pub(super) lifetime_syntax: Option<ast::Lifetime>,
6183
pub(super) lifetime_param_syntax: Option<ast::LifetimeParam>,
@@ -66,6 +88,8 @@ pub(crate) struct CompletionContext<'a> {
6688
pub(super) is_pat_or_const: Option<PatternRefutability>,
6789
pub(super) is_param: bool,
6890

91+
pub(super) completion_location: Option<ImmediateLocation>,
92+
6993
/// FIXME: `ActiveParameter` is string-based, which is very very wrong
7094
pub(super) active_parameter: Option<ActiveParameter>,
7195
/// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
@@ -94,20 +118,12 @@ pub(crate) struct CompletionContext<'a> {
94118
pub(super) locals: Vec<(String, Local)>,
95119

96120
pub(super) mod_declaration_under_caret: Option<ast::Module>,
97-
pub(super) has_trait_parent: bool,
98-
pub(super) has_impl_parent: bool,
99121

100122
// keyword patterns
101123
pub(super) previous_token: Option<SyntaxToken>,
102-
pub(super) block_expr_parent: bool,
103-
pub(super) bind_pat_parent: bool,
104-
pub(super) ref_pat_parent: bool,
105124
pub(super) in_loop_body: bool,
106-
pub(super) has_field_list_parent: bool,
107-
pub(super) trait_as_prev_sibling: bool,
108-
pub(super) impl_as_prev_sibling: bool,
125+
pub(super) prev_sibling: Option<PrevSibling>,
109126
pub(super) is_match_arm: bool,
110-
pub(super) has_item_list_or_source_file_parent: bool,
111127
pub(super) incomplete_let: bool,
112128

113129
no_completion_required: bool,
@@ -159,11 +175,10 @@ impl<'a> CompletionContext<'a> {
159175
name_ref_syntax: None,
160176
lifetime_syntax: None,
161177
lifetime_param_syntax: None,
162-
function_syntax: None,
178+
function_def: None,
163179
use_item_syntax: None,
164180
record_lit_syntax: None,
165181
record_pat_syntax: None,
166-
record_field_syntax: None,
167182
impl_def: None,
168183
active_parameter: ActiveParameter::at(db, position),
169184
is_label_ref: false,
@@ -185,17 +200,10 @@ impl<'a> CompletionContext<'a> {
185200
attribute_under_caret: None,
186201
mod_declaration_under_caret: None,
187202
previous_token: None,
188-
block_expr_parent: false,
189-
bind_pat_parent: false,
190-
ref_pat_parent: false,
191203
in_loop_body: false,
192-
has_trait_parent: false,
193-
has_impl_parent: false,
194-
has_field_list_parent: false,
195-
trait_as_prev_sibling: false,
196-
impl_as_prev_sibling: false,
204+
completion_location: None,
205+
prev_sibling: None,
197206
is_match_arm: false,
198-
has_item_list_or_source_file_parent: false,
199207
no_completion_required: false,
200208
incomplete_let: false,
201209
locals,
@@ -274,23 +282,68 @@ impl<'a> CompletionContext<'a> {
274282
self.previous_token.as_ref().map_or(false, |tok| tok.kind() == kind)
275283
}
276284

285+
pub(crate) fn has_impl_or_trait_parent(&self) -> bool {
286+
matches!(
287+
self.completion_location,
288+
Some(ImmediateLocation::Trait) | Some(ImmediateLocation::Impl)
289+
)
290+
}
291+
292+
pub(crate) fn has_block_expr_parent(&self) -> bool {
293+
matches!(self.completion_location, Some(ImmediateLocation::BlockExpr))
294+
}
295+
296+
pub(crate) fn has_item_list_parent(&self) -> bool {
297+
matches!(self.completion_location, Some(ImmediateLocation::ItemList))
298+
}
299+
300+
pub(crate) fn has_ident_or_ref_pat_parent(&self) -> bool {
301+
matches!(
302+
self.completion_location,
303+
Some(ImmediateLocation::IdentPat) | Some(ImmediateLocation::RefPatOrExpr)
304+
)
305+
}
306+
307+
pub(crate) fn has_impl_parent(&self) -> bool {
308+
matches!(self.completion_location, Some(ImmediateLocation::Impl))
309+
}
310+
311+
pub(crate) fn has_field_list_parent(&self) -> bool {
312+
matches!(self.completion_location, Some(ImmediateLocation::RecordFieldList))
313+
}
314+
315+
pub(crate) fn has_impl_or_trait_prev_sibling(&self) -> bool {
316+
self.prev_sibling.is_some()
317+
}
318+
277319
fn fill_keyword_patterns(&mut self, file_with_fake_ident: &SyntaxNode, offset: TextSize) {
278320
let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap();
279321
let syntax_element = NodeOrToken::Token(fake_ident_token);
280322
self.previous_token = previous_token(syntax_element.clone());
281-
self.block_expr_parent = has_block_expr_parent(syntax_element.clone());
282-
self.bind_pat_parent = has_bind_pat_parent(syntax_element.clone());
283-
self.ref_pat_parent = has_ref_parent(syntax_element.clone());
284323
self.in_loop_body = is_in_loop_body(syntax_element.clone());
285-
self.has_trait_parent = has_trait_parent(syntax_element.clone());
286-
self.has_impl_parent = has_impl_parent(syntax_element.clone());
287-
self.has_field_list_parent = has_field_list_parent(syntax_element.clone());
288-
self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone());
289-
self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone());
290324
self.is_match_arm = is_match_arm(syntax_element.clone());
325+
if has_prev_sibling(syntax_element.clone(), IMPL) {
326+
self.prev_sibling = Some(PrevSibling::Impl)
327+
} else if has_prev_sibling(syntax_element.clone(), TRAIT) {
328+
self.prev_sibling = Some(PrevSibling::Trait)
329+
}
330+
331+
if has_block_expr_parent(syntax_element.clone()) {
332+
self.completion_location = Some(ImmediateLocation::BlockExpr);
333+
} else if has_bind_pat_parent(syntax_element.clone()) {
334+
self.completion_location = Some(ImmediateLocation::IdentPat);
335+
} else if has_ref_parent(syntax_element.clone()) {
336+
self.completion_location = Some(ImmediateLocation::RefPatOrExpr);
337+
} else if has_impl_parent(syntax_element.clone()) {
338+
self.completion_location = Some(ImmediateLocation::Impl);
339+
} else if has_field_list_parent(syntax_element.clone()) {
340+
self.completion_location = Some(ImmediateLocation::RecordFieldList);
341+
} else if has_trait_parent(syntax_element.clone()) {
342+
self.completion_location = Some(ImmediateLocation::Trait);
343+
} else if has_item_list_or_source_file_parent(syntax_element.clone()) {
344+
self.completion_location = Some(ImmediateLocation::ItemList);
345+
}
291346

292-
self.has_item_list_or_source_file_parent =
293-
has_item_list_or_source_file_parent(syntax_element.clone());
294347
self.mod_declaration_under_caret =
295348
find_node_at_offset::<ast::Module>(&file_with_fake_ident, offset)
296349
.filter(|module| module.item_list().is_none());
@@ -542,31 +595,20 @@ impl<'a> CompletionContext<'a> {
542595
.last()
543596
.unwrap();
544597

545-
match top_node.parent().map(|it| it.kind()) {
546-
Some(SOURCE_FILE) | Some(ITEM_LIST) => {
547-
self.is_new_item = true;
548-
return;
549-
}
550-
_ => (),
598+
if matches!(top_node.parent().map(|it| it.kind()), Some(SOURCE_FILE) | Some(ITEM_LIST)) {
599+
self.is_new_item = true;
600+
return;
551601
}
552602

553603
self.use_item_syntax =
554604
self.sema.token_ancestors_with_macros(self.token.clone()).find_map(ast::Use::cast);
555605

556-
self.function_syntax = self
606+
self.function_def = self
557607
.sema
558608
.token_ancestors_with_macros(self.token.clone())
559609
.take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
560610
.find_map(ast::Fn::cast);
561611

562-
self.record_field_syntax = self
563-
.sema
564-
.token_ancestors_with_macros(self.token.clone())
565-
.take_while(|it| {
566-
it.kind() != SOURCE_FILE && it.kind() != MODULE && it.kind() != CALL_EXPR
567-
})
568-
.find_map(ast::RecordExprField::cast);
569-
570612
let parent = match name_ref.syntax().parent() {
571613
Some(it) => it,
572614
None => return,
@@ -639,6 +681,7 @@ impl<'a> CompletionContext<'a> {
639681
}
640682
}
641683
}
684+
642685
if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
643686
// The receiver comes before the point of insertion of the fake
644687
// ident, so it should have the same range in the non-modified file
@@ -656,6 +699,7 @@ impl<'a> CompletionContext<'a> {
656699
false
657700
};
658701
}
702+
659703
if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) {
660704
// As above
661705
self.dot_receiver = method_call_expr

0 commit comments

Comments
 (0)