Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/inlay_hints/closing_brace.rs')
| -rw-r--r-- | crates/ide/src/inlay_hints/closing_brace.rs | 102 |
1 files changed, 92 insertions, 10 deletions
diff --git a/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs index ca3a982760..b2ee254701 100644 --- a/crates/ide/src/inlay_hints/closing_brace.rs +++ b/crates/ide/src/inlay_hints/closing_brace.rs @@ -91,9 +91,9 @@ pub(super) fn hints( match_ast! { match parent { ast::Fn(it) => { - // FIXME: this could include parameters, but `HirDisplay` prints too much info - // and doesn't respect the max length either, so the hints end up way too long - (format!("fn {}", it.name()?), it.name().map(name)) + let hint_text = format_function_hint(&it, config.max_length?) + .unwrap_or_else(|| format!("fn {}", it.name().map(|n| n.to_string()).unwrap_or_default())); + (hint_text, it.name().map(name)) }, ast::Static(it) => (format!("static {}", it.name()?), it.name().map(name)), ast::Const(it) => { @@ -156,6 +156,47 @@ pub(super) fn hints( None } +fn format_function_hint(func: &ast::Fn, max_length: usize) -> Option<String> { + let name = func.name()?; + let name_str = name.to_string(); + + let params = if let Some(param_list) = func.param_list() { + let mut param_parts = Vec::new(); + let mut total_len = 0; + let max_param_len = max_length.saturating_sub(name_str.len() + 4); + + for param in param_list.params() { + let param_text = if let Some(pat) = param.pat() { + if let Some(ty) = param.ty() { format!("{}: {}", pat, ty) } else { pat.to_string() } + } else if let Some(ty) = param.ty() { + format!("_: {}", ty) + } else { + let param_source = param.syntax().text().to_string(); + if param_source.trim() == "..." { "...".to_string() } else { "_".to_string() } + }; + + let param_len = param_text.len() + if param_parts.is_empty() { 0 } else { 2 }; + if total_len + param_len > max_param_len { + param_parts.push("...".to_string()); + break; + } + + total_len += param_len; + param_parts.push(param_text); + } + + if param_parts.is_empty() { + "()".to_string() + } else { + format!("({})", param_parts.join(", ")) + } + } else { + "()".to_string() + }; + + Some(format!("fn {}{}", name_str, params)) +} + #[cfg(test)] mod tests { use crate::{ @@ -166,7 +207,11 @@ mod tests { #[test] fn hints_closing_brace() { check_with_config( - InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG }, + InlayHintsConfig { + closing_brace_hints_min_lines: Some(2), + max_length: Some(30), + ..DISABLED_CONFIG + }, r#" fn a() {} @@ -175,17 +220,17 @@ fn f() { fn g() { } -//^ fn g +//^ fn g() fn h<T>(with: T, arguments: u8, ...) { } -//^ fn h +//^ fn h(with: T, arguments: u8, ...) trait Tr { fn f(); fn g() { } - //^ fn g + //^ fn g() } //^ trait Tr impl Tr for () { @@ -222,7 +267,7 @@ fn f() { let v = vec![ ]; } -//^ fn f +//^ fn f() "#, ); } @@ -230,7 +275,11 @@ fn f() { #[test] fn hints_closing_brace_for_block_expr() { check_with_config( - InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG }, + InlayHintsConfig { + closing_brace_hints_min_lines: Some(2), + max_length: Some(10), + ..DISABLED_CONFIG + }, r#" fn test() { 'end: { @@ -258,7 +307,40 @@ fn test() { //^ 'a } -//^ fn test +//^ fn test() +"#, + ); + } + + #[test] + fn hints_closing_brace_function_parameters() { + check_with_config( + InlayHintsConfig { + closing_brace_hints_min_lines: Some(1), + max_length: Some(50), + ..DISABLED_CONFIG + }, + r#" +fn simple() { + let v = vec![ + ]; + } +//^ fn simple() + +fn with_params(x: i32, y: String) { + + } +//^ fn with_params(x: i32, y: String) + +fn long_params(very_long_parameter_name: ComplexType, another: AnotherType) { + + } +//^ fn long_params(...) + +fn many_params(a: i32, b: i32, c: i32, d: i32, e: i32) { + + } +//^ fn many_params(a: i32, b: i32, c: i32, d: i32, ...) "#, ); } |