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.rs77
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 @@
34use hir::{self, Docs, HasSource}; 34use hir::{self, Docs, HasSource};
35use ra_assists::utils::get_missing_impl_items; 35use ra_assists::utils::get_missing_impl_items;
36use ra_syntax::{ 36use ra_syntax::{
37 ast::{self, edit}, 37 ast::{self, edit, ImplDef},
38 AstNode, SyntaxKind, SyntaxNode, TextRange, 38 AstNode, SyntaxKind, SyntaxNode, TextRange,
39}; 39};
40use ra_text_edit::TextEdit; 40use ra_text_edit::TextEdit;
@@ -47,29 +47,7 @@ use crate::{
47}; 47};
48 48
49pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { 49pub(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
104fn 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
126fn add_function_impl( 134fn 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"