aldrin_parser/ast/
struct_def.rs

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