sdml_core/model/definitions/
structures.rs

1use crate::model::{
2    annotations::{Annotation, HasAnnotations},
3    check::Validate,
4    definitions::HasMembers,
5    identifiers::{Identifier, IdentifierReference},
6    members::Member,
7    References, Span,
8};
9use std::{collections::HashSet, fmt::Debug};
10
11use sdml_errors::diagnostics::functions::IdentifierCaseConvention;
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15// ------------------------------------------------------------------------------------------------
16// Public Types ❱ Type Definitions ❱ Structures
17// ------------------------------------------------------------------------------------------------
18
19/// Corresponds to the grammar rule `structure_def`.
20#[derive(Clone, Debug)]
21#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
22pub struct StructureDef {
23    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
24    span: Option<Box<Span>>,
25    name: Identifier,
26    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
27    body: Option<StructureBody>,
28}
29
30/// Corresponds to the grammar rule `structure_body`.
31#[derive(Clone, Debug, Default)]
32#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
33pub struct StructureBody {
34    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
35    span: Option<Box<Span>>,
36    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
37    annotations: Vec<Annotation>,
38    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
39    members: Vec<Member>,
40}
41
42// ------------------------------------------------------------------------------------------------
43// Public Types ❱ Type Definitions ❱ Structures
44// ------------------------------------------------------------------------------------------------
45
46impl_has_name_for!(StructureDef);
47
48impl_has_optional_body_for!(StructureDef, StructureBody);
49
50impl_has_source_span_for!(StructureDef);
51
52impl_references_for!(StructureDef => delegate optional body);
53
54impl_annotation_builder!(StructureDef, optional body);
55
56impl_maybe_incomplete_for!(StructureDef);
57
58impl Validate for StructureDef {
59    fn validate(
60        &self,
61        top: &crate::model::modules::Module,
62        cache: &impl crate::store::ModuleStore,
63        loader: &impl crate::load::ModuleLoader,
64        check_constraints: bool,
65    ) {
66        self.name
67            .validate(top, loader, Some(IdentifierCaseConvention::TypeDefinition));
68        if let Some(body) = &self.body {
69            body.validate(top, cache, loader, check_constraints);
70        }
71    }
72}
73
74impl StructureDef {
75    // --------------------------------------------------------------------------------------------
76    // Constructors
77    // --------------------------------------------------------------------------------------------
78
79    pub fn new(name: Identifier) -> Self {
80        Self {
81            span: None,
82            name,
83            body: None,
84        }
85    }
86}
87
88// ------------------------------------------------------------------------------------------------
89
90impl_has_annotations_for!(StructureBody);
91
92impl_has_members_for!(StructureBody);
93
94impl_has_source_span_for!(StructureBody);
95
96impl_maybe_incomplete_for!(StructureBody; over members);
97
98impl_validate_for_annotations_and_members!(StructureBody);
99
100impl References for StructureBody {
101    fn referenced_types<'a>(&'a self, names: &mut HashSet<&'a IdentifierReference>) {
102        self.members().for_each(|m| m.referenced_types(names));
103    }
104
105    fn referenced_annotations<'a>(&'a self, names: &mut HashSet<&'a IdentifierReference>) {
106        self.members().for_each(|m| m.referenced_annotations(names));
107    }
108}