Merge pull request #19348 from jnyfah/some-branch

Add text edit support for return type hints on non-block body closures
This commit is contained in:
Lukas Wirth 2025-03-21 14:15:06 +00:00 committed by GitHub
commit 3edfbcd502
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 34 additions and 6 deletions

View file

@ -1140,12 +1140,11 @@ fn test() {
#[test] #[test]
fn no_edit_for_closure_return_without_body_block() { fn no_edit_for_closure_return_without_body_block() {
// We can lift this limitation; see FIXME in closure_ret module.
let config = InlayHintsConfig { let config = InlayHintsConfig {
closure_return_type_hints: ClosureReturnTypeHints::Always, closure_return_type_hints: ClosureReturnTypeHints::Always,
..TEST_CONFIG ..TEST_CONFIG
}; };
check_no_edit( check_edit(
config, config,
r#" r#"
struct S<T>(T); struct S<T>(T);
@ -1154,6 +1153,13 @@ fn test() {
let f = |a: S<usize>| S(a); let f = |a: S<usize>| S(a);
} }
"#, "#,
expect![[r#"
struct S<T>(T);
fn test() {
let f = || -> i32 { 3 };
let f = |a: S<usize>| -> S<S<usize>> { S(a) };
}
"#]],
); );
} }

View file

@ -1,8 +1,8 @@
//! Implementation of "closure return type" inlay hints. //! Implementation of "closure return type" inlay hints.
//! //!
//! Tests live in [`bind_pat`][super::bind_pat] module. //! Tests live in [`bind_pat`][super::bind_pat] module.
use hir::DisplayTarget; use hir::{DisplayTarget, HirDisplay};
use ide_db::famous_defs::FamousDefs; use ide_db::{famous_defs::FamousDefs, text_edit::TextEdit};
use syntax::ast::{self, AstNode}; use syntax::ast::{self, AstNode};
use crate::{ use crate::{
@ -48,7 +48,6 @@ pub(super) fn hints(
if arrow.is_none() { if arrow.is_none() {
label.prepend_str(" -> "); 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 { let text_edit = if has_block_body {
ty_to_text_edit( ty_to_text_edit(
sema, sema,
@ -62,7 +61,30 @@ pub(super) fn hints(
if arrow.is_none() { " -> " } else { "" }, if arrow.is_none() { " -> " } else { "" },
) )
} 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 { acc.push(InlayHint {