diff options
-rw-r--r-- | crates/ide_completion/src/render.rs | 128 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 2 |
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 | ||
11 | mod builder_ext; | 11 | mod builder_ext; |
12 | 12 | ||
13 | use base_db::Upcast; | ||
13 | use hir::{ | 14 | use hir::{ |
14 | AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, | 15 | db::HirDatabase, AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, |
16 | ScopeDef, Type, | ||
15 | }; | 17 | }; |
16 | use ide_db::{ | 18 | use ide_db::{ |
17 | helpers::{item_name, SnippetCap}, | 19 | helpers::{item_name, SnippetCap}, |
@@ -325,11 +327,20 @@ impl<'a> Render<'a> { | |||
325 | fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionRelevance> { | 327 | fn 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 | ||
340 | fn 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)] |
334 | mod tests { | 345 | mod 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"] | ||
1007 | trait Deref { | ||
1008 | type Target; | ||
1009 | fn deref(&self) -> &Self::Target; | ||
1010 | } | ||
1011 | |||
1012 | struct S; | ||
1013 | struct T(S); | ||
1014 | |||
1015 | impl Deref for T { | ||
1016 | type Target = S; | ||
1017 | |||
1018 | fn deref(&self) -> &Self::Target { | ||
1019 | &self.0 | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | fn foo(s: &S) {} | ||
1024 | |||
1025 | fn 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 | ] |