diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_ide/src/completion/complete_trait_impl.rs | 144 |
1 files changed, 128 insertions, 16 deletions
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index 18a1d2995..2bf654a57 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -34,7 +34,7 @@ | |||
34 | use hir::{self, Docs, HasSource}; | 34 | use hir::{self, Docs, HasSource}; |
35 | use ra_assists::utils::get_missing_impl_items; | 35 | use ra_assists::utils::get_missing_impl_items; |
36 | use ra_syntax::{ | 36 | use ra_syntax::{ |
37 | ast::{self, edit}, | 37 | ast::{self, edit, ImplDef}, |
38 | AstNode, SyntaxKind, SyntaxNode, TextRange, | 38 | AstNode, SyntaxKind, SyntaxNode, TextRange, |
39 | }; | 39 | }; |
40 | use ra_text_edit::TextEdit; | 40 | use ra_text_edit::TextEdit; |
@@ -47,22 +47,22 @@ use crate::{ | |||
47 | }; | 47 | }; |
48 | 48 | ||
49 | pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { | 49 | pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { |
50 | let trigger = ctx.token.ancestors().find(|p| match p.kind() { | 50 | if let Some((trigger, impl_def)) = completion_match(ctx) { |
51 | SyntaxKind::FN_DEF | ||
52 | | SyntaxKind::TYPE_ALIAS_DEF | ||
53 | | SyntaxKind::CONST_DEF | ||
54 | | SyntaxKind::BLOCK_EXPR => true, | ||
55 | _ => false, | ||
56 | }); | ||
57 | |||
58 | let impl_def = trigger | ||
59 | .as_ref() | ||
60 | .and_then(|node| node.parent()) | ||
61 | .and_then(|node| node.parent()) | ||
62 | .and_then(ast::ImplDef::cast); | ||
63 | |||
64 | if let (Some(trigger), Some(impl_def)) = (trigger, impl_def) { | ||
65 | match trigger.kind() { | 51 | match trigger.kind() { |
52 | SyntaxKind::NAME_REF => { | ||
53 | get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item { | ||
54 | hir::AssocItem::Function(fn_item) => { | ||
55 | add_function_impl(&trigger, acc, ctx, &fn_item) | ||
56 | } | ||
57 | hir::AssocItem::TypeAlias(type_item) => { | ||
58 | add_type_alias_impl(&trigger, acc, ctx, &type_item) | ||
59 | } | ||
60 | hir::AssocItem::Const(const_item) => { | ||
61 | add_const_impl(&trigger, acc, ctx, &const_item) | ||
62 | } | ||
63 | }) | ||
64 | } | ||
65 | |||
66 | SyntaxKind::FN_DEF => { | 66 | SyntaxKind::FN_DEF => { |
67 | for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( | 67 | for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( |
68 | |item| match item { | 68 | |item| match item { |
@@ -101,6 +101,21 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, ImplDef)> { | ||
105 | let (trigger, impl_def_offset) = ctx.token.ancestors().find_map(|p| match p.kind() { | ||
106 | SyntaxKind::FN_DEF | ||
107 | | SyntaxKind::TYPE_ALIAS_DEF | ||
108 | | SyntaxKind::CONST_DEF | ||
109 | | SyntaxKind::BLOCK_EXPR => Some((p, 2)), | ||
110 | SyntaxKind::NAME_REF => Some((p, 5)), | ||
111 | _ => None, | ||
112 | })?; | ||
113 | let impl_def = (0..impl_def_offset - 1) | ||
114 | .try_fold(trigger.parent()?, |t, _| t.parent()) | ||
115 | .and_then(ast::ImplDef::cast)?; | ||
116 | Some((trigger, impl_def)) | ||
117 | } | ||
118 | |||
104 | fn add_function_impl( | 119 | fn add_function_impl( |
105 | fn_def_node: &SyntaxNode, | 120 | fn_def_node: &SyntaxNode, |
106 | acc: &mut Completions, | 121 | acc: &mut Completions, |
@@ -210,6 +225,103 @@ mod tests { | |||
210 | } | 225 | } |
211 | 226 | ||
212 | #[test] | 227 | #[test] |
228 | fn name_ref_function_type_const() { | ||
229 | let completions = complete( | ||
230 | r" | ||
231 | trait Test { | ||
232 | type TestType; | ||
233 | const TEST_CONST: u16; | ||
234 | fn test(); | ||
235 | } | ||
236 | |||
237 | struct T1; | ||
238 | |||
239 | impl Test for T1 { | ||
240 | t<|> | ||
241 | } | ||
242 | ", | ||
243 | ); | ||
244 | assert_debug_snapshot!(completions, @r###" | ||
245 | [ | ||
246 | CompletionItem { | ||
247 | label: "const TEST_CONST: u16 = ", | ||
248 | source_range: [209; 210), | ||
249 | delete: [209; 210), | ||
250 | insert: "const TEST_CONST: u16 = ", | ||
251 | kind: Const, | ||
252 | lookup: "TEST_CONST", | ||
253 | }, | ||
254 | CompletionItem { | ||
255 | label: "fn test()", | ||
256 | source_range: [209; 210), | ||
257 | delete: [209; 210), | ||
258 | insert: "fn test() {}", | ||
259 | kind: Function, | ||
260 | lookup: "test", | ||
261 | }, | ||
262 | CompletionItem { | ||
263 | label: "type TestType = ", | ||
264 | source_range: [209; 210), | ||
265 | delete: [209; 210), | ||
266 | insert: "type TestType = ", | ||
267 | kind: TypeAlias, | ||
268 | lookup: "TestType", | ||
269 | }, | ||
270 | ] | ||
271 | "###); | ||
272 | } | ||
273 | |||
274 | #[test] | ||
275 | fn no_nested_fn_completions() { | ||
276 | let completions = complete( | ||
277 | r" | ||
278 | trait Test { | ||
279 | fn test(); | ||
280 | fn test2(); | ||
281 | } | ||
282 | |||
283 | struct T1; | ||
284 | |||
285 | impl Test for T1 { | ||
286 | fn test() { | ||
287 | t<|> | ||
288 | } | ||
289 | } | ||
290 | ", | ||
291 | ); | ||
292 | assert_debug_snapshot!(completions, @r###"[]"###); | ||
293 | } | ||
294 | |||
295 | #[test] | ||
296 | fn name_ref_single_function() { | ||
297 | let completions = complete( | ||
298 | r" | ||
299 | trait Test { | ||
300 | fn test(); | ||
301 | } | ||
302 | |||
303 | struct T1; | ||
304 | |||
305 | impl Test for T1 { | ||
306 | t<|> | ||
307 | } | ||
308 | ", | ||
309 | ); | ||
310 | assert_debug_snapshot!(completions, @r###" | ||
311 | [ | ||
312 | CompletionItem { | ||
313 | label: "fn test()", | ||
314 | source_range: [139; 140), | ||
315 | delete: [139; 140), | ||
316 | insert: "fn test() {}", | ||
317 | kind: Function, | ||
318 | lookup: "test", | ||
319 | }, | ||
320 | ] | ||
321 | "###); | ||
322 | } | ||
323 | |||
324 | #[test] | ||
213 | fn single_function() { | 325 | fn single_function() { |
214 | let completions = complete( | 326 | let completions = complete( |
215 | r" | 327 | r" |