diff --git a/data b/data index aafdd70..60095b4 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit aafdd706df0de038b0bcf661962fb12e0013b5bf +Subproject commit 60095b443a0cb6c5d54cd6259c433cfcdba1ea95 diff --git a/src/output/utils.rs b/src/output/utils.rs index 6f4d889..f5475eb 100644 --- a/src/output/utils.rs +++ b/src/output/utils.rs @@ -1,4 +1,6 @@ -use rustc_hir::def_id::DefId as IDefId; +extern crate rustc_hir_pretty; +use itertools::Itertools; +use rustc_hir::{Attribute, attrs::AttributeKind, def_id::DefId as IDefId}; use rustc_middle::ty::TyCtxt; use rustc_public::{ CrateDef, @@ -43,12 +45,67 @@ pub fn span(item: T, tcx: TyCtxt) -> String { src_map.span_to_string(span, rustc_span::FileNameDisplayPreference::Remapped) } -pub fn src(item: T, tcx: TyCtxt) -> String { - src_from_span(item.span(), tcx) +pub fn src(item: T, tcx: TyCtxt) -> String { + let [attrs, item_src] = if let Some(did) = did(item, tcx).as_local() + && let rustc_hir::Node::Item(hir_item) = tcx.hir_node_by_def_id(did) + { + let hir_id = hir_item.hir_id(); + let span = tcx.hir_span_with_body(hir_id); + let item_src = src_from_span_internal(span, tcx); + + let attrs = tcx + .hir_attrs(hir_id) + .iter() + .filter_map(|attr| match attr { + Attribute::Parsed(parsed) => { + if let AttributeKind::Align { .. } + | AttributeKind::AutomaticallyDerived(_) + | AttributeKind::Deprecation { .. } + | AttributeKind::ExportName { .. } + | AttributeKind::LinkName { .. } + | AttributeKind::LinkSection { .. } + | AttributeKind::Fundamental + | AttributeKind::Link(..) + | AttributeKind::MayDangle(..) + | AttributeKind::Marker(..) + | AttributeKind::Naked(..) + | AttributeKind::NoMangle(..) + | AttributeKind::NonExhaustive(..) + | AttributeKind::Pointee(..) + | AttributeKind::Repr { .. } + | AttributeKind::TargetFeature { .. } = parsed + { + Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)) + } else { + None + } + } + // Doc and rustc attribute can still apear, so we collect tool attribute below. + Attribute::Unparsed(_) => None, + }) + .chain(item.all_tool_attrs().iter().map(|a| a.as_str().to_owned())) + .join(""); + + [attrs, item_src] + } else { + // Non-local items are hard to query span with body and full attributes. + let item_src = src_from_span(item.span(), tcx); + let attrs = item.all_tool_attrs().iter().map(|a| a.as_str()).join(""); + [attrs, item_src] + }; + if attrs.is_empty() { + item_src + } else { + format!("{attrs}{item_src}") + } } pub fn src_from_span(span: Span, tcx: TyCtxt) -> String { let span = internal(tcx, span); + src_from_span_internal(span, tcx) +} + +fn src_from_span_internal(span: rustc_span::Span, tcx: TyCtxt) -> String { let src_map = tcx.sess.source_map(); src_map.span_to_snippet(span).unwrap_or_default() } diff --git a/ui/app/components/code/AdtPopup.vue b/ui/app/components/code/AdtPopup.vue index e151538..2ce3a01 100644 --- a/ui/app/components/code/AdtPopup.vue +++ b/ui/app/components/code/AdtPopup.vue @@ -1,6 +1,6 @@