From 90c62bcee9d1950d0e4b642fc2bd3ae5374e40cb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 May 2020 15:15:52 +0200 Subject: [PATCH] Prioritize locals with correct types --- .../src/completion/completion_context.rs | 2 +- crates/ra_ide/src/completion/presentation.rs | 58 +++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index b6b9627dea..da336973c1 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -34,7 +34,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) record_pat_syntax: Option, pub(super) record_field_syntax: Option, pub(super) impl_def: Option, - /// FIXME: `ActiveParameter` is string-based, which is very wrong + /// FIXME: `ActiveParameter` is string-based, which is very very wrong pub(super) active_parameter: Option, pub(super) is_param: bool, /// If a name-binding or reference to a const in a pattern. diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 2edb130cf7..077cf96477 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs @@ -17,12 +17,11 @@ use crate::{ impl Completions { pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) { let is_deprecated = is_deprecated(field, ctx.db); - let ty = ty.display(ctx.db).to_string(); let name = field.name(ctx.db); let mut completion_item = CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) .kind(CompletionItemKind::Field) - .detail(ty.clone()) + .detail(ty.display(ctx.db).to_string()) .set_documentation(field.docs(ctx.db)) .set_deprecated(is_deprecated); @@ -107,6 +106,12 @@ impl Completions { } }; + if let ScopeDef::Local(local) = resolution { + if let Some(score) = compute_score(ctx, &local.ty(ctx.db), &local_name) { + completion_item = completion_item.set_score(score); + } + } + // Add `<>` for generic types if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis { if let Some(cap) = ctx.config.snippet_cap { @@ -319,10 +324,11 @@ impl Completions { pub(crate) fn compute_score( ctx: &CompletionContext, - // FIXME: this definitely should be a `Type` - ty: &str, + ty: &Type, name: &str, ) -> Option { + // FIXME: this should not fall back to string equality. + let ty = &ty.display(ctx.db).to_string(); let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { tested_by!(test_struct_field_completion_in_record_lit); let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; @@ -1405,4 +1411,48 @@ mod tests { "### ); } + + #[test] + fn prioritize_exact_ref_match() { + assert_debug_snapshot!( + do_reference_completion( + r" + struct WorldSnapshot { _f: () }; + fn go(world: &WorldSnapshot) { + go(w<|>) + } + ", + ), + @r###" + [ + CompletionItem { + label: "WorldSnapshot", + source_range: 132..133, + delete: 132..133, + insert: "WorldSnapshot", + kind: Struct, + }, + CompletionItem { + label: "go(…)", + source_range: 132..133, + delete: 132..133, + insert: "go(${1:world})$0", + kind: Function, + lookup: "go", + detail: "fn go(world: &WorldSnapshot)", + trigger_call_info: true, + }, + CompletionItem { + label: "world", + source_range: 132..133, + delete: 132..133, + insert: "world", + kind: Binding, + detail: "&WorldSnapshot", + score: TypeAndNameMatch, + }, + ] + "### + ); + } }