Improve autocompletion by looking on the type and name

Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
This commit is contained in:
Benjamin Coenen 2020-04-21 14:31:57 +02:00
parent af3c19e85f
commit 1c3a1385a5
4 changed files with 47 additions and 48 deletions

View file

@ -7,11 +7,9 @@ use crate::{
completion_context::CompletionContext, completion_context::CompletionContext,
completion_item::{CompletionKind, Completions}, completion_item::{CompletionKind, Completions},
}, },
// CallInfo,
CompletionItem, CompletionItem,
}; };
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
// use std::cmp::Ordering;
/// Complete dot accesses, i.e. fields or methods (and .await syntax). /// Complete dot accesses, i.e. fields or methods (and .await syntax).
pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {

View file

@ -305,46 +305,6 @@ impl Builder {
self self
} }
#[allow(unused)] #[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 { pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder {
self.score = Some(score); self.score = Some(score);
self self
@ -363,7 +323,9 @@ impl<'a> Into<CompletionItem> for Builder {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum CompletionScore { pub enum CompletionScore {
/// If only type match
TypeMatch, TypeMatch,
/// If type and name match
TypeAndNameMatch, TypeAndNameMatch,
} }

View file

@ -6,12 +6,13 @@ use stdx::SepBy;
use test_utils::tested_by; use test_utils::tested_by;
use crate::{ use crate::{
call_info::call_info,
completion::{ completion::{
completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
CompletionKind, Completions, CompletionKind, Completions,
}, },
display::{const_label, macro_label, type_label, FunctionSignature}, display::{const_label, macro_label, type_label, FunctionSignature},
RootDatabase, CompletionScore, RootDatabase,
}; };
impl Completions { impl Completions {
@ -22,7 +23,7 @@ impl Completions {
ty: &Type, ty: &Type,
) { ) {
let is_deprecated = is_deprecated(field, ctx.db); let is_deprecated = is_deprecated(field, ctx.db);
CompletionItem::new( let mut completion_item = CompletionItem::new(
CompletionKind::Reference, CompletionKind::Reference,
ctx.source_range(), ctx.source_range(),
field.name(ctx.db).to_string(), field.name(ctx.db).to_string(),
@ -31,8 +32,11 @@ impl Completions {
.detail(ty.display(ctx.db).to_string()) .detail(ty.display(ctx.db).to_string())
.set_documentation(field.docs(ctx.db)) .set_documentation(field.docs(ctx.db))
.set_deprecated(is_deprecated) .set_deprecated(is_deprecated)
.compute_score(ctx) .build();
.add_to(self);
compute_score(&mut completion_item, ctx);
self.add(completion_item);
} }
pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &Type) { pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &Type) {
@ -295,6 +299,42 @@ impl Completions {
} }
} }
pub(crate) fn compute_score(completion_item: &mut CompletionItem, ctx: &CompletionContext) {
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;
}
} 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;
}
} else {
return;
};
// Compute score
// 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.set_score(CompletionScore::TypeAndNameMatch);
} else {
completion_item.set_score(CompletionScore::TypeMatch);
}
}
}
}
enum Params { enum Params {
Named(Vec<String>), Named(Vec<String>),
Anonymous(usize), Anonymous(usize),

View file

@ -73,7 +73,7 @@ impl FunctionSignature {
if let Some(param_type) = raw_param.split(':').nth(1) { if let Some(param_type) = raw_param.split(':').nth(1) {
parameter_types.push(param_type[1..].to_string()); parameter_types.push(param_type[1..].to_string());
} else { } else {
// The unwrap_or_else is useful when you have tuple struct // useful when you have tuple struct
parameter_types.push(raw_param.clone()); parameter_types.push(raw_param.clone());
} }
params.push(raw_param); params.push(raw_param);
@ -177,7 +177,6 @@ impl From<&'_ ast::FnDef> for FunctionSignature {
has_self_param = true; has_self_param = true;
let raw_param = self_param.syntax().text().to_string(); let raw_param = self_param.syntax().text().to_string();
// FIXME: better solution ?
res_types.push( res_types.push(
raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(), raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(),
); );