Clean up completion matching.

- Add test to ensure nested completions don't happen
This commit is contained in:
Steffen Lyngbaek 2020-03-08 17:50:41 -07:00
parent 7c439355ce
commit 9138d39947

View File

@ -34,7 +34,7 @@
use hir::{self, Docs, HasSource};
use ra_assists::utils::get_missing_impl_items;
use ra_syntax::{
ast::{self, edit},
ast::{self, edit, ImplDef},
AstNode, SyntaxKind, SyntaxNode, TextRange,
};
use ra_text_edit::TextEdit;
@ -47,29 +47,7 @@ use crate::{
};
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
let mut tokens = ctx.token.ancestors();
let completion_match = tokens
.find(|p| match p.kind() {
SyntaxKind::FN_DEF
| SyntaxKind::TYPE_ALIAS_DEF
| SyntaxKind::CONST_DEF
| SyntaxKind::NAME_REF
| SyntaxKind::BLOCK_EXPR => true,
_ => false,
})
.and_then(|trigger| {
for p in tokens {
match p.kind() {
// No nested completions
SyntaxKind::FN_DEF | SyntaxKind::BLOCK => return None,
SyntaxKind::IMPL_DEF => return ast::ImplDef::cast(p).map(|p| (trigger, p)),
_ => {}
}
}
None
});
if let Some((trigger, impl_def)) = completion_match {
if let Some((trigger, impl_def)) = completion_match(ctx) {
match trigger.kind() {
SyntaxKind::NAME_REF => {
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
}
}
fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, ImplDef)> {
let (trigger_idx, trigger) =
ctx.token.ancestors().enumerate().find(|(_idx, p)| match p.kind() {
SyntaxKind::FN_DEF
| SyntaxKind::TYPE_ALIAS_DEF
| SyntaxKind::CONST_DEF
| SyntaxKind::NAME_REF
| SyntaxKind::BLOCK_EXPR => true,
_ => false,
})?;
let (impl_def_idx, impl_def) =
ctx.token.ancestors().enumerate().skip(trigger_idx + 1).find_map(|(idx, p)| {
match p.kind() {
SyntaxKind::IMPL_DEF => ast::ImplDef::cast(p).map(|p| (idx, p)),
_ => None,
}
})?;
let _is_nested = ctx
.token
.ancestors()
.skip(trigger_idx + 1)
.take(impl_def_idx - trigger_idx - 1)
.find_map(|p| match p.kind() {
SyntaxKind::FN_DEF | SyntaxKind::BLOCK => Some(()),
_ => None,
})
.xor(Some(()))?;
Some((trigger, impl_def))
}
fn add_function_impl(
fn_def_node: &SyntaxNode,
acc: &mut Completions,
@ -278,6 +286,27 @@ mod tests {
"###);
}
#[test]
fn no_nested_fn_completions() {
let completions = complete(
r"
trait Test {
fn test();
fn test2();
}
struct T1;
impl Test for T1 {
fn test() {
t<|>
}
}
",
);
assert_debug_snapshot!(completions, @r###"[]"###);
}
#[test]
fn name_ref_single_function() {
let completions = complete(