aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/hover.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/hover.rs')
-rw-r--r--crates/ide/src/hover.rs128
1 files changed, 117 insertions, 11 deletions
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 2024acd94..20b799490 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -2,8 +2,8 @@ use hir::{
2 Adt, AsAssocItem, AssocItemContainer, FieldSource, GenericParam, HasAttrs, HasSource, 2 Adt, AsAssocItem, AssocItemContainer, FieldSource, GenericParam, HasAttrs, HasSource,
3 HirDisplay, Module, ModuleDef, ModuleSource, Semantics, 3 HirDisplay, Module, ModuleDef, ModuleSource, Semantics,
4}; 4};
5use ide_db::base_db::SourceDatabase;
6use ide_db::{ 5use ide_db::{
6 base_db::SourceDatabase,
7 defs::{Definition, NameClass, NameRefClass}, 7 defs::{Definition, NameClass, NameRefClass},
8 RootDatabase, 8 RootDatabase,
9}; 9};
@@ -94,7 +94,12 @@ pub(crate) fn hover(
94 let node = token.parent(); 94 let node = token.parent();
95 let definition = match_ast! { 95 let definition = match_ast! {
96 match node { 96 match node {
97 ast::Name(name) => NameClass::classify(&sema, &name).and_then(|d| d.defined(sema.db)), 97 // we don't use NameClass::referenced_or_defined here as we do not want to resolve
98 // field pattern shorthands to their definition
99 ast::Name(name) => NameClass::classify(&sema, &name).and_then(|class| match class {
100 NameClass::ConstReference(def) => Some(def),
101 def => def.defined(sema.db),
102 }),
98 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), 103 ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
99 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime) 104 ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
100 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)), 105 .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
@@ -182,12 +187,7 @@ fn runnable_action(
182) -> Option<HoverAction> { 187) -> Option<HoverAction> {
183 match def { 188 match def {
184 Definition::ModuleDef(it) => match it { 189 Definition::ModuleDef(it) => match it {
185 ModuleDef::Module(it) => match it.definition_source(sema.db).value { 190 ModuleDef::Module(it) => runnable_mod(&sema, it).map(|it| HoverAction::Runnable(it)),
186 ModuleSource::Module(it) => {
187 runnable_mod(&sema, it).map(|it| HoverAction::Runnable(it))
188 }
189 _ => None,
190 },
191 ModuleDef::Function(func) => { 191 ModuleDef::Function(func) => {
192 let src = func.source(sema.db)?; 192 let src = func.source(sema.db)?;
193 if src.file_id != file_id.into() { 193 if src.file_id != file_id.into() {
@@ -326,6 +326,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
326 match it.definition_source(db).value { 326 match it.definition_source(db).value {
327 ModuleSource::Module(it) => it.short_label(), 327 ModuleSource::Module(it) => it.short_label(),
328 ModuleSource::SourceFile(it) => it.short_label(), 328 ModuleSource::SourceFile(it) => it.short_label(),
329 ModuleSource::BlockExpr(it) => it.short_label(),
329 }, 330 },
330 mod_path, 331 mod_path,
331 ), 332 ),
@@ -338,7 +339,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
338 ModuleDef::Static(it) => from_def_source(db, it, mod_path), 339 ModuleDef::Static(it) => from_def_source(db, it, mod_path),
339 ModuleDef::Trait(it) => from_def_source(db, it, mod_path), 340 ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
340 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), 341 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
341 ModuleDef::BuiltinType(it) => Some(Markup::fenced_block(&it)), 342 ModuleDef::BuiltinType(it) => Some(Markup::fenced_block(&it.name())),
342 }, 343 },
343 Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))), 344 Definition::Local(it) => Some(Markup::fenced_block(&it.ty(db).display(db))),
344 Definition::SelfType(impl_def) => { 345 Definition::SelfType(impl_def) => {
@@ -1830,6 +1831,35 @@ pub struct B$0ar
1830 "#]], 1831 "#]],
1831 ); 1832 );
1832 } 1833 }
1834 #[test]
1835 fn test_hover_intra_link_reference_to_trait_method() {
1836 check(
1837 r#"
1838pub trait Foo {
1839 fn buzz() -> usize;
1840}
1841/// [Foo][buzz]
1842///
1843/// [buzz]: Foo::buzz
1844pub struct B$0ar
1845"#,
1846 expect![[r#"
1847 *Bar*
1848
1849 ```rust
1850 test
1851 ```
1852
1853 ```rust
1854 pub struct Bar
1855 ```
1856
1857 ---
1858
1859 [Foo](https://docs.rs/test/*/test/trait.Foo.html#tymethod.buzz)
1860 "#]],
1861 );
1862 }
1833 1863
1834 #[test] 1864 #[test]
1835 fn test_hover_external_url() { 1865 fn test_hover_external_url() {
@@ -3387,7 +3417,7 @@ impl<T> Foo<T$0> {}
3387 ``` 3417 ```
3388 "#]], 3418 "#]],
3389 ); 3419 );
3390 // lifetimes aren't being substituted yet 3420 // lifetimes bounds arent being tracked yet
3391 check( 3421 check(
3392 r#" 3422 r#"
3393struct Foo<T>(T); 3423struct Foo<T>(T);
@@ -3397,7 +3427,7 @@ impl<T: 'static> Foo<T$0> {}
3397 *T* 3427 *T*
3398 3428
3399 ```rust 3429 ```rust
3400 T: {error} 3430 T
3401 ``` 3431 ```
3402 "#]], 3432 "#]],
3403 ); 3433 );
@@ -3419,4 +3449,80 @@ impl<const LEN: usize> Foo<LEN$0> {}
3419 "#]], 3449 "#]],
3420 ); 3450 );
3421 } 3451 }
3452
3453 #[test]
3454 fn hover_const_pat() {
3455 check(
3456 r#"
3457/// This is a doc
3458const FOO: usize = 3;
3459fn foo() {
3460 match 5 {
3461 FOO$0 => (),
3462 _ => ()
3463 }
3464}
3465"#,
3466 expect![[r#"
3467 *FOO*
3468
3469 ```rust
3470 test
3471 ```
3472
3473 ```rust
3474 const FOO: usize = 3
3475 ```
3476
3477 ---
3478
3479 This is a doc
3480 "#]],
3481 );
3482 }
3483
3484 #[test]
3485 fn hover_mod_def() {
3486 check(
3487 r#"
3488//- /main.rs
3489mod foo$0;
3490//- /foo.rs
3491//! For the horde!
3492"#,
3493 expect![[r#"
3494 *foo*
3495 For the horde!
3496 "#]],
3497 );
3498 }
3499
3500 #[test]
3501 fn hover_self_in_use() {
3502 check(
3503 r#"
3504//! This should not appear
3505mod foo {
3506 /// But this should appear
3507 pub mod bar {}
3508}
3509use foo::bar::{self$0};
3510"#,
3511 expect![[r#"
3512 *self*
3513
3514 ```rust
3515 test::foo
3516 ```
3517
3518 ```rust
3519 pub mod bar
3520 ```
3521
3522 ---
3523
3524 But this should appear
3525 "#]],
3526 );
3527 }
3422} 3528}