aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs144
-rw-r--r--crates/ra_ide/src/completion/presentation.rs4
2 files changed, 131 insertions, 17 deletions
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 @@
1
2use crate::completion::{CompletionContext, Completions}; 1use crate::completion::{CompletionContext, Completions};
3 2
4use hir::{ self, db::HirDatabase, HasSource }; 3use ast::{ NameOwner };
4use hir::{ self, db::HirDatabase };
5 5
6use ra_syntax::{ ast, ast::AstNode }; 6use ra_syntax::{ ast, ast::AstNode };
7 7
8pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { 8pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
9 let impl_trait = ast::ItemList::cast(ctx.token.parent()) 9 let item_list = ast::ItemList::cast(ctx.token.parent());
10 .and_then(|item_list| item_list.syntax().parent()) 10 let impl_block = item_list
11 .and_then(|item_list_parent| ast::ImplBlock::cast(item_list_parent)) 11 .clone()
12 .and_then(|impl_block| resolve_target_trait(ctx.db, &ctx.analyzer, &impl_block)); 12 .and_then(|i| i.syntax().parent())
13 13 .and_then(|p| ast::ImplBlock::cast(p));
14 if let Some(x) = &impl_trait { 14
15 for trait_item in x.0.items(ctx.db) { 15 if item_list.is_none() || impl_block.is_none() {
16 match trait_item { 16 return;
17 hir::AssocItem::Function(f) => acc.add_function_impl(ctx, f), 17 }
18 _ => {} 18
19 let item_list = item_list.unwrap();
20 let impl_block = impl_block.unwrap();
21
22 let target_trait = resolve_target_trait(ctx.db, &ctx.analyzer, &impl_block);
23 if target_trait.is_none() {
24 return;
25 }
26
27 let trait_ = target_trait.unwrap();
28
29 let trait_items = trait_.items(ctx.db);
30 let missing_items = trait_items
31 .iter()
32 .filter(|i| {
33 match i {
34 hir::AssocItem::Function(f) => {
35 let f_name = f.name(ctx.db).to_string();
36
37 item_list
38 .impl_items()
39 .find(|impl_item| {
40 match impl_item {
41 ast::ImplItem::FnDef(impl_f) => {
42 if let Some(n) = impl_f.name() {
43 f_name == n.syntax().to_string()
44 } else {
45 false
46 }
47 },
48 _ => false
49 }
50 }).is_none()
51 },
52 hir::AssocItem::Const(c) => {
53 let c_name = c.name(ctx.db)
54 .map(|f| f.to_string());
55
56 if c_name.is_none() {
57 return false;
58 }
59
60 let c_name = c_name.unwrap();
61
62 item_list
63 .impl_items()
64 .find(|impl_item| {
65 match impl_item {
66 ast::ImplItem::ConstDef(c) => {
67 if let Some(n) = c.name() {
68 c_name == n.syntax().to_string()
69 } else {
70 false
71 }
72 },
73 _ => false
74 }
75 }).is_none()
76 },
77 hir::AssocItem::TypeAlias(t) => {
78 let t_name = t.name(ctx.db).to_string();
79
80 item_list
81 .impl_items()
82 .find(|impl_item| {
83 match impl_item {
84 ast::ImplItem::TypeAliasDef(t) => {
85 if let Some(n) = t.name() {
86 t_name == n.syntax().to_string()
87 } else {
88 false
89 }
90 },
91 _ => false
92 }
93 }).is_none()
94 }
19 } 95 }
96 });
97
98 for item in missing_items {
99 match item {
100 hir::AssocItem::Function(f) => acc.add_function_impl(ctx, f),
101 _ => {}
20 } 102 }
21 } 103 }
22} 104}
@@ -25,7 +107,7 @@ fn resolve_target_trait(
25 db: &impl HirDatabase, 107 db: &impl HirDatabase,
26 analyzer: &hir::SourceAnalyzer, 108 analyzer: &hir::SourceAnalyzer,
27 impl_block: &ast::ImplBlock 109 impl_block: &ast::ImplBlock
28) -> Option<(hir::Trait, ast::TraitDef)> { 110) -> Option<hir::Trait> {
29 let ast_path = impl_block 111 let ast_path = impl_block
30 .target_trait() 112 .target_trait()
31 .map(|it| it.syntax().clone()) 113 .map(|it| it.syntax().clone())
@@ -34,7 +116,7 @@ fn resolve_target_trait(
34 116
35 match analyzer.resolve_path(db, &ast_path) { 117 match analyzer.resolve_path(db, &ast_path) {
36 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => { 118 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => {
37 Some((def, def.source(db).value)) 119 Some(def)
38 } 120 }
39 _ => None, 121 _ => None,
40 } 122 }
@@ -70,11 +152,43 @@ mod tests {
70 label: "fn foo()", 152 label: "fn foo()",
71 source_range: [138; 138), 153 source_range: [138; 138),
72 delete: [138; 138), 154 delete: [138; 138),
73 insert: "fn foo() { $0 }", 155 insert: "fn foo() { $0}",
74 kind: Function, 156 kind: Function,
75 lookup: "foo", 157 lookup: "foo",
76 }, 158 },
77 ] 159 ]
78 "###); 160 "###);
79 } 161 }
162
163 #[test]
164 fn hide_implemented_fn() {
165 let completions = complete(
166 r"
167 trait Test {
168 fn foo();
169 fn bar();
170 }
171
172 struct T1;
173
174 impl Test for T1 {
175 fn foo() {}
176
177 <|>
178 }
179 ",
180 );
181 assert_debug_snapshot!(completions, @r###"
182 [
183 CompletionItem {
184 label: "fn bar()",
185 source_range: [193; 193),
186 delete: [193; 193),
187 insert: "fn bar() { $0}",
188 kind: Function,
189 lookup: "bar",
190 },
191 ]
192 "###);
193 }
80} \ No newline at end of file 194} \ 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 {
129 self.add_function_with_name(ctx, None, func) 129 self.add_function_with_name(ctx, None, func)
130 } 130 }
131 131
132 pub(crate) fn add_function_impl(&mut self, ctx: &CompletionContext, func: hir::Function) { 132 pub(crate) fn add_function_impl(&mut self, ctx: &CompletionContext, func: &hir::Function) {
133 use crate::display::FunctionSignature; 133 use crate::display::FunctionSignature;
134 134
135 let display = FunctionSignature::from_hir(ctx.db, func.clone()); 135 let display = FunctionSignature::from_hir(ctx.db, func.clone());
@@ -150,7 +150,7 @@ impl Completions {
150 150
151 let snippet = { 151 let snippet = {
152 let mut s = format!("{}", display); 152 let mut s = format!("{}", display);
153 s.push_str(" { $0 }"); 153 s.push_str(" { $0}");
154 s 154 s
155 }; 155 };
156 156