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(); let pair = pairs.next().unwrap();
33 let name = Ident::parse(pair);
34
35 pairs.next().unwrap(); 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(); 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(); 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}