diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-04-25 21:30:50 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-04-25 21:30:50 +0100 |
commit | fe99a29ad1226dd3f6801ea4bdb575506324be07 (patch) | |
tree | 4294c94e11a4ac689c13e2a3699d3c1aad8c94a3 | |
parent | 45832b990c7f291abe578dff3c460f4a1232f024 (diff) | |
parent | 5a355ff52bc3f05e13a1c675290781da68289bc4 (diff) |
Merge #4146
4146: Don't add call parens when an fn type is expected r=matklad a=jonas-schievink
This is pretty useful when dealing with callback- or fn-pointer-heavy FFI code, as I have recently.
Co-authored-by: Jonas Schievink <[email protected]>
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 58 |
2 files changed, 64 insertions, 1 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 3f645a1dd..fb788736d 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1136,6 +1136,13 @@ impl Type { | |||
1136 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. })) | 1136 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. })) |
1137 | } | 1137 | } |
1138 | 1138 | ||
1139 | pub fn is_fn(&self) -> bool { | ||
1140 | matches!(&self.ty.value, | ||
1141 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(..), .. }) | | ||
1142 | Ty::Apply(ApplicationTy { ctor: TypeCtor::FnPtr { .. }, .. }) | ||
1143 | ) | ||
1144 | } | ||
1145 | |||
1139 | pub fn contains_unknown(&self) -> bool { | 1146 | pub fn contains_unknown(&self) -> bool { |
1140 | return go(&self.ty.value); | 1147 | return go(&self.ty.value); |
1141 | 1148 | ||
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 7633cd7fd..f5b074461 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -349,6 +349,14 @@ impl Builder { | |||
349 | if ctx.use_item_syntax.is_some() || ctx.is_call { | 349 | if ctx.use_item_syntax.is_some() || ctx.is_call { |
350 | return self; | 350 | return self; |
351 | } | 351 | } |
352 | |||
353 | // Don't add parentheses if the expected type is some function reference. | ||
354 | if let Some(ty) = ctx.expected_type_of(&ctx.token.parent()) { | ||
355 | if ty.is_fn() { | ||
356 | return self; | ||
357 | } | ||
358 | } | ||
359 | |||
352 | let cap = match ctx.config.snippet_cap { | 360 | let cap = match ctx.config.snippet_cap { |
353 | Some(it) => it, | 361 | Some(it) => it, |
354 | None => return self, | 362 | None => return self, |
@@ -749,6 +757,54 @@ mod tests { | |||
749 | } | 757 | } |
750 | 758 | ||
751 | #[test] | 759 | #[test] |
760 | fn no_call_parens_if_fn_ptr_needed() { | ||
761 | assert_debug_snapshot!( | ||
762 | do_reference_completion( | ||
763 | r" | ||
764 | fn somefn(with: u8, a: u8, lot: u8, of: u8, args: u8) {} | ||
765 | |||
766 | struct ManualVtable { | ||
767 | method: fn(u8, u8, u8, u8, u8), | ||
768 | } | ||
769 | |||
770 | fn main() -> ManualVtable { | ||
771 | ManualVtable { | ||
772 | method: some<|> | ||
773 | } | ||
774 | } | ||
775 | " | ||
776 | ), | ||
777 | @r###" | ||
778 | [ | ||
779 | CompletionItem { | ||
780 | label: "ManualVtable", | ||
781 | source_range: 295..299, | ||
782 | delete: 295..299, | ||
783 | insert: "ManualVtable", | ||
784 | kind: Struct, | ||
785 | }, | ||
786 | CompletionItem { | ||
787 | label: "main", | ||
788 | source_range: 295..299, | ||
789 | delete: 295..299, | ||
790 | insert: "main", | ||
791 | kind: Function, | ||
792 | detail: "fn main() -> ManualVtable", | ||
793 | }, | ||
794 | CompletionItem { | ||
795 | label: "somefn", | ||
796 | source_range: 295..299, | ||
797 | delete: 295..299, | ||
798 | insert: "somefn", | ||
799 | kind: Function, | ||
800 | detail: "fn somefn(with: u8, a: u8, lot: u8, of: u8, args: u8)", | ||
801 | }, | ||
802 | ] | ||
803 | "### | ||
804 | ); | ||
805 | } | ||
806 | |||
807 | #[test] | ||
752 | fn arg_snippets_for_method_call() { | 808 | fn arg_snippets_for_method_call() { |
753 | assert_debug_snapshot!( | 809 | assert_debug_snapshot!( |
754 | do_reference_completion( | 810 | do_reference_completion( |
@@ -1179,7 +1235,7 @@ mod tests { | |||
1179 | 1235 | ||
1180 | #[test] | 1236 | #[test] |
1181 | fn test_struct_field_completion_in_record_lit() { | 1237 | fn test_struct_field_completion_in_record_lit() { |
1182 | covers!(test_struct_field_completion_in_func_call); | 1238 | covers!(test_struct_field_completion_in_record_lit); |
1183 | assert_debug_snapshot!( | 1239 | assert_debug_snapshot!( |
1184 | do_reference_completion( | 1240 | do_reference_completion( |
1185 | r" | 1241 | r" |