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::{self, ItemKind};
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 AssocFnWithoutBody = 12, AssocFnWithBody = 13, 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 match item.kind.unstripped() {
115 ItemKind::Module(..) => ItemType::Module,
116 ItemKind::ExternCrate { .. } => ItemType::ExternCrate,
117 ItemKind::Import(..) => ItemType::Import,
118 ItemKind::Struct(..) => ItemType::Struct,
119 ItemKind::Union(..) => ItemType::Union,
120 ItemKind::Enum(..) => ItemType::Enum,
121 ItemKind::Function(..) => ItemType::Function,
122 ItemKind::TypeAlias(..) => ItemType::TypeAlias,
123 ItemKind::Static(..) => ItemType::Static,
124 ItemKind::Constant(..) => ItemType::Constant,
125 ItemKind::Trait(..) => ItemType::Trait,
126 ItemKind::Impl(..) | ItemKind::PlaceholderImpl => ItemType::Impl,
127 ItemKind::AssocFunction(f) => match f.body {
128 Some(_) => ItemType::AssocFnWithBody,
129 None => ItemType::AssocFnWithoutBody,
130 },
131 ItemKind::StructField(..) => ItemType::StructField,
132 ItemKind::Variant(..) => ItemType::Variant,
133 ItemKind::ForeignFunction(..) => ItemType::Function, ItemKind::ForeignStatic(..) => ItemType::Static, ItemKind::DeclMacro(..) => ItemType::Macro,
136 ItemKind::PrimitiveType(..) => ItemType::Primitive,
137 ItemKind::AssocConstant(..) => ItemType::AssocConst,
138 ItemKind::AssocType(..) => ItemType::AssocType,
139 ItemKind::ForeignType => ItemType::ForeignType,
140 ItemKind::Keyword => ItemType::Keyword,
141 ItemKind::Attribute => ItemType::Attribute,
142 ItemKind::TraitAlias(..) => ItemType::TraitAlias,
143 ItemKind::ProcMacro(mac) => match mac.kind {
144 MacroKind::Bang => ItemType::Macro,
145 MacroKind::Attr => ItemType::ProcAttribute,
146 MacroKind::Derive => ItemType::ProcDerive,
147 },
148 ItemKind::Stripped(..) => unreachable!(),
149 }
150 }
151}
152
153impl ItemType {
154 pub(crate) fn from_def_id(def_id: DefId, tcx: TyCtxt<'_>) -> Self {
155 let def_kind = tcx.def_kind(def_id);
156 match def_kind {
157 DefKind::Enum => Self::Enum,
158 DefKind::Fn => Self::Function,
159 DefKind::Mod => Self::Module,
160 DefKind::Const => Self::Constant,
161 DefKind::Static { .. } => Self::Static,
162 DefKind::Struct => Self::Struct,
163 DefKind::Union => Self::Union,
164 DefKind::Trait => Self::Trait,
165 DefKind::TyAlias => Self::TypeAlias,
166 DefKind::TraitAlias => Self::TraitAlias,
167 DefKind::Macro(MacroKinds::ATTR) => ItemType::ProcAttribute,
168 DefKind::Macro(MacroKinds::DERIVE) => ItemType::ProcDerive,
169 DefKind::Macro(_) => ItemType::Macro,
170 DefKind::ForeignTy => Self::ForeignType,
171 DefKind::Variant => Self::Variant,
172 DefKind::Field => Self::StructField,
173 DefKind::AssocTy => Self::AssocType,
174 DefKind::AssocFn => {
175 if tcx.associated_item(def_id).defaultness(tcx).has_value() {
176 Self::AssocFnWithBody
177 } else {
178 Self::AssocFnWithoutBody
179 }
180 }
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::OpaqueTy
191 | DefKind::LifetimeParam
192 | DefKind::GlobalAsm
193 | DefKind::Impl { .. }
194 | DefKind::Closure
195 | DefKind::SyntheticCoroutineBody
196 | DefKind::TestBinderConstraints => 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::AssocFnWithoutBody => "tymethod",
214 ItemType::AssocFnWithBody => "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 | ItemType::DeclMacroAttribute => "attr",
225 ItemType::ProcDerive | ItemType::DeclMacroDerive => "derive",
226 ItemType::TraitAlias => "traitalias",
227 ItemType::Attribute => "attribute",
228 }
229 }
230 pub(crate) fn is_assoc_fn(&self) -> bool {
231 matches!(self, ItemType::AssocFnWithBody | ItemType::AssocFnWithoutBody)
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!(
239 self,
240 ItemType::Function | ItemType::AssocFnWithBody | ItemType::AssocFnWithoutBody
241 )
242 }
243}
244
245impl fmt::Display for ItemType {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 f.write_str(self.as_str())
248 }
249}