From 9138d39947c3009a1bdbf420b29e6bd06e6d6376 Mon Sep 17 00:00:00 2001 From: Steffen Lyngbaek Date: Sun, 8 Mar 2020 17:50:41 -0700 Subject: Clean up completion matching. - Add test to ensure nested completions don't happen --- .../ra_ide/src/completion/complete_trait_impl.rs | 77 +++++++++++++++------- 1 file changed, 53 insertions(+), 24 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index a4e1045fc..ba7d43f1e 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs @@ -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( -- cgit v1.2.3