Remove hover fallback in favor of ranged hover

This commit is contained in:
Lukas Wirth 2023-01-20 16:36:24 +01:00
parent a542bd46bf
commit 4685b97f74
2 changed files with 27 additions and 131 deletions

View File

@ -15,7 +15,7 @@ use ide_db::{
FxIndexSet, RootDatabase, FxIndexSet, RootDatabase,
}; };
use itertools::Itertools; use itertools::Itertools;
use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode, SyntaxToken, T}; use syntax::{ast, AstNode, SyntaxKind::*, SyntaxNode, T};
use crate::{ use crate::{
doc_links::token_as_doc_comment, doc_links::token_as_doc_comment,
@ -203,14 +203,10 @@ fn hover_simple(
}) })
}); });
result result.map(|mut res: HoverResult| {
.map(|mut res: HoverResult| { res.actions = dedupe_or_merge_hover_actions(res.actions);
res.actions = dedupe_or_merge_hover_actions(res.actions); RangeInfo::new(original_token.text_range(), res)
RangeInfo::new(original_token.text_range(), res) })
})
// fallback to type hover if there aren't any other suggestions
// this finds its own range instead of using the closest token's range
.or_else(|| descended().find_map(|token| hover_type_fallback(sema, config, token, token)))
} }
fn hover_ranged( fn hover_ranged(
@ -220,8 +216,11 @@ fn hover_ranged(
config: &HoverConfig, config: &HoverConfig,
) -> Option<RangeInfo<HoverResult>> { ) -> Option<RangeInfo<HoverResult>> {
// FIXME: make this work in attributes // FIXME: make this work in attributes
let expr_or_pat = let expr_or_pat = file
file.covering_element(range).ancestors().find_map(Either::<ast::Expr, ast::Pat>::cast)?; .covering_element(range)
.ancestors()
.take_while(|it| ast::MacroCall::can_cast(it.kind()) || !ast::Item::can_cast(it.kind()))
.find_map(Either::<ast::Expr, ast::Pat>::cast)?;
let res = match &expr_or_pat { let res = match &expr_or_pat {
Either::Left(ast::Expr::TryExpr(try_expr)) => render::try_expr(sema, config, try_expr), Either::Left(ast::Expr::TryExpr(try_expr)) => render::try_expr(sema, config, try_expr),
Either::Left(ast::Expr::PrefixExpr(prefix_expr)) Either::Left(ast::Expr::PrefixExpr(prefix_expr))
@ -268,39 +267,6 @@ pub(crate) fn hover_for_definition(
}) })
} }
fn hover_type_fallback(
sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig,
token: &SyntaxToken,
original_token: &SyntaxToken,
) -> Option<RangeInfo<HoverResult>> {
let node =
token.parent_ancestors().take_while(|it| !ast::Item::can_cast(it.kind())).find(|n| {
ast::Expr::can_cast(n.kind())
|| ast::Pat::can_cast(n.kind())
|| ast::Type::can_cast(n.kind())
})?;
let expr_or_pat = match_ast! {
match node {
ast::Expr(it) => Either::Left(it),
ast::Pat(it) => Either::Right(it),
// If this node is a MACRO_CALL, it means that `descend_into_macros_many` failed to resolve.
// (e.g expanding a builtin macro). So we give up here.
ast::MacroCall(_it) => return None,
_ => return None,
}
};
let res = render::type_info_of(sema, config, &expr_or_pat)?;
let range = sema
.original_range_opt(&node)
.map(|frange| frange.range)
.unwrap_or_else(|| original_token.text_range());
Some(RangeInfo::new(range, res))
}
fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
fn to_action(nav_target: NavigationTarget) -> HoverAction { fn to_action(nav_target: NavigationTarget) -> HoverAction {
HoverAction::Implementation(FilePosition { HoverAction::Implementation(FilePosition {

View File

@ -213,25 +213,6 @@ m!(ab$0c);
); );
} }
#[test]
fn hover_shows_type_of_an_expression() {
check(
r#"
pub fn foo() -> u32 { 1 }
fn main() {
let foo_test = foo()$0;
}
"#,
expect![[r#"
*foo()*
```rust
u32
```
"#]],
);
}
#[test] #[test]
fn hover_remove_markdown_if_configured() { fn hover_remove_markdown_if_configured() {
check_hover_no_markdown( check_hover_no_markdown(
@ -239,12 +220,14 @@ fn hover_remove_markdown_if_configured() {
pub fn foo() -> u32 { 1 } pub fn foo() -> u32 { 1 }
fn main() { fn main() {
let foo_test = foo()$0; let foo_test = foo$0();
} }
"#, "#,
expect![[r#" expect![[r#"
*foo()* *foo*
u32 test
pub fn foo() -> u32
"#]], "#]],
); );
} }
@ -304,33 +287,6 @@ fn main() { let foo_test = fo$0o(); }
"#]], "#]],
); );
// Multiple candidates but results are ambiguous.
check(
r#"
//- /a.rs
pub fn foo() -> u32 { 1 }
//- /b.rs
pub fn foo() -> &str { "" }
//- /c.rs
pub fn foo(a: u32, b: u32) {}
//- /main.rs
mod a;
mod b;
mod c;
fn main() { let foo_test = fo$0o(); }
"#,
expect![[r#"
*foo*
```rust
{unknown}
```
"#]],
);
// Use literal `crate` in path // Use literal `crate` in path
check( check(
r#" r#"
@ -1194,33 +1150,19 @@ fn test_hover_through_func_in_macro_recursive() {
macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
fn bar() -> u32 { 0 } fn bar() -> u32 { 0 }
fn foo() { let a = id!([0u32, bar($0)] ); } fn foo() { let a = id!([0u32, bar$0()] ); }
"#, "#,
expect![[r#" expect![[r#"
*bar()* *bar*
```rust
u32
```
"#]],
);
}
#[test] ```rust
fn test_hover_through_literal_string_in_macro() { test
check( ```
r#"
macro_rules! arr { ($($tt:tt)*) => { [$($tt)*] } } ```rust
fn foo() { fn bar() -> u32
let mastered_for_itunes = ""; ```
let _ = arr!("Tr$0acks", &mastered_for_itunes); "#]],
}
"#,
expect![[r#"
*"Tracks"*
```rust
&str
```
"#]],
); );
} }
@ -5655,30 +5597,18 @@ fn main() {
#[test] #[test]
fn hover_underscore_type() { fn hover_underscore_type() {
check( check_hover_no_result(
r#" r#"
fn main() { fn main() {
let x: _$0 = 0; let x: _$0 = 0;
} }
"#, "#,
expect![[r#"
*_*
```rust
{unknown}
```
"#]],
); );
check( check_hover_no_result(
r#" r#"
fn main() { fn main() {
let x: (_$0,) = (0,); let x: (_$0,) = (0,);
} }
"#, "#,
expect![[r#"
*_*
```rust
{unknown}
```
"#]],
); );
} }