diff options
Diffstat (limited to 'src/librustdoc/json/conversions.rs')
| -rw-r--r-- | src/librustdoc/json/conversions.rs | 99 | 
1 files changed, 98 insertions, 1 deletions
| diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index e7163bead92..0a84d8caa30 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -5,10 +5,12 @@ use rustc_abi::ExternAbi; use rustc_ast::ast; use rustc_attr_data_structures::{self as attrs, DeprecatedSince}; +use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; use rustc_hir::{HeaderSafety, Safety}; use rustc_metadata::rendered_const; +use rustc_middle::ty::TyCtxt; use rustc_middle::{bug, ty}; use rustc_span::{Pos, kw, sym}; use rustdoc_json_types::*; @@ -39,7 +41,12 @@ impl JsonRenderer<'_> { }) .collect(); let docs = item.opt_doc_value(); - let attrs = item.attributes(self.tcx, &self.cache, true); + let attrs = item + .attrs + .other_attrs + .iter() + .filter_map(|a| maybe_from_hir_attr(a, item.item_id, self.tcx)) + .collect(); let span = item.span(self.tcx); let visibility = item.visibility(self.tcx); let clean::ItemInner { name, item_id, .. } = *item.inner; @@ -886,3 +893,93 @@ impl FromClean<ItemType> for ItemKind { } } } + +/// Maybe convert a attribute from hir to json. +/// +/// Returns `None` if the attribute shouldn't be in the output. +fn maybe_from_hir_attr( + attr: &hir::Attribute, + item_id: ItemId, + tcx: TyCtxt<'_>, +) -> Option<Attribute> { + use attrs::AttributeKind as AK; + + let kind = match attr { + hir::Attribute::Parsed(kind) => kind, + + hir::Attribute::Unparsed(_) => { + // FIXME: We should handle `#[doc(hidden)]`. + return Some(other_attr(tcx, attr)); + } + }; + + Some(match kind { + AK::Deprecation { .. } => return None, // Handled separately into Item::deprecation. + AK::DocComment { .. } => unreachable!("doc comments stripped out earlier"), + + AK::MustUse { reason, span: _ } => { + Attribute::MustUse { reason: reason.map(|s| s.to_string()) } + } + AK::Repr { .. } => repr_attr( + tcx, + item_id.as_def_id().expect("all items that could have #[repr] have a DefId"), + ), + AK::ExportName { name, span: _ } => Attribute::ExportName(name.to_string()), + AK::LinkSection { name, span: _ } => Attribute::LinkSection(name.to_string()), + AK::TargetFeature(features, _span) => Attribute::TargetFeature { + enable: features.iter().map(|(feat, _span)| feat.to_string()).collect(), + }, + + AK::NoMangle(_) => Attribute::NoMangle, + AK::NonExhaustive(_) => Attribute::NonExhaustive, + AK::AutomaticallyDerived(_) => Attribute::AutomaticallyDerived, + + _ => other_attr(tcx, attr), + }) +} + +fn other_attr(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Attribute { + let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr); + assert_eq!(s.pop(), Some('\n')); + Attribute::Other(s) +} + +fn repr_attr(tcx: TyCtxt<'_>, def_id: DefId) -> Attribute { + let repr = tcx.adt_def(def_id).repr(); + + let kind = if repr.c() { + ReprKind::C + } else if repr.transparent() { + ReprKind::Transparent + } else if repr.simd() { + ReprKind::Simd + } else { + ReprKind::Rust + }; + + let align = repr.align.map(|a| a.bytes()); + let packed = repr.pack.map(|p| p.bytes()); + let int = repr.int.map(format_integer_type); + + Attribute::Repr(AttributeRepr { kind, align, packed, int }) +} + +fn format_integer_type(it: rustc_abi::IntegerType) -> String { + use rustc_abi::Integer::*; + use rustc_abi::IntegerType::*; + match it { + Pointer(true) => "isize", + Pointer(false) => "usize", + Fixed(I8, true) => "i8", + Fixed(I8, false) => "u8", + Fixed(I16, true) => "i16", + Fixed(I16, false) => "u16", + Fixed(I32, true) => "i32", + Fixed(I32, false) => "u32", + Fixed(I64, true) => "i64", + Fixed(I64, false) => "u64", + Fixed(I128, true) => "i128", + Fixed(I128, false) => "u128", + } + .to_owned() +} | 
