sdml_core/model/definitions/
dimensions.rs

1use crate::{
2    config::is_builtin_type_name,
3    load::ModuleLoader,
4    model::{
5        annotations::{
6            Annotation, AnnotationBuilder, AnnotationOnlyBody, AnnotationProperty, HasAnnotations,
7        },
8        check::{find_definition, validate_multiple_method_duplicates, MaybeIncomplete, Validate},
9        definitions::HasMultiMembers,
10        identifiers::{Identifier, IdentifierReference},
11        members::Member,
12        modules::Module,
13        values::Value,
14        HasName, HasOptionalBody, HasSourceSpan, References, Span,
15    },
16    store::ModuleStore,
17};
18use sdml_errors::diagnostics::functions::{
19    dimension_parent_not_entity, source_entity_missing_member, source_entity_not_entity,
20    type_definition_not_found, IdentifierCaseConvention,
21};
22use std::{
23    collections::{BTreeMap, BTreeSet},
24    fmt::Debug,
25};
26
27#[cfg(feature = "serde")]
28use serde::{Deserialize, Serialize};
29
30// ------------------------------------------------------------------------------------------------
31// Public Types ❱ Definitions ❱ Dimensions
32// ------------------------------------------------------------------------------------------------
33
34/// Corresponds to the grammar rule `dimension_def`.
35#[derive(Clone, Debug)]
36#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
37pub struct DimensionDef {
38    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
39    span: Option<Span>,
40    name: Identifier,
41    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
42    body: Option<DimensionBody>,
43}
44
45/// Corresponds to the grammar rule `dimension_body`.
46#[derive(Clone, Debug)]
47#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
48pub struct DimensionBody {
49    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
50    span: Option<Span>,
51    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
52    annotations: Vec<Annotation>,
53    identity: DimensionIdentity,
54    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "BTreeMap::is_empty"))]
55    parents: BTreeMap<Identifier, DimensionParent>,
56    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "BTreeMap::is_empty"))]
57    members: BTreeMap<Identifier, Member>,
58}
59
60/// Corresponds to the anonymous grammar rule in `dimension_body`.
61#[derive(Clone, Debug)]
62#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
63pub enum DimensionIdentity {
64    Source(SourceEntity),
65    Identity(Member),
66}
67
68/// Corresponds to the grammar rule `dimension_parent`.
69#[derive(Clone, Debug)]
70#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
71pub struct DimensionParent {
72    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
73    span: Option<Span>,
74    name: Identifier,
75    target_entity: IdentifierReference,
76    body: Option<AnnotationOnlyBody>,
77}
78
79/// Corresponds to the grammar rule `source_entity`.
80#[derive(Clone, Debug)]
81#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
82pub struct SourceEntity {
83    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
84    span: Option<Span>,
85    target_entity: IdentifierReference,
86    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
87    with_members: Vec<Identifier>,
88}
89
90// ------------------------------------------------------------------------------------------------
91// Implementations ❱ Definitions ❱ DimensionDef
92// ------------------------------------------------------------------------------------------------
93
94impl HasName for DimensionDef {
95    fn name(&self) -> &Identifier {
96        &self.name
97    }
98
99    fn set_name(&mut self, name: Identifier) {
100        self.name = name;
101    }
102}
103
104impl HasOptionalBody for DimensionDef {
105    type Body = DimensionBody;
106
107    fn body(&self) -> Option<&Self::Body> {
108        self.body.as_ref()
109    }
110
111    fn body_mut(&mut self) -> Option<&mut Self::Body> {
112        self.body.as_mut()
113    }
114
115    fn set_body(&mut self, body: Self::Body) {
116        self.body = Some(body);
117    }
118
119    fn unset_body(&mut self) {
120        self.body = None;
121    }
122}
123
124impl HasSourceSpan for DimensionDef {
125    fn with_source_span(self, span: Span) -> Self {
126        let mut self_mut = self;
127        self_mut.span = Some(span);
128        self_mut
129    }
130
131    fn source_span(&self) -> Option<&Span> {
132        self.span.as_ref()
133    }
134
135    fn set_source_span(&mut self, span: Span) {
136        self.span = Some(span);
137    }
138
139    fn unset_source_span(&mut self) {
140        self.span = None;
141    }
142}
143
144impl References for DimensionDef {
145    fn referenced_annotations<'a>(
146        &'a self,
147        names: &mut ::std::collections::BTreeSet<&'a IdentifierReference>,
148    ) {
149        if let Some(inner) = &self.body {
150            inner.referenced_annotations(names);
151        }
152    }
153
154    fn referenced_types<'a>(
155        &'a self,
156        names: &mut ::std::collections::BTreeSet<&'a IdentifierReference>,
157    ) {
158        if let Some(inner) = &self.body {
159            inner.referenced_types(names);
160        }
161    }
162}
163
164impl AnnotationBuilder for DimensionDef {
165    fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
166    where
167        Self: Sized,
168        I: Into<IdentifierReference>,
169        V: Into<Value>,
170    {
171        let mut self_mut = self;
172        if let Some(ref mut inner) = self_mut.body {
173            inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
174        }
175        self_mut
176    }
177}
178
179impl MaybeIncomplete for DimensionDef {
180    fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
181        if let Some(body) = &self.body {
182            body.is_incomplete(top, cache)
183        } else {
184            true
185        }
186    }
187}
188
189impl Validate for DimensionDef {
190    fn validate(
191        &self,
192        top: &Module,
193        cache: &impl ModuleStore,
194        loader: &impl ModuleLoader,
195        check_constraints: bool,
196    ) {
197        self.name
198            .validate(top, loader, Some(IdentifierCaseConvention::TypeDefinition));
199        if let Some(body) = &self.body {
200            body.validate(top, cache, loader, check_constraints);
201        }
202    }
203}
204
205impl DimensionDef {
206    // --------------------------------------------------------------------------------------------
207    // Constructors
208    // --------------------------------------------------------------------------------------------
209
210    pub fn new(name: Identifier) -> Self {
211        Self {
212            span: None,
213            name,
214            body: None,
215        }
216    }
217
218    pub fn with_body(self, body: DimensionBody) -> Self {
219        let mut self_mut = self;
220        self_mut.body = Some(body);
221        self_mut
222    }
223}
224
225// ------------------------------------------------------------------------------------------------
226// Implementations ❱ Definitions ❱ DimensionBody
227// ------------------------------------------------------------------------------------------------
228
229impl HasAnnotations for DimensionBody {
230    fn has_annotations(&self) -> bool {
231        !self.annotations.is_empty()
232    }
233
234    fn annotation_count(&self) -> usize {
235        self.annotations.len()
236    }
237
238    fn annotations(&self) -> impl Iterator<Item = &Annotation> {
239        self.annotations.iter()
240    }
241
242    fn annotations_mut(&mut self) -> impl Iterator<Item = &mut Annotation> {
243        self.annotations.iter_mut()
244    }
245
246    fn add_to_annotations<I>(&mut self, value: I)
247    where
248        I: Into<Annotation>,
249    {
250        self.annotations.push(value.into())
251    }
252
253    fn extend_annotations<I>(&mut self, extension: I)
254    where
255        I: IntoIterator<Item = Annotation>,
256    {
257        self.annotations.extend(extension)
258    }
259}
260
261impl HasSourceSpan for DimensionBody {
262    fn with_source_span(self, span: Span) -> Self {
263        let mut self_mut = self;
264        self_mut.span = Some(span);
265        self_mut
266    }
267
268    fn source_span(&self) -> Option<&Span> {
269        self.span.as_ref()
270    }
271
272    fn set_source_span(&mut self, span: Span) {
273        self.span = Some(span);
274    }
275
276    fn unset_source_span(&mut self) {
277        self.span = None;
278    }
279}
280
281impl MaybeIncomplete for DimensionBody {
282    fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
283        self.identity().is_incomplete(top, cache)
284            || self.members().any(|elem| elem.is_incomplete(top, cache))
285    }
286}
287
288impl Validate for DimensionBody {
289    fn validate(
290        &self,
291        top: &Module,
292        cache: &impl ModuleStore,
293        loader: &impl ModuleLoader,
294        check_constraints: bool,
295    ) {
296        validate_multiple_method_duplicates(self, top, cache, loader);
297
298        self.identity()
299            .validate(top, cache, loader, check_constraints);
300        self.annotations()
301            .for_each(|m| m.validate(top, cache, loader, check_constraints));
302        self.parents()
303            .for_each(|m| m.validate(top, cache, loader, check_constraints));
304        self.members()
305            .for_each(|m| m.validate(top, cache, loader, check_constraints));
306    }
307}
308
309impl References for DimensionBody {
310    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
311        self.identity().referenced_types(names);
312        self.parents().for_each(|m| m.referenced_types(names));
313        self.members().for_each(|m| m.referenced_types(names));
314    }
315
316    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
317        self.members().for_each(|m| m.referenced_annotations(names));
318    }
319}
320
321impl HasMultiMembers for DimensionBody {
322    fn has_any_members(&self) -> bool {
323        !(self.has_identity() || self.has_parents() || self.has_members())
324    }
325
326    fn contains_any_member(&self, name: &Identifier) -> bool {
327        self.contains_identity(name) || self.contains_parent(name) || self.contains_member(name)
328    }
329
330    fn all_member_count(&self) -> usize {
331        self.identity_count() + self.parent_count() + self.members.len()
332    }
333
334    fn all_member_names(&self) -> impl Iterator<Item = &Identifier> {
335        self.identity_names()
336            .chain(self.parent_names().chain(self.member_names()))
337    }
338}
339
340impl DimensionBody {
341    // --------------------------------------------------------------------------------------------
342    // Constructors
343    // --------------------------------------------------------------------------------------------
344
345    pub fn new<E>(entity: E) -> Self
346    where
347        E: Into<DimensionIdentity>,
348    {
349        Self {
350            span: Default::default(),
351            annotations: Default::default(),
352            identity: entity.into(),
353            parents: Default::default(),
354            members: Default::default(),
355        }
356    }
357
358    pub fn with_members<I>(self, members: I) -> Self
359    where
360        I: IntoIterator<Item = Member>,
361    {
362        let mut self_mut = self;
363        self_mut.members = members
364            .into_iter()
365            .map(|mem| (mem.name().clone(), mem))
366            .collect();
367        self_mut
368    }
369
370    pub fn with_parents<I>(self, parents: I) -> Self
371    where
372        I: IntoIterator<Item = DimensionParent>,
373    {
374        let mut self_mut = self;
375        self_mut.parents = parents
376            .into_iter()
377            .map(|mem| (mem.name().clone(), mem))
378            .collect();
379        self_mut
380    }
381
382    // --------------------------------------------------------------------------------------------
383    // Fields
384    // --------------------------------------------------------------------------------------------
385
386    pub const fn identity(&self) -> &DimensionIdentity {
387        &self.identity
388    }
389
390    pub fn set_identity<T>(&mut self, identity: T)
391    where
392        T: Into<DimensionIdentity>,
393    {
394        self.identity = identity.into();
395    }
396
397    fn has_identity(&self) -> bool {
398        matches!(self.identity, DimensionIdentity::Identity(_))
399    }
400
401    fn identity_count(&self) -> usize {
402        match self.identity() {
403            DimensionIdentity::Source(src) => src.member_count(),
404            DimensionIdentity::Identity(_) => 1,
405        }
406    }
407
408    fn identity_names<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Identifier> + 'a> {
409        match self.identity() {
410            DimensionIdentity::Source(src) => Box::new(src.members()),
411            DimensionIdentity::Identity(id) => Box::new(std::iter::once(id.name())),
412        }
413    }
414
415    fn contains_identity(&self, name: &Identifier) -> bool {
416        match self.identity() {
417            DimensionIdentity::Source(src) => src.contains_member(name),
418            DimensionIdentity::Identity(id) => name == id.name(),
419        }
420    }
421
422    // --------------------------------------------------------------------------------------------
423    // Members
424    // --------------------------------------------------------------------------------------------
425
426    pub fn has_members(&self) -> bool {
427        !self.members.is_empty()
428    }
429
430    pub fn member_count(&self) -> usize {
431        self.members.len()
432    }
433
434    pub fn contains_member(&self, name: &Identifier) -> bool {
435        self.members.contains_key(name)
436    }
437
438    pub fn member(&self, name: &Identifier) -> Option<&Member> {
439        self.members.get(name)
440    }
441
442    pub fn member_mut(&mut self, name: &Identifier) -> Option<&mut Member> {
443        self.members.get_mut(name)
444    }
445
446    pub fn members(&self) -> impl Iterator<Item = &Member> {
447        self.members.values()
448    }
449
450    pub fn members_mut(&mut self) -> impl Iterator<Item = &mut Member> {
451        self.members.values_mut()
452    }
453
454    pub fn member_names(&self) -> impl Iterator<Item = &Identifier> {
455        self.members.keys()
456    }
457
458    pub fn add_to_members(&mut self, value: Member) -> Option<Member> {
459        self.members.insert(value.name().clone(), value)
460    }
461
462    pub fn extend_member<I>(&mut self, extension: I)
463    where
464        I: IntoIterator<Item = Member>,
465    {
466        self.members.extend(
467            extension
468                .into_iter()
469                .map(|elem| (elem.name().clone(), elem)),
470        )
471    }
472
473    // --------------------------------------------------------------------------------------------
474    // Parents
475    // --------------------------------------------------------------------------------------------
476
477    pub fn has_parents(&self) -> bool {
478        !self.parents.is_empty()
479    }
480
481    pub fn parent_count(&self) -> usize {
482        self.parents.len()
483    }
484
485    pub fn contains_parent(&self, name: &Identifier) -> bool {
486        self.parents.contains_key(name)
487    }
488
489    pub fn parent(&self, name: &Identifier) -> Option<&DimensionParent> {
490        self.parents.get(name)
491    }
492
493    pub fn parent_mut(&mut self, name: &Identifier) -> Option<&mut DimensionParent> {
494        self.parents.get_mut(name)
495    }
496
497    pub fn parents(&self) -> impl Iterator<Item = &DimensionParent> {
498        self.parents.values()
499    }
500
501    pub fn parents_mut(&mut self) -> impl Iterator<Item = &mut DimensionParent> {
502        self.parents.values_mut()
503    }
504
505    pub fn parent_names(&self) -> impl Iterator<Item = &Identifier> {
506        self.parents.keys()
507    }
508
509    pub fn add_to_parents(&mut self, value: DimensionParent) -> Option<DimensionParent> {
510        self.parents.insert(value.name().clone(), value)
511    }
512
513    pub fn extend_parents<I>(&mut self, extension: I)
514    where
515        I: IntoIterator<Item = DimensionParent>,
516    {
517        self.parents.extend(
518            extension
519                .into_iter()
520                .map(|elem| (elem.name().clone(), elem)),
521        )
522    }
523}
524
525// ------------------------------------------------------------------------------------------------
526// Implementations ❱ Definitions ❱ DimensionIdentity
527// ------------------------------------------------------------------------------------------------
528
529impl From<SourceEntity> for DimensionIdentity {
530    fn from(value: SourceEntity) -> Self {
531        Self::Source(value)
532    }
533}
534
535impl From<&SourceEntity> for DimensionIdentity {
536    fn from(value: &SourceEntity) -> Self {
537        Self::Source(value.clone())
538    }
539}
540
541impl From<Member> for DimensionIdentity {
542    fn from(value: Member) -> Self {
543        Self::Identity(value)
544    }
545}
546
547impl From<&Member> for DimensionIdentity {
548    fn from(value: &Member) -> Self {
549        Self::Identity(value.clone())
550    }
551}
552
553impl References for DimensionIdentity {
554    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
555        match self {
556            DimensionIdentity::Source(v) => v.referenced_types(names),
557            DimensionIdentity::Identity(v) => v.referenced_types(names),
558        }
559    }
560}
561
562impl MaybeIncomplete for DimensionIdentity {
563    fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
564        match self {
565            Self::Source(_) => false,
566            Self::Identity(member) => member.is_incomplete(top, cache),
567        }
568    }
569}
570
571impl Validate for DimensionIdentity {
572    fn validate(
573        &self,
574        top: &Module,
575        cache: &impl ModuleStore,
576        loader: &impl ModuleLoader,
577        check_constraints: bool,
578    ) {
579        match self {
580            Self::Source(src) => src.validate(top, cache, loader, check_constraints),
581            Self::Identity(member) => member.validate(top, cache, loader, check_constraints),
582        }
583    }
584}
585
586impl DimensionIdentity {
587    // --------------------------------------------------------------------------------------------
588    // Variants
589    // --------------------------------------------------------------------------------------------
590
591    pub const fn is_source_entity(&self) -> bool {
592        matches!(self, Self::Source(_))
593    }
594
595    pub const fn as_source_entity(&self) -> Option<&SourceEntity> {
596        match self {
597            Self::Source(v) => Some(v),
598            _ => None,
599        }
600    }
601
602    pub const fn is_identity_member(&self) -> bool {
603        matches!(self, Self::Identity(_))
604    }
605
606    pub const fn as_identity_member(&self) -> Option<&Member> {
607        match self {
608            Self::Identity(v) => Some(v),
609            _ => None,
610        }
611    }
612}
613
614// ------------------------------------------------------------------------------------------------
615// Implementations ❱ Definitions ❱ DimensionParent
616// ------------------------------------------------------------------------------------------------
617
618impl HasName for DimensionParent {
619    fn name(&self) -> &Identifier {
620        &self.name
621    }
622
623    fn set_name(&mut self, name: Identifier) {
624        self.name = name;
625    }
626}
627
628impl HasSourceSpan for DimensionParent {
629    fn with_source_span(self, span: Span) -> Self {
630        let mut self_mut = self;
631        self_mut.span = Some(span);
632        self_mut
633    }
634
635    fn source_span(&self) -> Option<&Span> {
636        self.span.as_ref()
637    }
638
639    fn set_source_span(&mut self, span: Span) {
640        self.span = Some(span);
641    }
642
643    fn unset_source_span(&mut self) {
644        self.span = None;
645    }
646}
647
648impl HasOptionalBody for DimensionParent {
649    type Body = AnnotationOnlyBody;
650
651    fn body(&self) -> Option<&Self::Body> {
652        self.body.as_ref()
653    }
654
655    fn body_mut(&mut self) -> Option<&mut Self::Body> {
656        self.body.as_mut()
657    }
658
659    fn set_body(&mut self, body: Self::Body) {
660        self.body = Some(body);
661    }
662
663    fn unset_body(&mut self) {
664        self.body = None;
665    }
666}
667
668impl References for DimensionParent {
669    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
670        names.insert(self.target_entity());
671    }
672}
673
674impl Validate for DimensionParent {
675    fn validate(
676        &self,
677        top: &Module,
678        cache: &impl ModuleStore,
679        loader: &impl ModuleLoader,
680        _: bool,
681    ) {
682        let name = self.target_entity();
683        if let Some(defn) = find_definition(name, top, cache) {
684            if !defn.is_entity() {
685                loader
686                    .report(&dimension_parent_not_entity(
687                        top.file_id().copied().unwrap_or_default(),
688                        name.source_span().as_ref().map(|span| (*span).into()),
689                        name,
690                    ))
691                    .unwrap();
692            }
693        } else if !name
694            .as_identifier()
695            .map(is_builtin_type_name)
696            .unwrap_or_default()
697        {
698            loader
699                .report(&type_definition_not_found(
700                    top.file_id().copied().unwrap_or_default(),
701                    name.source_span().as_ref().map(|span| (*span).into()),
702                    name,
703                ))
704                .unwrap();
705        } else {
706            loader
707                .report(&dimension_parent_not_entity(
708                    top.file_id().copied().unwrap_or_default(),
709                    name.source_span().as_ref().map(|span| (*span).into()),
710                    name,
711                ))
712                .unwrap();
713        }
714    }
715}
716
717impl DimensionParent {
718    // --------------------------------------------------------------------------------------------
719    // Constructors
720    // --------------------------------------------------------------------------------------------
721
722    pub fn new<I>(name: Identifier, target_entity: I) -> Self
723    where
724        I: Into<IdentifierReference>,
725    {
726        Self {
727            span: Default::default(),
728            name,
729            target_entity: target_entity.into(),
730            body: Default::default(),
731        }
732    }
733
734    pub fn with_body(self, body: AnnotationOnlyBody) -> Self {
735        let mut self_mut = self;
736        self_mut.body = Some(body);
737        self_mut
738    }
739
740    // --------------------------------------------------------------------------------------------
741    // Fields
742    // --------------------------------------------------------------------------------------------
743
744    pub const fn target_entity(&self) -> &IdentifierReference {
745        &self.target_entity
746    }
747
748    pub fn set_target_entity<T>(&mut self, target_entity: T)
749    where
750        T: Into<IdentifierReference>,
751    {
752        self.target_entity = target_entity.into();
753    }
754}
755
756// ------------------------------------------------------------------------------------------------
757// Implementations ❱ Definitions ❱ SourceEntity
758// ------------------------------------------------------------------------------------------------
759
760impl From<IdentifierReference> for SourceEntity {
761    fn from(value: IdentifierReference) -> Self {
762        Self::new(value)
763    }
764}
765
766impl From<&IdentifierReference> for SourceEntity {
767    fn from(value: &IdentifierReference) -> Self {
768        Self::new(value.clone())
769    }
770}
771
772impl HasSourceSpan for SourceEntity {
773    fn with_source_span(self, span: Span) -> Self {
774        let mut self_mut = self;
775        self_mut.span = Some(span);
776        self_mut
777    }
778
779    fn source_span(&self) -> Option<&Span> {
780        self.span.as_ref()
781    }
782
783    fn set_source_span(&mut self, span: Span) {
784        self.span = Some(span);
785    }
786
787    fn unset_source_span(&mut self) {
788        self.span = None;
789    }
790}
791
792impl Validate for SourceEntity {
793    fn validate(
794        &self,
795        top: &Module,
796        cache: &impl ModuleStore,
797        loader: &impl ModuleLoader,
798        _check_constraints: bool,
799    ) {
800        let name = self.target_entity();
801        if let Some(defn) = find_definition(name, top, cache) {
802            if let Some(entity) = defn.as_entity() {
803                match (self.has_members(), entity.body()) {
804                    (true, Some(body)) => {
805                        for member in self.members() {
806                            if !body.contains_member(member) {
807                                loader
808                                    .report(&source_entity_missing_member(
809                                        top.file_id().copied().unwrap_or_default(),
810                                        name.source_span().as_ref().map(|span| (*span).into()),
811                                        name,
812                                    ))
813                                    .unwrap();
814                            }
815                        }
816                    }
817                    (true, None) => {
818                        for name in self.members() {
819                            loader
820                                .report(&source_entity_missing_member(
821                                    top.file_id().copied().unwrap_or_default(),
822                                    name.source_span().as_ref().map(|span| (*span).into()),
823                                    name,
824                                ))
825                                .unwrap();
826                        }
827                    }
828                    (false, _) => (),
829                }
830            } else {
831                loader
832                    .report(&source_entity_not_entity(
833                        top.file_id().copied().unwrap_or_default(),
834                        name.source_span().as_ref().map(|span| (*span).into()),
835                        name,
836                    ))
837                    .unwrap();
838            }
839        } else if !name
840            .as_identifier()
841            .map(is_builtin_type_name)
842            .unwrap_or_default()
843        {
844            loader
845                .report(&type_definition_not_found(
846                    top.file_id().copied().unwrap_or_default(),
847                    name.source_span().as_ref().map(|span| (*span).into()),
848                    name,
849                ))
850                .unwrap();
851        } else {
852            loader
853                .report(&source_entity_not_entity(
854                    top.file_id().copied().unwrap_or_default(),
855                    name.source_span().as_ref().map(|span| (*span).into()),
856                    name,
857                ))
858                .unwrap();
859        }
860    }
861}
862
863impl References for SourceEntity {
864    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
865        names.insert(self.target_entity());
866    }
867}
868
869impl SourceEntity {
870    // --------------------------------------------------------------------------------------------
871    // Constructors
872    // --------------------------------------------------------------------------------------------
873
874    pub fn new<T>(target_entity: T) -> Self
875    where
876        T: Into<IdentifierReference>,
877    {
878        Self {
879            span: Default::default(),
880            target_entity: target_entity.into(),
881            with_members: Default::default(),
882        }
883    }
884
885    pub fn with_members<I>(self, members: I) -> Self
886    where
887        I: IntoIterator<Item = Identifier>,
888    {
889        let mut self_mut = self;
890        self_mut.with_members = members.into_iter().collect();
891        self_mut
892    }
893
894    // --------------------------------------------------------------------------------------------
895    // Fields
896    // --------------------------------------------------------------------------------------------
897
898    pub const fn target_entity(&self) -> &IdentifierReference {
899        &self.target_entity
900    }
901
902    pub fn set_target_entity<T>(&mut self, target_entity: T)
903    where
904        T: Into<IdentifierReference>,
905    {
906        self.target_entity = target_entity.into();
907    }
908
909    // --------------------------------------------------------------------------------------------
910
911    pub fn has_members(&self) -> bool {
912        !self.with_members.is_empty()
913    }
914
915    pub fn member_count(&self) -> usize {
916        self.with_members.len()
917    }
918
919    pub fn contains_member(&self, name: &Identifier) -> bool {
920        self.members().any(|n| n == name)
921    }
922
923    pub fn members(&self) -> impl Iterator<Item = &Identifier> {
924        self.with_members.iter()
925    }
926
927    pub fn members_mut(&mut self) -> impl Iterator<Item = &mut Identifier> {
928        self.with_members.iter_mut()
929    }
930
931    pub fn add_to_members<I>(&mut self, value: I)
932    where
933        I: Into<Identifier>,
934    {
935        self.with_members.push(value.into())
936    }
937
938    pub fn extend_members<I>(&mut self, extension: I)
939    where
940        I: IntoIterator<Item = Identifier>,
941    {
942        self.with_members.extend(extension)
943    }
944}