|
7 | 7 | use rustc_abi::ExternAbi;
|
8 | 8 | use rustc_ast::ast;
|
9 | 9 | use rustc_attr_data_structures::{self as attrs, DeprecatedSince};
|
| 10 | +use rustc_hir as hir; |
10 | 11 | use rustc_hir::def::CtorKind;
|
11 | 12 | use rustc_hir::def_id::DefId;
|
12 | 13 | use rustc_metadata::rendered_const;
|
| 14 | +use rustc_middle::ty::TyCtxt; |
13 | 15 | use rustc_middle::{bug, ty};
|
14 | 16 | use rustc_span::{Pos, kw, sym};
|
15 | 17 | use rustdoc_json_types::*;
|
@@ -40,7 +42,12 @@ impl JsonRenderer<'_> {
|
40 | 42 | })
|
41 | 43 | .collect();
|
42 | 44 | let docs = item.opt_doc_value();
|
43 |
| - let attrs = item.attributes(self.tcx, &self.cache, true); |
| 45 | + let attrs = item |
| 46 | + .attrs |
| 47 | + .other_attrs |
| 48 | + .iter() |
| 49 | + .filter_map(|a| maybe_from_hir_attr(a, item.item_id, self.tcx)) |
| 50 | + .collect(); |
44 | 51 | let span = item.span(self.tcx);
|
45 | 52 | let visibility = item.visibility(self.tcx);
|
46 | 53 | let clean::ItemInner { name, item_id, .. } = *item.inner;
|
@@ -875,3 +882,104 @@ impl FromClean<ItemType> for ItemKind {
|
875 | 882 | }
|
876 | 883 | }
|
877 | 884 | }
|
| 885 | + |
| 886 | +/// Maybe convert a attribue from hir to json. |
| 887 | +/// |
| 888 | +/// Returns `None` if the attribute shouldn't be in the output. |
| 889 | +fn maybe_from_hir_attr( |
| 890 | + attr: &hir::Attribute, |
| 891 | + item_id: ItemId, |
| 892 | + tcx: TyCtxt<'_>, |
| 893 | +) -> Option<Attribute> { |
| 894 | + use attrs::AttributeKind as AK; |
| 895 | + |
| 896 | + let kind = match attr { |
| 897 | + hir::Attribute::Parsed(kind) => kind, |
| 898 | + |
| 899 | + // There are some currently unstrucured attrs that we *do* care about. |
| 900 | + // As the attribute migration progresses (#131229), this is expected to shrink |
| 901 | + // and eventually be removed as all attributes gain a strutured representation in |
| 902 | + // HIR. |
| 903 | + hir::Attribute::Unparsed(_) => { |
| 904 | + return Some(if attr.has_name(sym::non_exhaustive) { |
| 905 | + Attribute::NonExhaustive |
| 906 | + } else if attr.has_name(sym::automatically_derived) { |
| 907 | + Attribute::AutomaticallyDerived |
| 908 | + } else if attr.has_name(sym::export_name) { |
| 909 | + Attribute::ExportName( |
| 910 | + attr.value_str().expect("checked by attr validation").to_string(), |
| 911 | + ) |
| 912 | + } else if attr.has_name(sym::doc) |
| 913 | + && attr |
| 914 | + .meta_item_list() |
| 915 | + .is_some_and(|metas| metas.iter().any(|item| item.has_name(sym::hidden))) |
| 916 | + { |
| 917 | + Attribute::DocHidden |
| 918 | + } else { |
| 919 | + other_attr(tcx, attr) |
| 920 | + }); |
| 921 | + } |
| 922 | + }; |
| 923 | + |
| 924 | + Some(match kind { |
| 925 | + AK::Deprecation { .. } => return None, // Handled seperatly into Item::deprecation. |
| 926 | + AK::DocComment { .. } => unreachable!("doc comments stripped out earlier"), |
| 927 | + |
| 928 | + AK::MustUse { reason, span: _ } => { |
| 929 | + Attribute::MustUse { reason: reason.map(|s| s.to_string()) } |
| 930 | + } |
| 931 | + AK::Repr { .. } => repr_attr( |
| 932 | + tcx, |
| 933 | + item_id.as_def_id().expect("all items that could have #[repr] have a DefId"), |
| 934 | + ), |
| 935 | + AK::NoMangle(_) => Attribute::NoMangle, |
| 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