From da102d080eb9f387764b926d7307ea2efb861c56 Mon Sep 17 00:00:00 2001 From: Khanh Duong Quoc Date: Sun, 20 Oct 2024 15:49:10 +0900 Subject: [PATCH] feat: render docs from aliased type when type has no docs --- crates/ide/src/hover.rs | 2 +- crates/ide/src/hover/render.rs | 36 +++++++- crates/ide/src/hover/tests.rs | 145 +++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 4 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 124db2985bf0..96f4d2b2d987 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -406,7 +406,7 @@ pub(crate) fn hover_for_definition( let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default(); let markup = render::definition( - sema.db, + sema, def, famous_defs.as_ref(), ¬able_traits, diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 01fa316d5fce..bcdab3ba5721 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -10,9 +10,10 @@ use hir::{ use ide_db::{ base_db::SourceDatabase, defs::Definition, - documentation::HasDocs, + documentation::{Documentation, HasDocs}, famous_defs::FamousDefs, generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, + helpers::get_definition, syntax_helpers::prettify_macro_expansion, RootDatabase, }; @@ -414,7 +415,7 @@ pub(super) fn path( } pub(super) fn definition( - db: &RootDatabase, + sema @ &Semantics { db, .. }: &Semantics<'_, RootDatabase>, def: Definition, famous_defs: Option<&FamousDefs<'_, '_>>, notable_traits: &[(Trait, Vec<(Option, Name)>)], @@ -455,7 +456,7 @@ pub(super) fn definition( } _ => def.label(db, edition), }; - let docs = def.docs(db, famous_defs, edition); + let docs = get_docs(sema, def, famous_defs, edition); let value = (|| match def { Definition::Variant(it) => { if !it.parent_enum(db).is_data_carrying(db) { @@ -824,6 +825,35 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) -> .map(|module| path(db, module, definition_owner_name(db, def, edition), edition)) } +fn get_docs( + sema @ &Semantics { db, .. }: &Semantics<'_, RootDatabase>, + def: Definition, + famous_defs: Option<&FamousDefs<'_, '_>>, + edition: Edition, +) -> Option { + let mut docs = def.docs(db, famous_defs, edition); + let mut def = def; + + // Searching for type alias without docs attr. + while let Definition::TypeAlias(type_alias) = def { + if docs.is_some() { + break; + } + + let source = sema.source(type_alias)?; + let type_alias = source.value.ty()?; + + // Only take the first token, avoid searching docs for type parameters. + // E.g. `type Y = Box` + let token = type_alias.syntax().first_token()?; + + def = get_definition(sema, token)?; + docs = def.docs(db, famous_defs, edition); + } + + docs +} + fn markup(docs: Option, desc: String, mod_path: Option) -> Markup { let mut buf = String::new(); diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 81397b078552..7dc1bed6c073 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -9018,3 +9018,148 @@ foo!(BAR_$0); "#]], ); } + +#[test] +fn type_alias_without_docs() { + // Simple. + check( + r#" +/// Docs for B +struct B; + +type A$0 = B; +"#, + expect![[r#" + *A* + + ```rust + test + ``` + + ```rust + // size = 0, align = 1 + type A = B + ``` + + --- + + Docs for B + "#]], + ); + + // Nested. + check( + r#" +/// Docs for C +struct C; + +type B = C; + +type A$0 = B; +"#, + expect![[r#" + *A* + + ```rust + test + ``` + + ```rust + // size = 0, align = 1 + type A = B + ``` + + --- + + Docs for C + "#]], + ); + + // Show the first found docs. + check( + r#" +/// Docs for C +struct C; + +/// Docs for B +type B = C; + +type A$0 = B; +"#, + expect![[r#" + *A* + + ```rust + test + ``` + + ```rust + // size = 0, align = 1 + type A = B + ``` + + --- + + Docs for B + "#]], + ); + + // No docs found. + check( + r#" +struct C; + +type B = C; + +type A$0 = B; +"#, + expect![[r#" + *A* + + ```rust + test + ``` + + ```rust + // size = 0, align = 1 + type A = B + ``` + "#]], + ); + + // Multiple nested crate. + check( + r#" +//- /lib.rs crate:c +/// Docs for C +pub struct C; + +//- /lib.rs crate:b deps:c +pub use c::C; +pub type B = C; + +//- /lib.rs crate:a deps:b +pub use b::B; +pub type A = B; + +//- /main.rs crate:main deps:a +use a::A$0; +"#, + expect![[r#" + *A* + + ```rust + a + ``` + + ```rust + // size = 0, align = 1 + pub type A = B + ``` + + --- + + Docs for C + "#]], + ); +}