aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ide_completion/src/render.rs128
-rw-r--r--crates/rust-analyzer/src/to_proto.rs2
2 files changed, 126 insertions, 4 deletions
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;
10 10
11mod builder_ext; 11mod builder_ext;
12 12
13use base_db::Upcast;
13use hir::{ 14use hir::{
14 AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, 15 db::HirDatabase, AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability,
16 ScopeDef, Type,
15}; 17};
16use ide_db::{ 18use ide_db::{
17 helpers::{item_name, SnippetCap}, 19 helpers::{item_name, SnippetCap},
@@ -325,11 +327,20 @@ impl<'a> Render<'a> {
325fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionRelevance> { 327fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionRelevance> {
326 let (expected_name, expected_type) = ctx.expected_name_and_type()?; 328 let (expected_name, expected_type) = ctx.expected_name_and_type()?;
327 let mut res = CompletionRelevance::default(); 329 let mut res = CompletionRelevance::default();
328 res.exact_type_match = ty == &expected_type; 330 res.exact_type_match = ty == &expected_type
331 || autoderef_relevance(
332 ctx.db().upcast(),
333 ty,
334 expected_type.remove_ref().as_ref().unwrap_or(&expected_type),
335 );
329 res.exact_name_match = name == &expected_name; 336 res.exact_name_match = name == &expected_name;
330 Some(res) 337 Some(res)
331} 338}
332 339
340fn autoderef_relevance(db: &dyn HirDatabase, ty: &Type, expected_type: &Type) -> bool {
341 ty.autoderef(db).any(|deref_ty| &deref_ty == expected_type)
342}
343
333#[cfg(test)] 344#[cfg(test)]
334mod tests { 345mod tests {
335 use std::cmp::Reverse; 346 use std::cmp::Reverse;
@@ -979,7 +990,7 @@ fn main() {
979 detail: "S", 990 detail: "S",
980 relevance: CompletionRelevance { 991 relevance: CompletionRelevance {
981 exact_name_match: true, 992 exact_name_match: true,
982 exact_type_match: false, 993 exact_type_match: true,
983 }, 994 },
984 ref_match: "&mut ", 995 ref_match: "&mut ",
985 }, 996 },
@@ -987,4 +998,115 @@ fn main() {
987 "#]], 998 "#]],
988 ) 999 )
989 } 1000 }
1001
1002 #[test]
1003 fn suggest_deref() {
1004 check(
1005 r#"
1006#[lang = "deref"]
1007trait Deref {
1008 type Target;
1009 fn deref(&self) -> &Self::Target;
1010}
1011
1012struct S;
1013struct T(S);
1014
1015impl Deref for T {
1016 type Target = S;
1017
1018 fn deref(&self) -> &Self::Target {
1019 &self.0
1020 }
1021}
1022
1023fn foo(s: &S) {}
1024
1025fn main() {
1026 let t = T(S);
1027 let m = 123;
1028
1029 foo($0);
1030}
1031 "#,
1032 expect![[r#"
1033 [
1034 CompletionItem {
1035 label: "Deref",
1036 source_range: 293..293,
1037 delete: 293..293,
1038 insert: "Deref",
1039 kind: SymbolKind(
1040 Trait,
1041 ),
1042 },
1043 CompletionItem {
1044 label: "S",
1045 source_range: 293..293,
1046 delete: 293..293,
1047 insert: "S",
1048 kind: SymbolKind(
1049 Struct,
1050 ),
1051 },
1052 CompletionItem {
1053 label: "T",
1054 source_range: 293..293,
1055 delete: 293..293,
1056 insert: "T",
1057 kind: SymbolKind(
1058 Struct,
1059 ),
1060 },
1061 CompletionItem {
1062 label: "foo(…)",
1063 source_range: 293..293,
1064 delete: 293..293,
1065 insert: "foo(${1:s})$0",
1066 kind: SymbolKind(
1067 Function,
1068 ),
1069 lookup: "foo",
1070 detail: "-> ()",
1071 trigger_call_info: true,
1072 },
1073 CompletionItem {
1074 label: "m",
1075 source_range: 293..293,
1076 delete: 293..293,
1077 insert: "m",
1078 kind: SymbolKind(
1079 Local,
1080 ),
1081 detail: "i32",
1082 },
1083 CompletionItem {
1084 label: "main()",
1085 source_range: 293..293,
1086 delete: 293..293,
1087 insert: "main()$0",
1088 kind: SymbolKind(
1089 Function,
1090 ),
1091 lookup: "main",
1092 detail: "-> ()",
1093 },
1094 CompletionItem {
1095 label: "t",
1096 source_range: 293..293,
1097 delete: 293..293,
1098 insert: "t",
1099 kind: SymbolKind(
1100 Local,
1101 ),
1102 detail: "T",
1103 relevance: CompletionRelevance {
1104 exact_name_match: false,
1105 exact_type_match: true,
1106 },
1107 },
1108 ]
1109 "#]],
1110 )
1111 }
990} 1112}
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 1a8cdadad..fecae1259 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -1123,7 +1123,7 @@ mod tests {
1123 ( 1123 (
1124 "arg", 1124 "arg",
1125 Some( 1125 Some(
1126 "fffffffe", 1126 "fffffffd",
1127 ), 1127 ),
1128 ), 1128 ),
1129 ] 1129 ]