crux_cli/codegen/
item.rs

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}