aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide/src/completion.rs3
-rw-r--r--crates/ra_ide/src/completion/complete_impl_fn.rs80
-rw-r--r--crates/ra_ide/src/completion/presentation.rs33
3 files changed, 116 insertions, 0 deletions
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs
index abe1f36ce..f31f2593c 100644
--- a/crates/ra_ide/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
@@ -15,6 +15,7 @@ mod complete_path;
15mod complete_scope; 15mod complete_scope;
16mod complete_postfix; 16mod complete_postfix;
17mod complete_macro_in_item_position; 17mod complete_macro_in_item_position;
18mod complete_impl_fn;
18 19
19use ra_db::SourceDatabase; 20use ra_db::SourceDatabase;
20 21
@@ -73,5 +74,7 @@ pub(crate) fn completions(db: &db::RootDatabase, position: FilePosition) -> Opti
73 complete_pattern::complete_pattern(&mut acc, &ctx); 74 complete_pattern::complete_pattern(&mut acc, &ctx);
74 complete_postfix::complete_postfix(&mut acc, &ctx); 75 complete_postfix::complete_postfix(&mut acc, &ctx);
75 complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); 76 complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx);
77 complete_impl_fn::complete_impl_fn(&mut acc, &ctx);
78
76 Some(acc) 79 Some(acc)
77} 80}
diff --git a/crates/ra_ide/src/completion/complete_impl_fn.rs b/crates/ra_ide/src/completion/complete_impl_fn.rs
new file mode 100644
index 000000000..6d464cc1f
--- /dev/null
+++ b/crates/ra_ide/src/completion/complete_impl_fn.rs
@@ -0,0 +1,80 @@
1
2use crate::completion::{CompletionContext, Completions};
3
4use hir::{ self, db::HirDatabase, HasSource };
5
6use ra_syntax::{ ast, ast::AstNode };
7
8pub(crate) fn complete_impl_fn(acc: &mut Completions, ctx: &CompletionContext) {
9 let impl_trait = ast::ItemList::cast(ctx.token.parent())
10 .and_then(|item_list| item_list.syntax().parent())
11 .and_then(|item_list_parent| ast::ImplBlock::cast(item_list_parent))
12 .and_then(|impl_block| resolve_target_trait(ctx.db, &ctx.analyzer, &impl_block));
13
14 if let Some(x) = &impl_trait {
15 for trait_item in x.0.items(ctx.db) {
16 match trait_item {
17 hir::AssocItem::Function(f) => acc.add_function_impl(ctx, f),
18 _ => {}
19 }
20 }
21 }
22}
23
24fn resolve_target_trait(
25 db: &impl HirDatabase,
26 analyzer: &hir::SourceAnalyzer,
27 impl_block: &ast::ImplBlock
28) -> Option<(hir::Trait, ast::TraitDef)> {
29 let ast_path = impl_block
30 .target_trait()
31 .map(|it| it.syntax().clone())
32 .and_then(ast::PathType::cast)?
33 .path()?;
34
35 match analyzer.resolve_path(db, &ast_path) {
36 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => {
37 Some((def, def.source(db).value))
38 }
39 _ => None,
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use crate::completion::{do_completion, CompletionItem, CompletionKind};
46 use insta::assert_debug_snapshot;
47
48 fn complete(code: &str) -> Vec<CompletionItem> {
49 do_completion(code, CompletionKind::Reference)
50 }
51
52 #[test]
53 fn single_function() {
54 let completions = complete(
55 r"
56 trait Test {
57 fn foo();
58 }
59
60 struct T1;
61
62 impl Test for T1 {
63 <|>
64 }
65 ",
66 );
67 assert_debug_snapshot!(completions, @r###"
68 [
69 CompletionItem {
70 label: "fn foo()",
71 source_range: [138; 138),
72 delete: [138; 138),
73 insert: "fn foo() { $0 }",
74 kind: Function,
75 lookup: "foo",
76 },
77 ]
78 "###);
79 }
80} \ 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 97475fc0b..d0a43261f 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -129,6 +129,39 @@ 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) {
133 use crate::display::FunctionSignature;
134
135 let display = FunctionSignature::from_hir(ctx.db, func.clone());
136
137 let func_name = func.name(ctx.db);
138
139 let mut builder = CompletionItem::new(
140 CompletionKind::Reference,
141 ctx.source_range(),
142 format!("fn {}()", func_name.to_string()))
143 .set_documentation(func.docs(ctx.db));
144
145 let completion_kind = if func.has_self_param(ctx.db) {
146 CompletionItemKind::Method
147 } else {
148 CompletionItemKind::Function
149 };
150
151 let snippet = {
152 let mut s = format!("{}", display);
153 s.push_str(" { $0 }");
154 s
155 };
156
157 builder = builder
158 .insert_text(snippet)
159 .kind(completion_kind)
160 .lookup_by(func_name.to_string());
161
162 self.add(builder.build());
163 }
164
132 fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str { 165 fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str {
133 let mut votes = [0, 0, 0]; 166 let mut votes = [0, 0, 0];
134 for (idx, s) in docs.match_indices(&macro_name) { 167 for (idx, s) in docs.match_indices(&macro_name) {