mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-24 19:12:55 +00:00
Add hover for closure
This commit is contained in:
parent
370b72c7dd
commit
5df545b3f0
7 changed files with 249 additions and 7 deletions
|
@ -119,8 +119,8 @@ fn hover_simple(
|
|||
| T![crate]
|
||||
| T![Self]
|
||||
| T![_] => 4,
|
||||
// index and prefix ops
|
||||
T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
|
||||
// index and prefix ops and closure pipe
|
||||
T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] | T![|] => 3,
|
||||
kind if kind.is_keyword() => 2,
|
||||
T!['('] | T![')'] => 2,
|
||||
kind if kind.is_trivia() => 0,
|
||||
|
@ -219,6 +219,16 @@ fn hover_simple(
|
|||
};
|
||||
render::type_info_of(sema, config, &Either::Left(call_expr))
|
||||
})
|
||||
})
|
||||
// try closure
|
||||
.or_else(|| {
|
||||
descended().find_map(|token| {
|
||||
if token.kind() != T![|] {
|
||||
return None;
|
||||
}
|
||||
let c = token.parent().and_then(|x| x.parent()).and_then(ast::ClosureExpr::cast)?;
|
||||
render::closure_expr(sema, c)
|
||||
})
|
||||
});
|
||||
|
||||
result.map(|mut res: HoverResult| {
|
||||
|
|
|
@ -42,6 +42,38 @@ pub(super) fn type_info_of(
|
|||
type_info(sema, _config, original, adjusted)
|
||||
}
|
||||
|
||||
pub(super) fn closure_expr(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
c: ast::ClosureExpr,
|
||||
) -> Option<HoverResult> {
|
||||
let ty = &sema.type_of_expr(&c.into())?.original;
|
||||
let layout = ty
|
||||
.layout(sema.db)
|
||||
.map(|x| format!(" // size = {}, align = {}", x.size.bytes(), x.align.abi.bytes()))
|
||||
.unwrap_or_default();
|
||||
let c = ty.as_closure()?;
|
||||
let mut captures = c
|
||||
.captured_items(sema.db)
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
format!("* `{}` by {}", x.display_place(c.clone().into(), sema.db), x.display_kind())
|
||||
})
|
||||
.join("\n");
|
||||
if captures.trim().is_empty() {
|
||||
captures = "This closure captures nothing".to_string();
|
||||
}
|
||||
let mut res = HoverResult::default();
|
||||
res.markup = format!(
|
||||
"```rust\n{}{}\n{}\n```\n\n## Captures\n{}",
|
||||
c.display_with_id(sema.db),
|
||||
layout,
|
||||
c.display_with_impl(sema.db),
|
||||
captures,
|
||||
)
|
||||
.into();
|
||||
Some(res)
|
||||
}
|
||||
|
||||
pub(super) fn try_expr(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
_config: &HoverConfig,
|
||||
|
|
|
@ -198,6 +198,85 @@ fn main() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_closure() {
|
||||
check(
|
||||
r#"
|
||||
//- minicore: copy
|
||||
fn main() {
|
||||
let x = 2;
|
||||
let y = $0|z| x + z;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*|*
|
||||
```rust
|
||||
{closure#0} // size = 8, align = 8
|
||||
impl Fn(i32) -> i32
|
||||
```
|
||||
|
||||
## Captures
|
||||
* `x` by immutable borrow
|
||||
"#]],
|
||||
);
|
||||
|
||||
check(
|
||||
r#"
|
||||
//- minicore: copy
|
||||
fn foo(x: impl Fn(i32) -> i32) {
|
||||
|
||||
}
|
||||
fn main() {
|
||||
foo($0|x: i32| x)
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*|*
|
||||
```rust
|
||||
{closure#0} // size = 0, align = 1
|
||||
impl Fn(i32) -> i32
|
||||
```
|
||||
|
||||
## Captures
|
||||
This closure captures nothing
|
||||
"#]],
|
||||
);
|
||||
|
||||
check(
|
||||
r#"
|
||||
//- minicore: copy
|
||||
|
||||
struct Z { f: i32 }
|
||||
|
||||
struct Y(&'static mut Z)
|
||||
|
||||
struct X {
|
||||
f1: Y,
|
||||
f2: (Y, Y),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: X;
|
||||
let y = $0|| {
|
||||
x.f1;
|
||||
&mut x.f2.0 .0.f;
|
||||
};
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*|*
|
||||
```rust
|
||||
{closure#0} // size = 16, align = 8
|
||||
impl FnOnce()
|
||||
```
|
||||
|
||||
## Captures
|
||||
* `x.f1` by move
|
||||
* `(*x.f2.0.0).f` by mutable borrow
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_shows_long_type_of_an_expression() {
|
||||
check(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue