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 | 134 |
1 files changed, 67 insertions, 67 deletions
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index d3a9975b2b..787b74fc62 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -3,8 +3,8 @@ use std::{mem, ops::Not}; use either::Either; use hir::{ - db::DefDatabase, Adt, AsAssocItem, AssocItem, CaptureKind, HasCrate, HasSource, HirDisplay, - Layout, LayoutError, Semantics, TypeInfo, + Adt, AsAssocItem, CaptureKind, HasCrate, HasSource, HirDisplay, Layout, LayoutError, Name, + Semantics, Trait, Type, TypeInfo, }; use ide_db::{ base_db::SourceDatabase, @@ -25,7 +25,7 @@ use syntax::{ use crate::{ doc_links::{remove_links, rewrite_links}, - hover::walk_and_push_ty, + hover::{notable_traits, walk_and_push_ty}, HoverAction, HoverConfig, HoverResult, Markup, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, }; @@ -117,7 +117,9 @@ pub(super) fn try_expr( }; walk_and_push_ty(sema.db, &inner_ty, &mut push_new_def); walk_and_push_ty(sema.db, &body_ty, &mut push_new_def); - res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets)); + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + res.actions.push(actions); + } let inner_ty = inner_ty.display(sema.db).to_string(); let body_ty = body_ty.display(sema.db).to_string(); @@ -195,7 +197,9 @@ pub(super) fn deref_expr( ) .into() }; - res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets)); + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + res.actions.push(actions); + } Some(res) } @@ -302,7 +306,9 @@ pub(super) fn struct_rest_pat( Markup::fenced_block(&s) }; - res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets)); + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + res.actions.push(actions); + } res } @@ -388,6 +394,7 @@ pub(super) fn definition( db: &RootDatabase, def: Definition, famous_defs: Option<&FamousDefs<'_, '_>>, + notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)], config: &HoverConfig, ) -> Option<Markup> { let mod_path = definition_mod_path(db, &def); @@ -464,61 +471,8 @@ pub(super) fn definition( _ => None, }; - 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 { + if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits) { desc.push_str(¬able_traits); desc.push('\n'); } @@ -535,6 +489,39 @@ pub(super) fn definition( markup(docs.map(Into::into), desc, mod_path) } +fn render_notable_trait_comment( + db: &RootDatabase, + notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)], +) -> Option<String> { + let mut desc = String::new(); + let mut needs_impl_header = true; + for (trait_, assoc_types) in notable_traits { + desc.push_str(if mem::take(&mut needs_impl_header) { + " // notable traits implemented: " + } else { + ", " + }); + format_to!(desc, "{}", trait_.name(db).display(db),); + if !assoc_types.is_empty() { + desc.push('<'); + format_to!( + desc, + "{}", + assoc_types.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) +} + fn type_info( sema: &Semantics<'_, RootDatabase>, config: &HoverConfig, @@ -552,8 +539,12 @@ fn type_info( } }; walk_and_push_ty(sema.db, &original, &mut push_new_def); - - res.markup = if let Some(adjusted_ty) = adjusted { + let mut desc = match render_notable_trait_comment(sema.db, ¬able_traits(sema.db, &original)) + { + Some(desc) => desc + "\n", + None => String::new(), + }; + desc += &if let Some(adjusted_ty) = adjusted { walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def); let original = original.display(sema.db).to_string(); let adjusted = adjusted_ty.display(sema.db).to_string(); @@ -565,11 +556,13 @@ fn type_info( apad = static_text_diff_len + adjusted.len().max(original.len()), opad = original.len(), ) - .into() } else { - Markup::fenced_block(&original.display(sema.db)) + Markup::fenced_block(&original.display(sema.db)).into() }; - res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets)); + res.markup = desc.into(); + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + res.actions.push(actions); + } Some(res) } @@ -621,6 +614,9 @@ fn closure_ty( { format_to!(markup, "{layout}"); } + if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) { + push_new_def(hir::Trait::from(trait_).into()) + } format_to!( markup, "\n{}\n```{adjusted}\n\n## Captures\n{}", @@ -629,7 +625,9 @@ fn closure_ty( ); let mut res = HoverResult::default(); - res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets)); + if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets) { + res.actions.push(actions); + } res.markup = markup.into(); Some(res) } @@ -783,7 +781,9 @@ fn keyword_hints( KeywordHint { description, keyword_mod, - actions: vec![HoverAction::goto_type_from_targets(sema.db, targets)], + actions: HoverAction::goto_type_from_targets(sema.db, targets) + .into_iter() + .collect(), } } _ => KeywordHint { |