Skip to content

Commit fe99a29

Browse files
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]>
2 parents 45832b9 + 5a355ff commit fe99a29

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,13 @@ impl Type {
11361136
matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. }))
11371137
}
11381138

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+
11391146
pub fn contains_unknown(&self) -> bool {
11401147
return go(&self.ty.value);
11411148

crates/ra_ide/src/completion/presentation.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,14 @@ impl Builder {
349349
if ctx.use_item_syntax.is_some() || ctx.is_call {
350350
return self;
351351
}
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+
352360
let cap = match ctx.config.snippet_cap {
353361
Some(it) => it,
354362
None => return self,
@@ -748,6 +756,54 @@ mod tests {
748756
);
749757
}
750758

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+
751807
#[test]
752808
fn arg_snippets_for_method_call() {
753809
assert_debug_snapshot!(
@@ -1179,7 +1235,7 @@ mod tests {
11791235

11801236
#[test]
11811237
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);
11831239
assert_debug_snapshot!(
11841240
do_reference_completion(
11851241
r"

0 commit comments

Comments
 (0)