diff options
Diffstat (limited to 'crates/ide_completion/src/patterns.rs')
-rw-r--r-- | crates/ide_completion/src/patterns.rs | 58 |
1 files changed, 23 insertions, 35 deletions
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index 3d8a83ed8..04f2c532b 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs | |||
@@ -4,7 +4,7 @@ use syntax::{ | |||
4 | algo::non_trivia_sibling, | 4 | algo::non_trivia_sibling, |
5 | ast::{self, LoopBodyOwner}, | 5 | ast::{self, LoopBodyOwner}, |
6 | match_ast, AstNode, Direction, NodeOrToken, SyntaxElement, | 6 | match_ast, AstNode, Direction, NodeOrToken, SyntaxElement, |
7 | SyntaxKind::*, | 7 | SyntaxKind::{self, *}, |
8 | SyntaxNode, SyntaxToken, T, | 8 | SyntaxNode, SyntaxToken, T, |
9 | }; | 9 | }; |
10 | 10 | ||
@@ -73,6 +73,7 @@ fn test_has_block_expr_parent() { | |||
73 | pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { | 73 | pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { |
74 | element.ancestors().any(|it| it.kind() == IDENT_PAT) | 74 | element.ancestors().any(|it| it.kind() == IDENT_PAT) |
75 | } | 75 | } |
76 | |||
76 | #[test] | 77 | #[test] |
77 | fn test_has_bind_pat_parent() { | 78 | fn test_has_bind_pat_parent() { |
78 | check_pattern_is_applicable(r"fn my_fn(m$0) {}", has_bind_pat_parent); | 79 | check_pattern_is_applicable(r"fn my_fn(m$0) {}", has_bind_pat_parent); |
@@ -91,11 +92,10 @@ fn test_has_ref_parent() { | |||
91 | } | 92 | } |
92 | 93 | ||
93 | pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { | 94 | pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { |
94 | let ancestor = not_same_range_ancestor(element); | 95 | match not_same_range_ancestor(element) { |
95 | if !ancestor.is_some() { | 96 | Some(it) => it.kind() == SOURCE_FILE || it.kind() == ITEM_LIST, |
96 | return true; | 97 | None => true, |
97 | } | 98 | } |
98 | ancestor.filter(|it| it.kind() == SOURCE_FILE || it.kind() == ITEM_LIST).is_some() | ||
99 | } | 99 | } |
100 | #[test] | 100 | #[test] |
101 | fn test_has_item_list_or_source_file_parent() { | 101 | fn test_has_item_list_or_source_file_parent() { |
@@ -134,42 +134,30 @@ fn test_for_is_prev2() { | |||
134 | check_pattern_is_applicable(r"for i i$0", for_is_prev2); | 134 | check_pattern_is_applicable(r"for i i$0", for_is_prev2); |
135 | } | 135 | } |
136 | 136 | ||
137 | pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { | 137 | pub(crate) fn has_prev_sibling(element: SyntaxElement, kind: SyntaxKind) -> bool { |
138 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT).is_some() | 138 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == kind).is_some() |
139 | } | ||
140 | #[test] | ||
141 | fn test_has_trait_as_prev_sibling() { | ||
142 | check_pattern_is_applicable(r"trait A w$0 {}", has_trait_as_prev_sibling); | ||
143 | } | ||
144 | |||
145 | pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { | ||
146 | previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == IMPL).is_some() | ||
147 | } | 139 | } |
148 | #[test] | 140 | #[test] |
149 | fn test_has_impl_as_prev_sibling() { | 141 | fn test_has_impl_as_prev_sibling() { |
150 | check_pattern_is_applicable(r"impl A w$0 {}", has_impl_as_prev_sibling); | 142 | check_pattern_is_applicable(r"impl A w$0 {}", |it| has_prev_sibling(it, IMPL)); |
151 | } | 143 | } |
152 | 144 | ||
153 | pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { | 145 | pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { |
154 | for node in element.ancestors() { | 146 | element |
155 | if node.kind() == FN || node.kind() == CLOSURE_EXPR { | 147 | .ancestors() |
156 | break; | 148 | .take_while(|it| it.kind() != FN && it.kind() != CLOSURE_EXPR) |
157 | } | 149 | .find_map(|it| { |
158 | let loop_body = match_ast! { | 150 | let loop_body = match_ast! { |
159 | match node { | 151 | match it { |
160 | ast::ForExpr(it) => it.loop_body(), | 152 | ast::ForExpr(it) => it.loop_body(), |
161 | ast::WhileExpr(it) => it.loop_body(), | 153 | ast::WhileExpr(it) => it.loop_body(), |
162 | ast::LoopExpr(it) => it.loop_body(), | 154 | ast::LoopExpr(it) => it.loop_body(), |
163 | _ => None, | 155 | _ => None, |
164 | } | 156 | } |
165 | }; | 157 | }; |
166 | if let Some(body) = loop_body { | 158 | loop_body.filter(|it| it.syntax().text_range().contains_range(element.text_range())) |
167 | if body.syntax().text_range().contains_range(element.text_range()) { | 159 | }) |
168 | return true; | 160 | .is_some() |
169 | } | ||
170 | } | ||
171 | } | ||
172 | false | ||
173 | } | 161 | } |
174 | 162 | ||
175 | fn not_same_range_ancestor(element: SyntaxElement) -> Option<SyntaxNode> { | 163 | fn not_same_range_ancestor(element: SyntaxElement) -> Option<SyntaxNode> { |