Skip to content

Commit d02f6f2

Browse files
committed
format function
1 parent c3b1543 commit d02f6f2

File tree

2 files changed

+169
-44
lines changed

2 files changed

+169
-44
lines changed

src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -109,50 +109,90 @@ pub(super) fn hints(
109109
}
110110
has_adjustments = true;
111111

112-
// FIXME: Add some nicer tooltips to each of these
113-
let (text, coercion) = match kind {
112+
let (text, coercion, detailed_tooltip) = match kind {
114113
Adjust::NeverToAny if config.adjustment_hints == AdjustmentHints::Always => {
115114
allow_edit = false;
116-
("<never-to-any>", "never to any")
117-
}
118-
Adjust::Deref(None) => ("*", "dereference"),
119-
Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => {
120-
("*", "`Deref` dereference")
121-
}
122-
Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => {
123-
("*", "`DerefMut` dereference")
124-
}
125-
Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => ("&", "borrow"),
126-
Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => ("&mut ", "unique borrow"),
127-
Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => {
128-
("&raw const ", "const pointer borrow")
129-
}
130-
Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => {
131-
("&raw mut ", "mut pointer borrow")
115+
(
116+
"<never-to-any>",
117+
"never to any",
118+
"Coerces the never type `!` into any other type. This happens in code paths that never return, like after `panic!()` or `return`.",
119+
)
132120
}
121+
Adjust::Deref(None) => (
122+
"*",
123+
"dereference",
124+
"Built-in dereference of a reference to access the underlying value. The compiler inserts `*` to get the value from `&T`.",
125+
),
126+
Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => (
127+
"*",
128+
"`Deref` dereference",
129+
"Dereference via the `Deref` trait. Used for types like `Box<T>` or `Rc<T>` so they act like plain `T`.",
130+
),
131+
Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => (
132+
"*",
133+
"`DerefMut` dereference",
134+
"Mutable dereference using the `DerefMut` trait. Enables smart pointers to give mutable access to their inner values.",
135+
),
136+
Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => (
137+
"&",
138+
"shared borrow",
139+
"Inserts `&` to create a shared reference. Lets you use a value without moving or cloning it.",
140+
),
141+
Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => (
142+
"&mut ",
143+
"mutable borrow",
144+
"Inserts `&mut` to create a unique, mutable reference. Lets you modify a value without taking ownership.",
145+
),
146+
Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => (
147+
"&raw const ",
148+
"const raw pointer",
149+
"Converts a reference to a raw const pointer `*const T`. Often used when working with FFI or unsafe code.",
150+
),
151+
Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => (
152+
"&raw mut ",
153+
"mut raw pointer",
154+
"Converts a mutable reference to a raw mutable pointer `*mut T`. Allows mutation in unsafe contexts.",
155+
),
133156
// some of these could be represented via `as` casts, but that's not too nice and
134157
// handling everything as a prefix expr makes the `(` and `)` insertion easier
135158
Adjust::Pointer(cast) if config.adjustment_hints == AdjustmentHints::Always => {
136159
allow_edit = false;
137160
match cast {
138-
PointerCast::ReifyFnPointer => {
139-
("<fn-item-to-fn-pointer>", "fn item to fn pointer")
140-
}
161+
PointerCast::ReifyFnPointer => (
162+
"<fn-item-to-fn-pointer>",
163+
"fn item to fn pointer",
164+
"Converts a named function to a function pointer `fn()`. Useful when passing functions as values."
165+
),
141166
PointerCast::UnsafeFnPointer => (
142167
"<safe-fn-pointer-to-unsafe-fn-pointer>",
143168
"safe fn pointer to unsafe fn pointer",
169+
"Coerces a safe function pointer to an unsafe one. Allows calling it in an unsafe context."
170+
),
171+
PointerCast::ClosureFnPointer(Safety::Unsafe) => (
172+
"<closure-to-unsafe-fn-pointer>",
173+
"closure to unsafe fn pointer",
174+
"Converts a non-capturing closure to an unsafe function pointer. Required for use in `extern` or unsafe APIs."
175+
),
176+
PointerCast::ClosureFnPointer(Safety::Safe) => (
177+
"<closure-to-fn-pointer>",
178+
"closure to fn pointer",
179+
"Converts a non-capturing closure to a function pointer. Lets closures behave like plain functions."
180+
),
181+
PointerCast::MutToConstPointer => (
182+
"<mut-ptr-to-const-ptr>",
183+
"mut ptr to const ptr",
184+
"Coerces `*mut T` to `*const T`. Safe because const pointers restrict what you can do."
185+
),
186+
PointerCast::ArrayToPointer => (
187+
"<array-ptr-to-element-ptr>",
188+
"array to pointer",
189+
"Converts an array to a pointer to its first element. Similar to how arrays decay to pointers in C."
190+
),
191+
PointerCast::Unsize => (
192+
"<unsize>",
193+
"unsize coercion",
194+
"Converts a sized type to an unsized one. Used for things like turning arrays into slices or concrete types into trait objects."
144195
),
145-
PointerCast::ClosureFnPointer(Safety::Unsafe) => {
146-
("<closure-to-unsafe-fn-pointer>", "closure to unsafe fn pointer")
147-
}
148-
PointerCast::ClosureFnPointer(Safety::Safe) => {
149-
("<closure-to-fn-pointer>", "closure to fn pointer")
150-
}
151-
PointerCast::MutToConstPointer => {
152-
("<mut-ptr-to-const-ptr>", "mut ptr to const ptr")
153-
}
154-
PointerCast::ArrayToPointer => ("<array-ptr-to-element-ptr>", ""),
155-
PointerCast::Unsize => ("<unsize>", "unsize"),
156196
}
157197
}
158198
_ => continue,
@@ -162,9 +202,12 @@ pub(super) fn hints(
162202
linked_location: None,
163203
tooltip: Some(config.lazy_tooltip(|| {
164204
InlayTooltip::Markdown(format!(
165-
"`{}` → `{}` ({coercion} coercion)",
205+
"`{}` → `{}`\n\n**{}**\n\n{}",
166206
source.display(sema.db, display_target),
167207
target.display(sema.db, display_target),
208+
coercion.chars().next().unwrap().to_uppercase().collect::<String>()
209+
+ &coercion[1..],
210+
detailed_tooltip
168211
))
169212
})),
170213
};
@@ -175,7 +218,7 @@ pub(super) fn hints(
175218
}
176219

177220
if !postfix && needs_inner_parens {
178-
pre.label.append_str("(");
221+
(&mut pre.label).append_str("(");
179222
}
180223
if needs_outer_parens || (!postfix && needs_inner_parens) {
181224
post.label.append_str(")");

src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ pub(super) fn hints(
9191
match_ast! {
9292
match parent {
9393
ast::Fn(it) => {
94-
// FIXME: this could include parameters, but `HirDisplay` prints too much info
95-
// and doesn't respect the max length either, so the hints end up way too long
96-
(format!("fn {}", it.name()?), it.name().map(name))
94+
let hint_text = format_function_hint(&it, config.max_length?)
95+
.unwrap_or_else(|| format!("fn {}", it.name().map(|n| n.to_string()).unwrap_or_default()));
96+
(hint_text, it.name().map(name))
9797
},
9898
ast::Static(it) => (format!("static {}", it.name()?), it.name().map(name)),
9999
ast::Const(it) => {
@@ -156,6 +156,47 @@ pub(super) fn hints(
156156
None
157157
}
158158

159+
fn format_function_hint(func: &ast::Fn, max_length: usize) -> Option<String> {
160+
let name = func.name()?;
161+
let name_str = name.to_string();
162+
163+
let params = if let Some(param_list) = func.param_list() {
164+
let mut param_parts = Vec::new();
165+
let mut total_len = 0;
166+
let max_param_len = max_length.saturating_sub(name_str.len() + 4);
167+
168+
for param in param_list.params() {
169+
let param_text = if let Some(pat) = param.pat() {
170+
if let Some(ty) = param.ty() { format!("{}: {}", pat, ty) } else { pat.to_string() }
171+
} else if let Some(ty) = param.ty() {
172+
format!("_: {}", ty)
173+
} else {
174+
let param_source = param.syntax().text().to_string();
175+
if param_source.trim() == "..." { "...".to_string() } else { "_".to_string() }
176+
};
177+
178+
let param_len = param_text.len() + if param_parts.is_empty() { 0 } else { 2 };
179+
if total_len + param_len > max_param_len {
180+
param_parts.push("...".to_string());
181+
break;
182+
}
183+
184+
total_len += param_len;
185+
param_parts.push(param_text);
186+
}
187+
188+
if param_parts.is_empty() {
189+
"()".to_string()
190+
} else {
191+
format!("({})", param_parts.join(", "))
192+
}
193+
} else {
194+
"()".to_string()
195+
};
196+
197+
Some(format!("fn {}{}", name_str, params))
198+
}
199+
159200
#[cfg(test)]
160201
mod tests {
161202
use crate::{
@@ -166,7 +207,11 @@ mod tests {
166207
#[test]
167208
fn hints_closing_brace() {
168209
check_with_config(
169-
InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
210+
InlayHintsConfig {
211+
closing_brace_hints_min_lines: Some(2),
212+
max_length: Some(30),
213+
..DISABLED_CONFIG
214+
},
170215
r#"
171216
fn a() {}
172217
@@ -175,17 +220,17 @@ fn f() {
175220
176221
fn g() {
177222
}
178-
//^ fn g
223+
//^ fn g()
179224
180225
fn h<T>(with: T, arguments: u8, ...) {
181226
}
182-
//^ fn h
227+
//^ fn h(with: T, arguments: u8, ...)
183228
184229
trait Tr {
185230
fn f();
186231
fn g() {
187232
}
188-
//^ fn g
233+
//^ fn g()
189234
}
190235
//^ trait Tr
191236
impl Tr for () {
@@ -222,15 +267,19 @@ fn f() {
222267
let v = vec![
223268
];
224269
}
225-
//^ fn f
270+
//^ fn f()
226271
"#,
227272
);
228273
}
229274

230275
#[test]
231276
fn hints_closing_brace_for_block_expr() {
232277
check_with_config(
233-
InlayHintsConfig { closing_brace_hints_min_lines: Some(2), ..DISABLED_CONFIG },
278+
InlayHintsConfig {
279+
closing_brace_hints_min_lines: Some(2),
280+
max_length: Some(10),
281+
..DISABLED_CONFIG
282+
},
234283
r#"
235284
fn test() {
236285
'end: {
@@ -258,7 +307,40 @@ fn test() {
258307
//^ 'a
259308
260309
}
261-
//^ fn test
310+
//^ fn test()
311+
"#,
312+
);
313+
}
314+
315+
#[test]
316+
fn hints_closing_brace_function_parameters() {
317+
check_with_config(
318+
InlayHintsConfig {
319+
closing_brace_hints_min_lines: Some(1),
320+
max_length: Some(50),
321+
..DISABLED_CONFIG
322+
},
323+
r#"
324+
fn simple() {
325+
let v = vec![
326+
];
327+
}
328+
//^ fn simple()
329+
330+
fn with_params(x: i32, y: String) {
331+
332+
}
333+
//^ fn with_params(x: i32, y: String)
334+
335+
fn long_params(very_long_parameter_name: ComplexType, another: AnotherType) {
336+
337+
}
338+
//^ fn long_params(...)
339+
340+
fn many_params(a: i32, b: i32, c: i32, d: i32, e: i32) {
341+
342+
}
343+
//^ fn many_params(a: i32, b: i32, c: i32, d: i32, ...)
262344
"#,
263345
);
264346
}

0 commit comments

Comments
 (0)