From 071ef268b5c8fb9afec1db912ebcc5d6577f5e73 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Fri, 17 Apr 2020 10:29:32 +0200 Subject: feat: improve dot completions with scoring Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/completion.rs | 3 - crates/ra_ide/src/completion/complete_dot.rs | 19 +---- crates/ra_ide/src/completion/completion_item.rs | 106 +++++++++++------------- crates/ra_ide/src/completion/presentation.rs | 1 + 4 files changed, 52 insertions(+), 77 deletions(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index 38c8aed8d..19bc4321c 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs @@ -94,8 +94,5 @@ pub(crate) fn completions( complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); complete_trait_impl::complete_trait_impl(&mut acc, &ctx); - // Compute score for completion items - acc.compute_score(&ctx); - Some(acc) } 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 @@ //! FIXME: write short doc here -use hir::{ - HasVisibility, - // HirDisplay, - Type, -}; +use hir::{HasVisibility, Type}; use crate::{ - call_info::call_info, completion::{ completion_context::CompletionContext, - completion_item::{CompletionKind, Completions, ScoreOption}, + completion_item::{CompletionKind, Completions}, }, // CallInfo, CompletionItem, @@ -46,15 +41,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { for receiver in receiver.autoderef(ctx.db) { - let fields = receiver.fields(ctx.db); - - if let Some(record_field) = &ctx.record_field_syntax { - acc.with_score_option(ScoreOption::RecordField(record_field.clone())); - } else if let Some(call_info) = call_info(ctx.db, ctx.file_position) { - acc.with_score_option(ScoreOption::CallFn(call_info)); - } - - for (field, ty) in fields { + for (field, ty) in receiver.fields(ctx.db) { if ctx.scope().module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) { // Skip private field. FIXME: If the definition location of the // 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 @@ //! FIXME: write short doc here -use std::{cmp::Ordering, fmt}; +use std::fmt; use super::completion_context::CompletionContext; -use crate::CallInfo; +use crate::call_info::call_info; use hir::{Documentation, HirDisplay}; -use ra_syntax::{ast::RecordField, TextRange}; +use ra_syntax::TextRange; use ra_text_edit::TextEdit; /// `CompletionItem` describes a single completion variant in the editor pop-up. @@ -199,6 +199,10 @@ impl CompletionItem { self.score.clone() } + pub fn set_score(&mut self, score: CompletionScore) { + self.score = Some(score); + } + pub fn trigger_call_info(&self) -> bool { self.trigger_call_info } @@ -300,6 +304,47 @@ impl Builder { self.deprecated = Some(deprecated); self } + #[allow(unused)] + pub(crate) fn compute_score(mut self, ctx: &CompletionContext) -> Builder { + let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { + if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) { + ( + struct_field.name(ctx.db).to_string(), + struct_field.signature_ty(ctx.db).display(ctx.db).to_string(), + ) + } else { + return self; + } + } else if let Some(call_info) = call_info(ctx.db, ctx.file_position) { + if call_info.active_parameter_type().is_some() + && call_info.active_parameter_name().is_some() + { + ( + call_info.active_parameter_name().unwrap(), + call_info.active_parameter_type().unwrap(), + ) + } else { + return self; + } + } else { + return self; + }; + + // Compute score + // For the same type + if let Some(a_parameter_type) = &self.detail { + if &active_type == a_parameter_type { + // If same type + same name then go top position + if active_name == self.label { + return self.set_score(CompletionScore::TypeAndNameMatch); + } else { + return self.set_score(CompletionScore::TypeMatch); + } + } + } + + self + } pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder { self.score = Some(score); self @@ -316,12 +361,6 @@ impl<'a> Into for Builder { } } -#[derive(Debug)] -pub(crate) enum ScoreOption { - CallFn(CallInfo), - RecordField(RecordField), -} - #[derive(Debug, Clone)] pub enum CompletionScore { TypeMatch, @@ -332,7 +371,6 @@ pub enum CompletionScore { #[derive(Debug, Default)] pub(crate) struct Completions { buf: Vec, - score_option: Option, } impl Completions { @@ -346,54 +384,6 @@ impl Completions { { items.into_iter().for_each(|item| self.add(item.into())) } - - pub(crate) fn with_score_option(&mut self, score_option: ScoreOption) { - self.score_option = Some(score_option); - } - - pub(crate) fn compute_score(&mut self, ctx: &CompletionContext) { - if self.score_option.is_none() { - return; - } - - let (active_name, active_type) = match self.score_option.as_ref().unwrap() { - ScoreOption::CallFn(call_info) => { - if call_info.active_parameter_type().is_none() - || call_info.active_parameter_name().is_none() - { - return; - } - ( - call_info.active_parameter_name().unwrap(), - call_info.active_parameter_type().unwrap(), - ) - } - ScoreOption::RecordField(record_field) => { - if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) { - ( - struct_field.name(ctx.db).to_string(), - struct_field.signature_ty(ctx.db).display(ctx.db).to_string(), - ) - } else { - return; - } - } - }; - - for completion_item in &mut self.buf { - // For the same type - if let Some(a_parameter_type) = &completion_item.detail { - if &active_type == a_parameter_type { - // If same type + same name then go top position - if active_name == completion_item.label { - completion_item.score = Some(CompletionScore::TypeAndNameMatch); - } else { - completion_item.score = Some(CompletionScore::TypeMatch); - } - } - } - } - } } impl Into> 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 { .detail(ty.display(ctx.db).to_string()) .set_documentation(field.docs(ctx.db)) .set_deprecated(is_deprecated) + .compute_score(ctx) .add_to(self); } -- cgit v1.2.3