aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion/patterns.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion/patterns.rs')
-rw-r--r--crates/ra_ide/src/completion/patterns.rs130
1 files changed, 50 insertions, 80 deletions
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)]
12use crate::completion::test_utils::check_pattern_is_applicable;
13
11pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool { 14pub(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]
22fn test_has_trait_parent() {
23 check_pattern_is_applicable(r"trait A { f<|> }", has_trait_parent);
24}
18 25
19pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { 26pub(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]
34fn test_has_impl_parent() {
35 check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent);
36}
26 37
27pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { 38pub(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]
42fn 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
31pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { 46pub(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]
50fn 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
35pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool { 55pub(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]
61fn 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
41pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { 66pub(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]
74fn 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
49pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { 79pub(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]
87fn test_is_match_arm() {
88 check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm);
89}
56 90
57pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { 91pub(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]
99fn test_unsafe_is_prev() {
100 check_pattern_is_applicable(r"unsafe i<|>", unsafe_is_prev);
101}
64 102
65pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { 103pub(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]
111fn test_if_is_prev() {
112 check_pattern_is_applicable(r"if l<|>", if_is_prev);
113}
72 114
73pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { 115pub(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]
119fn test_has_trait_as_prev_sibling() {
120 check_pattern_is_applicable(r"trait A w<|> {}", has_trait_as_prev_sibling);
121}
76 122
77pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { 123pub(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]
127fn test_has_impl_as_prev_sibling() {
128 check_pattern_is_applicable(r"impl A w<|> {}", has_impl_as_prev_sibling);
129}
80 130
81pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { 131pub(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)]
147mod 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}