mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 13:25:09 +00:00
Already implemented fn will no longer be suggested for trait implementations.
This commit is contained in:
parent
bc1fc6239d
commit
698ff91c13
2 changed files with 130 additions and 16 deletions
|
@ -1,22 +1,104 @@
|
||||||
|
|
||||||
use crate::completion::{CompletionContext, Completions};
|
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 };
|
use ra_syntax::{ ast, ast::AstNode };
|
||||||
|
|
||||||
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
let impl_trait = ast::ItemList::cast(ctx.token.parent())
|
let item_list = ast::ItemList::cast(ctx.token.parent());
|
||||||
.and_then(|item_list| item_list.syntax().parent())
|
let impl_block = item_list
|
||||||
.and_then(|item_list_parent| ast::ImplBlock::cast(item_list_parent))
|
.clone()
|
||||||
.and_then(|impl_block| resolve_target_trait(ctx.db, &ctx.analyzer, &impl_block));
|
.and_then(|i| i.syntax().parent())
|
||||||
|
.and_then(|p| ast::ImplBlock::cast(p));
|
||||||
|
|
||||||
if let Some(x) = &impl_trait {
|
if item_list.is_none() || impl_block.is_none() {
|
||||||
for trait_item in x.0.items(ctx.db) {
|
return;
|
||||||
match trait_item {
|
}
|
||||||
hir::AssocItem::Function(f) => acc.add_function_impl(ctx, f),
|
|
||||||
_ => {}
|
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,
|
db: &impl HirDatabase,
|
||||||
analyzer: &hir::SourceAnalyzer,
|
analyzer: &hir::SourceAnalyzer,
|
||||||
impl_block: &ast::ImplBlock
|
impl_block: &ast::ImplBlock
|
||||||
) -> Option<(hir::Trait, ast::TraitDef)> {
|
) -> Option<hir::Trait> {
|
||||||
let ast_path = impl_block
|
let ast_path = impl_block
|
||||||
.target_trait()
|
.target_trait()
|
||||||
.map(|it| it.syntax().clone())
|
.map(|it| it.syntax().clone())
|
||||||
|
@ -34,7 +116,7 @@ fn resolve_target_trait(
|
||||||
|
|
||||||
match analyzer.resolve_path(db, &ast_path) {
|
match analyzer.resolve_path(db, &ast_path) {
|
||||||
Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => {
|
Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => {
|
||||||
Some((def, def.source(db).value))
|
Some(def)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -70,11 +152,43 @@ mod tests {
|
||||||
label: "fn foo()",
|
label: "fn foo()",
|
||||||
source_range: [138; 138),
|
source_range: [138; 138),
|
||||||
delete: [138; 138),
|
delete: [138; 138),
|
||||||
insert: "fn foo() { $0 }",
|
insert: "fn foo() { $0}",
|
||||||
kind: Function,
|
kind: Function,
|
||||||
lookup: "foo",
|
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",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"###);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -129,7 +129,7 @@ impl Completions {
|
||||||
self.add_function_with_name(ctx, None, func)
|
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;
|
use crate::display::FunctionSignature;
|
||||||
|
|
||||||
let display = FunctionSignature::from_hir(ctx.db, func.clone());
|
let display = FunctionSignature::from_hir(ctx.db, func.clone());
|
||||||
|
@ -150,7 +150,7 @@ impl Completions {
|
||||||
|
|
||||||
let snippet = {
|
let snippet = {
|
||||||
let mut s = format!("{}", display);
|
let mut s = format!("{}", display);
|
||||||
s.push_str(" { $0 }");
|
s.push_str(" { $0}");
|
||||||
s
|
s
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue