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