diff options
Diffstat (limited to 'crates/ide/src/hover.rs')
-rw-r--r-- | crates/ide/src/hover.rs | 128 |
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 | }; |
5 | use ide_db::base_db::SourceDatabase; | ||
6 | use ide_db::{ | 5 | use 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#" | ||
1838 | pub trait Foo { | ||
1839 | fn buzz() -> usize; | ||
1840 | } | ||
1841 | /// [Foo][buzz] | ||
1842 | /// | ||
1843 | /// [buzz]: Foo::buzz | ||
1844 | pub 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#" |
3393 | struct Foo<T>(T); | 3423 | struct 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 | ||
3458 | const FOO: usize = 3; | ||
3459 | fn 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 | ||
3489 | mod 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 | ||
3505 | mod foo { | ||
3506 | /// But this should appear | ||
3507 | pub mod bar {} | ||
3508 | } | ||
3509 | use 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 | } |