Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: hide type inlay hints for initializations of closures #12263

Merged
merged 1 commit into from May 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 72 additions & 5 deletions crates/ide/src/inlay_hints.rs
Expand Up @@ -26,6 +26,7 @@ pub struct InlayHintsConfig {
pub lifetime_elision_hints: LifetimeElisionHints,
pub param_names_for_lifetime_elision_hints: bool,
pub hide_named_constructor_hints: bool,
pub hide_closure_initialization_hints: bool,
pub max_length: Option<usize>,
pub closing_brace_hints_min_lines: Option<usize>,
}
Expand Down Expand Up @@ -467,10 +468,11 @@ fn closure_ret_hints(
return None;
}

let param_list = match closure.body() {
Some(ast::Expr::BlockExpr(_)) => closure.param_list()?,
_ => return None,
};
if !closure_has_block_body(&closure) {
return None;
}

let param_list = closure.param_list()?;

let closure = sema.descend_node_into_attributes(closure.clone()).pop()?;
let ty = sema.type_of_expr(&ast::Expr::ClosureExpr(closure))?.adjusted();
Expand Down Expand Up @@ -693,7 +695,7 @@ fn bind_pat_hints(
let desc_pat = descended.as_ref().unwrap_or(pat);
let ty = sema.type_of_pat(&desc_pat.clone().into())?.original;

if should_not_display_type_hint(sema, pat, &ty) {
if should_not_display_type_hint(sema, config, pat, &ty) {
return None;
}

Expand Down Expand Up @@ -848,6 +850,7 @@ fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &hir

fn should_not_display_type_hint(
sema: &Semantics<RootDatabase>,
config: &InlayHintsConfig,
bind_pat: &ast::IdentPat,
pat_ty: &hir::Type,
) -> bool {
Expand All @@ -863,6 +866,18 @@ fn should_not_display_type_hint(
}
}

if config.hide_closure_initialization_hints {
if let Some(parent) = bind_pat.syntax().parent() {
if let Some(it) = ast::LetStmt::cast(parent.clone()) {
if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
if closure_has_block_body(&closure) {
return true;
}
}
}
}
}

for node in bind_pat.syntax().ancestors() {
match_ast! {
match node {
Expand All @@ -889,6 +904,10 @@ fn should_not_display_type_hint(
false
}

fn closure_has_block_body(closure: &ast::ClosureExpr) -> bool {
matches!(closure.body(), Some(ast::Expr::BlockExpr(_)))
}

fn should_hide_param_name_hint(
sema: &Semantics<RootDatabase>,
callable: &hir::Callable,
Expand Down Expand Up @@ -1083,6 +1102,7 @@ mod tests {
reborrow_hints: ReborrowHints::Always,
binding_mode_hints: false,
hide_named_constructor_hints: false,
hide_closure_initialization_hints: false,
param_names_for_lifetime_elision_hints: false,
max_length: None,
closing_brace_hints_min_lines: None,
Expand Down Expand Up @@ -2034,6 +2054,53 @@ fn main() {
);
}

#[test]
fn skip_closure_type_hints() {
check_with_config(
InlayHintsConfig {
type_hints: true,
hide_closure_initialization_hints: true,
..DISABLED_CONFIG
},
r#"
//- minicore: fn
fn main() {
let multiple_2 = |x: i32| { x * 2 };

let multiple_2 = |x: i32| x * 2;
// ^^^^^^^^^^ |i32| -> i32

let (not) = (|x: bool| { !x });
// ^^^ |bool| -> bool

let (is_zero, _b) = (|x: usize| { x == 0 }, false);
// ^^^^^^^ |usize| -> bool
// ^^ bool

let plus_one = |x| { x + 1 };
// ^ u8
foo(plus_one);

let add_mul = bar(|x: u8| { x + 1 });
// ^^^^^^^ impl FnOnce(u8) -> u8 + ?Sized

let closure = if let Some(6) = add_mul(2).checked_sub(1) {
// ^^^^^^^ fn(i32) -> i32
|x: i32| { x * 2 }
} else {
|x: i32| { x * 3 }
};
}

fn foo(f: impl FnOnce(u8) -> u8) {}

fn bar(f: impl FnOnce(u8) -> u8) -> impl FnOnce(u8) -> u8 {
move |x: u8| f(x) * 2
}
"#,
);
}

#[test]
fn hint_truncation() {
check_with_config(
Expand Down
1 change: 1 addition & 0 deletions crates/ide/src/static_index.rs
Expand Up @@ -113,6 +113,7 @@ impl StaticIndex<'_> {
lifetime_elision_hints: crate::LifetimeElisionHints::Never,
reborrow_hints: crate::ReborrowHints::Never,
hide_named_constructor_hints: false,
hide_closure_initialization_hints: false,
param_names_for_lifetime_elision_hints: false,
binding_mode_hints: false,
max_length: Some(25),
Expand Down
6 changes: 6 additions & 0 deletions crates/rust-analyzer/src/config.rs
Expand Up @@ -281,6 +281,9 @@ config_data! {
inlayHints_renderColons: bool = "true",
/// Whether to show inlay type hints for variables.
inlayHints_typeHints_enable: bool = "true",
/// Whether to hide inlay type hints for `let` statements that initialize to a closure.
/// Only applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.
inlayHints_typeHints_hideClosureInitialization: bool = "false",
andylizi marked this conversation as resolved.
Show resolved Hide resolved
/// Whether to hide inlay type hints for constructors.
inlayHints_typeHints_hideNamedConstructor: bool = "false",

Expand Down Expand Up @@ -1000,6 +1003,9 @@ impl Config {
LifetimeElisionDef::SkipTrivial => ide::LifetimeElisionHints::SkipTrivial,
},
hide_named_constructor_hints: self.data.inlayHints_typeHints_hideNamedConstructor,
hide_closure_initialization_hints: self
.data
.inlayHints_typeHints_hideClosureInitialization,
reborrow_hints: match self.data.inlayHints_reborrowHints_enable {
ReborrowHintsDef::Always => ide::ReborrowHints::Always,
ReborrowHintsDef::Never => ide::ReborrowHints::Never,
Expand Down
6 changes: 6 additions & 0 deletions docs/user/generated_config.adoc
Expand Up @@ -407,6 +407,12 @@ Whether to render leading colons for type hints, and trailing colons for paramet
--
Whether to show inlay type hints for variables.
--
[[rust-analyzer.inlayHints.typeHints.hideClosureInitialization]]rust-analyzer.inlayHints.typeHints.hideClosureInitialization (default: `false`)::
+
--
Whether to hide inlay type hints for `let` statements that initialize to a closure.
Only applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.
--
[[rust-analyzer.inlayHints.typeHints.hideNamedConstructor]]rust-analyzer.inlayHints.typeHints.hideNamedConstructor (default: `false`)::
+
--
Expand Down
5 changes: 5 additions & 0 deletions editors/code/package.json
Expand Up @@ -868,6 +868,11 @@
"default": true,
"type": "boolean"
},
"rust-analyzer.inlayHints.typeHints.hideClosureInitialization": {
"markdownDescription": "Whether to hide inlay type hints for `let` statements that initialize to a closure.\nOnly applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.",
"default": false,
"type": "boolean"
},
"rust-analyzer.inlayHints.typeHints.hideNamedConstructor": {
"markdownDescription": "Whether to hide inlay type hints for constructors.",
"default": false,
Expand Down