aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/completion/complete_keyword.rs183
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs26
-rw-r--r--crates/ra_ide/src/completion/patterns.rs84
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs52
4 files changed, 100 insertions, 245 deletions
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs
index 8ea51c7aa..432793de2 100644
--- a/crates/ra_ide/src/completion/complete_keyword.rs
+++ b/crates/ra_ide/src/completion/complete_keyword.rs
@@ -61,7 +61,6 @@ fn add_keyword(
61 61
62pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { 62pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
63 add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); 63 add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent);
64 add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent);
65 add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); 64 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); 65 add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item);
67 add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); 66 add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item);
@@ -111,12 +110,9 @@ fn complete_return(
111 110
112#[cfg(test)] 111#[cfg(test)]
113mod tests { 112mod tests {
114 use crate::{ 113 use crate::completion::{
115 completion::{ 114 test_utils::{do_completion, get_completions},
116 test_utils::{do_completion, do_completion_with_position}, 115 CompletionItem, CompletionKind,
117 CompletionItem, CompletionKind,
118 },
119 CompletionItemKind,
120 }; 116 };
121 use insta::assert_debug_snapshot; 117 use insta::assert_debug_snapshot;
122 118
@@ -124,132 +120,39 @@ mod tests {
124 do_completion(code, CompletionKind::Keyword) 120 do_completion(code, CompletionKind::Keyword)
125 } 121 }
126 122
127 fn get_completion_text_and_assert_positions(code: &str) -> Vec<(String, String)> { 123 fn get_keyword_completions(code: &str) -> Vec<String> {
128 let (position, completion_items) = 124 get_completions(code, CompletionKind::Keyword)
129 do_completion_with_position(code, CompletionKind::Keyword);
130 let mut returned_keywords = Vec::<(String, String)>::new();
131
132 for item in completion_items {
133 assert!(item.text_edit().len() == 1);
134 assert!(item.kind() == Some(CompletionItemKind::Keyword));
135 let atom = item.text_edit().iter().next().unwrap().clone();
136 assert!(atom.delete.start() == position.offset);
137 assert!(atom.delete.end() == position.offset);
138 let pair = (item.label().to_string(), atom.insert);
139 returned_keywords.push(pair);
140 }
141 returned_keywords.sort();
142 returned_keywords
143 }
144
145 #[test]
146 fn completes_keywords_in_use_stmt_new_approach() {
147 assert_debug_snapshot!(
148 get_completion_text_and_assert_positions(r"
149 use <|>
150 "),
151 @r###"
152 [
153 (
154 "crate",
155 "crate::",
156 ),
157 (
158 "self",
159 "self",
160 ),
161 (
162 "super",
163 "super::",
164 ),
165 ]
166 "###
167 );
168 } 125 }
169 126
170 #[test] 127 #[test]
171 fn completes_keywords_in_use_stmt() { 128 fn completes_keywords_in_use_stmt() {
172 assert_debug_snapshot!( 129 assert_debug_snapshot!(
173 do_keyword_completion( 130 get_keyword_completions(r"use <|>"),
174 r"
175 use <|>
176 ",
177 ),
178 @r###" 131 @r###"
179 [ 132 [
180 CompletionItem { 133 "kw crate",
181 label: "crate", 134 "kw self",
182 source_range: 21..21, 135 "kw super",
183 delete: 21..21,
184 insert: "crate::",
185 kind: Keyword,
186 },
187 CompletionItem {
188 label: "self",
189 source_range: 21..21,
190 delete: 21..21,
191 insert: "self",
192 kind: Keyword,
193 },
194 CompletionItem {
195 label: "super",
196 source_range: 21..21,
197 delete: 21..21,
198 insert: "super::",
199 kind: Keyword,
200 },
201 ] 136 ]
202 "### 137 "###
203 ); 138 );
204 139
205 assert_debug_snapshot!( 140 assert_debug_snapshot!(
206 do_keyword_completion( 141 get_keyword_completions(r"use a::<|>"),
207 r"
208 use a::<|>
209 ",
210 ),
211 @r###" 142 @r###"
212 [ 143 [
213 CompletionItem { 144 "kw self",
214 label: "self", 145 "kw super",
215 source_range: 24..24,
216 delete: 24..24,
217 insert: "self",
218 kind: Keyword,
219 },
220 CompletionItem {
221 label: "super",
222 source_range: 24..24,
223 delete: 24..24,
224 insert: "super::",
225 kind: Keyword,
226 },
227 ] 146 ]
228 "### 147 "###
229 ); 148 );
230 149
231 assert_debug_snapshot!( 150 assert_debug_snapshot!(
232 do_keyword_completion( 151 get_keyword_completions(r"use a::{b, <|>}"),
233 r"
234 use a::{b, <|>}
235 ",
236 ),
237 @r###" 152 @r###"
238 [ 153 [
239 CompletionItem { 154 "kw self",
240 label: "self", 155 "kw super",
241 source_range: 28..28,
242 delete: 28..28,
243 insert: "self",
244 kind: Keyword,
245 },
246 CompletionItem {
247 label: "super",
248 source_range: 28..28,
249 delete: 28..28,
250 insert: "super::",
251 kind: Keyword,
252 },
253 ] 156 ]
254 "### 157 "###
255 ); 158 );
@@ -258,50 +161,22 @@ mod tests {
258 #[test] 161 #[test]
259 fn completes_various_keywords_in_function() { 162 fn completes_various_keywords_in_function() {
260 assert_debug_snapshot!( 163 assert_debug_snapshot!(
261 do_keyword_completion( 164 get_keyword_completions(r"fn quux() { <|> }"),
262 r"
263 fn quux() {
264 <|>
265 }
266 ",
267 ),
268 @r###" 165 @r###"
269 [ 166 [
270 CompletionItem { 167 "kw const",
271 label: "if", 168 "kw extern",
272 source_range: 49..49, 169 "kw fn",
273 delete: 49..49, 170 "kw let",
274 insert: "if $0 {}", 171 "kw loop",
275 kind: Keyword, 172 "kw match",
276 }, 173 "kw mod",
277 CompletionItem { 174 "kw return",
278 label: "loop", 175 "kw static",
279 source_range: 49..49, 176 "kw type",
280 delete: 49..49, 177 "kw unsafe",
281 insert: "loop {$0}", 178 "kw use",
282 kind: Keyword, 179 "kw while",
283 },
284 CompletionItem {
285 label: "match",
286 source_range: 49..49,
287 delete: 49..49,
288 insert: "match $0 {}",
289 kind: Keyword,
290 },
291 CompletionItem {
292 label: "return",
293 source_range: 49..49,
294 delete: 49..49,
295 insert: "return;",
296 kind: Keyword,
297 },
298 CompletionItem {
299 label: "while",
300 source_range: 49..49,
301 delete: 49..49,
302 insert: "while $0 {}",
303 kind: Keyword,
304 },
305 ] 180 ]
306 "### 181 "###
307 ); 182 );
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index cfb7c1e38..d1a4dd881 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -125,6 +125,32 @@ pub enum CompletionItemKind {
125 Attribute, 125 Attribute,
126} 126}
127 127
128impl CompletionItemKind {
129 pub fn tag(&self) -> String {
130 let tag = match self {
131 CompletionItemKind::Snippet => "sn",
132 CompletionItemKind::Keyword => "kw",
133 CompletionItemKind::Module => "md",
134 CompletionItemKind::Function => "fn",
135 CompletionItemKind::BuiltinType => "bt",
136 CompletionItemKind::Struct => "st",
137 CompletionItemKind::Enum => "en",
138 CompletionItemKind::EnumVariant => "ev",
139 CompletionItemKind::Binding => "bn",
140 CompletionItemKind::Field => "fd",
141 CompletionItemKind::Static => "sc",
142 CompletionItemKind::Const => "ct",
143 CompletionItemKind::Trait => "tt",
144 CompletionItemKind::TypeAlias => "ta",
145 CompletionItemKind::Method => "me",
146 CompletionItemKind::TypeParam => "tp",
147 CompletionItemKind::Macro => "ma",
148 CompletionItemKind::Attribute => "at",
149 };
150 tag.to_owned()
151 }
152}
153
128#[derive(Debug, PartialEq, Eq, Copy, Clone)] 154#[derive(Debug, PartialEq, Eq, Copy, Clone)]
129pub(crate) enum CompletionKind { 155pub(crate) enum CompletionKind {
130 /// Parser-based keyword completion. 156 /// Parser-based keyword completion.
diff --git a/crates/ra_ide/src/completion/patterns.rs b/crates/ra_ide/src/completion/patterns.rs
index 25be0c307..bc39689ab 100644
--- a/crates/ra_ide/src/completion/patterns.rs
+++ b/crates/ra_ide/src/completion/patterns.rs
@@ -121,115 +121,51 @@ mod tests {
121 121
122 #[test] 122 #[test]
123 fn test_unsafe_is_prev() { 123 fn test_unsafe_is_prev() {
124 check_pattern_is_applicable( 124 check_pattern_is_applicable(r"unsafe i<|>", unsafe_is_prev);
125 r"
126 unsafe i<|>
127 ",
128 unsafe_is_prev,
129 );
130 } 125 }
131 126
132 #[test] 127 #[test]
133 fn test_if_is_prev() { 128 fn test_if_is_prev() {
134 check_pattern_is_applicable( 129 check_pattern_is_applicable(r"if l<|>", if_is_prev);
135 r"
136 if l<|>
137 ",
138 if_is_prev,
139 );
140 } 130 }
141 131
142 #[test] 132 #[test]
143 fn test_inside_trait() { 133 fn test_inside_trait() {
144 check_pattern_is_applicable( 134 check_pattern_is_applicable(r"trait A { fn<|> }", inside_trait);
145 r"
146 trait A {
147 fn<|>
148 }
149 ",
150 inside_trait,
151 );
152 } 135 }
153 136
154 #[test] 137 #[test]
155 fn test_has_trait_as_prev_sibling() { 138 fn test_has_trait_as_prev_sibling() {
156 check_pattern_is_applicable( 139 check_pattern_is_applicable(r"trait A w<|> {}", has_trait_as_prev_sibling);
157 r"
158 trait A w<|> {
159 }
160 ",
161 has_trait_as_prev_sibling,
162 );
163 } 140 }
164 141
165 #[test] 142 #[test]
166 fn test_has_impl_as_prev_sibling() { 143 fn test_has_impl_as_prev_sibling() {
167 check_pattern_is_applicable( 144 check_pattern_is_applicable(r"impl A w<|> {}", has_impl_as_prev_sibling);
168 r"
169 impl A w<|> {
170 }
171 ",
172 has_impl_as_prev_sibling,
173 );
174 } 145 }
175 146
176 #[test] 147 #[test]
177 fn test_parent_block_expr() { 148 fn test_parent_block_expr() {
178 check_pattern_is_applicable( 149 check_pattern_is_applicable(r"fn my_fn() { let a = 2; f<|> }", has_block_expr_parent);
179 r"
180 fn my_fn() {
181 let a = 2;
182 f<|>
183 }
184 ",
185 has_block_expr_parent,
186 );
187 } 150 }
188 151
189 #[test] 152 #[test]
190 fn test_has_ref_pat_parent_in_func_parameters() { 153 fn test_has_ref_pat_parent_in_func_parameters() {
191 check_pattern_is_applicable( 154 check_pattern_is_applicable(r"fn my_fn(&<|>) {}", has_ref_pat_parent);
192 r"
193 fn my_fn(&<|>) {
194 let a = 2;
195 }
196 ",
197 has_ref_pat_parent,
198 );
199 } 155 }
200 156
201 #[test] 157 #[test]
202 fn test_has_ref_pat_parent_in_let_statement() { 158 fn test_has_ref_pat_parent_in_let_statement() {
203 check_pattern_is_applicable( 159 check_pattern_is_applicable(r"fn my_fn() { let &<|> }", has_ref_pat_parent);
204 r"
205 fn my_fn() {
206 let &<|>
207 }
208 ",
209 has_ref_pat_parent,
210 );
211 } 160 }
212 161
213 #[test] 162 #[test]
214 fn test_has_bind_pat_parent_in_func_parameters() { 163 fn test_has_bind_pat_parent_in_func_parameters() {
215 check_pattern_is_applicable( 164 check_pattern_is_applicable(r"fn my_fn(m<|>) {}", has_bind_pat_parent);
216 r"
217 fn my_fn(m<|>) {
218 }
219 ",
220 has_bind_pat_parent,
221 );
222 } 165 }
223 166
224 #[test] 167 #[test]
225 fn test_has_bind_pat_parent_in_let_statement() { 168 fn test_has_bind_pat_parent_in_let_statement() {
226 check_pattern_is_applicable( 169 check_pattern_is_applicable(r"fn my_fn() { let m<|> }", has_bind_pat_parent);
227 r"
228 fn my_fn() {
229 let m<|>
230 }
231 ",
232 has_bind_pat_parent,
233 );
234 } 170 }
235} 171}
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index f439f974d..c660de7b1 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -3,7 +3,7 @@
3use crate::{ 3use crate::{
4 completion::{completion_item::CompletionKind, CompletionConfig}, 4 completion::{completion_item::CompletionKind, CompletionConfig},
5 mock_analysis::{analysis_and_position, single_file_with_position}, 5 mock_analysis::{analysis_and_position, single_file_with_position},
6 CompletionItem, FilePosition, 6 CompletionItem,
7}; 7};
8use hir::Semantics; 8use hir::Semantics;
9use ra_syntax::{AstNode, NodeOrToken, SyntaxElement}; 9use ra_syntax::{AstNode, NodeOrToken, SyntaxElement};
@@ -12,11 +12,8 @@ pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionI
12 do_completion_with_options(code, kind, &CompletionConfig::default()) 12 do_completion_with_options(code, kind, &CompletionConfig::default())
13} 13}
14 14
15pub(crate) fn do_completion_with_position( 15pub(crate) fn get_completions(code: &str, kind: CompletionKind) -> Vec<String> {
16 code: &str, 16 get_completions_with_options(code, kind, &CompletionConfig::default())
17 kind: CompletionKind,
18) -> (FilePosition, Vec<CompletionItem>) {
19 do_completion_with_options_and_position(code, kind, &CompletionConfig::default())
20} 17}
21 18
22pub(crate) fn do_completion_with_options( 19pub(crate) fn do_completion_with_options(
@@ -24,25 +21,46 @@ pub(crate) fn do_completion_with_options(
24 kind: CompletionKind, 21 kind: CompletionKind,
25 options: &CompletionConfig, 22 options: &CompletionConfig,
26) -> Vec<CompletionItem> { 23) -> Vec<CompletionItem> {
27 do_completion_with_options_and_position(code, kind, options).1 24 let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, options)
25 .into_iter()
26 .filter(|c| c.completion_kind == kind)
27 .collect();
28 kind_completions.sort_by_key(|c| c.label().to_owned());
29 kind_completions
28} 30}
29 31
30pub(crate) fn do_completion_with_options_and_position( 32fn get_all_completion_items(code: &str, options: &CompletionConfig) -> Vec<CompletionItem> {
31 code: &str,
32 kind: CompletionKind,
33 options: &CompletionConfig,
34) -> (FilePosition, Vec<CompletionItem>) {
35 let (analysis, position) = if code.contains("//-") { 33 let (analysis, position) = if code.contains("//-") {
36 analysis_and_position(code) 34 analysis_and_position(code)
37 } else { 35 } else {
38 single_file_with_position(code) 36 single_file_with_position(code)
39 }; 37 };
40 let completions = analysis.completions(options, position).unwrap().unwrap(); 38 analysis.completions(options, position).unwrap().unwrap().into()
41 let completion_items: Vec<CompletionItem> = completions.into(); 39}
42 let mut kind_completions: Vec<CompletionItem> = 40
43 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); 41pub(crate) fn get_all_completions(code: &str, options: &CompletionConfig) -> Vec<String> {
42 let mut kind_completions = get_all_completion_items(code, options);
43 kind_completions.sort_by_key(|c| c.label().to_owned());
44 kind_completions
45 .into_iter()
46 .map(|it| format!("{} {}", it.kind().unwrap().tag(), it.label()))
47 .collect()
48}
49
50pub(crate) fn get_completions_with_options(
51 code: &str,
52 kind: CompletionKind,
53 options: &CompletionConfig,
54) -> Vec<String> {
55 let mut kind_completions: Vec<CompletionItem> = get_all_completion_items(code, options)
56 .into_iter()
57 .filter(|c| c.completion_kind == kind)
58 .collect();
44 kind_completions.sort_by_key(|c| c.label().to_owned()); 59 kind_completions.sort_by_key(|c| c.label().to_owned());
45 (position, kind_completions) 60 kind_completions
61 .into_iter()
62 .map(|it| format!("{} {}", it.kind().unwrap().tag(), it.label()))
63 .collect()
46} 64}
47 65
48pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { 66pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) {