1use std::fmt;
4
5use rustc_hir::def::{CtorOf, DefKind, MacroKinds};
6use rustc_hir::def_id::DefId;
7use rustc_middle::ty::TyCtxt;
8use rustc_span::hygiene::MacroKind;
9use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
10
11use crate::clean;
12
13macro_rules! item_type {
14 ($($variant:ident = $number:literal,)+) => {
15
16#[derive(Copy, PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)]
35#[repr(u8)]
36pub(crate) enum ItemType {
37 $($variant = $number,)+
38}
39
40impl Serialize for ItemType {
41 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42 where
43 S: Serializer,
44 {
45 (*self as u8).serialize(serializer)
46 }
47}
48
49impl<'de> Deserialize<'de> for ItemType {
50 fn deserialize<D>(deserializer: D) -> Result<ItemType, D::Error>
51 where
52 D: Deserializer<'de>,
53 {
54 struct ItemTypeVisitor;
55 impl<'de> de::Visitor<'de> for ItemTypeVisitor {
56 type Value = ItemType;
57 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 write!(formatter, "an integer between 0 and 27")
59 }
60 fn visit_u64<E: de::Error>(self, v: u64) -> Result<ItemType, E> {
61 Ok(match v {
62 $($number => ItemType::$variant,)+
63 _ => return Err(E::missing_field("unknown number for `ItemType` enum")),
64 })
65 }
66 }
67 deserializer.deserialize_any(ItemTypeVisitor)
68 }
69}
70
71 }
72}
73
74item_type! {
75 Keyword = 0,
76 Primitive = 1,
77 Module = 2,
78 ExternCrate = 3,
79 Import = 4,
80 Struct = 5,
81 Enum = 6,
82 Function = 7,
83 TypeAlias = 8,
84 Static = 9,
85 Trait = 10,
86 Impl = 11,
87 TyMethod = 12,
88 Method = 13,
89 StructField = 14,
90 Variant = 15,
91 Macro = 16,
92 AssocType = 17,
93 Constant = 18,
94 AssocConst = 19,
95 Union = 20,
96 ForeignType = 21,
97 ProcAttribute = 23,
99 ProcDerive = 24,
100 TraitAlias = 25,
101 Attribute = 27,
104 DeclMacroAttribute = 28,
109 DeclMacroDerive = 29,
110}
111
112impl<'a> From<&'a clean::Item> for ItemType {
113 fn from(item: &'a clean::Item) -> ItemType {
114 let kind = match &item.kind {
115 clean::StrippedItem(item) => item,
116 kind => kind,
117 };
118
119 match kind {
120 clean::ModuleItem(..) => ItemType::Module,
121 clean::ExternCrateItem { .. } => ItemType::ExternCrate,
122 clean::ImportItem(..) => ItemType::Import,
123 clean::StructItem(..) => ItemType::Struct,
124 clean::UnionItem(..) => ItemType::Union,
125 clean::EnumItem(..) => ItemType::Enum,
126 clean::FunctionItem(..) => ItemType::Function,
127 clean::TypeAliasItem(..) => ItemType::TypeAlias,
128 clean::StaticItem(..) => ItemType::Static,
129 clean::ConstantItem(..) => ItemType::Constant,
130 clean::TraitItem(..) => ItemType::Trait,
131 clean::ImplItem(..) | clean::PlaceholderImplItem => ItemType::Impl,
132 clean::RequiredMethodItem(..) => ItemType::TyMethod,
133 clean::MethodItem(..) => ItemType::Method,
134 clean::StructFieldItem(..) => ItemType::StructField,
135 clean::VariantItem(..) => ItemType::Variant,
136 clean::ForeignFunctionItem(..) => ItemType::Function, clean::ForeignStaticItem(..) => ItemType::Static, clean::MacroItem(..) => ItemType::Macro,
139 clean::PrimitiveItem(..) => ItemType::Primitive,
140 clean::RequiredAssocConstItem(..)
141 | clean::ProvidedAssocConstItem(..)
142 | clean::ImplAssocConstItem(..) => ItemType::AssocConst,
143 clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType,
144 clean::ForeignTypeItem => ItemType::ForeignType,
145 clean::KeywordItem => ItemType::Keyword,
146 clean::AttributeItem => ItemType::Attribute,
147 clean::TraitAliasItem(..) => ItemType::TraitAlias,
148 clean::ProcMacroItem(mac) => match mac.kind {
149 MacroKind::Bang => ItemType::Macro,
150 MacroKind::Attr => ItemType::ProcAttribute,
151 MacroKind::Derive => ItemType::ProcDerive,
152 },
153 clean::StrippedItem(..) => unreachable!(),
154 }
155 }
156}
157
158impl ItemType {
159 pub(crate) fn from_def_id(def_id: DefId, tcx: TyCtxt<'_>) -> Self {
160 let def_kind = tcx.def_kind(def_id);
161 match def_kind {
162 DefKind::Enum => Self::Enum,
163 DefKind::Fn => Self::Function,
164 DefKind::Mod => Self::Module,
165 DefKind::Const { .. } => Self::Constant,
166 DefKind::Static { .. } => Self::Static,
167 DefKind::Struct => Self::Struct,
168 DefKind::Union => Self::Union,
169 DefKind::Trait => Self::Trait,
170 DefKind::TyAlias => Self::TypeAlias,
171 DefKind::TraitAlias => Self::TraitAlias,
172 DefKind::Macro(MacroKinds::ATTR) => ItemType::ProcAttribute,
173 DefKind::Macro(MacroKinds::DERIVE) => ItemType::ProcDerive,
174 DefKind::Macro(_) => ItemType::Macro,
175 DefKind::ForeignTy => Self::ForeignType,
176 DefKind::Variant => Self::Variant,
177 DefKind::Field => Self::StructField,
178 DefKind::AssocTy => Self::AssocType,
179 DefKind::AssocFn => {
180 if tcx.associated_item(def_id).defaultness(tcx).has_value() {
181 Self::Method
182 } else {
183 Self::TyMethod
184 }
185 }
186 DefKind::Ctor(CtorOf::Struct, _) => Self::Struct,
187 DefKind::Ctor(CtorOf::Variant, _) => Self::Variant,
188 DefKind::AssocConst { .. } => Self::AssocConst,
189 DefKind::TyParam
190 | DefKind::ConstParam
191 | DefKind::ExternCrate
192 | DefKind::Use
193 | DefKind::ForeignMod
194 | DefKind::AnonConst
195 | DefKind::InlineConst
196 | DefKind::OpaqueTy
197 | DefKind::LifetimeParam
198 | DefKind::GlobalAsm
199 | DefKind::Impl { .. }
200 | DefKind::Closure
201 | DefKind::SyntheticCoroutineBody => Self::ForeignType,
202 }
203 }
204
205 pub(crate) fn as_str(&self) -> &'static str {
206 match self {
207 ItemType::Module => "mod",
208 ItemType::ExternCrate => "externcrate",
209 ItemType::Import => "import",
210 ItemType::Struct => "struct",
211 ItemType::Union => "union",
212 ItemType::Enum => "enum",
213 ItemType::Function => "fn",
214 ItemType::TypeAlias => "type",
215 ItemType::Static => "static",
216 ItemType::Trait => "trait",
217 ItemType::Impl => "impl",
218 ItemType::TyMethod => "tymethod",
219 ItemType::Method => "method",
220 ItemType::StructField => "structfield",
221 ItemType::Variant => "variant",
222 ItemType::Macro => "macro",
223 ItemType::Primitive => "primitive",
224 ItemType::AssocType => "associatedtype",
225 ItemType::Constant => "constant",
226 ItemType::AssocConst => "associatedconstant",
227 ItemType::ForeignType => "foreigntype",
228 ItemType::Keyword => "keyword",
229 ItemType::ProcAttribute | ItemType::DeclMacroAttribute => "attr",
230 ItemType::ProcDerive | ItemType::DeclMacroDerive => "derive",
231 ItemType::TraitAlias => "traitalias",
232 ItemType::Attribute => "attribute",
233 }
234 }
235 pub(crate) fn is_method(&self) -> bool {
236 matches!(self, ItemType::Method | ItemType::TyMethod)
237 }
238 pub(crate) fn is_adt(&self) -> bool {
239 matches!(self, ItemType::Struct | ItemType::Union | ItemType::Enum)
240 }
241 pub(crate) fn is_fn_like(&self) -> bool {
243 matches!(self, ItemType::Function | ItemType::Method | ItemType::TyMethod)
244 }
245}
246
247impl fmt::Display for ItemType {
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 f.write_str(self.as_str())
250 }
251}