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