aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-03-14 14:27:53 +0000
committerGitHub <[email protected]>2021-03-14 14:27:53 +0000
commitf57e2f55984758a83644b852a4cc47e0b27945df (patch)
tree54d6221f672f343b848660434b653d269b7381ec /crates/ide_completion
parenta32ca8ef796986b42536c3a14515db2cec1131b3 (diff)
parent8a9ebe62a114ef83d46771b28e483f6b8ea5478e (diff)
Merge #7993
7993: Use auto-deref in completion scoring r=JoshMcguigan a=ivan770 Closes #7982 Co-authored-by: ivan770 <[email protected]>
Diffstat (limited to 'crates/ide_completion')
-rw-r--r--crates/ide_completion/src/render.rs158
1 files changed, 137 insertions, 21 deletions
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index db31896e5..fcb8115fb 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},
@@ -251,19 +253,23 @@ impl<'a> Render<'a> {
251 253
252 if let ScopeDef::Local(local) = resolution { 254 if let ScopeDef::Local(local) = resolution {
253 let ty = local.ty(self.ctx.db()); 255 let ty = local.ty(self.ctx.db());
256
254 if let Some(relevance) = compute_relevance(&self.ctx, &ty, &local_name) { 257 if let Some(relevance) = compute_relevance(&self.ctx, &ty, &local_name) {
255 item.set_relevance(relevance); 258 item.set_relevance(relevance);
256 } 259 }
260
257 if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() { 261 if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() {
258 if let Some(ty_without_ref) = expected_type.remove_ref() { 262 if ty != expected_type {
259 if ty_without_ref == ty { 263 if let Some(ty_without_ref) = expected_type.remove_ref() {
260 cov_mark::hit!(suggest_ref); 264 if relevance_type_match(self.ctx.db().upcast(), &ty, &ty_without_ref) {
261 let mutability = if expected_type.is_mutable_reference() { 265 cov_mark::hit!(suggest_ref);
262 Mutability::Mut 266 let mutability = if expected_type.is_mutable_reference() {
263 } else { 267 Mutability::Mut
264 Mutability::Shared 268 } else {
265 }; 269 Mutability::Shared
266 item.ref_match(mutability); 270 };
271 item.ref_match(mutability);
272 }
267 } 273 }
268 } 274 }
269 } 275 }
@@ -330,10 +336,12 @@ fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option<Compl
330 Some(res) 336 Some(res)
331} 337}
332 338
339fn relevance_type_match(db: &dyn HirDatabase, ty: &Type, expected_type: &Type) -> bool {
340 ty == expected_type || ty.autoderef(db).any(|deref_ty| &deref_ty == expected_type)
341}
342
333#[cfg(test)] 343#[cfg(test)]
334mod tests { 344mod tests {
335 use std::cmp::Reverse;
336
337 use expect_test::{expect, Expect}; 345 use expect_test::{expect, Expect};
338 346
339 use crate::{ 347 use crate::{
@@ -358,17 +366,27 @@ mod tests {
358 } 366 }
359 } 367 }
360 368
361 let mut completions = get_all_items(TEST_CONFIG, ra_fixture); 369 let actual = get_all_items(TEST_CONFIG, ra_fixture)
362 completions.sort_by_key(|it| (Reverse(it.relevance()), it.label().to_string()));
363 let actual = completions
364 .into_iter() 370 .into_iter()
365 .filter(|it| it.completion_kind == CompletionKind::Reference) 371 .filter(|it| it.completion_kind == CompletionKind::Reference)
366 .map(|it| { 372 .flat_map(|it| {
373 let mut items = vec![];
374
367 let tag = it.kind().unwrap().tag(); 375 let tag = it.kind().unwrap().tag();
368 let relevance = display_relevance(it.relevance()); 376 let relevance = display_relevance(it.relevance());
369 format!("{} {} {}\n", tag, it.label(), relevance) 377 items.push(format!("{} {} {}\n", tag, it.label(), relevance));
378
379 if let Some((mutability, relevance)) = it.ref_match() {
380 let label = format!("&{}{}", mutability.as_keyword_for_ref(), it.label());
381 let relevance = display_relevance(relevance);
382
383 items.push(format!("{} {} {}\n", tag, label, relevance));
384 }
385
386 items
370 }) 387 })
371 .collect::<String>(); 388 .collect::<String>();
389
372 expect.assert_eq(&actual); 390 expect.assert_eq(&actual);
373 } 391 }
374 392
@@ -838,9 +856,9 @@ fn test(bar: u32) { }
838fn foo(s: S) { test(s.$0) } 856fn foo(s: S) { test(s.$0) }
839"#, 857"#,
840 expect![[r#" 858 expect![[r#"
859 fd foo []
841 fd bar [type+name] 860 fd bar [type+name]
842 fd baz [type] 861 fd baz [type]
843 fd foo []
844 "#]], 862 "#]],
845 ); 863 );
846 } 864 }
@@ -855,9 +873,9 @@ struct B { x: (), y: f32, bar: u32 }
855fn foo(a: A) { B { bar: a.$0 }; } 873fn foo(a: A) { B { bar: a.$0 }; }
856"#, 874"#,
857 expect![[r#" 875 expect![[r#"
876 fd foo []
858 fd bar [type+name] 877 fd bar [type+name]
859 fd baz [type] 878 fd baz [type]
860 fd foo []
861 "#]], 879 "#]],
862 ) 880 )
863 } 881 }
@@ -885,9 +903,9 @@ fn f(foo: i64) { }
885fn foo(a: A) { f(B { bar: a.$0 }); } 903fn foo(a: A) { f(B { bar: a.$0 }); }
886"#, 904"#,
887 expect![[r#" 905 expect![[r#"
906 fd foo []
888 fd bar [type+name] 907 fd bar [type+name]
889 fd baz [type] 908 fd baz [type]
890 fd foo []
891 "#]], 909 "#]],
892 ); 910 );
893 } 911 }
@@ -915,9 +933,9 @@ struct Foo;
915fn f(foo: &Foo) { f(foo, w$0) } 933fn f(foo: &Foo) { f(foo, w$0) }
916"#, 934"#,
917 expect![[r#" 935 expect![[r#"
936 lc foo []
918 st Foo [] 937 st Foo []
919 fn f(…) [] 938 fn f(…) []
920 lc foo []
921 "#]], 939 "#]],
922 ); 940 );
923 } 941 }
@@ -987,4 +1005,102 @@ fn main() {
987 "#]], 1005 "#]],
988 ) 1006 )
989 } 1007 }
1008
1009 #[test]
1010 fn suggest_deref() {
1011 check_relevance(
1012 r#"
1013#[lang = "deref"]
1014trait Deref {
1015 type Target;
1016 fn deref(&self) -> &Self::Target;
1017}
1018
1019struct S;
1020struct T(S);
1021
1022impl Deref for T {
1023 type Target = S;
1024
1025 fn deref(&self) -> &Self::Target {
1026 &self.0
1027 }
1028}
1029
1030fn foo(s: &S) {}
1031
1032fn main() {
1033 let t = T(S);
1034 let m = 123;
1035
1036 foo($0);
1037}
1038 "#,
1039 expect![[r#"
1040 lc m []
1041 lc t []
1042 lc &t [type]
1043 st T []
1044 st S []
1045 fn main() []
1046 tt Deref []
1047 fn foo(…) []
1048 "#]],
1049 )
1050 }
1051
1052 #[test]
1053 fn suggest_deref_mut() {
1054 check_relevance(
1055 r#"
1056#[lang = "deref"]
1057trait Deref {
1058 type Target;
1059 fn deref(&self) -> &Self::Target;
1060}
1061
1062#[lang = "deref_mut"]
1063pub trait DerefMut: Deref {
1064 fn deref_mut(&mut self) -> &mut Self::Target;
1065}
1066
1067struct S;
1068struct T(S);
1069
1070impl Deref for T {
1071 type Target = S;
1072
1073 fn deref(&self) -> &Self::Target {
1074 &self.0
1075 }
1076}
1077
1078impl DerefMut for T {
1079 fn deref_mut(&mut self) -> &mut Self::Target {
1080 &mut self.0
1081 }
1082}
1083
1084fn foo(s: &mut S) {}
1085
1086fn main() {
1087 let t = T(S);
1088 let m = 123;
1089
1090 foo($0);
1091}
1092 "#,
1093 expect![[r#"
1094 lc m []
1095 lc t []
1096 lc &mut t [type]
1097 tt DerefMut []
1098 tt Deref []
1099 fn foo(…) []
1100 st T []
1101 st S []
1102 fn main() []
1103 "#]],
1104 )
1105 }
990} 1106}