aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion
diff options
context:
space:
mode:
authorBenjamin Coenen <[email protected]>2020-04-17 09:29:32 +0100
committerBenjamin Coenen <[email protected]>2020-04-17 09:29:32 +0100
commit071ef268b5c8fb9afec1db912ebcc5d6577f5e73 (patch)
tree78d3889c33d0591653ca3fac976b2224d3ec4148 /crates/ra_ide/src/completion
parent6ebc8bbeb005f5d3f2b00d1ae1f1804116e3a8f5 (diff)
feat: improve dot completions with scoring
Signed-off-by: Benjamin Coenen <[email protected]>
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs19
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs106
-rw-r--r--crates/ra_ide/src/completion/presentation.rs1
3 files changed, 52 insertions, 74 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 174b39964..c16357a7e 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -1,16 +1,11 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{ 3use hir::{HasVisibility, Type};
4 HasVisibility,
5 // HirDisplay,
6 Type,
7};
8 4
9use crate::{ 5use crate::{
10 call_info::call_info,
11 completion::{ 6 completion::{
12 completion_context::CompletionContext, 7 completion_context::CompletionContext,
13 completion_item::{CompletionKind, Completions, ScoreOption}, 8 completion_item::{CompletionKind, Completions},
14 }, 9 },
15 // CallInfo, 10 // CallInfo,
16 CompletionItem, 11 CompletionItem,
@@ -46,15 +41,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
46 41
47fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { 42fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
48 for receiver in receiver.autoderef(ctx.db) { 43 for receiver in receiver.autoderef(ctx.db) {
49 let fields = receiver.fields(ctx.db); 44 for (field, ty) in receiver.fields(ctx.db) {
50
51 if let Some(record_field) = &ctx.record_field_syntax {
52 acc.with_score_option(ScoreOption::RecordField(record_field.clone()));
53 } else if let Some(call_info) = call_info(ctx.db, ctx.file_position) {
54 acc.with_score_option(ScoreOption::CallFn(call_info));
55 }
56
57 for (field, ty) in fields {
58 if ctx.scope().module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) { 45 if ctx.scope().module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) {
59 // Skip private field. FIXME: If the definition location of the 46 // Skip private field. FIXME: If the definition location of the
60 // field is editable, we should show the completion 47 // field is editable, we should show the completion
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index 84d51bafe..a3ae9c86b 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -1,11 +1,11 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::{cmp::Ordering, fmt}; 3use std::fmt;
4 4
5use super::completion_context::CompletionContext; 5use super::completion_context::CompletionContext;
6use crate::CallInfo; 6use crate::call_info::call_info;
7use hir::{Documentation, HirDisplay}; 7use hir::{Documentation, HirDisplay};
8use ra_syntax::{ast::RecordField, TextRange}; 8use ra_syntax::TextRange;
9use ra_text_edit::TextEdit; 9use ra_text_edit::TextEdit;
10 10
11/// `CompletionItem` describes a single completion variant in the editor pop-up. 11/// `CompletionItem` describes a single completion variant in the editor pop-up.
@@ -199,6 +199,10 @@ impl CompletionItem {
199 self.score.clone() 199 self.score.clone()
200 } 200 }
201 201
202 pub fn set_score(&mut self, score: CompletionScore) {
203 self.score = Some(score);
204 }
205
202 pub fn trigger_call_info(&self) -> bool { 206 pub fn trigger_call_info(&self) -> bool {
203 self.trigger_call_info 207 self.trigger_call_info
204 } 208 }
@@ -300,6 +304,47 @@ impl Builder {
300 self.deprecated = Some(deprecated); 304 self.deprecated = Some(deprecated);
301 self 305 self
302 } 306 }
307 #[allow(unused)]
308 pub(crate) fn compute_score(mut self, ctx: &CompletionContext) -> Builder {
309 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
310 if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) {
311 (
312 struct_field.name(ctx.db).to_string(),
313 struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
314 )
315 } else {
316 return self;
317 }
318 } else if let Some(call_info) = call_info(ctx.db, ctx.file_position) {
319 if call_info.active_parameter_type().is_some()
320 && call_info.active_parameter_name().is_some()
321 {
322 (
323 call_info.active_parameter_name().unwrap(),
324 call_info.active_parameter_type().unwrap(),
325 )
326 } else {
327 return self;
328 }
329 } else {
330 return self;
331 };
332
333 // Compute score
334 // For the same type
335 if let Some(a_parameter_type) = &self.detail {
336 if &active_type == a_parameter_type {
337 // If same type + same name then go top position
338 if active_name == self.label {
339 return self.set_score(CompletionScore::TypeAndNameMatch);
340 } else {
341 return self.set_score(CompletionScore::TypeMatch);
342 }
343 }
344 }
345
346 self
347 }
303 pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder { 348 pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder {
304 self.score = Some(score); 349 self.score = Some(score);
305 self 350 self
@@ -316,12 +361,6 @@ impl<'a> Into<CompletionItem> for Builder {
316 } 361 }
317} 362}
318 363
319#[derive(Debug)]
320pub(crate) enum ScoreOption {
321 CallFn(CallInfo),
322 RecordField(RecordField),
323}
324
325#[derive(Debug, Clone)] 364#[derive(Debug, Clone)]
326pub enum CompletionScore { 365pub enum CompletionScore {
327 TypeMatch, 366 TypeMatch,
@@ -332,7 +371,6 @@ pub enum CompletionScore {
332#[derive(Debug, Default)] 371#[derive(Debug, Default)]
333pub(crate) struct Completions { 372pub(crate) struct Completions {
334 buf: Vec<CompletionItem>, 373 buf: Vec<CompletionItem>,
335 score_option: Option<ScoreOption>,
336} 374}
337 375
338impl Completions { 376impl Completions {
@@ -346,54 +384,6 @@ impl Completions {
346 { 384 {
347 items.into_iter().for_each(|item| self.add(item.into())) 385 items.into_iter().for_each(|item| self.add(item.into()))
348 } 386 }
349
350 pub(crate) fn with_score_option(&mut self, score_option: ScoreOption) {
351 self.score_option = Some(score_option);
352 }
353
354 pub(crate) fn compute_score(&mut self, ctx: &CompletionContext) {
355 if self.score_option.is_none() {
356 return;
357 }
358
359 let (active_name, active_type) = match self.score_option.as_ref().unwrap() {
360 ScoreOption::CallFn(call_info) => {
361 if call_info.active_parameter_type().is_none()
362 || call_info.active_parameter_name().is_none()
363 {
364 return;
365 }
366 (
367 call_info.active_parameter_name().unwrap(),
368 call_info.active_parameter_type().unwrap(),
369 )
370 }
371 ScoreOption::RecordField(record_field) => {
372 if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) {
373 (
374 struct_field.name(ctx.db).to_string(),
375 struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
376 )
377 } else {
378 return;
379 }
380 }
381 };
382
383 for completion_item in &mut self.buf {
384 // For the same type
385 if let Some(a_parameter_type) = &completion_item.detail {
386 if &active_type == a_parameter_type {
387 // If same type + same name then go top position
388 if active_name == completion_item.label {
389 completion_item.score = Some(CompletionScore::TypeAndNameMatch);
390 } else {
391 completion_item.score = Some(CompletionScore::TypeMatch);
392 }
393 }
394 }
395 }
396 }
397} 387}
398 388
399impl Into<Vec<CompletionItem>> for Completions { 389impl Into<Vec<CompletionItem>> for Completions {
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 55f75b15a..5c3360ce4 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -31,6 +31,7 @@ impl Completions {
31 .detail(ty.display(ctx.db).to_string()) 31 .detail(ty.display(ctx.db).to_string())
32 .set_documentation(field.docs(ctx.db)) 32 .set_documentation(field.docs(ctx.db))
33 .set_deprecated(is_deprecated) 33 .set_deprecated(is_deprecated)
34 .compute_score(ctx)
34 .add_to(self); 35 .add_to(self);
35 } 36 }
36 37