From 698ff91c1309b189ca0f08e3d62d219305ae5f46 Mon Sep 17 00:00:00 2001 From: Kevin DeLorey <2295721+kdelorey@users.noreply.github.com> Date: Tue, 28 Jan 2020 20:30:53 -0600 Subject: Already implemented fn will no longer be suggested for trait implementations. --- .../ra_ide/src/completion/complete_trait_impl.rs | 144 ++++++++++++++++++--- crates/ra_ide/src/completion/presentation.rs | 4 +- 2 files changed, 131 insertions(+), 17 deletions(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index 3bec57426..52ad7dd9d 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs @@ -1,22 +1,104 @@ - use crate::completion::{CompletionContext, Completions}; -use hir::{ self, db::HirDatabase, HasSource }; +use ast::{ NameOwner }; +use hir::{ self, db::HirDatabase }; use ra_syntax::{ ast, ast::AstNode }; pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { - let impl_trait = ast::ItemList::cast(ctx.token.parent()) - .and_then(|item_list| item_list.syntax().parent()) - .and_then(|item_list_parent| ast::ImplBlock::cast(item_list_parent)) - .and_then(|impl_block| resolve_target_trait(ctx.db, &ctx.analyzer, &impl_block)); - - if let Some(x) = &impl_trait { - for trait_item in x.0.items(ctx.db) { - match trait_item { - hir::AssocItem::Function(f) => acc.add_function_impl(ctx, f), - _ => {} + let item_list = ast::ItemList::cast(ctx.token.parent()); + let impl_block = item_list + .clone() + .and_then(|i| i.syntax().parent()) + .and_then(|p| ast::ImplBlock::cast(p)); + + if item_list.is_none() || impl_block.is_none() { + return; + } + + let item_list = item_list.unwrap(); + let impl_block = impl_block.unwrap(); + + let target_trait = resolve_target_trait(ctx.db, &ctx.analyzer, &impl_block); + if target_trait.is_none() { + return; + } + + let trait_ = target_trait.unwrap(); + + let trait_items = trait_.items(ctx.db); + let missing_items = trait_items + .iter() + .filter(|i| { + match i { + hir::AssocItem::Function(f) => { + let f_name = f.name(ctx.db).to_string(); + + item_list + .impl_items() + .find(|impl_item| { + match impl_item { + ast::ImplItem::FnDef(impl_f) => { + if let Some(n) = impl_f.name() { + f_name == n.syntax().to_string() + } else { + false + } + }, + _ => false + } + }).is_none() + }, + hir::AssocItem::Const(c) => { + let c_name = c.name(ctx.db) + .map(|f| f.to_string()); + + if c_name.is_none() { + return false; + } + + let c_name = c_name.unwrap(); + + item_list + .impl_items() + .find(|impl_item| { + match impl_item { + ast::ImplItem::ConstDef(c) => { + if let Some(n) = c.name() { + c_name == n.syntax().to_string() + } else { + false + } + }, + _ => false + } + }).is_none() + }, + hir::AssocItem::TypeAlias(t) => { + let t_name = t.name(ctx.db).to_string(); + + item_list + .impl_items() + .find(|impl_item| { + match impl_item { + ast::ImplItem::TypeAliasDef(t) => { + if let Some(n) = t.name() { + t_name == n.syntax().to_string() + } else { + false + } + }, + _ => false + } + }).is_none() + } } + }); + + for item in missing_items { + match item { + hir::AssocItem::Function(f) => acc.add_function_impl(ctx, f), + _ => {} } } } @@ -25,7 +107,7 @@ fn resolve_target_trait( db: &impl HirDatabase, analyzer: &hir::SourceAnalyzer, impl_block: &ast::ImplBlock -) -> Option<(hir::Trait, ast::TraitDef)> { +) -> Option { let ast_path = impl_block .target_trait() .map(|it| it.syntax().clone()) @@ -34,7 +116,7 @@ fn resolve_target_trait( match analyzer.resolve_path(db, &ast_path) { Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => { - Some((def, def.source(db).value)) + Some(def) } _ => None, } @@ -70,11 +152,43 @@ mod tests { label: "fn foo()", source_range: [138; 138), delete: [138; 138), - insert: "fn foo() { $0 }", + insert: "fn foo() { $0}", kind: Function, lookup: "foo", }, ] "###); } + + #[test] + fn hide_implemented_fn() { + let completions = complete( + r" + trait Test { + fn foo(); + fn bar(); + } + + struct T1; + + impl Test for T1 { + fn foo() {} + + <|> + } + ", + ); + assert_debug_snapshot!(completions, @r###" + [ + CompletionItem { + label: "fn bar()", + source_range: [193; 193), + delete: [193; 193), + insert: "fn bar() { $0}", + kind: Function, + lookup: "bar", + }, + ] + "###); + } } \ No newline at end of file diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index d0a43261f..0689013ba 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs @@ -129,7 +129,7 @@ impl Completions { self.add_function_with_name(ctx, None, func) } - pub(crate) fn add_function_impl(&mut self, ctx: &CompletionContext, func: hir::Function) { + pub(crate) fn add_function_impl(&mut self, ctx: &CompletionContext, func: &hir::Function) { use crate::display::FunctionSignature; let display = FunctionSignature::from_hir(ctx.db, func.clone()); @@ -150,7 +150,7 @@ impl Completions { let snippet = { let mut s = format!("{}", display); - s.push_str(" { $0 }"); + s.push_str(" { $0}"); s }; -- cgit v1.2.3