aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion
diff options
context:
space:
mode:
authorMikhail Rakhmanov <[email protected]>2020-06-11 23:17:30 +0100
committerMikhail Rakhmanov <[email protected]>2020-06-11 23:17:30 +0100
commita2b4385f161134955fd729087f142d54c3a5e035 (patch)
tree57340237a1bc00f3b5383881bc289d224e4c6ee3 /crates/ra_ide/src/completion
parentf46bc12199dc88b88bd826f49d5c5af6e9caf727 (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.rs8
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs13
-rw-r--r--crates/ra_ide/src/completion/patterns.rs86
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs14
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::{
12use ra_text_edit::Indel; 12use ra_text_edit::Indel;
13 13
14use super::patterns::{ 14use 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};
18use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; 18use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition};
19use test_utils::mark; 19use 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
25pub(crate) fn goes_after_unsafe(element: SyntaxElement) -> bool { 25pub(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
33pub(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
33pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { 41pub(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)]
123mod 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};
8use hir::Semantics;
9use ra_syntax::{AstNode, NodeOrToken, SyntaxElement, SyntaxToken};
8 10
9pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { 11pub(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
33pub(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}