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.rs92
1 files changed, 80 insertions, 12 deletions
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index e617d462ec..8fbd445d96 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -5,7 +5,7 @@ use either::Either;
use hir::{
db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, AssocItemContainer, CaptureKind,
DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError,
- MethodViolationCode, Name, Semantics, Trait, Type, TypeInfo,
+ MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef,
};
use ide_db::{
base_db::SourceDatabase,
@@ -27,7 +27,7 @@ use syntax::{algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxToken, T}
use crate::{
doc_links::{remove_links, rewrite_links},
- hover::{notable_traits, walk_and_push_ty},
+ hover::{notable_traits, walk_and_push_ty, SubstTyLen},
interpret::render_const_eval_error,
HoverAction, HoverConfig, HoverResult, Markup, MemoryLayoutHoverConfig,
MemoryLayoutHoverRenderKind,
@@ -274,7 +274,7 @@ pub(super) fn keyword(
let markup = process_markup(
sema.db,
Definition::Module(doc_owner),
- &markup(Some(docs.into()), description, None, None),
+ &markup(Some(docs.into()), description, None, None, String::new()),
config,
);
Some(HoverResult { markup, actions })
@@ -336,8 +336,8 @@ pub(super) fn try_for_lint(attr: &ast::Attr, token: &SyntaxToken) -> Option<Hove
.and_then(|t| algo::non_trivia_sibling(t, Direction::Prev))
.filter(|t| t.kind() == T![:])
.and_then(|t| algo::non_trivia_sibling(t, Direction::Prev))
- .map_or(false, |t| {
- t.kind() == T![ident] && t.into_token().map_or(false, |t| t.text() == "clippy")
+ .is_some_and(|t| {
+ t.kind() == T![ident] && t.into_token().is_some_and(|t| t.text() == "clippy")
});
if is_clippy {
(true, CLIPPY_LINTS)
@@ -378,7 +378,18 @@ pub(super) fn process_markup(
fn definition_owner_name(db: &RootDatabase, def: &Definition, edition: Edition) -> Option<String> {
match def {
- Definition::Field(f) => Some(f.parent_def(db).name(db)),
+ Definition::Field(f) => {
+ let parent = f.parent_def(db);
+ let parent_name = parent.name(db);
+ let parent_name = parent_name.display(db, edition).to_string();
+ return match parent {
+ VariantDef::Variant(variant) => {
+ let enum_name = variant.parent_enum(db).name(db);
+ Some(format!("{}::{parent_name}", enum_name.display(db, edition)))
+ }
+ _ => Some(parent_name),
+ };
+ }
Definition::Local(l) => l.parent(db).name(db),
Definition::Variant(e) => Some(e.parent_enum(db).name(db)),
@@ -421,6 +432,7 @@ pub(super) fn definition(
notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
macro_arm: Option<u32>,
hovered_definition: bool,
+ subst_types: Option<&Vec<(Symbol, Type)>>,
config: &HoverConfig,
edition: Edition,
) -> Markup {
@@ -582,12 +594,21 @@ pub(super) fn definition(
_ => None,
};
+ let variance_info = || match def {
+ Definition::GenericParam(it) => it.variance(db).as_ref().map(ToString::to_string),
+ _ => None,
+ };
+
let mut extra = String::new();
if hovered_definition {
if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition) {
extra.push_str("\n___\n");
extra.push_str(&notable_traits);
}
+ if let Some(variance_info) = variance_info() {
+ extra.push_str("\n___\n");
+ extra.push_str(&variance_info);
+ }
if let Some(layout_info) = layout_info() {
extra.push_str("\n___\n");
extra.push_str(&layout_info);
@@ -604,7 +625,38 @@ pub(super) fn definition(
desc.push_str(&value);
}
- markup(docs.map(Into::into), desc, extra.is_empty().not().then_some(extra), mod_path)
+ let subst_types = match config.max_subst_ty_len {
+ SubstTyLen::Hide => String::new(),
+ SubstTyLen::LimitTo(_) | SubstTyLen::Unlimited => {
+ let limit = if let SubstTyLen::LimitTo(limit) = config.max_subst_ty_len {
+ Some(limit)
+ } else {
+ None
+ };
+ subst_types
+ .map(|subst_type| {
+ subst_type
+ .iter()
+ .filter(|(_, ty)| !ty.is_unknown())
+ .format_with(", ", |(name, ty), fmt| {
+ fmt(&format_args!(
+ "`{name}` = `{}`",
+ ty.display_truncated(db, limit, edition)
+ ))
+ })
+ .to_string()
+ })
+ .unwrap_or_default()
+ }
+ };
+
+ markup(
+ docs.map(Into::into),
+ desc,
+ extra.is_empty().not().then_some(extra),
+ mod_path,
+ subst_types,
+ )
}
pub(super) fn literal(
@@ -663,10 +715,22 @@ pub(super) fn literal(
let mut s = format!("```rust\n{ty}\n```\n___\n\n");
match value {
Ok(value) => {
+ let backtick_len = value.chars().filter(|c| *c == '`').count();
+ let spaces_len = value.chars().filter(|c| *c == ' ').count();
+ let backticks = "`".repeat(backtick_len + 1);
+ let space_char = if spaces_len == value.len() { "" } else { " " };
+
if let Some(newline) = value.find('\n') {
- format_to!(s, "value of literal (truncated up to newline): {}", &value[..newline])
+ format_to!(
+ s,
+ "value of literal (truncated up to newline): {backticks}{space_char}{}{space_char}{backticks}",
+ &value[..newline]
+ )
} else {
- format_to!(s, "value of literal: {value}")
+ format_to!(
+ s,
+ "value of literal: {backticks}{space_char}{value}{space_char}{backticks}"
+ )
}
}
Err(error) => format_to!(s, "invalid literal: {error}"),
@@ -831,12 +895,11 @@ fn closure_ty(
} else {
String::new()
};
- let mut markup = format!("```rust\n{}", c.display_with_id(sema.db, edition));
+ let mut markup = format!("```rust\n{}\n```", c.display_with_impl(sema.db, edition));
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```", c.display_with_impl(sema.db, edition),);
if let Some(layout) =
render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None)
{
@@ -872,6 +935,7 @@ fn markup(
rust: String,
extra: Option<String>,
mod_path: Option<String>,
+ subst_types: String,
) -> Markup {
let mut buf = String::new();
@@ -886,6 +950,10 @@ fn markup(
buf.push_str(&extra);
}
+ if !subst_types.is_empty() {
+ format_to!(buf, "\n___\n{subst_types}");
+ }
+
if let Some(doc) = docs {
format_to!(buf, "\n___\n\n{}", doc);
}
@@ -901,7 +969,7 @@ fn find_std_module(
let std_crate = famous_defs.std()?;
let std_root_module = std_crate.root_module();
std_root_module.children(db).find(|module| {
- module.name(db).map_or(false, |module| module.display(db, edition).to_string() == name)
+ module.name(db).is_some_and(|module| module.display(db, edition).to_string() == name)
})
}