|
5 | 5 | use rustc_abi::ExternAbi; |
6 | 6 | use rustc_ast::ast; |
7 | 7 | use rustc_attr_data_structures::{self as attrs, DeprecatedSince}; |
| 8 | +use rustc_hir as hir; |
8 | 9 | use rustc_hir::def::CtorKind; |
9 | 10 | use rustc_hir::def_id::DefId; |
10 | 11 | use rustc_hir::{HeaderSafety, Safety}; |
11 | 12 | use rustc_metadata::rendered_const; |
| 13 | +use rustc_middle::ty::TyCtxt; |
12 | 14 | use rustc_middle::{bug, ty}; |
13 | 15 | use rustc_span::{Pos, kw, sym}; |
14 | 16 | use rustdoc_json_types::*; |
@@ -39,7 +41,12 @@ impl JsonRenderer<'_> { |
39 | 41 | }) |
40 | 42 | .collect(); |
41 | 43 | let docs = item.opt_doc_value(); |
42 | | - let attrs = item.attributes(self.tcx, &self.cache, true); |
| 44 | + let attrs = item |
| 45 | + .attrs |
| 46 | + .other_attrs |
| 47 | + .iter() |
| 48 | + .filter_map(|a| maybe_from_hir_attr(a, item.item_id, self.tcx)) |
| 49 | + .collect(); |
43 | 50 | let span = item.span(self.tcx); |
44 | 51 | let visibility = item.visibility(self.tcx); |
45 | 52 | let clean::ItemInner { name, item_id, .. } = *item.inner; |
@@ -886,3 +893,93 @@ impl FromClean<ItemType> for ItemKind { |
886 | 893 | } |
887 | 894 | } |
888 | 895 | } |
| 896 | + |
| 897 | +/// Maybe convert a attribute from hir to json. |
| 898 | +/// |
| 899 | +/// Returns `None` if the attribute shouldn't be in the output. |
| 900 | +fn maybe_from_hir_attr( |
| 901 | + attr: &hir::Attribute, |
| 902 | + item_id: ItemId, |
| 903 | + tcx: TyCtxt<'_>, |
| 904 | +) -> Option<Attribute> { |
| 905 | + use attrs::AttributeKind as AK; |
| 906 | + |
| 907 | + let kind = match attr { |
| 908 | + hir::Attribute::Parsed(kind) => kind, |
| 909 | + |
| 910 | + hir::Attribute::Unparsed(_) => { |
| 911 | + // FIXME: We should handle `#[doc(hidden)]`. |
| 912 | + return Some(other_attr(tcx, attr)); |
| 913 | + } |
| 914 | + }; |
| 915 | + |
| 916 | + Some(match kind { |
| 917 | + AK::Deprecation { .. } => return None, // Handled separately into Item::deprecation. |
| 918 | + AK::DocComment { .. } => unreachable!("doc comments stripped out earlier"), |
| 919 | + |
| 920 | + AK::MustUse { reason, span: _ } => { |
| 921 | + Attribute::MustUse { reason: reason.map(|s| s.to_string()) } |
| 922 | + } |
| 923 | + AK::Repr { .. } => repr_attr( |
| 924 | + tcx, |
| 925 | + item_id.as_def_id().expect("all items that could have #[repr] have a DefId"), |
| 926 | + ), |
| 927 | + AK::ExportName { name, span: _ } => Attribute::ExportName(name.to_string()), |
| 928 | + AK::LinkSection { name, span: _ } => Attribute::LinkSection(name.to_string()), |
| 929 | + AK::TargetFeature(features, _span) => Attribute::TargetFeature { |
| 930 | + enable: features.iter().map(|(feat, _span)| feat.to_string()).collect(), |
| 931 | + }, |
| 932 | + |
| 933 | + AK::NoMangle(_) => Attribute::NoMangle, |
| 934 | + AK::NonExhaustive(_) => Attribute::NonExhaustive, |
| 935 | + AK::AutomaticallyDerived(_) => Attribute::AutomaticallyDerived, |
| 936 | + |
| 937 | + _ => other_attr(tcx, attr), |
| 938 | + }) |
| 939 | +} |
| 940 | + |
| 941 | +fn other_attr(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Attribute { |
| 942 | + let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr); |
| 943 | + assert_eq!(s.pop(), Some('\n')); |
| 944 | + Attribute::Other(s) |
| 945 | +} |
| 946 | + |
| 947 | +fn repr_attr(tcx: TyCtxt<'_>, def_id: DefId) -> Attribute { |
| 948 | + let repr = tcx.adt_def(def_id).repr(); |
| 949 | + |
| 950 | + let kind = if repr.c() { |
| 951 | + ReprKind::C |
| 952 | + } else if repr.transparent() { |
| 953 | + ReprKind::Transparent |
| 954 | + } else if repr.simd() { |
| 955 | + ReprKind::Simd |
| 956 | + } else { |
| 957 | + ReprKind::Rust |
| 958 | + }; |
| 959 | + |
| 960 | + let align = repr.align.map(|a| a.bytes()); |
| 961 | + let packed = repr.pack.map(|p| p.bytes()); |
| 962 | + let int = repr.int.map(format_integer_type); |
| 963 | + |
| 964 | + Attribute::Repr(AttributeRepr { kind, align, packed, int }) |
| 965 | +} |
| 966 | + |
| 967 | +fn format_integer_type(it: rustc_abi::IntegerType) -> String { |
| 968 | + use rustc_abi::Integer::*; |
| 969 | + use rustc_abi::IntegerType::*; |
| 970 | + match it { |
| 971 | + Pointer(true) => "isize", |
| 972 | + Pointer(false) => "usize", |
| 973 | + Fixed(I8, true) => "i8", |
| 974 | + Fixed(I8, false) => "u8", |
| 975 | + Fixed(I16, true) => "i16", |
| 976 | + Fixed(I16, false) => "u16", |
| 977 | + Fixed(I32, true) => "i32", |
| 978 | + Fixed(I32, false) => "u32", |
| 979 | + Fixed(I64, true) => "i64", |
| 980 | + Fixed(I64, false) => "u64", |
| 981 | + Fixed(I128, true) => "i128", |
| 982 | + Fixed(I128, false) => "u128", |
| 983 | + } |
| 984 | + .to_owned() |
| 985 | +} |
0 commit comments