aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion
diff options
context:
space:
mode:
authorKevin DeLorey <[email protected]>2020-02-09 18:24:34 +0000
committerKevin DeLorey <[email protected]>2020-02-09 18:24:59 +0000
commitd85abd77b98ff5925621c18f2ffe121640d17c80 (patch)
treee63952b8b78cd8c2b3c14cb721f141b9a5185275 /crates/ra_ide/src/completion
parenta957c473fdb79880c39b73dc9e0c923093cf16ac (diff)
Added a utility function that can be used to determine the missing impl items.
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs132
1 files changed, 18 insertions, 114 deletions
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs
index 0175f5e55..e2854ee97 100644
--- a/crates/ra_ide/src/completion/complete_trait_impl.rs
+++ b/crates/ra_ide/src/completion/complete_trait_impl.rs
@@ -1,124 +1,27 @@
1use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionKind, CompletionItemKind}; 1use crate::completion::{
2 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
3};
2 4
3use ra_syntax::ast::{self, NameOwner, AstNode}; 5use hir::{self, Docs};
4
5use hir::{self, db::HirDatabase, Docs};
6 6
7use ra_assists::utils::get_missing_impl_items;
7 8
8pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { 9pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
9 let impl_block = ctx.impl_block.as_ref(); 10 let impl_block = ctx.impl_block.as_ref();
10 let item_list = impl_block.and_then(|i| i.item_list()); 11 let item_list = impl_block.and_then(|i| i.item_list());
11 12
12 if item_list.is_none() 13 if item_list.is_none() || impl_block.is_none() || ctx.function_syntax.is_some() {
13 || impl_block.is_none()
14 || ctx.function_syntax.is_some() {
15 return; 14 return;
16 } 15 }
17 16
18 let item_list = item_list.unwrap();
19 let impl_block = impl_block.unwrap(); 17 let impl_block = impl_block.unwrap();
20 18
21 let target_trait = resolve_target_trait(ctx.db, &ctx.analyzer, &impl_block); 19 for item in get_missing_impl_items(ctx.db, &ctx.analyzer, impl_block) {
22 if target_trait.is_none() {
23 return;
24 }
25
26 let target_trait = target_trait.unwrap();
27
28 let trait_items = target_trait.items(ctx.db);
29 let missing_items = trait_items
30 .iter()
31 .filter(|i| {
32 match i {
33 hir::AssocItem::Function(f) => {
34 let f_name = f.name(ctx.db).to_string();
35
36 item_list
37 .impl_items()
38 .find(|impl_item| {
39 match impl_item {
40 ast::ImplItem::FnDef(impl_f) => {
41 if let Some(n) = impl_f.name() {
42 f_name == n.syntax().to_string()
43 } else {
44 false
45 }
46 },
47 _ => false
48 }
49 }).is_none()
50 },
51 hir::AssocItem::Const(c) => {
52 let c_name = c.name(ctx.db)
53 .map(|f| f.to_string());
54
55 if c_name.is_none() {
56 return false;
57 }
58
59 let c_name = c_name.unwrap();
60
61 item_list
62 .impl_items()
63 .find(|impl_item| {
64 match impl_item {
65 ast::ImplItem::ConstDef(c) => {
66 if let Some(n) = c.name() {
67 c_name == n.syntax().to_string()
68 } else {
69 false
70 }
71 },
72 _ => false
73 }
74 }).is_none()
75 },
76 hir::AssocItem::TypeAlias(t) => {
77 let t_name = t.name(ctx.db).to_string();
78
79 item_list
80 .impl_items()
81 .find(|impl_item| {
82 match impl_item {
83 ast::ImplItem::TypeAliasDef(t) => {
84 if let Some(n) = t.name() {
85 t_name == n.syntax().to_string()
86 } else {
87 false
88 }
89 },
90 _ => false
91 }
92 }).is_none()
93 }
94 }
95 });
96
97 for item in missing_items {
98 match item { 20 match item {
99 hir::AssocItem::Function(f) => add_function_impl(acc, ctx, f), 21 hir::AssocItem::Function(f) => add_function_impl(acc, ctx, &f),
100 hir::AssocItem::TypeAlias(t) => add_type_alias_impl(acc, ctx, t), 22 hir::AssocItem::TypeAlias(t) => add_type_alias_impl(acc, ctx, &t),
101 _ => {}, 23 _ => {}
102 }
103 }
104}
105
106fn resolve_target_trait(
107 db: &impl HirDatabase,
108 analyzer: &hir::SourceAnalyzer,
109 impl_block: &ast::ImplBlock
110) -> Option<hir::Trait> {
111 let ast_path = impl_block
112 .target_trait()
113 .map(|it| it.syntax().clone())
114 .and_then(ast::PathType::cast)?
115 .path()?;
116
117 match analyzer.resolve_path(db, &ast_path) {
118 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => {
119 Some(def)
120 } 24 }
121 _ => None,
122 } 25 }
123} 26}
124 27
@@ -144,20 +47,21 @@ fn add_function_impl(acc: &mut Completions, ctx: &CompletionContext, func: &hir:
144 } else { 47 } else {
145 CompletionItemKind::Function 48 CompletionItemKind::Function
146 }; 49 };
147 50
148 let snippet = { 51 let snippet = {
149 let mut s = format!("{}", display); 52 let mut s = format!("{}", display);
150 s.push_str(" {}"); 53 s.push_str(" {}");
151 s 54 s
152 }; 55 };
153 56
154 builder 57 builder.insert_text(snippet).kind(completion_kind).add_to(acc);
155 .insert_text(snippet)
156 .kind(completion_kind)
157 .add_to(acc);
158} 58}
159 59
160fn add_type_alias_impl(acc: &mut Completions, ctx: &CompletionContext, type_alias: &hir::TypeAlias) { 60fn add_type_alias_impl(
61 acc: &mut Completions,
62 ctx: &CompletionContext,
63 type_alias: &hir::TypeAlias,
64) {
161 let snippet = format!("type {} = ", type_alias.name(ctx.db).to_string()); 65 let snippet = format!("type {} = ", type_alias.name(ctx.db).to_string());
162 66
163 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) 67 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
@@ -290,4 +194,4 @@ mod tests {
290 ] 194 ]
291 "###); 195 "###);
292 } 196 }
293} \ No newline at end of file 197}