diff options
-rw-r--r-- | crates/hir/src/lib.rs | 7 | ||||
-rw-r--r-- | crates/ide_completion/src/item.rs | 13 | ||||
-rw-r--r-- | crates/ide_completion/src/render.rs | 90 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 7 |
4 files changed, 87 insertions, 30 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index d5a3d9034..641ea4221 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -1614,10 +1614,9 @@ impl Type { | |||
1614 | } | 1614 | } |
1615 | 1615 | ||
1616 | pub fn remove_ref(&self) -> Option<Type> { | 1616 | pub fn remove_ref(&self) -> Option<Type> { |
1617 | if let Ty::Ref(.., substs) = &self.ty.value { | 1617 | match &self.ty.value { |
1618 | Some(self.derived(substs[0].clone())) | 1618 | Ty::Ref(.., substs) => Some(self.derived(substs[0].clone())), |
1619 | } else { | 1619 | _ => None, |
1620 | None | ||
1621 | } | 1620 | } |
1622 | } | 1621 | } |
1623 | 1622 | ||
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs index b16f0775a..5e8ed75f1 100644 --- a/crates/ide_completion/src/item.rs +++ b/crates/ide_completion/src/item.rs | |||
@@ -68,7 +68,7 @@ pub struct CompletionItem { | |||
68 | 68 | ||
69 | /// Indicates that a reference or mutable reference to this variable is a | 69 | /// Indicates that a reference or mutable reference to this variable is a |
70 | /// possible match. | 70 | /// possible match. |
71 | ref_match: Option<(Mutability, CompletionScore)>, | 71 | ref_match: Option<Mutability>, |
72 | 72 | ||
73 | /// The import data to add to completion's edits. | 73 | /// The import data to add to completion's edits. |
74 | import_to_add: Option<ImportEdit>, | 74 | import_to_add: Option<ImportEdit>, |
@@ -104,6 +104,9 @@ impl fmt::Debug for CompletionItem { | |||
104 | if let Some(score) = &self.score { | 104 | if let Some(score) = &self.score { |
105 | s.field("score", score); | 105 | s.field("score", score); |
106 | } | 106 | } |
107 | if let Some(mutability) = &self.ref_match { | ||
108 | s.field("ref_match", &format!("&{}", mutability.as_keyword_for_ref())); | ||
109 | } | ||
107 | if self.trigger_call_info { | 110 | if self.trigger_call_info { |
108 | s.field("trigger_call_info", &true); | 111 | s.field("trigger_call_info", &true); |
109 | } | 112 | } |
@@ -261,7 +264,7 @@ impl CompletionItem { | |||
261 | self.trigger_call_info | 264 | self.trigger_call_info |
262 | } | 265 | } |
263 | 266 | ||
264 | pub fn ref_match(&self) -> Option<(Mutability, CompletionScore)> { | 267 | pub fn ref_match(&self) -> Option<Mutability> { |
265 | self.ref_match | 268 | self.ref_match |
266 | } | 269 | } |
267 | 270 | ||
@@ -311,7 +314,7 @@ pub(crate) struct Builder { | |||
311 | deprecated: bool, | 314 | deprecated: bool, |
312 | trigger_call_info: Option<bool>, | 315 | trigger_call_info: Option<bool>, |
313 | score: Option<CompletionScore>, | 316 | score: Option<CompletionScore>, |
314 | ref_match: Option<(Mutability, CompletionScore)>, | 317 | ref_match: Option<Mutability>, |
315 | } | 318 | } |
316 | 319 | ||
317 | impl Builder { | 320 | impl Builder { |
@@ -430,8 +433,8 @@ impl Builder { | |||
430 | self.import_to_add = import_to_add; | 433 | self.import_to_add = import_to_add; |
431 | self | 434 | self |
432 | } | 435 | } |
433 | pub(crate) fn ref_match(mut self, ref_match: (Mutability, CompletionScore)) -> Builder { | 436 | pub(crate) fn ref_match(mut self, mutability: Mutability) -> Builder { |
434 | self.ref_match = Some(ref_match); | 437 | self.ref_match = Some(mutability); |
435 | self | 438 | self |
436 | } | 439 | } |
437 | } | 440 | } |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 0a6ac8804..0a1b0f95d 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -254,10 +254,17 @@ impl<'a> Render<'a> { | |||
254 | { | 254 | { |
255 | item = item.set_score(score); | 255 | item = item.set_score(score); |
256 | } | 256 | } |
257 | if let Some(ref_match) = | 257 | |
258 | refed_type_matches(&active_type, &active_name, &ty, &local_name) | 258 | if let Some(ty_without_ref) = active_type.remove_ref() { |
259 | { | 259 | if ty_without_ref == ty { |
260 | item = item.ref_match(ref_match); | 260 | cov_mark::hit!(suggest_ref); |
261 | let mutability = if active_type.is_mutable_reference() { | ||
262 | Mutability::Mut | ||
263 | } else { | ||
264 | Mutability::Shared | ||
265 | }; | ||
266 | item = item.ref_match(mutability) | ||
267 | } | ||
261 | } | 268 | } |
262 | } | 269 | } |
263 | } | 270 | } |
@@ -340,19 +347,6 @@ fn compute_score_from_active( | |||
340 | 347 | ||
341 | Some(res) | 348 | Some(res) |
342 | } | 349 | } |
343 | fn refed_type_matches( | ||
344 | active_type: &Type, | ||
345 | active_name: &str, | ||
346 | ty: &Type, | ||
347 | name: &str, | ||
348 | ) -> Option<(Mutability, CompletionScore)> { | ||
349 | let derefed_active = active_type.remove_ref()?; | ||
350 | let score = compute_score_from_active(&derefed_active, &active_name, &ty, &name)?; | ||
351 | Some(( | ||
352 | if active_type.is_mutable_reference() { Mutability::Mut } else { Mutability::Shared }, | ||
353 | score, | ||
354 | )) | ||
355 | } | ||
356 | 350 | ||
357 | fn compute_score(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionScore> { | 351 | fn compute_score(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionScore> { |
358 | let (active_name, active_type) = ctx.active_name_and_type()?; | 352 | let (active_name, active_type) = ctx.active_name_and_type()?; |
@@ -947,4 +941,66 @@ fn f(foo: &Foo) { f(foo, w$0) } | |||
947 | "#]], | 941 | "#]], |
948 | ); | 942 | ); |
949 | } | 943 | } |
944 | |||
945 | #[test] | ||
946 | fn suggest_ref_mut() { | ||
947 | cov_mark::check!(suggest_ref); | ||
948 | check( | ||
949 | r#" | ||
950 | struct S; | ||
951 | fn foo(s: &mut S) {} | ||
952 | fn main() { | ||
953 | let mut s = S; | ||
954 | foo($0); | ||
955 | } | ||
956 | "#, | ||
957 | expect![[r#" | ||
958 | [ | ||
959 | CompletionItem { | ||
960 | label: "S", | ||
961 | source_range: 70..70, | ||
962 | delete: 70..70, | ||
963 | insert: "S", | ||
964 | kind: SymbolKind( | ||
965 | Struct, | ||
966 | ), | ||
967 | }, | ||
968 | CompletionItem { | ||
969 | label: "foo(…)", | ||
970 | source_range: 70..70, | ||
971 | delete: 70..70, | ||
972 | insert: "foo(${1:&mut s})$0", | ||
973 | kind: SymbolKind( | ||
974 | Function, | ||
975 | ), | ||
976 | lookup: "foo", | ||
977 | detail: "-> ()", | ||
978 | trigger_call_info: true, | ||
979 | }, | ||
980 | CompletionItem { | ||
981 | label: "main()", | ||
982 | source_range: 70..70, | ||
983 | delete: 70..70, | ||
984 | insert: "main()$0", | ||
985 | kind: SymbolKind( | ||
986 | Function, | ||
987 | ), | ||
988 | lookup: "main", | ||
989 | detail: "-> ()", | ||
990 | }, | ||
991 | CompletionItem { | ||
992 | label: "s", | ||
993 | source_range: 70..70, | ||
994 | delete: 70..70, | ||
995 | insert: "s", | ||
996 | kind: SymbolKind( | ||
997 | Local, | ||
998 | ), | ||
999 | detail: "S", | ||
1000 | ref_match: "&mut ", | ||
1001 | }, | ||
1002 | ] | ||
1003 | "#]], | ||
1004 | ) | ||
1005 | } | ||
950 | } | 1006 | } |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 261d9fb18..a730fb448 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -232,9 +232,8 @@ pub(crate) fn completion_item( | |||
232 | } | 232 | } |
233 | 233 | ||
234 | let mut res = match item.ref_match() { | 234 | let mut res = match item.ref_match() { |
235 | Some(ref_match) => { | 235 | Some(mutability) => { |
236 | let mut refed = lsp_item.clone(); | 236 | let mut refed = lsp_item.clone(); |
237 | let (mutability, _score) = ref_match; | ||
238 | let label = format!("&{}{}", mutability.as_keyword_for_ref(), refed.label); | 237 | let label = format!("&{}{}", mutability.as_keyword_for_ref(), refed.label); |
239 | set_score(&mut refed, &label); | 238 | set_score(&mut refed, &label); |
240 | refed.label = label; | 239 | refed.label = label; |
@@ -243,8 +242,8 @@ pub(crate) fn completion_item( | |||
243 | None => vec![lsp_item], | 242 | None => vec![lsp_item], |
244 | }; | 243 | }; |
245 | 244 | ||
246 | for mut r in res.iter_mut() { | 245 | for lsp_item in res.iter_mut() { |
247 | r.insert_text_format = Some(insert_text_format(item.insert_text_format())); | 246 | lsp_item.insert_text_format = Some(insert_text_format(item.insert_text_format())); |
248 | } | 247 | } |
249 | res | 248 | res |
250 | } | 249 | } |