diff options
-rw-r--r-- | crates/ra_ide/src/completion/complete_keyword.rs | 269 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_item.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/patterns.rs | 130 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/test_utils.rs | 2 |
4 files changed, 154 insertions, 255 deletions
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index d016f0c7c..0ab330b73 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs | |||
@@ -36,184 +36,98 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC | |||
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
39 | fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { | ||
40 | let res = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) | ||
41 | .kind(CompletionItemKind::Keyword); | ||
42 | |||
43 | match ctx.config.snippet_cap { | ||
44 | Some(cap) => res.insert_snippet(cap, snippet), | ||
45 | _ => res.insert_text(if snippet.contains('$') { kw } else { snippet }), | ||
46 | } | ||
47 | .build() | ||
48 | } | ||
49 | |||
50 | fn add_keyword( | ||
51 | ctx: &CompletionContext, | ||
52 | acc: &mut Completions, | ||
53 | kw: &str, | ||
54 | snippet: &str, | ||
55 | should_add: bool, | ||
56 | ) { | ||
57 | if should_add { | ||
58 | acc.add(keyword(ctx, kw, snippet)); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { | 39 | pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { |
63 | let has_trait_or_impl_parent = ctx.has_impl_parent || ctx.has_trait_parent; | 40 | let has_trait_or_impl_parent = ctx.has_impl_parent || ctx.has_trait_parent; |
64 | if ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling { | 41 | if ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling { |
65 | add_keyword(ctx, acc, "where", "where ", true); | 42 | add_keyword(ctx, acc, "where", "where "); |
66 | return; | 43 | return; |
67 | } | 44 | } |
68 | if ctx.unsafe_is_prev { | 45 | if ctx.unsafe_is_prev { |
69 | add_keyword( | 46 | if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { |
70 | ctx, | 47 | add_keyword(ctx, acc, "fn", "fn $0() {}") |
71 | acc, | 48 | } |
72 | "fn", | 49 | |
73 | "fn $0() {}", | 50 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) |
74 | ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, | 51 | || ctx.block_expr_parent |
75 | ); | 52 | { |
76 | add_keyword( | 53 | add_keyword(ctx, acc, "trait", "trait $0 {}"); |
77 | ctx, | 54 | add_keyword(ctx, acc, "impl", "impl $0 {}"); |
78 | acc, | 55 | } |
79 | "trait", | 56 | |
80 | "trait $0 {}", | ||
81 | (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | ||
82 | || ctx.block_expr_parent, | ||
83 | ); | ||
84 | add_keyword( | ||
85 | ctx, | ||
86 | acc, | ||
87 | "impl", | ||
88 | "impl $0 {}", | ||
89 | (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | ||
90 | || ctx.block_expr_parent, | ||
91 | ); | ||
92 | return; | 57 | return; |
93 | } | 58 | } |
94 | add_keyword( | 59 | if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { |
95 | ctx, | 60 | add_keyword(ctx, acc, "fn", "fn $0() {}"); |
96 | acc, | 61 | } |
97 | "fn", | 62 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) |
98 | "fn $0() {}", | 63 | || ctx.block_expr_parent |
99 | ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, | 64 | { |
100 | ); | 65 | add_keyword(ctx, acc, "use", "use "); |
101 | add_keyword( | 66 | add_keyword(ctx, acc, "impl", "impl $0 {}"); |
102 | ctx, | 67 | add_keyword(ctx, acc, "trait", "trait $0 {}"); |
103 | acc, | 68 | } |
104 | "use", | 69 | |
105 | "use ", | 70 | if ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent { |
106 | (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 71 | add_keyword(ctx, acc, "enum", "enum $0 {}"); |
107 | || ctx.block_expr_parent, | 72 | add_keyword(ctx, acc, "struct", "struct $0 {}"); |
108 | ); | 73 | add_keyword(ctx, acc, "union", "union $0 {}"); |
109 | add_keyword( | 74 | } |
110 | ctx, | 75 | |
111 | acc, | 76 | if ctx.block_expr_parent || ctx.is_match_arm { |
112 | "impl", | 77 | add_keyword(ctx, acc, "match", "match $0 {}"); |
113 | "impl $0 {}", | 78 | add_keyword(ctx, acc, "loop", "loop {$0}"); |
114 | (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 79 | } |
115 | || ctx.block_expr_parent, | 80 | if ctx.block_expr_parent { |
116 | ); | 81 | add_keyword(ctx, acc, "while", "while $0 {}"); |
117 | add_keyword( | 82 | } |
118 | ctx, | 83 | if ctx.if_is_prev || ctx.block_expr_parent { |
119 | acc, | 84 | add_keyword(ctx, acc, "let", "let "); |
120 | "trait", | 85 | } |
121 | "trait $0 {}", | 86 | if ctx.if_is_prev || ctx.block_expr_parent || ctx.is_match_arm { |
122 | (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 87 | add_keyword(ctx, acc, "if", "if "); |
123 | || ctx.block_expr_parent, | 88 | add_keyword(ctx, acc, "if let", "if let "); |
124 | ); | 89 | } |
125 | add_keyword( | 90 | if ctx.after_if { |
126 | ctx, | 91 | add_keyword(ctx, acc, "else", "else {$0}"); |
127 | acc, | 92 | add_keyword(ctx, acc, "else if", "else if $0 {}"); |
128 | "enum", | 93 | } |
129 | "enum $0 {}", | 94 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) |
130 | ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, | 95 | || ctx.block_expr_parent |
131 | ); | 96 | { |
132 | add_keyword( | 97 | add_keyword(ctx, acc, "mod", "mod $0 {}"); |
133 | ctx, | 98 | } |
134 | acc, | 99 | if ctx.bind_pat_parent || ctx.ref_pat_parent { |
135 | "struct", | 100 | add_keyword(ctx, acc, "mut", "mut "); |
136 | "struct $0 {}", | 101 | } |
137 | ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, | 102 | if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { |
138 | ); | 103 | add_keyword(ctx, acc, "const", "const "); |
139 | add_keyword( | 104 | add_keyword(ctx, acc, "type", "type "); |
140 | ctx, | 105 | } |
141 | acc, | 106 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) |
142 | "union", | 107 | || ctx.block_expr_parent |
143 | "union $0 {}", | 108 | { |
144 | ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, | 109 | add_keyword(ctx, acc, "static", "static "); |
145 | ); | 110 | }; |
146 | add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent || ctx.is_match_arm); | 111 | if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) |
147 | add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm); | 112 | || ctx.block_expr_parent |
148 | add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); | 113 | { |
149 | add_keyword(ctx, acc, "let", "let ", ctx.if_is_prev || ctx.block_expr_parent); | 114 | add_keyword(ctx, acc, "extern", "extern "); |
150 | add_keyword(ctx, acc, "if", "if ", ctx.if_is_prev || ctx.block_expr_parent || ctx.is_match_arm); | 115 | } |
151 | add_keyword( | 116 | if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm { |
152 | ctx, | 117 | add_keyword(ctx, acc, "unsafe", "unsafe "); |
153 | acc, | 118 | } |
154 | "if let", | 119 | if ctx.in_loop_body { |
155 | "if let ", | 120 | if ctx.can_be_stmt { |
156 | ctx.if_is_prev || ctx.block_expr_parent || ctx.is_match_arm, | 121 | add_keyword(ctx, acc, "continue", "continue;"); |
157 | ); | 122 | add_keyword(ctx, acc, "break", "break;"); |
158 | add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); | 123 | } else { |
159 | add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); | 124 | add_keyword(ctx, acc, "continue", "continue"); |
160 | add_keyword( | 125 | add_keyword(ctx, acc, "break", "break"); |
161 | ctx, | 126 | } |
162 | acc, | 127 | } |
163 | "mod", | 128 | if ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent { |
164 | "mod $0 {}", | 129 | add_keyword(ctx, acc, "pub", "pub ") |
165 | (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | 130 | } |
166 | || ctx.block_expr_parent, | ||
167 | ); | ||
168 | add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent); | ||
169 | add_keyword( | ||
170 | ctx, | ||
171 | acc, | ||
172 | "const", | ||
173 | "const ", | ||
174 | ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, | ||
175 | ); | ||
176 | add_keyword( | ||
177 | ctx, | ||
178 | acc, | ||
179 | "type", | ||
180 | "type ", | ||
181 | ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, | ||
182 | ); | ||
183 | add_keyword( | ||
184 | ctx, | ||
185 | acc, | ||
186 | "static", | ||
187 | "static ", | ||
188 | (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | ||
189 | || ctx.block_expr_parent, | ||
190 | ); | ||
191 | add_keyword( | ||
192 | ctx, | ||
193 | acc, | ||
194 | "extern", | ||
195 | "extern ", | ||
196 | (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) | ||
197 | || ctx.block_expr_parent, | ||
198 | ); | ||
199 | add_keyword( | ||
200 | ctx, | ||
201 | acc, | ||
202 | "unsafe", | ||
203 | "unsafe ", | ||
204 | ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm, | ||
205 | ); | ||
206 | add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt); | ||
207 | add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt); | ||
208 | add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt); | ||
209 | add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); | ||
210 | add_keyword( | ||
211 | ctx, | ||
212 | acc, | ||
213 | "pub", | ||
214 | "pub ", | ||
215 | ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent, | ||
216 | ); | ||
217 | 131 | ||
218 | if !ctx.is_trivial_path { | 132 | if !ctx.is_trivial_path { |
219 | return; | 133 | return; |
@@ -225,6 +139,21 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
225 | acc.add_all(complete_return(ctx, &fn_def, ctx.can_be_stmt)); | 139 | acc.add_all(complete_return(ctx, &fn_def, ctx.can_be_stmt)); |
226 | } | 140 | } |
227 | 141 | ||
142 | fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { | ||
143 | let res = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) | ||
144 | .kind(CompletionItemKind::Keyword); | ||
145 | |||
146 | match ctx.config.snippet_cap { | ||
147 | Some(cap) => res.insert_snippet(cap, snippet), | ||
148 | _ => res.insert_text(if snippet.contains('$') { kw } else { snippet }), | ||
149 | } | ||
150 | .build() | ||
151 | } | ||
152 | |||
153 | fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) { | ||
154 | acc.add(keyword(ctx, kw, snippet)); | ||
155 | } | ||
156 | |||
228 | fn complete_return( | 157 | fn complete_return( |
229 | ctx: &CompletionContext, | 158 | ctx: &CompletionContext, |
230 | fn_def: &ast::FnDef, | 159 | fn_def: &ast::FnDef, |
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index d1a4dd881..98348b349 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs | |||
@@ -126,8 +126,9 @@ pub enum CompletionItemKind { | |||
126 | } | 126 | } |
127 | 127 | ||
128 | impl CompletionItemKind { | 128 | impl CompletionItemKind { |
129 | pub fn tag(&self) -> String { | 129 | #[cfg(test)] |
130 | let tag = match self { | 130 | pub(crate) fn tag(&self) -> &'static str { |
131 | match self { | ||
131 | CompletionItemKind::Snippet => "sn", | 132 | CompletionItemKind::Snippet => "sn", |
132 | CompletionItemKind::Keyword => "kw", | 133 | CompletionItemKind::Keyword => "kw", |
133 | CompletionItemKind::Module => "md", | 134 | CompletionItemKind::Module => "md", |
@@ -146,8 +147,7 @@ impl CompletionItemKind { | |||
146 | CompletionItemKind::TypeParam => "tp", | 147 | CompletionItemKind::TypeParam => "tp", |
147 | CompletionItemKind::Macro => "ma", | 148 | CompletionItemKind::Macro => "ma", |
148 | CompletionItemKind::Attribute => "at", | 149 | CompletionItemKind::Attribute => "at", |
149 | }; | 150 | } |
150 | tag.to_owned() | ||
151 | } | 151 | } |
152 | } | 152 | } |
153 | 153 | ||
diff --git a/crates/ra_ide/src/completion/patterns.rs b/crates/ra_ide/src/completion/patterns.rs index fdcd3faa5..b2fe13280 100644 --- a/crates/ra_ide/src/completion/patterns.rs +++ b/crates/ra_ide/src/completion/patterns.rs | |||
@@ -8,6 +8,9 @@ use ra_syntax::{ | |||
8 | SyntaxNode, SyntaxToken, | 8 | SyntaxNode, SyntaxToken, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | #[cfg(test)] | ||
12 | use crate::completion::test_utils::check_pattern_is_applicable; | ||
13 | |||
11 | pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool { | 14 | pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool { |
12 | not_same_range_ancestor(element) | 15 | not_same_range_ancestor(element) |
13 | .filter(|it| it.kind() == ITEM_LIST) | 16 | .filter(|it| it.kind() == ITEM_LIST) |
@@ -15,6 +18,10 @@ pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool { | |||
15 | .filter(|it| it.kind() == TRAIT_DEF) | 18 | .filter(|it| it.kind() == TRAIT_DEF) |
16 | .is_some() | 19 | .is_some() |
17 | } | 20 | } |
21 | #[test] | ||
22 | fn test_has_trait_parent() { | ||
23 | check_pattern_is_applicable(r"trait A { f<|> }", has_trait_parent); | ||
24 | } | ||
18 | 25 | ||
19 | pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { | 26 | pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { |
20 | not_same_range_ancestor(element) | 27 | not_same_range_ancestor(element) |
@@ -23,20 +30,38 @@ pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { | |||
23 | .filter(|it| it.kind() == IMPL_DEF) | 30 | .filter(|it| it.kind() == IMPL_DEF) |
24 | .is_some() | 31 | .is_some() |
25 | } | 32 | } |
33 | #[test] | ||
34 | fn test_has_impl_parent() { | ||
35 | check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent); | ||
36 | } | ||
26 | 37 | ||
27 | pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { | 38 | pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { |
28 | not_same_range_ancestor(element).filter(|it| it.kind() == BLOCK_EXPR).is_some() | 39 | not_same_range_ancestor(element).filter(|it| it.kind() == BLOCK_EXPR).is_some() |
29 | } | 40 | } |
41 | #[test] | ||
42 | fn test_has_block_expr_parent() { | ||
43 | check_pattern_is_applicable(r"fn my_fn() { let a = 2; f<|> }", has_block_expr_parent); | ||
44 | } | ||
30 | 45 | ||
31 | pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { | 46 | pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { |
32 | element.ancestors().find(|it| it.kind() == BIND_PAT).is_some() | 47 | element.ancestors().find(|it| it.kind() == BIND_PAT).is_some() |
33 | } | 48 | } |
49 | #[test] | ||
50 | fn test_has_bind_pat_parent() { | ||
51 | check_pattern_is_applicable(r"fn my_fn(m<|>) {}", has_bind_pat_parent); | ||
52 | check_pattern_is_applicable(r"fn my_fn() { let m<|> }", has_bind_pat_parent); | ||
53 | } | ||
34 | 54 | ||
35 | pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool { | 55 | pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool { |
36 | not_same_range_ancestor(element) | 56 | not_same_range_ancestor(element) |
37 | .filter(|it| it.kind() == REF_PAT || it.kind() == REF_EXPR) | 57 | .filter(|it| it.kind() == REF_PAT || it.kind() == REF_EXPR) |
38 | .is_some() | 58 | .is_some() |
39 | } | 59 | } |
60 | #[test] | ||
61 | fn test_has_ref_parent() { | ||
62 | check_pattern_is_applicable(r"fn my_fn(&m<|>) {}", has_ref_parent); | ||
63 | check_pattern_is_applicable(r"fn my() { let &m<|> }", has_ref_parent); | ||
64 | } | ||
40 | 65 | ||
41 | pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { | 66 | pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { |
42 | let ancestor = not_same_range_ancestor(element); | 67 | let ancestor = not_same_range_ancestor(element); |
@@ -45,6 +70,11 @@ pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> boo | |||
45 | } | 70 | } |
46 | ancestor.filter(|it| it.kind() == SOURCE_FILE || it.kind() == ITEM_LIST).is_some() | 71 | ancestor.filter(|it| it.kind() == SOURCE_FILE || it.kind() == ITEM_LIST).is_some() |
47 | } | 72 | } |
73 | #[test] | ||
74 | fn test_has_item_list_or_source_file_parent() { | ||
75 | check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent); | ||
76 | check_pattern_is_applicable(r"impl { f<|> }", has_item_list_or_source_file_parent); | ||
77 | } | ||
48 | 78 | ||
49 | pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { | 79 | pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { |
50 | not_same_range_ancestor(element.clone()).filter(|it| it.kind() == MATCH_ARM).is_some() | 80 | not_same_range_ancestor(element.clone()).filter(|it| it.kind() == MATCH_ARM).is_some() |
@@ -53,6 +83,10 @@ pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { | |||
53 | .filter(|it| it.kind() == FAT_ARROW) | 83 | .filter(|it| it.kind() == FAT_ARROW) |
54 | .is_some() | 84 | .is_some() |
55 | } | 85 | } |
86 | #[test] | ||
87 | fn test_is_match_arm() { | ||
88 | check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm); | ||
89 | } | ||
56 | 90 | ||
57 | pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { | 91 | pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { |
58 | element | 92 | element |
@@ -61,6 +95,10 @@ pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { | |||
61 | .filter(|it| it.kind() == UNSAFE_KW) | 95 | .filter(|it| it.kind() == UNSAFE_KW) |
62 | .is_some() | 96 | .is_some() |
63 | } | 97 | } |
98 | #[test] | ||
99 | fn test_unsafe_is_prev() { | ||
100 | check_pattern_is_applicable(r"unsafe i<|>", unsafe_is_prev); | ||
101 | } | ||
64 | 102 | ||
65 | pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { | 103 | pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { |
66 | element | 104 | element |
@@ -69,14 +107,26 @@ pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { | |||
69 | .filter(|it| it.kind() == IF_KW) | 107 | .filter(|it| it.kind() == IF_KW) |
70 | .is_some() | 108 | .is_some() |
71 | } | 109 | } |
110 | #[test] | ||
111 | fn test_if_is_prev() { | ||
112 | check_pattern_is_applicable(r"if l<|>", if_is_prev); | ||
113 | } | ||
72 | 114 | ||
73 | pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { | 115 | pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { |
74 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT_DEF).is_some() | 116 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT_DEF).is_some() |
75 | } | 117 | } |
118 | #[test] | ||
119 | fn test_has_trait_as_prev_sibling() { | ||
120 | check_pattern_is_applicable(r"trait A w<|> {}", has_trait_as_prev_sibling); | ||
121 | } | ||
76 | 122 | ||
77 | pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { | 123 | pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { |
78 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == IMPL_DEF).is_some() | 124 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == IMPL_DEF).is_some() |
79 | } | 125 | } |
126 | #[test] | ||
127 | fn test_has_impl_as_prev_sibling() { | ||
128 | check_pattern_is_applicable(r"impl A w<|> {}", has_impl_as_prev_sibling); | ||
129 | } | ||
80 | 130 | ||
81 | pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { | 131 | pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { |
82 | let leaf = match element { | 132 | let leaf = match element { |
@@ -142,83 +192,3 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option<Syntax | |||
142 | non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev) | 192 | non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev) |
143 | } | 193 | } |
144 | } | 194 | } |
145 | |||
146 | #[cfg(test)] | ||
147 | mod tests { | ||
148 | use super::{ | ||
149 | has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent, | ||
150 | has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling, | ||
151 | has_trait_parent, if_is_prev, is_match_arm, unsafe_is_prev, | ||
152 | }; | ||
153 | use crate::completion::test_utils::check_pattern_is_applicable; | ||
154 | |||
155 | #[test] | ||
156 | fn test_unsafe_is_prev() { | ||
157 | check_pattern_is_applicable(r"unsafe i<|>", unsafe_is_prev); | ||
158 | } | ||
159 | |||
160 | #[test] | ||
161 | fn test_if_is_prev() { | ||
162 | check_pattern_is_applicable(r"if l<|>", if_is_prev); | ||
163 | } | ||
164 | |||
165 | #[test] | ||
166 | fn test_has_trait_parent() { | ||
167 | check_pattern_is_applicable(r"trait A { f<|> }", has_trait_parent); | ||
168 | } | ||
169 | |||
170 | #[test] | ||
171 | fn test_has_impl_parent() { | ||
172 | check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent); | ||
173 | } | ||
174 | |||
175 | #[test] | ||
176 | fn test_has_trait_as_prev_sibling() { | ||
177 | check_pattern_is_applicable(r"trait A w<|> {}", has_trait_as_prev_sibling); | ||
178 | } | ||
179 | |||
180 | #[test] | ||
181 | fn test_has_impl_as_prev_sibling() { | ||
182 | check_pattern_is_applicable(r"impl A w<|> {}", has_impl_as_prev_sibling); | ||
183 | } | ||
184 | |||
185 | #[test] | ||
186 | fn test_parent_block_expr() { | ||
187 | check_pattern_is_applicable(r"fn my_fn() { let a = 2; f<|> }", has_block_expr_parent); | ||
188 | } | ||
189 | |||
190 | #[test] | ||
191 | fn test_has_ref_pat_parent_in_func_parameters() { | ||
192 | check_pattern_is_applicable(r"fn my_fn(&m<|>) {}", has_ref_parent); | ||
193 | } | ||
194 | |||
195 | #[test] | ||
196 | fn test_has_ref_pat_parent_in_let_statement() { | ||
197 | check_pattern_is_applicable(r"fn my() { let &m<|> }", has_ref_parent); | ||
198 | } | ||
199 | |||
200 | #[test] | ||
201 | fn test_has_bind_pat_parent_in_func_parameters() { | ||
202 | check_pattern_is_applicable(r"fn my_fn(m<|>) {}", has_bind_pat_parent); | ||
203 | } | ||
204 | |||
205 | #[test] | ||
206 | fn test_has_bind_pat_parent_in_let_statement() { | ||
207 | check_pattern_is_applicable(r"fn my_fn() { let m<|> }", has_bind_pat_parent); | ||
208 | } | ||
209 | |||
210 | #[test] | ||
211 | fn test_is_match_arm() { | ||
212 | check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm); | ||
213 | } | ||
214 | |||
215 | #[test] | ||
216 | fn test_has_source_file_parent() { | ||
217 | check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent); | ||
218 | } | ||
219 | |||
220 | #[test] | ||
221 | fn test_has_item_list_parent() { | ||
222 | check_pattern_is_applicable(r"impl { f<|> }", has_item_list_or_source_file_parent); | ||
223 | } | ||
224 | } | ||
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs index 8b838a0a5..ba724116d 100644 --- a/crates/ra_ide/src/completion/test_utils.rs +++ b/crates/ra_ide/src/completion/test_utils.rs | |||
@@ -25,7 +25,7 @@ pub(crate) fn do_completion_with_options( | |||
25 | .into_iter() | 25 | .into_iter() |
26 | .filter(|c| c.completion_kind == kind) | 26 | .filter(|c| c.completion_kind == kind) |
27 | .collect(); | 27 | .collect(); |
28 | kind_completions.sort_by_key(|c| c.label().to_owned()); | 28 | kind_completions.sort_by(|l, r| l.label().cmp(r.label())); |
29 | kind_completions | 29 | kind_completions |
30 | } | 30 | } |
31 | 31 | ||