diff options
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r-- | crates/ra_ide/src/completion/complete_trait_impl.rs | 77 |
1 files changed, 53 insertions, 24 deletions
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index a4e1045fc..ba7d43f1e 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,29 +47,7 @@ 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 mut tokens = ctx.token.ancestors(); | 50 | if let Some((trigger, impl_def)) = completion_match(ctx) { |
51 | let completion_match = tokens | ||
52 | .find(|p| match p.kind() { | ||
53 | SyntaxKind::FN_DEF | ||
54 | | SyntaxKind::TYPE_ALIAS_DEF | ||
55 | | SyntaxKind::CONST_DEF | ||
56 | | SyntaxKind::NAME_REF | ||
57 | | SyntaxKind::BLOCK_EXPR => true, | ||
58 | _ => false, | ||
59 | }) | ||
60 | .and_then(|trigger| { | ||
61 | for p in tokens { | ||
62 | match p.kind() { | ||
63 | // No nested completions | ||
64 | SyntaxKind::FN_DEF | SyntaxKind::BLOCK => return None, | ||
65 | SyntaxKind::IMPL_DEF => return ast::ImplDef::cast(p).map(|p| (trigger, p)), | ||
66 | _ => {} | ||
67 | } | ||
68 | } | ||
69 | None | ||
70 | }); | ||
71 | |||
72 | if let Some((trigger, impl_def)) = completion_match { | ||
73 | match trigger.kind() { | 51 | match trigger.kind() { |
74 | SyntaxKind::NAME_REF => { | 52 | SyntaxKind::NAME_REF => { |
75 | get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item { | 53 | get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item { |
@@ -123,6 +101,36 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext | |||
123 | } | 101 | } |
124 | } | 102 | } |
125 | 103 | ||
104 | fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, ImplDef)> { | ||
105 | let (trigger_idx, trigger) = | ||
106 | ctx.token.ancestors().enumerate().find(|(_idx, p)| match p.kind() { | ||
107 | SyntaxKind::FN_DEF | ||
108 | | SyntaxKind::TYPE_ALIAS_DEF | ||
109 | | SyntaxKind::CONST_DEF | ||
110 | | SyntaxKind::NAME_REF | ||
111 | | SyntaxKind::BLOCK_EXPR => true, | ||
112 | _ => false, | ||
113 | })?; | ||
114 | let (impl_def_idx, impl_def) = | ||
115 | ctx.token.ancestors().enumerate().skip(trigger_idx + 1).find_map(|(idx, p)| { | ||
116 | match p.kind() { | ||
117 | SyntaxKind::IMPL_DEF => ast::ImplDef::cast(p).map(|p| (idx, p)), | ||
118 | _ => None, | ||
119 | } | ||
120 | })?; | ||
121 | let _is_nested = ctx | ||
122 | .token | ||
123 | .ancestors() | ||
124 | .skip(trigger_idx + 1) | ||
125 | .take(impl_def_idx - trigger_idx - 1) | ||
126 | .find_map(|p| match p.kind() { | ||
127 | SyntaxKind::FN_DEF | SyntaxKind::BLOCK => Some(()), | ||
128 | _ => None, | ||
129 | }) | ||
130 | .xor(Some(()))?; | ||
131 | Some((trigger, impl_def)) | ||
132 | } | ||
133 | |||
126 | fn add_function_impl( | 134 | fn add_function_impl( |
127 | fn_def_node: &SyntaxNode, | 135 | fn_def_node: &SyntaxNode, |
128 | acc: &mut Completions, | 136 | acc: &mut Completions, |
@@ -279,6 +287,27 @@ mod tests { | |||
279 | } | 287 | } |
280 | 288 | ||
281 | #[test] | 289 | #[test] |
290 | fn no_nested_fn_completions() { | ||
291 | let completions = complete( | ||
292 | r" | ||
293 | trait Test { | ||
294 | fn test(); | ||
295 | fn test2(); | ||
296 | } | ||
297 | |||
298 | struct T1; | ||
299 | |||
300 | impl Test for T1 { | ||
301 | fn test() { | ||
302 | t<|> | ||
303 | } | ||
304 | } | ||
305 | ", | ||
306 | ); | ||
307 | assert_debug_snapshot!(completions, @r###"[]"###); | ||
308 | } | ||
309 | |||
310 | #[test] | ||
282 | fn name_ref_single_function() { | 311 | fn name_ref_single_function() { |
283 | let completions = complete( | 312 | let completions = complete( |
284 | r" | 313 | r" |