diff options
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/completion.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 114 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_item.rs | 62 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/test_utils.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 4 |
6 files changed, 91 insertions, 108 deletions
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index 185450508..38c8aed8d 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs | |||
@@ -29,7 +29,7 @@ use crate::{ | |||
29 | }; | 29 | }; |
30 | 30 | ||
31 | pub use crate::completion::completion_item::{ | 31 | pub use crate::completion::completion_item::{ |
32 | CompletionItem, CompletionItemKind, InsertTextFormat, | 32 | CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, |
33 | }; | 33 | }; |
34 | 34 | ||
35 | #[derive(Clone, Debug, PartialEq, Eq)] | 35 | #[derive(Clone, Debug, PartialEq, Eq)] |
@@ -94,8 +94,8 @@ pub(crate) fn completions( | |||
94 | complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); | 94 | complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); |
95 | complete_trait_impl::complete_trait_impl(&mut acc, &ctx); | 95 | complete_trait_impl::complete_trait_impl(&mut acc, &ctx); |
96 | 96 | ||
97 | // Reorder completion items if there is a sort_option | 97 | // Compute score for completion items |
98 | acc.sort(&ctx); | 98 | acc.compute_score(&ctx); |
99 | 99 | ||
100 | Some(acc) | 100 | Some(acc) |
101 | } | 101 | } |
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index 2e228b638..174b39964 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -6,12 +6,11 @@ use hir::{ | |||
6 | Type, | 6 | Type, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | use crate::completion::completion_item::CompletionKind; | ||
10 | use crate::{ | 9 | use crate::{ |
11 | call_info::call_info, | 10 | call_info::call_info, |
12 | completion::{ | 11 | completion::{ |
13 | completion_context::CompletionContext, | 12 | completion_context::CompletionContext, |
14 | completion_item::{Completions, SortOption}, | 13 | completion_item::{CompletionKind, Completions, ScoreOption}, |
15 | }, | 14 | }, |
16 | // CallInfo, | 15 | // CallInfo, |
17 | CompletionItem, | 16 | CompletionItem, |
@@ -49,40 +48,12 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty | |||
49 | for receiver in receiver.autoderef(ctx.db) { | 48 | for receiver in receiver.autoderef(ctx.db) { |
50 | let fields = receiver.fields(ctx.db); | 49 | let fields = receiver.fields(ctx.db); |
51 | 50 | ||
52 | // If we use this implementation we can delete call_info in the CompletionContext | ||
53 | if let Some(record_field) = &ctx.record_field_syntax { | 51 | if let Some(record_field) = &ctx.record_field_syntax { |
54 | acc.with_sort_option(SortOption::RecordField(record_field.clone())); | 52 | acc.with_score_option(ScoreOption::RecordField(record_field.clone())); |
55 | } else if let Some(call_info) = call_info(ctx.db, ctx.file_position) { | 53 | } else if let Some(call_info) = call_info(ctx.db, ctx.file_position) { |
56 | acc.with_sort_option(SortOption::CallFn(call_info)); | 54 | acc.with_score_option(ScoreOption::CallFn(call_info)); |
57 | } | 55 | } |
58 | 56 | ||
59 | // // For Call Fn | ||
60 | // if let Some(call_info) = &ctx.call_info { | ||
61 | // if let Some(active_parameter_type) = call_info.active_parameter_type() { | ||
62 | // let active_parameter_name = call_info.active_parameter_name().unwrap(); | ||
63 | // fields.sort_by(|a, b| { | ||
64 | // // For the same type | ||
65 | // if active_parameter_type == a.1.display(ctx.db).to_string() { | ||
66 | // // If same type + same name then go top position | ||
67 | // if active_parameter_name == a.0.name(ctx.db).to_string() { | ||
68 | // Ordering::Less | ||
69 | // } else { | ||
70 | // if active_parameter_type == b.1.display(ctx.db).to_string() { | ||
71 | // Ordering::Equal | ||
72 | // } else { | ||
73 | // Ordering::Less | ||
74 | // } | ||
75 | // } | ||
76 | // } else { | ||
77 | // Ordering::Greater | ||
78 | // } | ||
79 | // }); | ||
80 | // } | ||
81 | // } | ||
82 | |||
83 | // For Lit struct fields | ||
84 | // --- | ||
85 | |||
86 | for (field, ty) in fields { | 57 | for (field, ty) in fields { |
87 | if ctx.scope().module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) { | 58 | if ctx.scope().module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) { |
88 | // Skip private field. FIXME: If the definition location of the | 59 | // Skip private field. FIXME: If the definition location of the |
@@ -116,20 +87,13 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T | |||
116 | 87 | ||
117 | #[cfg(test)] | 88 | #[cfg(test)] |
118 | mod tests { | 89 | mod tests { |
119 | use crate::completion::{ | 90 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; |
120 | test_utils::{do_completion, do_completion_without_sort}, | ||
121 | CompletionItem, CompletionKind, | ||
122 | }; | ||
123 | use insta::assert_debug_snapshot; | 91 | use insta::assert_debug_snapshot; |
124 | 92 | ||
125 | fn do_ref_completion(code: &str) -> Vec<CompletionItem> { | 93 | fn do_ref_completion(code: &str) -> Vec<CompletionItem> { |
126 | do_completion(code, CompletionKind::Reference) | 94 | do_completion(code, CompletionKind::Reference) |
127 | } | 95 | } |
128 | 96 | ||
129 | fn do_ref_completion_without_sort(code: &str) -> Vec<CompletionItem> { | ||
130 | do_completion_without_sort(code, CompletionKind::Reference) | ||
131 | } | ||
132 | |||
133 | #[test] | 97 | #[test] |
134 | fn test_struct_field_completion() { | 98 | fn test_struct_field_completion() { |
135 | assert_debug_snapshot!( | 99 | assert_debug_snapshot!( |
@@ -159,7 +123,7 @@ mod tests { | |||
159 | #[test] | 123 | #[test] |
160 | fn test_struct_field_completion_in_func_call() { | 124 | fn test_struct_field_completion_in_func_call() { |
161 | assert_debug_snapshot!( | 125 | assert_debug_snapshot!( |
162 | do_ref_completion_without_sort( | 126 | do_ref_completion( |
163 | r" | 127 | r" |
164 | struct A { another_field: i64, the_field: u32, my_string: String } | 128 | struct A { another_field: i64, the_field: u32, my_string: String } |
165 | fn test(my_param: u32) -> u32 { my_param } | 129 | fn test(my_param: u32) -> u32 { my_param } |
@@ -171,14 +135,6 @@ mod tests { | |||
171 | @r###" | 135 | @r###" |
172 | [ | 136 | [ |
173 | CompletionItem { | 137 | CompletionItem { |
174 | label: "the_field", | ||
175 | source_range: [201; 201), | ||
176 | delete: [201; 201), | ||
177 | insert: "the_field", | ||
178 | kind: Field, | ||
179 | detail: "u32", | ||
180 | }, | ||
181 | CompletionItem { | ||
182 | label: "another_field", | 138 | label: "another_field", |
183 | source_range: [201; 201), | 139 | source_range: [201; 201), |
184 | delete: [201; 201), | 140 | delete: [201; 201), |
@@ -194,6 +150,15 @@ mod tests { | |||
194 | kind: Field, | 150 | kind: Field, |
195 | detail: "{unknown}", | 151 | detail: "{unknown}", |
196 | }, | 152 | }, |
153 | CompletionItem { | ||
154 | label: "the_field", | ||
155 | source_range: [201; 201), | ||
156 | delete: [201; 201), | ||
157 | insert: "the_field", | ||
158 | kind: Field, | ||
159 | detail: "u32", | ||
160 | score: TypeMatch, | ||
161 | }, | ||
197 | ] | 162 | ] |
198 | "### | 163 | "### |
199 | ); | 164 | ); |
@@ -202,7 +167,7 @@ mod tests { | |||
202 | #[test] | 167 | #[test] |
203 | fn test_struct_field_completion_in_func_call_with_type_and_name() { | 168 | fn test_struct_field_completion_in_func_call_with_type_and_name() { |
204 | assert_debug_snapshot!( | 169 | assert_debug_snapshot!( |
205 | do_ref_completion_without_sort( | 170 | do_ref_completion( |
206 | r" | 171 | r" |
207 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } | 172 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } |
208 | fn test(the_field: u32) -> u32 { the_field } | 173 | fn test(the_field: u32) -> u32 { the_field } |
@@ -214,12 +179,12 @@ mod tests { | |||
214 | @r###" | 179 | @r###" |
215 | [ | 180 | [ |
216 | CompletionItem { | 181 | CompletionItem { |
217 | label: "the_field", | 182 | label: "another_field", |
218 | source_range: [208; 208), | 183 | source_range: [208; 208), |
219 | delete: [208; 208), | 184 | delete: [208; 208), |
220 | insert: "the_field", | 185 | insert: "another_field", |
221 | kind: Field, | 186 | kind: Field, |
222 | detail: "u32", | 187 | detail: "i64", |
223 | }, | 188 | }, |
224 | CompletionItem { | 189 | CompletionItem { |
225 | label: "another_good_type", | 190 | label: "another_good_type", |
@@ -228,14 +193,16 @@ mod tests { | |||
228 | insert: "another_good_type", | 193 | insert: "another_good_type", |
229 | kind: Field, | 194 | kind: Field, |
230 | detail: "u32", | 195 | detail: "u32", |
196 | score: TypeMatch, | ||
231 | }, | 197 | }, |
232 | CompletionItem { | 198 | CompletionItem { |
233 | label: "another_field", | 199 | label: "the_field", |
234 | source_range: [208; 208), | 200 | source_range: [208; 208), |
235 | delete: [208; 208), | 201 | delete: [208; 208), |
236 | insert: "another_field", | 202 | insert: "the_field", |
237 | kind: Field, | 203 | kind: Field, |
238 | detail: "i64", | 204 | detail: "u32", |
205 | score: TypeAndNameMatch, | ||
239 | }, | 206 | }, |
240 | ] | 207 | ] |
241 | "### | 208 | "### |
@@ -245,7 +212,7 @@ mod tests { | |||
245 | #[test] | 212 | #[test] |
246 | fn test_struct_field_completion_in_record_lit() { | 213 | fn test_struct_field_completion_in_record_lit() { |
247 | assert_debug_snapshot!( | 214 | assert_debug_snapshot!( |
248 | do_ref_completion_without_sort( | 215 | do_ref_completion( |
249 | r" | 216 | r" |
250 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } | 217 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } |
251 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } | 218 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } |
@@ -259,12 +226,12 @@ mod tests { | |||
259 | @r###" | 226 | @r###" |
260 | [ | 227 | [ |
261 | CompletionItem { | 228 | CompletionItem { |
262 | label: "the_field", | 229 | label: "another_field", |
263 | source_range: [270; 270), | 230 | source_range: [270; 270), |
264 | delete: [270; 270), | 231 | delete: [270; 270), |
265 | insert: "the_field", | 232 | insert: "another_field", |
266 | kind: Field, | 233 | kind: Field, |
267 | detail: "u32", | 234 | detail: "i64", |
268 | }, | 235 | }, |
269 | CompletionItem { | 236 | CompletionItem { |
270 | label: "another_good_type", | 237 | label: "another_good_type", |
@@ -273,14 +240,16 @@ mod tests { | |||
273 | insert: "another_good_type", | 240 | insert: "another_good_type", |
274 | kind: Field, | 241 | kind: Field, |
275 | detail: "u32", | 242 | detail: "u32", |
243 | score: TypeMatch, | ||
276 | }, | 244 | }, |
277 | CompletionItem { | 245 | CompletionItem { |
278 | label: "another_field", | 246 | label: "the_field", |
279 | source_range: [270; 270), | 247 | source_range: [270; 270), |
280 | delete: [270; 270), | 248 | delete: [270; 270), |
281 | insert: "another_field", | 249 | insert: "the_field", |
282 | kind: Field, | 250 | kind: Field, |
283 | detail: "i64", | 251 | detail: "u32", |
252 | score: TypeAndNameMatch, | ||
284 | }, | 253 | }, |
285 | ] | 254 | ] |
286 | "### | 255 | "### |
@@ -290,7 +259,7 @@ mod tests { | |||
290 | #[test] | 259 | #[test] |
291 | fn test_struct_field_completion_in_record_lit_and_fn_call() { | 260 | fn test_struct_field_completion_in_record_lit_and_fn_call() { |
292 | assert_debug_snapshot!( | 261 | assert_debug_snapshot!( |
293 | do_ref_completion_without_sort( | 262 | do_ref_completion( |
294 | r" | 263 | r" |
295 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } | 264 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } |
296 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } | 265 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } |
@@ -311,6 +280,7 @@ mod tests { | |||
311 | insert: "another_field", | 280 | insert: "another_field", |
312 | kind: Field, | 281 | kind: Field, |
313 | detail: "i64", | 282 | detail: "i64", |
283 | score: TypeMatch, | ||
314 | }, | 284 | }, |
315 | CompletionItem { | 285 | CompletionItem { |
316 | label: "another_good_type", | 286 | label: "another_good_type", |
@@ -336,7 +306,7 @@ mod tests { | |||
336 | #[test] | 306 | #[test] |
337 | fn test_struct_field_completion_in_fn_call_and_record_lit() { | 307 | fn test_struct_field_completion_in_fn_call_and_record_lit() { |
338 | assert_debug_snapshot!( | 308 | assert_debug_snapshot!( |
339 | do_ref_completion_without_sort( | 309 | do_ref_completion( |
340 | r" | 310 | r" |
341 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } | 311 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } |
342 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } | 312 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } |
@@ -351,12 +321,12 @@ mod tests { | |||
351 | @r###" | 321 | @r###" |
352 | [ | 322 | [ |
353 | CompletionItem { | 323 | CompletionItem { |
354 | label: "the_field", | 324 | label: "another_field", |
355 | source_range: [328; 328), | 325 | source_range: [328; 328), |
356 | delete: [328; 328), | 326 | delete: [328; 328), |
357 | insert: "the_field", | 327 | insert: "another_field", |
358 | kind: Field, | 328 | kind: Field, |
359 | detail: "u32", | 329 | detail: "i64", |
360 | }, | 330 | }, |
361 | CompletionItem { | 331 | CompletionItem { |
362 | label: "another_good_type", | 332 | label: "another_good_type", |
@@ -365,14 +335,16 @@ mod tests { | |||
365 | insert: "another_good_type", | 335 | insert: "another_good_type", |
366 | kind: Field, | 336 | kind: Field, |
367 | detail: "u32", | 337 | detail: "u32", |
338 | score: TypeMatch, | ||
368 | }, | 339 | }, |
369 | CompletionItem { | 340 | CompletionItem { |
370 | label: "another_field", | 341 | label: "the_field", |
371 | source_range: [328; 328), | 342 | source_range: [328; 328), |
372 | delete: [328; 328), | 343 | delete: [328; 328), |
373 | insert: "another_field", | 344 | insert: "the_field", |
374 | kind: Field, | 345 | kind: Field, |
375 | detail: "i64", | 346 | detail: "u32", |
347 | score: TypeAndNameMatch, | ||
376 | }, | 348 | }, |
377 | ] | 349 | ] |
378 | "### | 350 | "### |
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index c9c3fdc0e..84d51bafe 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs | |||
@@ -53,6 +53,9 @@ pub struct CompletionItem { | |||
53 | /// If completing a function call, ask the editor to show parameter popup | 53 | /// If completing a function call, ask the editor to show parameter popup |
54 | /// after completion. | 54 | /// after completion. |
55 | trigger_call_info: bool, | 55 | trigger_call_info: bool, |
56 | |||
57 | /// Score is usefull to pre select or display in better order completion items | ||
58 | score: Option<CompletionScore>, | ||
56 | } | 59 | } |
57 | 60 | ||
58 | // We use custom debug for CompletionItem to make `insta`'s diffs more readable. | 61 | // We use custom debug for CompletionItem to make `insta`'s diffs more readable. |
@@ -82,6 +85,9 @@ impl fmt::Debug for CompletionItem { | |||
82 | if self.deprecated { | 85 | if self.deprecated { |
83 | s.field("deprecated", &true); | 86 | s.field("deprecated", &true); |
84 | } | 87 | } |
88 | if let Some(score) = &self.score { | ||
89 | s.field("score", score); | ||
90 | } | ||
85 | if self.trigger_call_info { | 91 | if self.trigger_call_info { |
86 | s.field("trigger_call_info", &true); | 92 | s.field("trigger_call_info", &true); |
87 | } | 93 | } |
@@ -149,6 +155,7 @@ impl CompletionItem { | |||
149 | text_edit: None, | 155 | text_edit: None, |
150 | deprecated: None, | 156 | deprecated: None, |
151 | trigger_call_info: None, | 157 | trigger_call_info: None, |
158 | score: None, | ||
152 | } | 159 | } |
153 | } | 160 | } |
154 | /// What user sees in pop-up in the UI. | 161 | /// What user sees in pop-up in the UI. |
@@ -188,6 +195,10 @@ impl CompletionItem { | |||
188 | self.deprecated | 195 | self.deprecated |
189 | } | 196 | } |
190 | 197 | ||
198 | pub fn score(&self) -> Option<CompletionScore> { | ||
199 | self.score.clone() | ||
200 | } | ||
201 | |||
191 | pub fn trigger_call_info(&self) -> bool { | 202 | pub fn trigger_call_info(&self) -> bool { |
192 | self.trigger_call_info | 203 | self.trigger_call_info |
193 | } | 204 | } |
@@ -208,6 +219,7 @@ pub(crate) struct Builder { | |||
208 | text_edit: Option<TextEdit>, | 219 | text_edit: Option<TextEdit>, |
209 | deprecated: Option<bool>, | 220 | deprecated: Option<bool>, |
210 | trigger_call_info: Option<bool>, | 221 | trigger_call_info: Option<bool>, |
222 | score: Option<CompletionScore>, | ||
211 | } | 223 | } |
212 | 224 | ||
213 | impl Builder { | 225 | impl Builder { |
@@ -237,6 +249,7 @@ impl Builder { | |||
237 | completion_kind: self.completion_kind, | 249 | completion_kind: self.completion_kind, |
238 | deprecated: self.deprecated.unwrap_or(false), | 250 | deprecated: self.deprecated.unwrap_or(false), |
239 | trigger_call_info: self.trigger_call_info.unwrap_or(false), | 251 | trigger_call_info: self.trigger_call_info.unwrap_or(false), |
252 | score: self.score, | ||
240 | } | 253 | } |
241 | } | 254 | } |
242 | pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { | 255 | pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { |
@@ -287,6 +300,10 @@ impl Builder { | |||
287 | self.deprecated = Some(deprecated); | 300 | self.deprecated = Some(deprecated); |
288 | self | 301 | self |
289 | } | 302 | } |
303 | pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder { | ||
304 | self.score = Some(score); | ||
305 | self | ||
306 | } | ||
290 | pub(crate) fn trigger_call_info(mut self) -> Builder { | 307 | pub(crate) fn trigger_call_info(mut self) -> Builder { |
291 | self.trigger_call_info = Some(true); | 308 | self.trigger_call_info = Some(true); |
292 | self | 309 | self |
@@ -300,16 +317,22 @@ impl<'a> Into<CompletionItem> for Builder { | |||
300 | } | 317 | } |
301 | 318 | ||
302 | #[derive(Debug)] | 319 | #[derive(Debug)] |
303 | pub(crate) enum SortOption { | 320 | pub(crate) enum ScoreOption { |
304 | CallFn(CallInfo), | 321 | CallFn(CallInfo), |
305 | RecordField(RecordField), | 322 | RecordField(RecordField), |
306 | } | 323 | } |
307 | 324 | ||
325 | #[derive(Debug, Clone)] | ||
326 | pub enum CompletionScore { | ||
327 | TypeMatch, | ||
328 | TypeAndNameMatch, | ||
329 | } | ||
330 | |||
308 | /// Represents an in-progress set of completions being built. | 331 | /// Represents an in-progress set of completions being built. |
309 | #[derive(Debug, Default)] | 332 | #[derive(Debug, Default)] |
310 | pub(crate) struct Completions { | 333 | pub(crate) struct Completions { |
311 | buf: Vec<CompletionItem>, | 334 | buf: Vec<CompletionItem>, |
312 | sort_option: Option<SortOption>, | 335 | score_option: Option<ScoreOption>, |
313 | } | 336 | } |
314 | 337 | ||
315 | impl Completions { | 338 | impl Completions { |
@@ -324,17 +347,17 @@ impl Completions { | |||
324 | items.into_iter().for_each(|item| self.add(item.into())) | 347 | items.into_iter().for_each(|item| self.add(item.into())) |
325 | } | 348 | } |
326 | 349 | ||
327 | pub(crate) fn with_sort_option(&mut self, sort_option: SortOption) { | 350 | pub(crate) fn with_score_option(&mut self, score_option: ScoreOption) { |
328 | self.sort_option = Some(sort_option); | 351 | self.score_option = Some(score_option); |
329 | } | 352 | } |
330 | 353 | ||
331 | pub(crate) fn sort(&mut self, ctx: &CompletionContext) { | 354 | pub(crate) fn compute_score(&mut self, ctx: &CompletionContext) { |
332 | if self.sort_option.is_none() { | 355 | if self.score_option.is_none() { |
333 | return; | 356 | return; |
334 | } | 357 | } |
335 | 358 | ||
336 | let (active_name, active_type) = match self.sort_option.as_ref().unwrap() { | 359 | let (active_name, active_type) = match self.score_option.as_ref().unwrap() { |
337 | SortOption::CallFn(call_info) => { | 360 | ScoreOption::CallFn(call_info) => { |
338 | if call_info.active_parameter_type().is_none() | 361 | if call_info.active_parameter_type().is_none() |
339 | || call_info.active_parameter_name().is_none() | 362 | || call_info.active_parameter_name().is_none() |
340 | { | 363 | { |
@@ -345,7 +368,7 @@ impl Completions { | |||
345 | call_info.active_parameter_type().unwrap(), | 368 | call_info.active_parameter_type().unwrap(), |
346 | ) | 369 | ) |
347 | } | 370 | } |
348 | SortOption::RecordField(record_field) => { | 371 | ScoreOption::RecordField(record_field) => { |
349 | if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) { | 372 | if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) { |
350 | ( | 373 | ( |
351 | struct_field.name(ctx.db).to_string(), | 374 | struct_field.name(ctx.db).to_string(), |
@@ -357,26 +380,19 @@ impl Completions { | |||
357 | } | 380 | } |
358 | }; | 381 | }; |
359 | 382 | ||
360 | self.buf.sort_by(|a, b| { | 383 | for completion_item in &mut self.buf { |
361 | // For the same type | 384 | // For the same type |
362 | if let Some(a_parameter_type) = &a.detail { | 385 | if let Some(a_parameter_type) = &completion_item.detail { |
363 | if &active_type == a_parameter_type { | 386 | if &active_type == a_parameter_type { |
364 | // If same type + same name then go top position | 387 | // If same type + same name then go top position |
365 | if active_name != a.label { | 388 | if active_name == completion_item.label { |
366 | if let Some(b_parameter_type) = &b.detail { | 389 | completion_item.score = Some(CompletionScore::TypeAndNameMatch); |
367 | if &active_type == b_parameter_type { | 390 | } else { |
368 | return Ordering::Equal; | 391 | completion_item.score = Some(CompletionScore::TypeMatch); |
369 | } | ||
370 | } | ||
371 | } | 392 | } |
372 | Ordering::Less | ||
373 | } else { | ||
374 | Ordering::Greater | ||
375 | } | 393 | } |
376 | } else { | ||
377 | Ordering::Greater | ||
378 | } | 394 | } |
379 | }); | 395 | } |
380 | } | 396 | } |
381 | } | 397 | } |
382 | 398 | ||
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 8be2d02d0..55f75b15a 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -367,7 +367,7 @@ mod tests { | |||
367 | ra_fixture: &str, | 367 | ra_fixture: &str, |
368 | options: CompletionConfig, | 368 | options: CompletionConfig, |
369 | ) -> Vec<CompletionItem> { | 369 | ) -> Vec<CompletionItem> { |
370 | do_completion_with_options(ra_fixture, CompletionKind::Reference, &options, true) | 370 | do_completion_with_options(ra_fixture, CompletionKind::Reference, &options) |
371 | } | 371 | } |
372 | 372 | ||
373 | #[test] | 373 | #[test] |
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs index f54d15a90..eb90b5279 100644 --- a/crates/ra_ide/src/completion/test_utils.rs +++ b/crates/ra_ide/src/completion/test_utils.rs | |||
@@ -7,18 +7,13 @@ use crate::{ | |||
7 | }; | 7 | }; |
8 | 8 | ||
9 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | 9 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { |
10 | do_completion_with_options(code, kind, &CompletionConfig::default(), true) | 10 | do_completion_with_options(code, kind, &CompletionConfig::default()) |
11 | } | ||
12 | |||
13 | pub(crate) fn do_completion_without_sort(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | ||
14 | do_completion_with_options(code, kind, &CompletionConfig::default(), false) | ||
15 | } | 11 | } |
16 | 12 | ||
17 | pub(crate) fn do_completion_with_options( | 13 | pub(crate) fn do_completion_with_options( |
18 | code: &str, | 14 | code: &str, |
19 | kind: CompletionKind, | 15 | kind: CompletionKind, |
20 | options: &CompletionConfig, | 16 | options: &CompletionConfig, |
21 | sort_by_key: bool, | ||
22 | ) -> Vec<CompletionItem> { | 17 | ) -> Vec<CompletionItem> { |
23 | let (analysis, position) = if code.contains("//-") { | 18 | let (analysis, position) = if code.contains("//-") { |
24 | analysis_and_position(code) | 19 | analysis_and_position(code) |
@@ -29,8 +24,6 @@ pub(crate) fn do_completion_with_options( | |||
29 | let completion_items: Vec<CompletionItem> = completions.into(); | 24 | let completion_items: Vec<CompletionItem> = completions.into(); |
30 | let mut kind_completions: Vec<CompletionItem> = | 25 | let mut kind_completions: Vec<CompletionItem> = |
31 | completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); | 26 | completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); |
32 | if sort_by_key { | 27 | kind_completions.sort_by_key(|c| c.label().to_owned()); |
33 | kind_completions.sort_by_key(|c| c.label().to_owned()); | ||
34 | } | ||
35 | kind_completions | 28 | kind_completions |
36 | } | 29 | } |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 357c01cdf..ddaa30a16 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -67,7 +67,9 @@ use crate::display::ToNav; | |||
67 | pub use crate::{ | 67 | pub use crate::{ |
68 | assists::{Assist, AssistId}, | 68 | assists::{Assist, AssistId}, |
69 | call_hierarchy::CallItem, | 69 | call_hierarchy::CallItem, |
70 | completion::{CompletionConfig, CompletionItem, CompletionItemKind, InsertTextFormat}, | 70 | completion::{ |
71 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, | ||
72 | }, | ||
71 | diagnostics::Severity, | 73 | diagnostics::Severity, |
72 | display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, | 74 | display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, |
73 | expand_macro::ExpandedMacro, | 75 | expand_macro::ExpandedMacro, |