Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/hover/render.rs')
| -rw-r--r-- | crates/ide/src/hover/render.rs | 79 |
1 files changed, 71 insertions, 8 deletions
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 9d449bd18e..d3a9975b2b 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -1,7 +1,10 @@ //! Logic for rendering the different hover messages +use std::{mem, ops::Not}; + use either::Either; use hir::{ - Adt, AsAssocItem, CaptureKind, HasSource, HirDisplay, Layout, LayoutError, Semantics, TypeInfo, + db::DefDatabase, Adt, AsAssocItem, AssocItem, CaptureKind, HasCrate, HasSource, HirDisplay, + Layout, LayoutError, Semantics, TypeInfo, }; use ide_db::{ base_db::SourceDatabase, @@ -390,7 +393,6 @@ pub(super) fn definition( let mod_path = definition_mod_path(db, &def); let label = def.label(db)?; let docs = def.docs(db, famous_defs); - let value = match def { Definition::Variant(it) => { if !it.parent_enum(db).is_data_carrying(db) { @@ -462,14 +464,75 @@ pub(super) fn definition( _ => None, }; - let label = match (value, layout_info) { - (Some(value), Some(layout_info)) => format!("{layout_info}\n{label} = {value}"), - (Some(value), None) => format!("{label} = {value}"), - (None, Some(layout_info)) => format!("{layout_info}\n{label}"), - (None, None) => label, + let def_ty = match def { + Definition::Local(it) => Some(it.ty(db)), + Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)), + Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)), + Definition::Field(field) => Some(field.ty(db)), + Definition::TupleField(it) => Some(it.ty(db)), + Definition::Function(it) => Some(it.ty(db)), + Definition::Adt(it) => Some(it.ty(db)), + Definition::Const(it) => Some(it.ty(db)), + Definition::Static(it) => Some(it.ty(db)), + Definition::TypeAlias(it) => Some(it.ty(db)), + Definition::BuiltinType(it) => Some(it.ty(db)), + _ => None, }; + let notable_traits = def_ty.and_then(|ty| { + let mut desc = String::new(); + let mut needs_impl_header = true; + for &trait_ in db.notable_traits_in_deps(ty.krate(db).into()).iter().flat_map(|it| &**it) { + let trait_ = trait_.into(); + if ty.impls_trait(db, trait_, &[]) { + let aliases: Vec<_> = trait_ + .items(db) + .into_iter() + .filter_map(AssocItem::as_type_alias) + .map(|alias| (ty.normalize_trait_assoc_type(db, &[], alias), alias.name(db))) + .collect(); + desc.push_str(if mem::take(&mut needs_impl_header) { + " // notable traits impls: " + } else { + ", " + }); + format_to!(desc, "{}", trait_.name(db).display(db),); + if !aliases.is_empty() { + desc.push('<'); + format_to!( + desc, + "{}", + aliases.into_iter().format_with(", ", |(ty, name), f| { + f(&name.display(db))?; + f(&" = ")?; + match ty { + Some(ty) => f(&ty.display(db)), + None => f(&"?"), + } + }) + ); + desc.push('>'); + } + } + } + desc.is_empty().not().then(|| desc) + }); + + let mut desc = String::new(); + if let Some(notable_traits) = notable_traits { + desc.push_str(¬able_traits); + desc.push('\n'); + } + if let Some(layout_info) = layout_info { + desc.push_str(&layout_info); + desc.push('\n'); + } + desc.push_str(&label); + if let Some(value) = value { + desc.push_str(" = "); + desc.push_str(&value); + } - markup(docs.map(Into::into), label, mod_path) + markup(docs.map(Into::into), desc, mod_path) } fn type_info( |