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.rs122
1 files changed, 94 insertions, 28 deletions
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 69b83f3b12..c24864a18b 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -11,7 +11,7 @@ use hir::{
use ide_db::{
RootDatabase,
defs::Definition,
- documentation::HasDocs,
+ documentation::{DocsRangeMap, HasDocs},
famous_defs::FamousDefs,
generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES},
syntax_helpers::prettify_macro_expansion,
@@ -21,7 +21,7 @@ use rustc_apfloat::{
Float,
ieee::{Half as f16, Quad as f128},
};
-use span::Edition;
+use span::{Edition, TextSize};
use stdx::format_to;
use syntax::{AstNode, AstToken, Direction, SyntaxToken, T, algo, ast, match_ast};
@@ -276,13 +276,10 @@ pub(super) fn keyword(
keyword_hints(sema, token, parent, edition, display_target);
let doc_owner = find_std_module(&famous_defs, &keyword_mod, edition)?;
- let docs = doc_owner.docs(sema.db)?;
- let markup = process_markup(
- sema.db,
- Definition::Module(doc_owner),
- &markup(Some(docs.into()), description, None, None, String::new()),
- config,
- );
+ let (docs, range_map) = doc_owner.docs_with_rangemap(sema.db)?;
+ let (markup, range_map) =
+ markup(Some(docs.into()), Some(range_map), description, None, None, String::new());
+ let markup = process_markup(sema.db, Definition::Module(doc_owner), &markup, range_map, config);
Some(HoverResult { markup, actions })
}
@@ -371,11 +368,15 @@ pub(super) fn process_markup(
db: &RootDatabase,
def: Definition,
markup: &Markup,
+ markup_range_map: Option<DocsRangeMap>,
config: &HoverConfig,
) -> Markup {
let markup = markup.as_str();
- let markup =
- if config.links_in_hover { rewrite_links(db, markup, def) } else { remove_links(markup) };
+ let markup = if config.links_in_hover {
+ rewrite_links(db, markup, def, markup_range_map)
+ } else {
+ remove_links(markup)
+ };
Markup::from(markup)
}
@@ -482,7 +483,7 @@ pub(super) fn definition(
config: &HoverConfig,
edition: Edition,
display_target: DisplayTarget,
-) -> Markup {
+) -> (Markup, Option<DocsRangeMap>) {
let mod_path = definition_path(db, &def, edition);
let label = match def {
Definition::Trait(trait_) => trait_
@@ -518,7 +519,12 @@ pub(super) fn definition(
}
_ => def.label(db, display_target),
};
- let docs = def.docs(db, famous_defs, display_target);
+ let (docs, range_map) =
+ if let Some((docs, doc_range)) = def.docs_with_rangemap(db, famous_defs, display_target) {
+ (Some(docs), doc_range)
+ } else {
+ (None, None)
+ };
let value = || match def {
Definition::Variant(it) => {
if !it.parent_enum(db).is_data_carrying(db) {
@@ -624,27 +630,57 @@ pub(super) fn definition(
}
},
|_| None,
+ |_| None,
+ ),
+ Definition::Adt(it @ Adt::Struct(strukt)) => render_memory_layout(
+ config.memory_layout,
+ || it.layout(db),
+ |_| None,
+ |layout| {
+ let mut field_size =
+ |i: usize| Some(strukt.fields(db).get(i)?.layout(db).ok()?.size());
+ if strukt.repr(db).is_some_and(|it| it.inhibit_struct_field_reordering()) {
+ Some(("tail padding", layout.tail_padding(&mut field_size)?))
+ } else {
+ Some(("largest padding", layout.largest_padding(&mut field_size)?))
+ }
+ },
+ |_| None,
+ ),
+ Definition::Adt(it) => render_memory_layout(
+ config.memory_layout,
+ || it.layout(db),
+ |_| None,
+ |_| None,
+ |_| None,
),
- Definition::Adt(it) => {
- render_memory_layout(config.memory_layout, || it.layout(db), |_| None, |_| None)
- }
Definition::Variant(it) => render_memory_layout(
config.memory_layout,
|| it.layout(db),
|_| None,
+ |_| None,
|layout| layout.enum_tag_size(),
),
- Definition::TypeAlias(it) => {
- render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None)
- }
- Definition::Local(it) => {
- render_memory_layout(config.memory_layout, || it.ty(db).layout(db), |_| None, |_| None)
- }
+ Definition::TypeAlias(it) => render_memory_layout(
+ config.memory_layout,
+ || it.ty(db).layout(db),
+ |_| None,
+ |_| None,
+ |_| None,
+ ),
+ Definition::Local(it) => render_memory_layout(
+ config.memory_layout,
+ || it.ty(db).layout(db),
+ |_| None,
+ |_| None,
+ |_| None,
+ ),
Definition::SelfType(it) => render_memory_layout(
config.memory_layout,
|| it.self_ty(db).layout(db),
|_| None,
|_| None,
+ |_| None,
),
_ => None,
};
@@ -807,6 +843,7 @@ pub(super) fn definition(
markup(
docs.map(Into::into),
+ range_map,
desc,
extra.is_empty().not().then_some(extra),
mod_path,
@@ -1048,9 +1085,13 @@ fn closure_ty(
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())
}
- if let Some(layout) =
- render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None)
- {
+ if let Some(layout) = render_memory_layout(
+ config.memory_layout,
+ || original.layout(sema.db),
+ |_| None,
+ |_| None,
+ |_| None,
+ ) {
format_to!(markup, "\n___\n{layout}");
}
format_to!(markup, "{adjusted}\n\n## Captures\n{}", captures_rendered,);
@@ -1083,11 +1124,12 @@ fn definition_path(db: &RootDatabase, &def: &Definition, edition: Edition) -> Op
fn markup(
docs: Option<String>,
+ range_map: Option<DocsRangeMap>,
rust: String,
extra: Option<String>,
mod_path: Option<String>,
subst_types: String,
-) -> Markup {
+) -> (Markup, Option<DocsRangeMap>) {
let mut buf = String::new();
if let Some(mod_path) = mod_path {
@@ -1106,9 +1148,15 @@ fn markup(
}
if let Some(doc) = docs {
- format_to!(buf, "\n___\n\n{}", doc);
+ format_to!(buf, "\n___\n\n");
+ let offset = TextSize::new(buf.len() as u32);
+ let buf_range_map = range_map.map(|range_map| range_map.shift_docstring_line_range(offset));
+ format_to!(buf, "{}", doc);
+
+ (buf.into(), buf_range_map)
+ } else {
+ (buf.into(), None)
}
- buf.into()
}
fn find_std_module(
@@ -1128,6 +1176,7 @@ fn render_memory_layout(
config: Option<MemoryLayoutHoverConfig>,
layout: impl FnOnce() -> Result<Layout, LayoutError>,
offset: impl FnOnce(&Layout) -> Option<u64>,
+ padding: impl FnOnce(&Layout) -> Option<(&str, u64)>,
tag: impl FnOnce(&Layout) -> Option<usize>,
) -> Option<String> {
let config = config?;
@@ -1185,6 +1234,23 @@ fn render_memory_layout(
}
}
+ if let Some(render) = config.padding {
+ if let Some((padding_name, padding)) = padding(&layout) {
+ format_to!(label, "{padding_name} = ");
+ match render {
+ MemoryLayoutHoverRenderKind::Decimal => format_to!(label, "{padding}"),
+ MemoryLayoutHoverRenderKind::Hexadecimal => format_to!(label, "{padding:#X}"),
+ MemoryLayoutHoverRenderKind::Both if padding >= 10 => {
+ format_to!(label, "{padding} ({padding:#X})")
+ }
+ MemoryLayoutHoverRenderKind::Both => {
+ format_to!(label, "{padding}")
+ }
+ }
+ format_to!(label, ", ");
+ }
+ }
+
if config.niches {
if let Some(niches) = layout.niches() {
if niches > 1024 {