sdml_core/model/definitions/
dimensions.rs

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