Skip to content

Commit 9138d39

Browse files
committed
Clean up completion matching.
- Add test to ensure nested completions don't happen
1 parent 7c43935 commit 9138d39

File tree

1 file changed

+53
-24
lines changed

1 file changed

+53
-24
lines changed

crates/ra_ide/src/completion/complete_trait_impl.rs

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
use hir::{self, Docs, HasSource};
3535
use ra_assists::utils::get_missing_impl_items;
3636
use ra_syntax::{
37-
ast::{self, edit},
37+
ast::{self, edit, ImplDef},
3838
AstNode, SyntaxKind, SyntaxNode, TextRange,
3939
};
4040
use ra_text_edit::TextEdit;
@@ -47,29 +47,7 @@ use crate::{
4747
};
4848

4949
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
50-
let mut tokens = ctx.token.ancestors();
51-
let completion_match = tokens
52-
.find(|p| match p.kind() {
53-
SyntaxKind::FN_DEF
54-
| SyntaxKind::TYPE_ALIAS_DEF
55-
| SyntaxKind::CONST_DEF
56-
| SyntaxKind::NAME_REF
57-
| SyntaxKind::BLOCK_EXPR => true,
58-
_ => false,
59-
})
60-
.and_then(|trigger| {
61-
for p in tokens {
62-
match p.kind() {
63-
// No nested completions
64-
SyntaxKind::FN_DEF | SyntaxKind::BLOCK => return None,
65-
SyntaxKind::IMPL_DEF => return ast::ImplDef::cast(p).map(|p| (trigger, p)),
66-
_ => {}
67-
}
68-
}
69-
None
70-
});
71-
72-
if let Some((trigger, impl_def)) = completion_match {
50+
if let Some((trigger, impl_def)) = completion_match(ctx) {
7351
match trigger.kind() {
7452
SyntaxKind::NAME_REF => {
7553
get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item {
@@ -123,6 +101,36 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
123101
}
124102
}
125103

104+
fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, ImplDef)> {
105+
let (trigger_idx, trigger) =
106+
ctx.token.ancestors().enumerate().find(|(_idx, p)| match p.kind() {
107+
SyntaxKind::FN_DEF
108+
| SyntaxKind::TYPE_ALIAS_DEF
109+
| SyntaxKind::CONST_DEF
110+
| SyntaxKind::NAME_REF
111+
| SyntaxKind::BLOCK_EXPR => true,
112+
_ => false,
113+
})?;
114+
let (impl_def_idx, impl_def) =
115+
ctx.token.ancestors().enumerate().skip(trigger_idx + 1).find_map(|(idx, p)| {
116+
match p.kind() {
117+
SyntaxKind::IMPL_DEF => ast::ImplDef::cast(p).map(|p| (idx, p)),
118+
_ => None,
119+
}
120+
})?;
121+
let _is_nested = ctx
122+
.token
123+
.ancestors()
124+
.skip(trigger_idx + 1)
125+
.take(impl_def_idx - trigger_idx - 1)
126+
.find_map(|p| match p.kind() {
127+
SyntaxKind::FN_DEF | SyntaxKind::BLOCK => Some(()),
128+
_ => None,
129+
})
130+
.xor(Some(()))?;
131+
Some((trigger, impl_def))
132+
}
133+
126134
fn add_function_impl(
127135
fn_def_node: &SyntaxNode,
128136
acc: &mut Completions,
@@ -278,6 +286,27 @@ mod tests {
278286
"###);
279287
}
280288

289+
#[test]
290+
fn no_nested_fn_completions() {
291+
let completions = complete(
292+
r"
293+
trait Test {
294+
fn test();
295+
fn test2();
296+
}
297+
298+
struct T1;
299+
300+
impl Test for T1 {
301+
fn test() {
302+
t<|>
303+
}
304+
}
305+
",
306+
);
307+
assert_debug_snapshot!(completions, @r###"[]"###);
308+
}
309+
281310
#[test]
282311
fn name_ref_single_function() {
283312
let completions = complete(

0 commit comments

Comments
 (0)