aldrin_parser/ast/
enum_def.rs

1use super::{Attribute, Comment, DocString, Ident, LitInt, Prelude, TypeName};
2use crate::error::{
3    DuplicateEnumVariant, DuplicateEnumVariantId, EmptyEnum, InvalidEnumVariantId, RecursiveEnum,
4};
5use crate::grammar::Rule;
6use crate::validate::Validate;
7use crate::warning::{BrokenDocLink, NonCamelCaseEnum, NonCamelCaseEnumVariant};
8use crate::Span;
9use pest::iterators::Pair;
10
11#[derive(Debug, Clone)]
12pub struct EnumDef {
13    span: Span,
14    comment: Vec<Comment>,
15    doc: Vec<DocString>,
16    attrs: Vec<Attribute>,
17    name: Ident,
18    vars: Vec<EnumVariant>,
19    fallback: Option<EnumFallback>,
20}
21
22impl EnumDef {
23    pub(crate) fn parse(pair: Pair<Rule>) -> Self {
24        assert_eq!(pair.as_rule(), Rule::enum_def);
25
26        let span = Span::from_pair(&pair);
27        let mut pairs = pair.into_inner();
28        let mut prelude = Prelude::regular(&mut pairs);
29
30        pairs.next().unwrap(); // Skip keyword.
31
32        let pair = pairs.next().unwrap();
33        let name = Ident::parse(pair);
34
35        pairs.next().unwrap(); // Skip {.
36
37        let mut vars = Vec::new();
38        let mut fallback = None;
39
40        for pair in pairs {
41            match pair.as_rule() {
42                Rule::enum_variant => vars.push(EnumVariant::parse(pair)),
43                Rule::enum_fallback => fallback = Some(EnumFallback::parse(pair)),
44                Rule::tok_cur_close => break,
45                _ => unreachable!(),
46            }
47        }
48
49        Self {
50            span,
51            comment: prelude.take_comment(),
52            doc: prelude.take_doc(),
53            attrs: prelude.take_attrs(),
54            name,
55            vars,
56            fallback,
57        }
58    }
59
60    pub(crate) fn validate(&self, validate: &mut Validate) {
61        DuplicateEnumVariant::validate(
62            &self.vars,
63            self.fallback.as_ref(),
64            Some(&self.name),
65            validate,
66        );
67
68        BrokenDocLink::validate(&self.doc, validate);
69        DuplicateEnumVariantId::validate(&self.vars, Some(&self.name), validate);
70        NonCamelCaseEnum::validate(self, validate);
71        RecursiveEnum::validate(self, validate);
72
73        EmptyEnum::validate(
74            &self.vars,
75            self.fallback.as_ref(),
76            self.span,
77            Some(&self.name),
78            validate,
79        );
80
81        self.name.validate(true, validate);
82
83        for var in &self.vars {
84            var.validate(validate);
85        }
86
87        if let Some(ref fallback) = self.fallback {
88            fallback.validate(validate);
89        }
90    }
91
92    pub fn span(&self) -> Span {
93        self.span
94    }
95
96    pub fn comment(&self) -> &[Comment] {
97        &self.comment
98    }
99
100    pub fn doc(&self) -> &[DocString] {
101        &self.doc
102    }
103
104    pub fn attributes(&self) -> &[Attribute] {
105        &self.attrs
106    }
107
108    pub fn name(&self) -> &Ident {
109        &self.name
110    }
111
112    pub fn variants(&self) -> &[EnumVariant] {
113        &self.vars
114    }
115
116    pub fn fallback(&self) -> Option<&EnumFallback> {
117        self.fallback.as_ref()
118    }
119}
120
121#[derive(Debug, Clone)]
122pub struct InlineEnum {
123    span: Span,
124    kw_span: Span,
125    doc: Vec<DocString>,
126    attrs: Vec<Attribute>,
127    vars: Vec<EnumVariant>,
128    fallback: Option<EnumFallback>,
129}
130
131impl InlineEnum {
132    pub(crate) fn parse(pair: Pair<Rule>) -> Self {
133        assert_eq!(pair.as_rule(), Rule::enum_inline);
134
135        let span = Span::from_pair(&pair);
136        let mut pairs = pair.into_inner();
137
138        let pair = pairs.next().unwrap();
139        let kw_span = Span::from_pair(&pair);
140
141        pairs.next().unwrap(); // Skip {.
142
143        let mut prelude = Prelude::inline(&mut pairs);
144        let mut vars = Vec::new();
145        let mut fallback = None;
146
147        for pair in pairs {
148            match pair.as_rule() {
149                Rule::enum_variant => vars.push(EnumVariant::parse(pair)),
150                Rule::enum_fallback => fallback = Some(EnumFallback::parse(pair)),
151                Rule::tok_cur_close => break,
152                _ => unreachable!(),
153            }
154        }
155
156        Self {
157            span,
158            kw_span,
159            doc: prelude.take_doc(),
160            attrs: prelude.take_attrs(),
161            vars,
162            fallback,
163        }
164    }
165
166    pub(crate) fn validate(&self, validate: &mut Validate) {
167        BrokenDocLink::validate(&self.doc, validate);
168        DuplicateEnumVariant::validate(&self.vars, self.fallback.as_ref(), None, validate);
169        DuplicateEnumVariantId::validate(&self.vars, None, validate);
170
171        EmptyEnum::validate(
172            &self.vars,
173            self.fallback.as_ref(),
174            self.span,
175            None,
176            validate,
177        );
178
179        for var in &self.vars {
180            var.validate(validate);
181        }
182
183        if let Some(ref fallback) = self.fallback {
184            fallback.validate(validate);
185        }
186    }
187
188    pub fn span(&self) -> Span {
189        self.span
190    }
191
192    pub fn keyword_span(&self) -> Span {
193        self.kw_span
194    }
195
196    pub fn doc(&self) -> &[DocString] {
197        &self.doc
198    }
199
200    pub fn attributes(&self) -> &[Attribute] {
201        &self.attrs
202    }
203
204    pub fn variants(&self) -> &[EnumVariant] {
205        &self.vars
206    }
207
208    pub fn fallback(&self) -> Option<&EnumFallback> {
209        self.fallback.as_ref()
210    }
211}
212
213#[derive(Debug, Clone)]
214pub struct EnumVariant {
215    span: Span,
216    comment: Vec<Comment>,
217    doc: Vec<DocString>,
218    name: Ident,
219    id: LitInt,
220    var_type: Option<TypeName>,
221}
222
223impl EnumVariant {
224    fn parse(pair: Pair<Rule>) -> Self {
225        assert_eq!(pair.as_rule(), Rule::enum_variant);
226
227        let span = Span::from_pair(&pair);
228        let mut pairs = pair.into_inner();
229        let mut prelude = Prelude::regular(&mut pairs);
230
231        let pair = pairs.next().unwrap();
232        let name = Ident::parse(pair);
233
234        pairs.next().unwrap(); // Skip @.
235
236        let pair = pairs.next().unwrap();
237        let id = LitInt::parse(pair);
238
239        let pair = pairs.next().unwrap();
240        let var_type = match pair.as_rule() {
241            Rule::tok_eq => {
242                let pair = pairs.next().unwrap();
243                Some(TypeName::parse(pair))
244            }
245
246            Rule::tok_term => None,
247            _ => unreachable!(),
248        };
249
250        Self {
251            span,
252            comment: prelude.take_comment(),
253            doc: prelude.take_doc(),
254            name,
255            id,
256            var_type,
257        }
258    }
259
260    fn validate(&self, validate: &mut Validate) {
261        BrokenDocLink::validate(&self.doc, validate);
262        InvalidEnumVariantId::validate(self, validate);
263        NonCamelCaseEnumVariant::validate(&self.name, validate);
264
265        self.name.validate(true, validate);
266
267        if let Some(ref var_type) = self.var_type {
268            var_type.validate(false, validate);
269        }
270    }
271
272    pub fn span(&self) -> Span {
273        self.span
274    }
275
276    pub fn comment(&self) -> &[Comment] {
277        &self.comment
278    }
279
280    pub fn doc(&self) -> &[DocString] {
281        &self.doc
282    }
283
284    pub fn name(&self) -> &Ident {
285        &self.name
286    }
287
288    pub fn id(&self) -> &LitInt {
289        &self.id
290    }
291
292    pub fn variant_type(&self) -> Option<&TypeName> {
293        self.var_type.as_ref()
294    }
295}
296
297#[derive(Debug, Clone)]
298pub struct EnumFallback {
299    span: Span,
300    comment: Vec<Comment>,
301    doc: Vec<DocString>,
302    name: Ident,
303}
304
305impl EnumFallback {
306    pub(crate) fn parse(pair: Pair<Rule>) -> Self {
307        assert_eq!(pair.as_rule(), Rule::enum_fallback);
308
309        let span = Span::from_pair(&pair);
310        let mut pairs = pair.into_inner();
311        let mut prelude = Prelude::regular(&mut pairs);
312
313        Self {
314            span,
315            comment: prelude.take_comment(),
316            doc: prelude.take_doc(),
317            name: Ident::parse(pairs.next().unwrap()),
318        }
319    }
320
321    pub(crate) fn validate(&self, validate: &mut Validate) {
322        BrokenDocLink::validate(&self.doc, validate);
323        NonCamelCaseEnumVariant::validate(&self.name, validate);
324
325        self.name.validate(true, validate);
326    }
327
328    pub fn span(&self) -> Span {
329        self.span
330    }
331
332    pub fn comment(&self) -> &[Comment] {
333        &self.comment
334    }
335
336    pub fn doc(&self) -> &[DocString] {
337        &self.doc
338    }
339
340    pub fn name(&self) -> &Ident {
341        &self.name
342    }
343}