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 | 122 |
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 { |