sdml_core/model/definitions/
entities.rs

1use crate::load::ModuleLoader;
2use crate::model::References;
3use crate::model::{
4    annotations::Annotation,
5    check::Validate,
6    definitions::HasMembers,
7    identifiers::{Identifier, IdentifierReference},
8    members::Member,
9    modules::Module,
10    Span,
11};
12use crate::store::ModuleStore;
13use sdml_errors::diagnostics::functions::IdentifierCaseConvention;
14use std::{collections::HashSet, fmt::Debug};
15
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18
19// ------------------------------------------------------------------------------------------------
20// Public Types ❱ Type Definitions ❱ Entities
21// ------------------------------------------------------------------------------------------------
22
23/// Corresponds to the grammar rule `entity_def`.
24#[derive(Clone, Debug)]
25#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
26pub struct EntityDef {
27    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
28    span: Option<Box<Span>>,
29    name: Identifier,
30    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
31    body: Option<EntityBody>,
32}
33
34/// Corresponds to the grammar rule `entity_body`.
35#[derive(Clone, Debug)]
36#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
37pub struct EntityBody {
38    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
39    span: Option<Box<Span>>,
40    identity: Member,
41    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
42    annotations: Vec<Annotation>,
43    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
44    members: Vec<Member>,
45}
46
47// ------------------------------------------------------------------------------------------------
48// Implementations ❱ Type Definitions ❱ Entities
49// ------------------------------------------------------------------------------------------------
50
51impl_has_name_for!(EntityDef);
52
53impl_has_optional_body_for!(EntityDef, EntityBody);
54
55impl_has_source_span_for!(EntityDef);
56
57impl_references_for!(EntityDef => delegate optional body);
58
59impl_annotation_builder!(EntityDef, optional body);
60
61impl_maybe_incomplete_for!(EntityDef);
62
63impl Validate for EntityDef {
64    fn validate(
65        &self,
66        top: &Module,
67        cache: &impl ModuleStore,
68        loader: &impl ModuleLoader,
69        check_constraints: bool,
70    ) {
71        self.name
72            .validate(top, loader, Some(IdentifierCaseConvention::TypeDefinition));
73        if let Some(body) = &self.body {
74            body.validate(top, cache, loader, check_constraints);
75        }
76    }
77}
78
79impl EntityDef {
80    // --------------------------------------------------------------------------------------------
81    // EntityDef :: Constructors
82    // --------------------------------------------------------------------------------------------
83
84    pub const fn new(name: Identifier) -> Self {
85        Self {
86            span: None,
87            name,
88            body: None,
89        }
90    }
91}
92
93// ------------------------------------------------------------------------------------------------
94
95impl_has_annotations_for!(EntityBody);
96
97impl_has_members_for!(EntityBody);
98
99impl_has_source_span_for!(EntityBody);
100
101impl_maybe_incomplete_for!(EntityBody; over members);
102
103impl Validate for EntityBody {
104    fn validate(
105        &self,
106        top: &Module,
107        cache: &impl ModuleStore,
108        loader: &impl ModuleLoader,
109        check_constraints: bool,
110    ) {
111        self.identity
112            .validate(top, cache, loader, check_constraints);
113        for annotation in &self.annotations {
114            annotation.validate(top, cache, loader, check_constraints);
115        }
116        for member in &self.members {
117            member.validate(top, cache, loader, check_constraints);
118        }
119    }
120}
121
122impl References for EntityBody {
123    fn referenced_annotations<'a>(&'a self, names: &mut HashSet<&'a IdentifierReference>) {
124        self.members().for_each(|m| m.referenced_annotations(names))
125    }
126
127    fn referenced_types<'a>(&'a self, names: &mut HashSet<&'a IdentifierReference>) {
128        self.members().for_each(|m| m.referenced_types(names))
129    }
130}
131
132impl EntityBody {
133    // --------------------------------------------------------------------------------------------
134    // Constructors
135    // --------------------------------------------------------------------------------------------
136
137    pub fn new(identity: Member) -> Self {
138        Self {
139            span: None,
140            identity,
141            annotations: Default::default(),
142            members: Default::default(),
143        }
144    }
145
146    // --------------------------------------------------------------------------------------------
147    // Fields
148    // --------------------------------------------------------------------------------------------
149
150    get_and_set!(pub identity, set_identity => Member);
151}