diff --git a/crates/ide/src/inlay_hints/bind_pat.rs b/crates/ide/src/inlay_hints/bind_pat.rs index 10cb91713d..632893a025 100644 --- a/crates/ide/src/inlay_hints/bind_pat.rs +++ b/crates/ide/src/inlay_hints/bind_pat.rs @@ -1140,12 +1140,11 @@ fn test() { #[test] fn no_edit_for_closure_return_without_body_block() { - // We can lift this limitation; see FIXME in closure_ret module. let config = InlayHintsConfig { closure_return_type_hints: ClosureReturnTypeHints::Always, ..TEST_CONFIG }; - check_no_edit( + check_edit( config, r#" struct S(T); @@ -1154,6 +1153,13 @@ fn test() { let f = |a: S| S(a); } "#, + expect![[r#" + struct S(T); + fn test() { + let f = || -> i32 { 3 }; + let f = |a: S| -> S> { S(a) }; + } + "#]], ); } diff --git a/crates/ide/src/inlay_hints/closure_ret.rs b/crates/ide/src/inlay_hints/closure_ret.rs index 16551b64f7..0014c8127d 100644 --- a/crates/ide/src/inlay_hints/closure_ret.rs +++ b/crates/ide/src/inlay_hints/closure_ret.rs @@ -1,8 +1,8 @@ //! Implementation of "closure return type" inlay hints. //! //! Tests live in [`bind_pat`][super::bind_pat] module. -use hir::DisplayTarget; -use ide_db::famous_defs::FamousDefs; +use hir::{DisplayTarget, HirDisplay}; +use ide_db::{famous_defs::FamousDefs, text_edit::TextEdit}; use syntax::ast::{self, AstNode}; use crate::{ @@ -48,7 +48,6 @@ pub(super) fn hints( if arrow.is_none() { label.prepend_str(" -> "); } - // FIXME?: We could provide text edit to insert braces for closures with non-block body. let text_edit = if has_block_body { ty_to_text_edit( sema, @@ -62,7 +61,30 @@ pub(super) fn hints( if arrow.is_none() { " -> " } else { "" }, ) } else { - None + Some(config.lazy_text_edit(|| { + let body = closure.body(); + let body_range = match body { + Some(body) => body.syntax().text_range(), + None => return TextEdit::builder().finish(), + }; + let mut builder = TextEdit::builder(); + let insert_pos = param_list.syntax().text_range().end(); + + let rendered = match sema.scope(closure.syntax()).and_then(|scope| { + ty.display_source_code(scope.db, scope.module().into(), false).ok() + }) { + Some(rendered) => rendered, + None => return TextEdit::builder().finish(), + }; + + let arrow_text = if arrow.is_none() { " -> ".to_owned() } else { "".to_owned() }; + builder.insert(insert_pos, arrow_text); + builder.insert(insert_pos, rendered); + builder.insert(body_range.start(), "{ ".to_owned()); + builder.insert(body_range.end(), " }".to_owned()); + + builder.finish() + })) }; acc.push(InlayHint {