sdml_core/model/members/
mod.rs

1/*!
2Provide the Rust types that implement *member*-related components of the SDML Grammar.
3*/
4
5use crate::{
6    load::ModuleLoader,
7    model::{
8        annotations::{AnnotationBuilder, AnnotationOnlyBody, AnnotationProperty, HasAnnotations},
9        check::{find_definition, MaybeIncomplete, Validate},
10        definitions::Definition,
11        identifiers::{Identifier, IdentifierReference},
12        modules::Module,
13        values::Value,
14        HasName, HasOptionalBody, HasSourceSpan, References, Span,
15    },
16    store::ModuleStore,
17};
18use sdml_errors::diagnostics::functions::{
19    property_reference_not_property, type_definition_not_found, IdentifierCaseConvention,
20};
21use std::{collections::BTreeSet, fmt::Debug};
22use tracing::error;
23
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Serialize};
26
27// ------------------------------------------------------------------------------------------------
28// Public Types ❱ Members ❱ Member
29// ------------------------------------------------------------------------------------------------
30
31/// Corresponds to the grammar rules `member` and `entity_identity`.
32#[derive(Clone, Debug)]
33#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
34pub struct Member {
35    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
36    span: Option<Span>,
37    kind: MemberKind,
38}
39
40#[derive(Clone, Debug)]
41#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
42pub enum MemberKind {
43    Reference(IdentifierReference),
44    Definition(MemberDef),
45}
46
47/// Corresponds to the definition component within grammar rule `by_reference_member`.
48#[derive(Clone, Debug)]
49#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
50pub struct MemberDef {
51    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
52    span: Option<Span>,
53    name: Identifier,
54    target_cardinality: Cardinality,
55    target_type: TypeReference,
56    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
57    body: Option<AnnotationOnlyBody>,
58}
59
60// ------------------------------------------------------------------------------------------------
61// Implementations ❱ Members ❱ Member
62// ------------------------------------------------------------------------------------------------
63
64impl<T> From<T> for Member
65where
66    T: Into<MemberKind>,
67{
68    fn from(kind: T) -> Self {
69        Self {
70            span: Default::default(),
71            kind: kind.into(),
72        }
73    }
74}
75
76impl HasSourceSpan for Member {
77    fn with_source_span(self, span: Span) -> Self {
78        let mut self_mut = self;
79        self_mut.span = Some(span);
80        self_mut
81    }
82
83    fn source_span(&self) -> Option<&Span> {
84        self.span.as_ref()
85    }
86
87    fn set_source_span(&mut self, span: Span) {
88        self.span = Some(span);
89    }
90
91    fn unset_source_span(&mut self) {
92        self.span = None;
93    }
94}
95
96impl MaybeIncomplete for Member {
97    fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
98        match &self.kind {
99            MemberKind::Reference(name) => {
100                if let Some(defn) = find_definition(name, top, cache) {
101                    if matches!(defn, Definition::Property(_)) {
102                        defn.is_incomplete(top, cache)
103                    } else {
104                        error!("Member property reference not a property");
105                        false
106                    }
107                } else {
108                    error!("Member property reference not found");
109                    false
110                }
111            }
112            MemberKind::Definition(v) => v.is_incomplete(top, cache),
113        }
114    }
115}
116
117impl Validate for Member {
118    fn validate(
119        &self,
120        top: &Module,
121        cache: &impl ModuleStore,
122        loader: &impl ModuleLoader,
123        check_constraints: bool,
124    ) {
125        match &self.kind {
126            MemberKind::Reference(name) => {
127                if let Some(defn) = find_definition(name, top, cache) {
128                    if !matches!(defn, Definition::Property(_)) {
129                        error!("Member property reference not a property");
130                        loader
131                            .report(&property_reference_not_property(
132                                top.file_id().copied().unwrap_or_default(),
133                                name.source_span().map(|span| span.byte_range()),
134                                name,
135                            ))
136                            .unwrap()
137                    }
138                } else {
139                    error!("Member property reference not found");
140                    loader
141                        .report(&type_definition_not_found(
142                            top.file_id().copied().unwrap_or_default(),
143                            name.source_span().map(|span| span.byte_range()),
144                            name,
145                        ))
146                        .unwrap()
147                }
148            }
149            MemberKind::Definition(v) => {
150                v.validate(top, cache, loader, check_constraints);
151            }
152        }
153        validate_is_incomplete_named(self, self.name(), top, cache, loader);
154    }
155}
156
157impl References for Member {
158    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
159        match &self.kind {
160            MemberKind::Reference(v) => {
161                names.insert(v);
162            }
163            MemberKind::Definition(v) => v.referenced_annotations(names),
164        }
165    }
166
167    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
168        match &self.kind {
169            MemberKind::Reference(v) => {
170                names.insert(v);
171            }
172            MemberKind::Definition(v) => v.referenced_types(names),
173        }
174    }
175}
176
177impl Member {
178    // --------------------------------------------------------------------------------------------
179    // Constructors
180    // --------------------------------------------------------------------------------------------
181
182    pub const fn new_reference(in_property: IdentifierReference) -> Self {
183        Self {
184            span: None,
185            kind: MemberKind::Reference(in_property),
186        }
187    }
188
189    pub const fn new_definition(definition: MemberDef) -> Self {
190        Self {
191            span: None,
192            kind: MemberKind::Definition(definition),
193        }
194    }
195
196    // --------------------------------------------------------------------------------------------
197    // Variants
198    // --------------------------------------------------------------------------------------------
199
200    pub const fn kind(&self) -> &MemberKind {
201        &self.kind
202    }
203
204    #[inline(always)]
205    pub const fn is_definition(&self) -> bool {
206        self.kind.is_definition()
207    }
208
209    #[inline(always)]
210    pub const fn as_definition(&self) -> Option<&MemberDef> {
211        self.kind.as_definition()
212    }
213
214    #[inline(always)]
215    pub const fn is_property_reference(&self) -> bool {
216        self.kind.is_property_reference()
217    }
218
219    #[inline(always)]
220    pub const fn as_property_reference(&self) -> Option<&IdentifierReference> {
221        self.kind.as_property_reference()
222    }
223
224    // --------------------------------------------------------------------------------------------
225    // Delegated
226    // --------------------------------------------------------------------------------------------
227
228    pub fn name(&self) -> &Identifier {
229        match self.kind() {
230            MemberKind::Reference(v) => v.member(),
231            MemberKind::Definition(defn) => defn.name(),
232        }
233    }
234
235    pub fn resolve_target_type(
236        &self,
237        module: &Module,
238        cache: &impl ModuleStore,
239    ) -> Option<TypeReference> {
240        match self.kind() {
241            MemberKind::Reference(v) => {
242                if let Some(Definition::Property(property)) = cache.resolve_or_in(v, module.name())
243                {
244                    Some(property.member_def().target_type().clone())
245                } else {
246                    None
247                }
248            }
249            MemberKind::Definition(defn) => Some(defn.target_type().clone()),
250        }
251    }
252
253    pub fn resolve_target_cardinality(
254        &self,
255        module: &Module,
256        cache: &impl ModuleStore,
257    ) -> Option<Cardinality> {
258        match self.kind() {
259            MemberKind::Reference(v) => {
260                if let Some(Definition::Property(property)) = cache.resolve_or_in(v, module.name())
261                {
262                    Some(property.member_def().target_cardinality().clone())
263                } else {
264                    None
265                }
266            }
267            MemberKind::Definition(defn) => Some(defn.target_cardinality().clone()),
268        }
269    }
270}
271
272// ------------------------------------------------------------------------------------------------
273// Implementations ❱ Members ❱ MemberKind
274// ------------------------------------------------------------------------------------------------
275
276impl From<MemberDef> for MemberKind {
277    fn from(value: MemberDef) -> Self {
278        Self::Definition(value)
279    }
280}
281
282impl From<IdentifierReference> for MemberKind {
283    fn from(value: IdentifierReference) -> Self {
284        Self::Reference(value)
285    }
286}
287
288impl MemberKind {
289    // --------------------------------------------------------------------------------------------
290    // Variants
291    // --------------------------------------------------------------------------------------------
292
293    pub const fn is_definition(&self) -> bool {
294        matches!(self, Self::Definition(_))
295    }
296
297    pub const fn as_definition(&self) -> Option<&MemberDef> {
298        match self {
299            Self::Definition(v) => Some(v),
300            _ => None,
301        }
302    }
303
304    pub const fn is_property_reference(&self) -> bool {
305        matches!(self, Self::Reference(_))
306    }
307
308    pub const fn as_property_reference(&self) -> Option<&IdentifierReference> {
309        match self {
310            Self::Reference(v) => Some(v),
311            _ => None,
312        }
313    }
314}
315
316// ------------------------------------------------------------------------------------------------
317// Implementations ❱ Members ❱ MemberDef
318// ------------------------------------------------------------------------------------------------
319
320impl HasName for MemberDef {
321    fn name(&self) -> &Identifier {
322        &self.name
323    }
324
325    fn set_name(&mut self, name: Identifier) {
326        self.name = name;
327    }
328}
329
330impl HasCardinality for MemberDef {
331    fn target_cardinality(&self) -> &Cardinality {
332        &self.target_cardinality
333    }
334
335    fn set_target_cardinality(&mut self, target_cardinality: Cardinality) {
336        self.target_cardinality = target_cardinality;
337    }
338}
339
340impl HasOptionalBody for MemberDef {
341    type Body = AnnotationOnlyBody;
342
343    fn body(&self) -> Option<&Self::Body> {
344        self.body.as_ref()
345    }
346
347    fn body_mut(&mut self) -> Option<&mut Self::Body> {
348        self.body.as_mut()
349    }
350
351    fn set_body(&mut self, body: Self::Body) {
352        self.body = Some(body);
353    }
354
355    fn unset_body(&mut self) {
356        self.body = None;
357    }
358}
359
360impl HasSourceSpan for MemberDef {
361    fn with_source_span(self, span: Span) -> Self {
362        let mut self_mut = self;
363        self_mut.span = Some(span);
364        self_mut
365    }
366
367    fn source_span(&self) -> Option<&Span> {
368        self.span.as_ref()
369    }
370
371    fn set_source_span(&mut self, span: Span) {
372        self.span = Some(span);
373    }
374
375    fn unset_source_span(&mut self) {
376        self.span = None;
377    }
378}
379
380impl HasType for MemberDef {
381    fn target_type(&self) -> &TypeReference {
382        &self.target_type
383    }
384
385    fn set_target_type(&mut self, target_type: TypeReference) {
386        self.target_type = target_type;
387    }
388}
389
390impl AnnotationBuilder for MemberDef {
391    fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
392    where
393        Self: Sized,
394        I: Into<IdentifierReference>,
395        V: Into<Value>,
396    {
397        let mut self_mut = self;
398        if let Some(ref mut inner) = self_mut.body {
399            inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
400        }
401        self_mut
402    }
403}
404
405impl References for MemberDef {
406    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
407        self.body
408            .as_ref()
409            .map(|b| b.referenced_annotations(names))
410            .unwrap_or_default()
411    }
412
413    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
414        self.target_type.referenced_types(names);
415    }
416}
417
418impl MaybeIncomplete for MemberDef {
419    fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
420        self.target_type.is_incomplete(top, cache)
421    }
422}
423
424impl Validate for MemberDef {
425    fn validate(
426        &self,
427        top: &Module,
428        cache: &impl ModuleStore,
429        loader: &impl ModuleLoader,
430        check_constraints: bool,
431    ) {
432        self.name()
433            .validate(top, loader, Some(IdentifierCaseConvention::Member));
434        self.target_type()
435            .validate(top, cache, loader, check_constraints);
436        self.target_cardinality()
437            .validate(top, cache, loader, check_constraints);
438    }
439}
440
441impl MemberDef {
442    // --------------------------------------------------------------------------------------------
443    // Constructors
444    // --------------------------------------------------------------------------------------------
445
446    pub fn new<T>(name: Identifier, target_type: T) -> Self
447    where
448        T: Into<TypeReference>,
449    {
450        Self {
451            span: None,
452            name,
453            target_type: target_type.into(),
454            target_cardinality: Cardinality::one(),
455            body: None,
456        }
457    }
458
459    pub const fn new_unknown(name: Identifier) -> Self {
460        Self {
461            span: None,
462            name,
463            target_type: TypeReference::Unknown,
464            target_cardinality: Cardinality::one(),
465            body: None,
466        }
467    }
468
469    pub fn with_target_type(self, target_type: TypeReference) -> Self {
470        let mut self_mut = self;
471        self_mut.target_type = target_type;
472        self_mut
473    }
474
475    pub fn with_target_cardinality(self, target_cardinality: Cardinality) -> Self {
476        let mut self_mut = self;
477        self_mut.target_cardinality = target_cardinality;
478        self_mut
479    }
480
481    pub fn with_body(self, body: AnnotationOnlyBody) -> Self {
482        let mut self_mut = self;
483        self_mut.body = Some(body);
484        self_mut
485    }
486
487    // --------------------------------------------------------------------------------------------
488    // Fields
489    // --------------------------------------------------------------------------------------------
490
491    pub const fn target_type(&self) -> &TypeReference {
492        &self.target_type
493    }
494
495    pub fn set_target_type(&mut self, target_type: TypeReference) {
496        self.target_type = target_type;
497    }
498
499    pub const fn target_cardinality(&self) -> &Cardinality {
500        &self.target_cardinality
501    }
502
503    pub fn set_target_cardinality(&mut self, target_cardinality: Cardinality) {
504        self.target_cardinality = target_cardinality;
505    }
506}
507
508// ------------------------------------------------------------------------------------------------
509// Modules
510// ------------------------------------------------------------------------------------------------
511
512mod cardinality;
513pub use cardinality::{
514    Cardinality, CardinalityRange, HasCardinality, Ordering, PseudoSequenceType, Uniqueness,
515    DEFAULT_CARDINALITY, DEFAULT_CARDINALITY_RANGE, TYPE_BAG_CARDINALITY, TYPE_LIST_CARDINALITY,
516    TYPE_MAYBE_CARDINALITY, TYPE_ORDERED_SET_CARDINALITY, TYPE_SET_CARDINALITY,
517};
518
519mod types;
520pub use types::{HasType, MappingType, TypeReference};
521
522use super::check::validate_is_incomplete_named;