diff options
author | Mikhail Rakhmanov <[email protected]> | 2020-06-11 23:17:30 +0100 |
---|---|---|
committer | Mikhail Rakhmanov <[email protected]> | 2020-06-11 23:17:30 +0100 |
commit | a2b4385f161134955fd729087f142d54c3a5e035 (patch) | |
tree | 57340237a1bc00f3b5383881bc289d224e4c6ee3 /crates/ra_ide/src/completion | |
parent | f46bc12199dc88b88bd826f49d5c5af6e9caf727 (diff) |
Add few smoke tests for patterns and refactoring
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r-- | crates/ra_ide/src/completion/complete_keyword.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 13 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/patterns.rs | 86 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/test_utils.rs | 14 |
4 files changed, 111 insertions, 10 deletions
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 50f003949..675991154 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs | |||
@@ -65,13 +65,13 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
65 | add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); | 65 | add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); |
66 | add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); | 66 | add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); |
67 | add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); | 67 | add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); |
68 | add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.after_unsafe); | 68 | add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); |
69 | add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !ctx.after_unsafe); | 69 | add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); |
70 | add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !ctx.after_unsafe); | 70 | add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); |
71 | add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent); | 71 | add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent); |
72 | add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent); | 72 | add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent); |
73 | add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); | 73 | add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); |
74 | add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent); | 74 | add_keyword(ctx, acc, "let", "let ", ctx.if_is_prev || ctx.block_expr_parent); |
75 | add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); | 75 | add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); |
76 | add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); | 76 | add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); |
77 | add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent); | 77 | add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent); |
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index e579e2ee2..41aec5686 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -12,8 +12,8 @@ use ra_syntax::{ | |||
12 | use ra_text_edit::Indel; | 12 | use ra_text_edit::Indel; |
13 | 13 | ||
14 | use super::patterns::{ | 14 | use super::patterns::{ |
15 | goes_after_unsafe, has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, | 15 | has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_ref_pat_parent, |
16 | has_ref_pat_parent, has_trait_as_prev_sibling, inside_trait, is_in_loop_body, | 16 | has_trait_as_prev_sibling, if_is_prev, inside_trait, is_in_loop_body, unsafe_is_prev, |
17 | }; | 17 | }; |
18 | use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; | 18 | use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; |
19 | use test_utils::mark; | 19 | use test_utils::mark; |
@@ -64,7 +64,8 @@ pub(crate) struct CompletionContext<'a> { | |||
64 | pub(super) is_path_type: bool, | 64 | pub(super) is_path_type: bool, |
65 | pub(super) has_type_args: bool, | 65 | pub(super) has_type_args: bool, |
66 | pub(super) attribute_under_caret: Option<ast::Attr>, | 66 | pub(super) attribute_under_caret: Option<ast::Attr>, |
67 | pub(super) after_unsafe: bool, | 67 | pub(super) unsafe_is_prev: bool, |
68 | pub(super) if_is_prev: bool, | ||
68 | pub(super) block_expr_parent: bool, | 69 | pub(super) block_expr_parent: bool, |
69 | pub(super) bind_pat_parent: bool, | 70 | pub(super) bind_pat_parent: bool, |
70 | pub(super) ref_pat_parent: bool, | 71 | pub(super) ref_pat_parent: bool, |
@@ -130,7 +131,7 @@ impl<'a> CompletionContext<'a> { | |||
130 | has_type_args: false, | 131 | has_type_args: false, |
131 | dot_receiver_is_ambiguous_float_literal: false, | 132 | dot_receiver_is_ambiguous_float_literal: false, |
132 | attribute_under_caret: None, | 133 | attribute_under_caret: None, |
133 | after_unsafe: false, | 134 | unsafe_is_prev: false, |
134 | in_loop_body: false, | 135 | in_loop_body: false, |
135 | ref_pat_parent: false, | 136 | ref_pat_parent: false, |
136 | bind_pat_parent: false, | 137 | bind_pat_parent: false, |
@@ -138,6 +139,7 @@ impl<'a> CompletionContext<'a> { | |||
138 | inside_trait: false, | 139 | inside_trait: false, |
139 | trait_as_prev_sibling: false, | 140 | trait_as_prev_sibling: false, |
140 | impl_as_prev_sibling: false, | 141 | impl_as_prev_sibling: false, |
142 | if_is_prev: false, | ||
141 | }; | 143 | }; |
142 | 144 | ||
143 | let mut original_file = original_file.syntax().clone(); | 145 | let mut original_file = original_file.syntax().clone(); |
@@ -212,7 +214,8 @@ impl<'a> CompletionContext<'a> { | |||
212 | let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap(); | 214 | let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap(); |
213 | let syntax_element = NodeOrToken::Token(fake_ident_token.clone()); | 215 | let syntax_element = NodeOrToken::Token(fake_ident_token.clone()); |
214 | self.block_expr_parent = has_block_expr_parent(syntax_element.clone()); | 216 | self.block_expr_parent = has_block_expr_parent(syntax_element.clone()); |
215 | self.after_unsafe = goes_after_unsafe(syntax_element.clone()); | 217 | self.unsafe_is_prev = unsafe_is_prev(syntax_element.clone()); |
218 | self.if_is_prev = if_is_prev(syntax_element.clone()); | ||
216 | self.bind_pat_parent = has_bind_pat_parent(syntax_element.clone()); | 219 | self.bind_pat_parent = has_bind_pat_parent(syntax_element.clone()); |
217 | self.ref_pat_parent = has_ref_pat_parent(syntax_element.clone()); | 220 | self.ref_pat_parent = has_ref_pat_parent(syntax_element.clone()); |
218 | self.in_loop_body = is_in_loop_body(syntax_element.clone()); | 221 | self.in_loop_body = is_in_loop_body(syntax_element.clone()); |
diff --git a/crates/ra_ide/src/completion/patterns.rs b/crates/ra_ide/src/completion/patterns.rs index 31d32ccd9..df2594152 100644 --- a/crates/ra_ide/src/completion/patterns.rs +++ b/crates/ra_ide/src/completion/patterns.rs | |||
@@ -22,7 +22,7 @@ pub(crate) fn has_ref_pat_parent(element: SyntaxElement) -> bool { | |||
22 | element.ancestors().find(|it| it.kind() == REF_PAT).is_some() | 22 | element.ancestors().find(|it| it.kind() == REF_PAT).is_some() |
23 | } | 23 | } |
24 | 24 | ||
25 | pub(crate) fn goes_after_unsafe(element: SyntaxElement) -> bool { | 25 | pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { |
26 | element | 26 | element |
27 | .into_token() | 27 | .into_token() |
28 | .and_then(|it| previous_non_trivia_token(it)) | 28 | .and_then(|it| previous_non_trivia_token(it)) |
@@ -30,6 +30,14 @@ pub(crate) fn goes_after_unsafe(element: SyntaxElement) -> bool { | |||
30 | .is_some() | 30 | .is_some() |
31 | } | 31 | } |
32 | 32 | ||
33 | pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { | ||
34 | element | ||
35 | .into_token() | ||
36 | .and_then(|it| previous_non_trivia_token(it)) | ||
37 | .filter(|it| it.kind() == IF_KW) | ||
38 | .is_some() | ||
39 | } | ||
40 | |||
33 | pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { | 41 | pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { |
34 | not_same_range_ancestor(element).filter(|it| it.kind() == BLOCK_EXPR).is_some() | 42 | not_same_range_ancestor(element).filter(|it| it.kind() == BLOCK_EXPR).is_some() |
35 | } | 43 | } |
@@ -110,3 +118,79 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option<Syntax | |||
110 | non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev) | 118 | non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev) |
111 | } | 119 | } |
112 | } | 120 | } |
121 | |||
122 | #[cfg(test)] | ||
123 | mod tests { | ||
124 | use super::{ | ||
125 | has_block_expr_parent, has_impl_as_prev_sibling, has_trait_as_prev_sibling, if_is_prev, | ||
126 | inside_trait, unsafe_is_prev, | ||
127 | }; | ||
128 | use crate::completion::test_utils::check_pattern_is_applicable; | ||
129 | |||
130 | #[test] | ||
131 | fn test_unsafe_is_prev() { | ||
132 | check_pattern_is_applicable( | ||
133 | r" | ||
134 | unsafe i<|> | ||
135 | ", | ||
136 | unsafe_is_prev, | ||
137 | ); | ||
138 | } | ||
139 | |||
140 | #[test] | ||
141 | fn test_if_is_prev() { | ||
142 | check_pattern_is_applicable( | ||
143 | r" | ||
144 | if l<|> | ||
145 | ", | ||
146 | if_is_prev, | ||
147 | ); | ||
148 | } | ||
149 | |||
150 | #[test] | ||
151 | fn test_inside_trait() { | ||
152 | check_pattern_is_applicable( | ||
153 | r" | ||
154 | trait A { | ||
155 | fn<|> | ||
156 | } | ||
157 | ", | ||
158 | inside_trait, | ||
159 | ); | ||
160 | } | ||
161 | |||
162 | #[test] | ||
163 | fn test_has_trait_as_prev_sibling() { | ||
164 | check_pattern_is_applicable( | ||
165 | r" | ||
166 | trait A w<|> { | ||
167 | } | ||
168 | ", | ||
169 | has_trait_as_prev_sibling, | ||
170 | ); | ||
171 | } | ||
172 | |||
173 | #[test] | ||
174 | fn test_has_impl_as_prev_sibling() { | ||
175 | check_pattern_is_applicable( | ||
176 | r" | ||
177 | impl A w<|> { | ||
178 | } | ||
179 | ", | ||
180 | has_impl_as_prev_sibling, | ||
181 | ); | ||
182 | } | ||
183 | |||
184 | #[test] | ||
185 | fn test_parent_block_expr() { | ||
186 | check_pattern_is_applicable( | ||
187 | r" | ||
188 | fn my_fn() { | ||
189 | let a = 2; | ||
190 | f<|> | ||
191 | } | ||
192 | ", | ||
193 | has_block_expr_parent, | ||
194 | ); | ||
195 | } | ||
196 | } | ||
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs index bf22452a2..e9e89104e 100644 --- a/crates/ra_ide/src/completion/test_utils.rs +++ b/crates/ra_ide/src/completion/test_utils.rs | |||
@@ -5,6 +5,8 @@ use crate::{ | |||
5 | mock_analysis::{analysis_and_position, single_file_with_position}, | 5 | mock_analysis::{analysis_and_position, single_file_with_position}, |
6 | CompletionItem, | 6 | CompletionItem, |
7 | }; | 7 | }; |
8 | use hir::Semantics; | ||
9 | use ra_syntax::{AstNode, NodeOrToken, SyntaxElement, SyntaxToken}; | ||
8 | 10 | ||
9 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | 11 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { |
10 | do_completion_with_options(code, kind, &CompletionConfig::default()) | 12 | do_completion_with_options(code, kind, &CompletionConfig::default()) |
@@ -27,3 +29,15 @@ pub(crate) fn do_completion_with_options( | |||
27 | kind_completions.sort_by_key(|c| c.label().to_owned()); | 29 | kind_completions.sort_by_key(|c| c.label().to_owned()); |
28 | kind_completions | 30 | kind_completions |
29 | } | 31 | } |
32 | |||
33 | pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { | ||
34 | let (analysis, pos) = single_file_with_position(code); | ||
35 | analysis | ||
36 | .with_db(|db| { | ||
37 | let sema = Semantics::new(db); | ||
38 | let original_file = sema.parse(pos.file_id); | ||
39 | let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap(); | ||
40 | assert!(check(NodeOrToken::Token(token))); | ||
41 | }) | ||
42 | .unwrap(); | ||
43 | } | ||