From 064095742980d4c825391f643e437520599f51d8 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Sun, 12 Apr 2020 17:45:07 +0200 Subject: Improve autocompletion by looking on the type and name, change implementation, include sort in Completions struct Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/completion/completion_item.rs | 50 ++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'crates/ra_ide/src/completion/completion_item.rs') diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index bc0f1aff5..f8e6e53f1 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs @@ -1,7 +1,8 @@ //! FIXME: write short doc here -use std::fmt; +use std::{cmp::Ordering, fmt}; +use crate::CallInfo; use hir::Documentation; use ra_syntax::TextRange; use ra_text_edit::TextEdit; @@ -297,10 +298,17 @@ impl<'a> Into for Builder { } } +#[derive(Debug)] +pub(crate) enum SortOption { + CallFn(CallInfo), + // LitStruct, +} + /// Represents an in-progress set of completions being built. #[derive(Debug, Default)] pub(crate) struct Completions { buf: Vec, + sort_option: Option, } impl Completions { @@ -314,6 +322,46 @@ impl Completions { { items.into_iter().for_each(|item| self.add(item.into())) } + + pub(crate) fn with_sort_option(&mut self, sort_option: SortOption) { + self.sort_option = Some(sort_option); + } + + pub(crate) fn sort(&mut self) { + if self.sort_option.is_none() { + return; + } + let sort_option = self.sort_option.as_ref().unwrap(); + + match sort_option { + SortOption::CallFn(call_info) => { + if let Some(active_parameter_type) = call_info.active_parameter_type() { + let active_parameter_name = call_info.active_parameter_name().unwrap(); + + self.buf.sort_by(|a, b| { + // For the same type + if let Some(a_parameter_type) = &a.detail { + if &active_parameter_type == a_parameter_type { + // If same type + same name then go top position + if active_parameter_name != a.label { + if let Some(b_parameter_type) = &b.detail { + if &active_parameter_type == b_parameter_type { + return Ordering::Equal; + } + } + } + Ordering::Less + } else { + Ordering::Greater + } + } else { + Ordering::Greater + } + }); + } + } // _ => unimplemented!("sort options not already implemented"), + } + } } impl Into> for Completions { -- cgit v1.2.3 From 06076f95a7ca764696b055eb754e163f884eefaa Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Wed, 15 Apr 2020 22:10:57 +0200 Subject: feat: improve dot completions in a struct literal expression Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/completion/completion_item.rs | 74 +++++++++++++++---------- 1 file changed, 45 insertions(+), 29 deletions(-) (limited to 'crates/ra_ide/src/completion/completion_item.rs') diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index f8e6e53f1..c9c3fdc0e 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs @@ -2,9 +2,10 @@ use std::{cmp::Ordering, fmt}; +use super::completion_context::CompletionContext; use crate::CallInfo; -use hir::Documentation; -use ra_syntax::TextRange; +use hir::{Documentation, HirDisplay}; +use ra_syntax::{ast::RecordField, TextRange}; use ra_text_edit::TextEdit; /// `CompletionItem` describes a single completion variant in the editor pop-up. @@ -301,7 +302,7 @@ impl<'a> Into for Builder { #[derive(Debug)] pub(crate) enum SortOption { CallFn(CallInfo), - // LitStruct, + RecordField(RecordField), } /// Represents an in-progress set of completions being built. @@ -327,40 +328,55 @@ impl Completions { self.sort_option = Some(sort_option); } - pub(crate) fn sort(&mut self) { + pub(crate) fn sort(&mut self, ctx: &CompletionContext) { if self.sort_option.is_none() { return; } - let sort_option = self.sort_option.as_ref().unwrap(); - match sort_option { + let (active_name, active_type) = match self.sort_option.as_ref().unwrap() { SortOption::CallFn(call_info) => { - if let Some(active_parameter_type) = call_info.active_parameter_type() { - let active_parameter_name = call_info.active_parameter_name().unwrap(); - - self.buf.sort_by(|a, b| { - // For the same type - if let Some(a_parameter_type) = &a.detail { - if &active_parameter_type == a_parameter_type { - // If same type + same name then go top position - if active_parameter_name != a.label { - if let Some(b_parameter_type) = &b.detail { - if &active_parameter_type == b_parameter_type { - return Ordering::Equal; - } - } - } - Ordering::Less - } else { - Ordering::Greater + 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(), + ) + } + SortOption::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; + } + } + }; + + self.buf.sort_by(|a, b| { + // For the same type + if let Some(a_parameter_type) = &a.detail { + if &active_type == a_parameter_type { + // If same type + same name then go top position + if active_name != a.label { + if let Some(b_parameter_type) = &b.detail { + if &active_type == b_parameter_type { + return Ordering::Equal; } - } else { - Ordering::Greater } - }); + } + Ordering::Less + } else { + Ordering::Greater } - } // _ => unimplemented!("sort options not already implemented"), - } + } else { + Ordering::Greater + } + }); } } -- cgit v1.2.3 From 6ebc8bbeb005f5d3f2b00d1ae1f1804116e3a8f5 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Thu, 16 Apr 2020 18:30:08 +0200 Subject: feat: improve dot completions with scoring Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/completion/completion_item.rs | 62 ++++++++++++++++--------- 1 file changed, 39 insertions(+), 23 deletions(-) (limited to 'crates/ra_ide/src/completion/completion_item.rs') 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 { /// If completing a function call, ask the editor to show parameter popup /// after completion. trigger_call_info: bool, + + /// Score is usefull to pre select or display in better order completion items + score: Option, } // We use custom debug for CompletionItem to make `insta`'s diffs more readable. @@ -82,6 +85,9 @@ impl fmt::Debug for CompletionItem { if self.deprecated { s.field("deprecated", &true); } + if let Some(score) = &self.score { + s.field("score", score); + } if self.trigger_call_info { s.field("trigger_call_info", &true); } @@ -149,6 +155,7 @@ impl CompletionItem { text_edit: None, deprecated: None, trigger_call_info: None, + score: None, } } /// What user sees in pop-up in the UI. @@ -188,6 +195,10 @@ impl CompletionItem { self.deprecated } + pub fn score(&self) -> Option { + self.score.clone() + } + pub fn trigger_call_info(&self) -> bool { self.trigger_call_info } @@ -208,6 +219,7 @@ pub(crate) struct Builder { text_edit: Option, deprecated: Option, trigger_call_info: Option, + score: Option, } impl Builder { @@ -237,6 +249,7 @@ impl Builder { completion_kind: self.completion_kind, deprecated: self.deprecated.unwrap_or(false), trigger_call_info: self.trigger_call_info.unwrap_or(false), + score: self.score, } } pub(crate) fn lookup_by(mut self, lookup: impl Into) -> Builder { @@ -287,6 +300,10 @@ impl Builder { self.deprecated = Some(deprecated); self } + pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder { + self.score = Some(score); + self + } pub(crate) fn trigger_call_info(mut self) -> Builder { self.trigger_call_info = Some(true); self @@ -300,16 +317,22 @@ impl<'a> Into for Builder { } #[derive(Debug)] -pub(crate) enum SortOption { +pub(crate) enum ScoreOption { CallFn(CallInfo), RecordField(RecordField), } +#[derive(Debug, Clone)] +pub enum CompletionScore { + TypeMatch, + TypeAndNameMatch, +} + /// Represents an in-progress set of completions being built. #[derive(Debug, Default)] pub(crate) struct Completions { buf: Vec, - sort_option: Option, + score_option: Option, } impl Completions { @@ -324,17 +347,17 @@ impl Completions { items.into_iter().for_each(|item| self.add(item.into())) } - pub(crate) fn with_sort_option(&mut self, sort_option: SortOption) { - self.sort_option = Some(sort_option); + pub(crate) fn with_score_option(&mut self, score_option: ScoreOption) { + self.score_option = Some(score_option); } - pub(crate) fn sort(&mut self, ctx: &CompletionContext) { - if self.sort_option.is_none() { + pub(crate) fn compute_score(&mut self, ctx: &CompletionContext) { + if self.score_option.is_none() { return; } - let (active_name, active_type) = match self.sort_option.as_ref().unwrap() { - SortOption::CallFn(call_info) => { + 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() { @@ -345,7 +368,7 @@ impl Completions { call_info.active_parameter_type().unwrap(), ) } - SortOption::RecordField(record_field) => { + ScoreOption::RecordField(record_field) => { if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) { ( struct_field.name(ctx.db).to_string(), @@ -357,26 +380,19 @@ impl Completions { } }; - self.buf.sort_by(|a, b| { + for completion_item in &mut self.buf { // For the same type - if let Some(a_parameter_type) = &a.detail { + 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 != a.label { - if let Some(b_parameter_type) = &b.detail { - if &active_type == b_parameter_type { - return Ordering::Equal; - } - } + if active_name == completion_item.label { + completion_item.score = Some(CompletionScore::TypeAndNameMatch); + } else { + completion_item.score = Some(CompletionScore::TypeMatch); } - Ordering::Less - } else { - Ordering::Greater } - } else { - Ordering::Greater } - }); + } } } -- cgit v1.2.3 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/completion_item.rs | 106 +++++++++++------------- 1 file changed, 48 insertions(+), 58 deletions(-) (limited to 'crates/ra_ide/src/completion/completion_item.rs') 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 { -- cgit v1.2.3 From 1c3a1385a587f0713908c0ae888ffad31f13de11 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Tue, 21 Apr 2020 14:31:57 +0200 Subject: Improve autocompletion by looking on the type and name Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/completion/completion_item.rs | 42 ++----------------------- 1 file changed, 2 insertions(+), 40 deletions(-) (limited to 'crates/ra_ide/src/completion/completion_item.rs') diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index a3ae9c86b..8b96b81db 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs @@ -305,46 +305,6 @@ impl Builder { 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 @@ -363,7 +323,9 @@ impl<'a> Into for Builder { #[derive(Debug, Clone)] pub enum CompletionScore { + /// If only type match TypeMatch, + /// If type and name match TypeAndNameMatch, } -- cgit v1.2.3 From b6a7be19d9df53e39fa9bc1779cc19b7b708e495 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Tue, 21 Apr 2020 14:36:56 +0200 Subject: Improve autocompletion by looking on the type and name Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/completion/completion_item.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'crates/ra_ide/src/completion/completion_item.rs') diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index 8b96b81db..e17586aa5 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs @@ -2,9 +2,7 @@ use std::fmt; -use super::completion_context::CompletionContext; -use crate::call_info::call_info; -use hir::{Documentation, HirDisplay}; +use hir::Documentation; use ra_syntax::TextRange; use ra_text_edit::TextEdit; -- cgit v1.2.3