mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
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:
parent
af3c19e85f
commit
1c3a1385a5
4 changed files with 47 additions and 48 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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(),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue