From d064ed5f63b746277895ae2aad37b5fd1516cce7 Mon Sep 17 00:00:00 2001 From: ivan770 Date: Sat, 13 Mar 2021 14:34:11 +0200 Subject: Count derefs as matched types if possible --- crates/ide_completion/src/render.rs | 128 +++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 3 deletions(-) (limited to 'crates/ide_completion/src') diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index db31896e5..027dee4f0 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs @@ -10,8 +10,10 @@ pub(crate) mod type_alias; mod builder_ext; +use base_db::Upcast; use hir::{ - AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, + db::HirDatabase, AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, + ScopeDef, Type, }; use ide_db::{ helpers::{item_name, SnippetCap}, @@ -325,11 +327,20 @@ impl<'a> Render<'a> { fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option { let (expected_name, expected_type) = ctx.expected_name_and_type()?; let mut res = CompletionRelevance::default(); - res.exact_type_match = ty == &expected_type; + res.exact_type_match = ty == &expected_type + || autoderef_relevance( + ctx.db().upcast(), + ty, + expected_type.remove_ref().as_ref().unwrap_or(&expected_type), + ); res.exact_name_match = name == &expected_name; Some(res) } +fn autoderef_relevance(db: &dyn HirDatabase, ty: &Type, expected_type: &Type) -> bool { + ty.autoderef(db).any(|deref_ty| &deref_ty == expected_type) +} + #[cfg(test)] mod tests { use std::cmp::Reverse; @@ -979,7 +990,7 @@ fn main() { detail: "S", relevance: CompletionRelevance { exact_name_match: true, - exact_type_match: false, + exact_type_match: true, }, ref_match: "&mut ", }, @@ -987,4 +998,115 @@ fn main() { "#]], ) } + + #[test] + fn suggest_deref() { + check( + r#" +#[lang = "deref"] +trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct S; +struct T(S); + +impl Deref for T { + type Target = S; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn foo(s: &S) {} + +fn main() { + let t = T(S); + let m = 123; + + foo($0); +} + "#, + expect![[r#" + [ + CompletionItem { + label: "Deref", + source_range: 293..293, + delete: 293..293, + insert: "Deref", + kind: SymbolKind( + Trait, + ), + }, + CompletionItem { + label: "S", + source_range: 293..293, + delete: 293..293, + insert: "S", + kind: SymbolKind( + Struct, + ), + }, + CompletionItem { + label: "T", + source_range: 293..293, + delete: 293..293, + insert: "T", + kind: SymbolKind( + Struct, + ), + }, + CompletionItem { + label: "foo(…)", + source_range: 293..293, + delete: 293..293, + insert: "foo(${1:s})$0", + kind: SymbolKind( + Function, + ), + lookup: "foo", + detail: "-> ()", + trigger_call_info: true, + }, + CompletionItem { + label: "m", + source_range: 293..293, + delete: 293..293, + insert: "m", + kind: SymbolKind( + Local, + ), + detail: "i32", + }, + CompletionItem { + label: "main()", + source_range: 293..293, + delete: 293..293, + insert: "main()$0", + kind: SymbolKind( + Function, + ), + lookup: "main", + detail: "-> ()", + }, + CompletionItem { + label: "t", + source_range: 293..293, + delete: 293..293, + insert: "t", + kind: SymbolKind( + Local, + ), + detail: "T", + relevance: CompletionRelevance { + exact_name_match: false, + exact_type_match: true, + }, + }, + ] + "#]], + ) + } } -- cgit v1.2.3