Unnamed repository; edit this file 'description' to name the repository.
feat: hide type inlay hints for initializations of closures
andylizi 2022-05-20
parent 44be090 · commit 2b1c1a9
-rw-r--r--crates/ide/src/inlay_hints.rs77
-rw-r--r--crates/ide/src/static_index.rs1
-rw-r--r--crates/rust-analyzer/src/config.rs6
-rw-r--r--docs/user/generated_config.adoc6
-rw-r--r--editors/code/package.json5
5 files changed, 90 insertions, 5 deletions
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 5eb63a42ad..3689bd5a42 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -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>,
}
@@ -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();
@@ -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;
}
@@ -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 {
@@ -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 {
@@ -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,
@@ -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,
@@ -2035,6 +2055,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(
InlayHintsConfig { max_length: Some(8), ..TEST_CONFIG },
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index 01d7213630..006b18b7fd 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -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),
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index afa83e6206..d7ae4c72f5 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -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",
/// Whether to hide inlay type hints for constructors.
inlayHints_typeHints_hideNamedConstructor: bool = "false",
@@ -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,
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 30722af08c..955f085d3f 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -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`)::
+
--
diff --git a/editors/code/package.json b/editors/code/package.json
index e81dfff278..f46c7ea92d 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -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,