1use iter_tools::Itertools;
2use rustdoc_types::{
3 Enum, Id, Impl, Item, ItemEnum, Path, Struct, StructKind, Type, Variant, VariantKind,
4};
5
6pub fn is_relevant(item: &Item) -> bool {
7 is_impl(item)
8 || is_struct_field(item)
9 || is_enum_variant(item)
10 || is_struct(item)
11 || is_enum(item)
12 || is_associated_type(item)
13}
14
15pub fn is_struct(item: &Item) -> bool {
16 matches!(
17 item,
18 Item {
19 inner: ItemEnum::Struct(_),
20 ..
21 }
22 )
23}
24
25pub fn is_struct_unit(item: &Item) -> bool {
26 matches!(
27 item,
28 Item {
29 inner: ItemEnum::Struct(Struct {
30 kind: StructKind::Unit,
31 ..
32 }),
33 ..
34 }
35 )
36}
37
38pub fn is_struct_plain(item: &Item) -> bool {
39 matches!(
40 item,
41 Item {
42 inner: ItemEnum::Struct(Struct {
43 kind: StructKind::Plain { .. },
44 ..
45 }),
46 ..
47 }
48 )
49}
50
51pub fn is_struct_tuple(item: &Item) -> bool {
52 matches!(
53 item,
54 Item {
55 inner: ItemEnum::Struct(Struct {
56 kind: StructKind::Tuple(_),
57 ..
58 }),
59 ..
60 }
61 )
62}
63
64pub fn has_field(item: &Item, field: &Item) -> bool {
65 match item {
66 Item {
67 inner: ItemEnum::Struct(Struct { kind, .. }),
68 ..
69 } => match kind {
70 StructKind::Unit => false,
71 StructKind::Tuple(fields) => fields.contains(&Some(field.id)),
72 StructKind::Plain {
73 fields,
74 has_stripped_fields: _,
75 } => fields.contains(&field.id),
76 },
77 Item {
78 inner: ItemEnum::Variant(Variant { kind, .. }),
79 ..
80 } => match kind {
81 VariantKind::Plain => false,
82 VariantKind::Tuple(fields) => fields.contains(&Some(field.id)),
83 VariantKind::Struct { fields, .. } => fields.contains(&field.id),
84 },
85 _ => false,
86 }
87}
88
89pub fn field_ids(item: &Item) -> Vec<Id> {
90 match item {
91 Item {
92 inner: ItemEnum::Struct(Struct { kind, .. }),
93 ..
94 } => match kind {
95 StructKind::Plain { fields, .. } => fields.to_vec(),
96 StructKind::Tuple(fields) => fields
97 .iter()
98 .filter_map(|f| f.as_ref())
99 .cloned()
100 .collect_vec(),
101 StructKind::Unit => vec![],
102 },
103 Item {
104 inner: ItemEnum::Variant(Variant { kind, .. }),
105 ..
106 } => match kind {
107 VariantKind::Plain => vec![],
108 VariantKind::Tuple(fields) => fields
109 .iter()
110 .filter_map(|f| f.as_ref())
111 .cloned()
112 .collect_vec(),
113 VariantKind::Struct { fields, .. } => fields.to_vec(),
114 },
115 _ => vec![],
116 }
117}
118
119fn is_struct_field(item: &Item) -> bool {
120 matches!(
121 item,
122 Item {
123 inner: ItemEnum::StructField(_),
124 ..
125 }
126 )
127}
128
129pub fn is_enum(item: &Item) -> bool {
130 matches!(
131 item,
132 Item {
133 inner: ItemEnum::Enum(_),
134 ..
135 }
136 )
137}
138
139fn is_enum_variant(item: &Item) -> bool {
140 matches!(
141 item,
142 Item {
143 inner: ItemEnum::Variant(_),
144 ..
145 }
146 )
147}
148
149pub fn has_variant(item: &Item, variant: &Item) -> bool {
150 match item {
151 Item {
152 inner: ItemEnum::Enum(Enum { variants, .. }),
153 ..
154 } => variants.contains(&variant.id),
155 _ => false,
156 }
157}
158
159pub fn variant_ids(item: &Item) -> Vec<Id> {
160 match item {
161 Item {
162 inner: ItemEnum::Enum(Enum { variants, .. }),
163 ..
164 } => variants.to_vec(),
165 _ => vec![],
166 }
167}
168
169pub fn is_plain_variant(item: &Item) -> bool {
170 matches!(
171 item,
172 Item {
173 inner: ItemEnum::Variant(Variant {
174 kind: VariantKind::Plain,
175 ..
176 }),
177 ..
178 }
179 )
180}
181
182pub fn is_struct_variant(item: &Item) -> bool {
183 matches!(
184 item,
185 Item {
186 inner: ItemEnum::Variant(Variant {
187 kind: VariantKind::Struct { .. },
188 ..
189 }),
190 ..
191 }
192 )
193}
194
195pub fn is_tuple_variant(item: &Item) -> bool {
196 matches!(
197 item,
198 Item {
199 inner: ItemEnum::Variant(Variant {
200 kind: VariantKind::Tuple(_),
201 ..
202 }),
203 ..
204 }
205 )
206}
207
208pub fn is_impl(item: &Item) -> bool {
209 matches!(
210 item,
211 Item {
212 inner: ItemEnum::Impl(Impl {
213 trait_: Some(Path { path, .. }),
214 ..
215 }),
216 ..
217 } if (["App", "Effect", "Capability", "Operation"]).contains(&path.as_str())
218 )
219}
220
221pub fn is_impl_for(item: &Item, for_: &Item, trait_name: &str) -> bool {
222 matches!(item, Item {
223 inner:
224 ItemEnum::Impl(Impl {
225 trait_: Some(Path { path, .. }),
226 for_: Type::ResolvedPath(Path { id, .. }),
227 ..
228 }),
229 ..
230 } if path == trait_name && id == &for_.id)
231}
232
233fn is_associated_type(item: &Item) -> bool {
234 matches!(
235 item,
236 Item {
237 inner: ItemEnum::AssocType { .. },
238 ..
239 }
240 )
241}
242
243pub fn has_associated_item(item: &Item, associated_item: &Item, with_name: &str) -> bool {
244 match item {
245 Item {
246 inner: ItemEnum::Impl(Impl { items, .. }),
247 ..
248 } => match &associated_item {
249 Item {
250 name: Some(name), ..
251 } if with_name == name => items.contains(&associated_item.id),
252 _ => false,
253 },
254 _ => false,
255 }
256}