sdml_core/model/
modules.rs

1/*!
2Provide the Rust types that implement *module*-related components of the SDML Grammar.
3*/
4use crate::load::ModuleLoader;
5use crate::model::definitions::{
6    DatatypeDef, EntityDef, EnumDef, EventDef, PropertyDef, StructureDef, UnionDef,
7};
8use crate::model::References;
9use crate::model::{
10    annotations::{Annotation, HasAnnotations},
11    check::{MaybeIncomplete, Validate},
12    definitions::{Definition, RdfDef, TypeClassDef},
13    identifiers::{Identifier, IdentifierReference, QualifiedIdentifier},
14    HasBody, HasName, HasSourceSpan, Span,
15};
16use crate::store::{InMemoryModuleCache, ModuleStore};
17use sdml_errors::diagnostics::functions::{
18    definition_not_found, imported_module_not_found, library_definition_not_allowed,
19    module_is_incomplete, module_version_info_empty, module_version_mismatch,
20    module_version_not_found, IdentifierCaseConvention,
21};
22use sdml_errors::{Error, FileId};
23use std::collections::BTreeMap;
24use std::fmt::Display;
25use std::hash::Hash;
26use std::path::PathBuf;
27use std::{collections::BTreeSet, fmt::Debug};
28use url::Url;
29
30#[cfg(feature = "serde")]
31use serde::{Deserialize, Serialize};
32
33// ------------------------------------------------------------------------------------------------
34// Public Types ❱ Modules
35// ------------------------------------------------------------------------------------------------
36
37///
38/// Corresponds the grammar rule `module`.
39///
40#[derive(Clone, Debug)]
41#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
42pub struct Module {
43    #[cfg_attr(feature = "serde", serde(skip))]
44    source_file: Option<PathBuf>,
45    #[cfg_attr(feature = "serde", serde(skip))]
46    file_id: Option<FileId>,
47    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
48    span: Option<Span>,
49    name: Identifier,
50    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
51    base_uri: Option<HeaderValue<Url>>,
52    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
53    version_info: Option<HeaderValue<String>>,
54    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
55    version_uri: Option<HeaderValue<Url>>,
56    body: ModuleBody,
57}
58
59#[derive(Clone, Debug)]
60#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
61pub struct HeaderValue<T> {
62    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
63    span: Option<Span>,
64    value: T,
65}
66
67///
68/// Corresponds the grammar rule `module_body`.
69///
70#[derive(Clone, Debug, Default)]
71#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
72pub struct ModuleBody {
73    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
74    span: Option<Span>,
75    file_id: Option<FileId>, // <- to report errors
76    is_library: bool,        // <- to catch errors
77    imports: Vec<ImportStatement>,
78    annotations: Vec<Annotation>,
79    definitions: BTreeMap<Identifier, Definition>,
80}
81
82// ------------------------------------------------------------------------------------------------
83// Public Types ❱ Modules ❱ Imports
84// ------------------------------------------------------------------------------------------------
85
86///
87/// Corresponds the grammar rule `import_statement`.
88///
89#[derive(Clone, Debug, Default)]
90#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
91pub struct ImportStatement {
92    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
93    span: Option<Span>,
94    imports: Vec<Import>,
95}
96
97///
98/// Corresponds the grammar rule `import`.
99///
100#[derive(Clone, Debug, PartialEq, Eq, Hash)]
101#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
102pub enum Import {
103    /// Corresponds to the grammar rule `module_import`.
104    Module(ModuleImport),
105    /// Corresponds to the grammar rule `member_import`.
106    Member(MemberImport),
107}
108
109///
110/// Corresponds the grammar rule `module_import`.
111///
112#[derive(Clone, Debug)]
113#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
114pub struct ModuleImport {
115    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
116    span: Option<Span>,
117    name: Identifier,
118    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
119    version_uri: Option<HeaderValue<Url>>,
120    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
121    renamed_as: Option<Identifier>,
122}
123
124///
125/// Corresponds the grammar rule `member_import`.
126///
127#[derive(Clone, Debug)]
128#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
129pub struct MemberImport {
130    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
131    span: Option<Span>,
132    name: QualifiedIdentifier,
133    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
134    renamed_as: Option<Identifier>,
135}
136
137// ------------------------------------------------------------------------------------------------
138// Implementations ❱ Modules ❱ Module
139// ------------------------------------------------------------------------------------------------
140
141impl HasSourceSpan for Module {
142    fn with_source_span(self, span: Span) -> Self {
143        let mut self_mut = self;
144        self_mut.span = Some(span);
145        self_mut
146    }
147
148    fn source_span(&self) -> Option<&Span> {
149        self.span.as_ref()
150    }
151
152    fn set_source_span(&mut self, span: Span) {
153        self.span = Some(span);
154    }
155
156    fn unset_source_span(&mut self) {
157        self.span = None;
158    }
159}
160
161impl HasName for Module {
162    fn name(&self) -> &Identifier {
163        &self.name
164    }
165
166    fn set_name(&mut self, name: Identifier) {
167        self.name = name;
168    }
169}
170
171impl HasBody for Module {
172    type Body = ModuleBody;
173
174    fn body(&self) -> &Self::Body {
175        &self.body
176    }
177
178    fn body_mut(&mut self) -> &mut Self::Body {
179        &mut self.body
180    }
181
182    fn set_body(&mut self, body: Self::Body) {
183        let mut body_mut = body;
184        body_mut.file_id = self.file_id;
185        body_mut.set_library_status(self.name());
186        self.body = body_mut;
187    }
188}
189
190impl References for Module {
191    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
192        self.body.referenced_types(names);
193    }
194
195    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
196        self.body.referenced_annotations(names);
197    }
198}
199
200impl Module {
201    // --------------------------------------------------------------------------------------------
202    // Constructors
203    // --------------------------------------------------------------------------------------------
204
205    pub fn empty(name: Identifier) -> Self {
206        Self::new(name, ModuleBody::default())
207    }
208
209    pub fn new(name: Identifier, body: ModuleBody) -> Self {
210        let mut body = body;
211        body.set_library_status(&name);
212        Self {
213            source_file: None,
214            file_id: None,
215            span: None,
216            name,
217            base_uri: None,
218            version_info: None,
219            version_uri: None,
220            body,
221        }
222    }
223
224    // --------------------------------------------------------------------------------------------
225    // Fields
226    // --------------------------------------------------------------------------------------------
227
228    pub fn with_source_file(self, source_file: PathBuf) -> Self {
229        Self {
230            source_file: Some(source_file),
231            ..self
232        }
233    }
234
235    pub fn with_base_uri(self, base_uri: Url) -> Self {
236        Self {
237            base_uri: Some(base_uri.into()),
238            ..self
239        }
240    }
241
242    pub fn with_version_info<S>(self, version_info: S) -> Self
243    where
244        S: Into<String>,
245    {
246        Self {
247            version_info: Some(HeaderValue::from(version_info.into())),
248            ..self
249        }
250    }
251
252    pub fn with_version_uri(self, version_uri: Url) -> Self {
253        Self {
254            version_uri: Some(version_uri.into()),
255            ..self
256        }
257    }
258
259    pub const fn has_source_file(&self) -> bool {
260        self.source_file.is_some()
261    }
262    pub const fn source_file(&self) -> Option<&PathBuf> {
263        self.source_file.as_ref()
264    }
265    pub fn set_source_file(&mut self, source_file: PathBuf) {
266        self.source_file = Some(source_file);
267    }
268    pub fn unset_source_file(&mut self) {
269        self.source_file = None;
270    }
271
272    pub const fn has_base_uri(&self) -> bool {
273        self.base_uri.is_some()
274    }
275    pub const fn base_uri(&self) -> Option<&HeaderValue<Url>> {
276        self.base_uri.as_ref()
277    }
278    pub fn set_base_uri(&mut self, base_uri: HeaderValue<Url>) {
279        self.base_uri = Some(base_uri);
280    }
281    pub fn unset_base_uri(&mut self) {
282        self.base_uri = None;
283    }
284
285    pub const fn has_version_info(&self) -> bool {
286        self.version_info.is_some()
287    }
288    pub const fn version_info(&self) -> Option<&HeaderValue<String>> {
289        self.version_info.as_ref()
290    }
291    pub fn set_version_info(&mut self, version_info: HeaderValue<String>) {
292        self.version_info = Some(version_info);
293    }
294    pub fn unset_version_info(&mut self) {
295        self.version_info = None;
296    }
297
298    pub const fn has_version_uri(&self) -> bool {
299        self.version_uri.is_some()
300    }
301    pub const fn version_uri(&self) -> Option<&HeaderValue<Url>> {
302        self.version_uri.as_ref()
303    }
304    pub fn set_version_uri(&mut self, version_uri: HeaderValue<Url>) {
305        self.version_uri = Some(version_uri);
306    }
307    pub fn unset_version_uri(&mut self) {
308        self.version_uri = None;
309    }
310
311    pub const fn has_file_id(&self) -> bool {
312        self.file_id.is_some()
313    }
314    pub const fn file_id(&self) -> Option<&FileId> {
315        self.file_id.as_ref()
316    }
317    pub fn set_file_id(&mut self, file_id: FileId) {
318        self.file_id = Some(file_id);
319    }
320    pub fn unset_file_id(&mut self) {
321        self.file_id = None;
322    }
323
324    // --------------------------------------------------------------------------------------------
325
326    #[inline(always)]
327    pub fn imported_modules(&self) -> BTreeSet<&Identifier> {
328        self.body.imported_modules()
329    }
330
331    #[inline(always)]
332    pub fn imported_module_versions(&self) -> BTreeMap<&Identifier, Option<&HeaderValue<Url>>> {
333        self.body.imported_module_versions()
334    }
335
336    #[inline(always)]
337    pub fn imported_types(&self) -> BTreeSet<&QualifiedIdentifier> {
338        self.body.imported_types()
339    }
340
341    #[inline(always)]
342    pub fn defined_names(&self) -> BTreeSet<&Identifier> {
343        self.body.defined_names()
344    }
345
346    // --------------------------------------------------------------------------------------------
347    // Pseudo-Validate
348    // --------------------------------------------------------------------------------------------
349
350    pub fn is_incomplete(&self, cache: &InMemoryModuleCache) -> bool {
351        if !self.is_library_module() {
352            self.body.is_incomplete(self, cache)
353        } else {
354            false
355        }
356    }
357
358    ///
359    /// # Checks
360    ///
361    /// 1. name is valid [`Identifier`]
362    /// 1. base URI is absolute [`Url`]
363    /// 1. version info string is not empty (warning)
364    /// 1. version URI is absolute [`Url`]
365    /// 1. body is valid
366    ///
367    pub fn validate(
368        &self,
369        cache: &InMemoryModuleCache,
370        loader: &impl ModuleLoader,
371        check_constraints: bool,
372    ) {
373        if !self.is_library_module() {
374            self.name
375                .validate(self, loader, Some(IdentifierCaseConvention::Module));
376            if let Some(version_info) = self.version_info() {
377                if version_info.as_ref().is_empty() {
378                    loader
379                        .report(&module_version_info_empty(
380                            self.file_id().copied().unwrap_or_default(),
381                            version_info.source_span().map(|span| span.byte_range()),
382                        ))
383                        .unwrap();
384                }
385            }
386            self.body.validate(self, cache, loader, check_constraints);
387            if self.is_incomplete(cache) {
388                loader
389                    .report(&module_is_incomplete(
390                        self.file_id().copied().unwrap_or_default(),
391                        self.source_span().map(|span| span.byte_range()),
392                        self.name(),
393                    ))
394                    .unwrap()
395            }
396        }
397    }
398
399    // --------------------------------------------------------------------------------------------
400    // Helpers
401    // --------------------------------------------------------------------------------------------
402
403    pub fn is_library_module(&self) -> bool {
404        Identifier::is_library_module_name(self.name().as_ref())
405    }
406
407    pub fn resolve_local(&self, name: &Identifier) -> Option<&Definition> {
408        self.body().definitions().find(|def| def.name() == name)
409    }
410}
411
412// ------------------------------------------------------------------------------------------------
413// Implementations ❱ Modules ❱ HeaderValue
414// ------------------------------------------------------------------------------------------------
415
416impl<T> AsRef<T> for HeaderValue<T> {
417    fn as_ref(&self) -> &T {
418        &self.value
419    }
420}
421
422impl<T> From<T> for HeaderValue<T> {
423    fn from(value: T) -> Self {
424        Self { span: None, value }
425    }
426}
427
428impl<T: Display> Display for HeaderValue<T> {
429    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
430        write!(f, "{}", self.value)
431    }
432}
433
434impl<T: PartialEq> PartialEq for HeaderValue<T> {
435    fn eq(&self, other: &Self) -> bool {
436        self.value == other.value
437    }
438}
439
440impl<T: PartialEq> PartialEq<T> for HeaderValue<T> {
441    fn eq(&self, other: &T) -> bool {
442        self.value == *other
443    }
444}
445
446impl<T: Eq> Eq for HeaderValue<T> {}
447
448impl<T: Hash> Hash for HeaderValue<T> {
449    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
450        // ignore: self.span.hash(state);
451        self.value.hash(state);
452    }
453}
454
455impl<T> HasSourceSpan for HeaderValue<T> {
456    fn with_source_span(self, span: Span) -> Self {
457        Self {
458            span: Some(span),
459            ..self
460        }
461    }
462
463    fn source_span(&self) -> Option<&Span> {
464        self.span.as_ref()
465    }
466
467    fn set_source_span(&mut self, span: Span) {
468        self.span = Some(span);
469    }
470
471    fn unset_source_span(&mut self) {
472        self.span = None;
473    }
474}
475
476impl<T: PartialEq> HeaderValue<T> {
477    pub fn eq_with_span(&self, other: &Self) -> bool {
478        self.span == other.span && self.value == other.value
479    }
480}
481
482impl<T> HeaderValue<T> {
483    pub const fn value(&self) -> &T {
484        &self.value
485    }
486
487    pub fn set_value(&mut self, value: T) {
488        self.value = value;
489    }
490}
491
492// ------------------------------------------------------------------------------------------------
493// Implementations ❱ Modules ❱ ModuleBody
494// ------------------------------------------------------------------------------------------------
495
496impl HasSourceSpan for ModuleBody {
497    fn with_source_span(self, span: Span) -> Self {
498        let mut self_mut = self;
499        self_mut.span = Some(span);
500        self_mut
501    }
502
503    fn source_span(&self) -> Option<&Span> {
504        self.span.as_ref()
505    }
506
507    fn set_source_span(&mut self, span: Span) {
508        self.span = Some(span);
509    }
510
511    fn unset_source_span(&mut self) {
512        self.span = None;
513    }
514}
515
516impl HasAnnotations for ModuleBody {
517    fn has_annotations(&self) -> bool {
518        !self.annotations.is_empty()
519    }
520
521    fn annotation_count(&self) -> usize {
522        self.annotations.len()
523    }
524
525    fn annotations(&self) -> impl Iterator<Item = &Annotation> {
526        self.annotations.iter()
527    }
528
529    fn annotations_mut(&mut self) -> impl Iterator<Item = &mut Annotation> {
530        self.annotations.iter_mut()
531    }
532
533    fn add_to_annotations<I>(&mut self, value: I)
534    where
535        I: Into<Annotation>,
536    {
537        self.annotations.push(value.into())
538    }
539
540    fn extend_annotations<I>(&mut self, extension: I)
541    where
542        I: IntoIterator<Item = Annotation>,
543    {
544        self.annotations.extend(extension)
545    }
546}
547
548impl References for ModuleBody {
549    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
550        self.definitions()
551            .for_each(|def| def.referenced_types(names))
552    }
553
554    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
555        self.definitions()
556            .for_each(|def| def.referenced_annotations(names));
557    }
558}
559
560impl MaybeIncomplete for ModuleBody {
561    fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
562        self.definitions()
563            .any(|elem| elem.is_incomplete(top, cache))
564    }
565}
566
567impl Validate for ModuleBody {
568    ///
569    /// # Checks
570    ///
571    /// 1. All import statements are valid [`ImportStatement`]s
572    /// 1. All annotations are valid [`Annotation`]s
573    /// 1. All definitions are valid [`Definition`]s
574    ///
575    fn validate(
576        &self,
577        top: &Module,
578        cache: &impl ModuleStore,
579        loader: &impl ModuleLoader,
580        check_constraints: bool,
581    ) {
582        self.imports()
583            .for_each(|imp| imp.validate(top, cache, loader, check_constraints));
584        self.annotations()
585            .for_each(|ann| ann.validate(top, cache, loader, check_constraints));
586        self.definitions()
587            .for_each(|def| def.validate(top, cache, loader, check_constraints));
588    }
589}
590
591impl ModuleBody {
592    // --------------------------------------------------------------------------------------------
593    // Constructors
594    // --------------------------------------------------------------------------------------------
595
596    pub fn with_imports<I>(self, import_statements: I) -> Self
597    where
598        I: IntoIterator<Item = ImportStatement>,
599    {
600        let mut self_mut = self;
601        self_mut.extend_imports(import_statements);
602        self_mut
603    }
604
605    pub fn with_definitions<I>(self, definitions: I) -> Self
606    where
607        I: IntoIterator<Item = Definition>,
608    {
609        let mut self_mut = self;
610        self_mut.extend_definitions(definitions).unwrap();
611        self_mut
612    }
613
614    // --------------------------------------------------------------------------------------------
615    // Fields
616    // --------------------------------------------------------------------------------------------
617
618    pub fn set_library_status(&mut self, module_name: &Identifier) {
619        self.is_library = Identifier::is_library_module_name(module_name);
620    }
621
622    // --------------------------------------------------------------------------------------------
623
624    pub fn has_imports(&self) -> bool {
625        !self.imports.is_empty()
626    }
627
628    pub fn imports_len(&self) -> usize {
629        self.imports.len()
630    }
631
632    pub fn imports(&self) -> impl Iterator<Item = &ImportStatement> {
633        self.imports.iter()
634    }
635
636    pub fn imports_mut(&mut self) -> impl Iterator<Item = &mut ImportStatement> {
637        self.imports.iter_mut()
638    }
639
640    pub fn add_to_imports<I>(&mut self, value: I)
641    where
642        I: Into<ImportStatement>,
643    {
644        self.imports.push(value.into())
645    }
646
647    pub fn extend_imports<I>(&mut self, extension: I)
648    where
649        I: IntoIterator<Item = ImportStatement>,
650    {
651        self.imports.extend(extension)
652    }
653
654    // --------------------------------------------------------------------------------------------
655
656    pub fn has_definitions(&self) -> bool {
657        !self.definitions.is_empty()
658    }
659
660    pub fn definition_count(&self) -> usize {
661        self.definitions.len()
662    }
663
664    pub fn contains_definition(&self, name: &Identifier) -> bool {
665        self.definitions.contains_key(name)
666    }
667
668    pub fn definition(&self, name: &Identifier) -> Option<&Definition> {
669        self.definitions.get(name)
670    }
671
672    pub fn definition_mut(&mut self, name: &Identifier) -> Option<&mut Definition> {
673        self.definitions.get_mut(name)
674    }
675
676    pub fn definitions(&self) -> impl Iterator<Item = &Definition> {
677        self.definitions.values()
678    }
679
680    pub fn definitions_mut(&mut self) -> impl Iterator<Item = &mut Definition> {
681        self.definitions.values_mut()
682    }
683
684    pub fn definition_names(&self) -> impl Iterator<Item = &Identifier> {
685        self.definitions.keys()
686    }
687
688    pub fn add_to_definitions<I>(&mut self, value: I) -> Result<(), Error>
689    where
690        I: Into<Definition>,
691    {
692        let definition = value.into();
693        if !self.is_library && matches!(definition, Definition::Rdf(_) | Definition::TypeClass(_)) {
694            Err(library_definition_not_allowed(
695                self.file_id.unwrap_or_default(),
696                definition.source_span().map(|s| s.into()),
697                definition.name(),
698            )
699            .into())
700        } else {
701            self.definitions
702                .insert(definition.name().clone(), definition);
703            Ok(())
704        }
705    }
706
707    pub fn extend_definitions<I>(&mut self, extension: I) -> Result<(), Error>
708    where
709        I: IntoIterator<Item = Definition>,
710    {
711        // we do this manually to ensure the library rules in ModuleBody::push
712        for definition in extension.into_iter() {
713            self.add_to_definitions(definition)?;
714        }
715        Ok(())
716    }
717
718    // --------------------------------------------------------------------------------------------
719    // Helpers
720    // --------------------------------------------------------------------------------------------
721
722    pub fn imported_modules(&self) -> BTreeSet<&Identifier> {
723        self.imports()
724            .flat_map(|stmt| stmt.imported_modules())
725            .collect()
726    }
727
728    pub fn imported_module_versions(&self) -> BTreeMap<&Identifier, Option<&HeaderValue<Url>>> {
729        self.imports()
730            .flat_map(|stmt| stmt.imported_module_versions())
731            .collect()
732    }
733
734    pub fn imported_types(&self) -> BTreeSet<&QualifiedIdentifier> {
735        self.imports()
736            .flat_map(|stmt| stmt.imported_types())
737            .collect()
738    }
739
740    // --------------------------------------------------------------------------------------------
741
742    #[inline]
743    pub fn get_definition(&self, name: &Identifier) -> Option<&Definition> {
744        self.definitions().find(|d| d.name() == name)
745    }
746
747    #[inline]
748    pub fn datatype_definitions(&self) -> impl Iterator<Item = &DatatypeDef> {
749        self.definitions().filter_map(|d| match d {
750            Definition::Datatype(v) => Some(v),
751            _ => None,
752        })
753    }
754
755    #[inline]
756    pub fn entity_definitions(&self) -> impl Iterator<Item = &EntityDef> {
757        self.definitions().filter_map(|d| match d {
758            Definition::Entity(v) => Some(v),
759            _ => None,
760        })
761    }
762
763    #[inline]
764    pub fn enum_definitions(&self) -> impl Iterator<Item = &EnumDef> {
765        self.definitions().filter_map(|d| match d {
766            Definition::Enum(v) => Some(v),
767            _ => None,
768        })
769    }
770
771    #[inline]
772    pub fn event_definitions(&self) -> impl Iterator<Item = &EventDef> {
773        self.definitions().filter_map(|d| match d {
774            Definition::Event(v) => Some(v),
775            _ => None,
776        })
777    }
778
779    #[inline]
780    pub fn property_definitions(&self) -> impl Iterator<Item = &PropertyDef> {
781        self.definitions().filter_map(|d| match d {
782            Definition::Property(v) => Some(v),
783            _ => None,
784        })
785    }
786
787    #[inline]
788    pub fn rdf_definitions(&self) -> impl Iterator<Item = &RdfDef> {
789        self.definitions().filter_map(|d| match d {
790            Definition::Rdf(v) => Some(v),
791            _ => None,
792        })
793    }
794
795    #[inline]
796    pub fn structure_definitions(&self) -> impl Iterator<Item = &StructureDef> {
797        self.definitions().filter_map(|d| match d {
798            Definition::Structure(v) => Some(v),
799            _ => None,
800        })
801    }
802
803    #[inline]
804    pub fn type_class_definitions(&self) -> impl Iterator<Item = &TypeClassDef> {
805        self.definitions().filter_map(|d| match d {
806            Definition::TypeClass(v) => Some(v),
807            _ => None,
808        })
809    }
810
811    #[inline]
812    pub fn union_definitions(&self) -> impl Iterator<Item = &UnionDef> {
813        self.definitions().filter_map(|d| match d {
814            Definition::Union(v) => Some(v),
815            _ => None,
816        })
817    }
818
819    pub fn defined_names(&self) -> BTreeSet<&Identifier> {
820        self.definitions().map(|def| def.name()).collect()
821    }
822}
823
824// ------------------------------------------------------------------------------------------------
825// Implementations ❱ Modules ❱ ImportStatement
826// ------------------------------------------------------------------------------------------------
827
828impl From<Import> for ImportStatement {
829    fn from(value: Import) -> Self {
830        Self::new(vec![value])
831    }
832}
833
834impl From<Vec<Import>> for ImportStatement {
835    fn from(value: Vec<Import>) -> Self {
836        Self::new(value)
837    }
838}
839
840impl FromIterator<Import> for ImportStatement {
841    fn from_iter<T: IntoIterator<Item = Import>>(iter: T) -> Self {
842        Self::new(Vec::from_iter(iter))
843    }
844}
845
846impl From<ImportStatement> for Vec<Import> {
847    fn from(value: ImportStatement) -> Self {
848        value.imports
849    }
850}
851
852impl HasSourceSpan for ImportStatement {
853    fn with_source_span(self, span: Span) -> Self {
854        let mut self_mut = self;
855        self_mut.span = Some(span);
856        self_mut
857    }
858
859    fn source_span(&self) -> Option<&Span> {
860        self.span.as_ref()
861    }
862
863    fn set_source_span(&mut self, span: Span) {
864        self.span = Some(span);
865    }
866
867    fn unset_source_span(&mut self) {
868        self.span = None;
869    }
870}
871
872impl Validate for ImportStatement {
873    ///
874    /// # Checks
875    ///
876    /// - For each [`Import`]:
877    ///   - If module import:
878    ///     1. Ensure it is in the cache
879    ///     1. If the import has a version URI ensure the imported module has a matching one
880    ///     1.
881    ///     1.
882    ///     1.
883    ///
884    ///
885    ///
886    fn validate(
887        &self,
888        top: &Module,
889        cache: &impl ModuleStore,
890        loader: &impl ModuleLoader,
891        _: bool,
892    ) {
893        for import in self.imports() {
894            match import {
895                Import::Module(module_ref) => {
896                    module_ref.effective_name().validate(
897                        top,
898                        loader,
899                        Some(IdentifierCaseConvention::Module),
900                    );
901                    if let Some(actual_module) = cache.get(module_ref.name()) {
902                        match (module_ref.version_uri(), actual_module.version_uri()) {
903                            (None, _) => {}
904                            (Some(expected), Some(actual)) => {
905                                if actual != expected {
906                                    loader
907                                        .report(&module_version_mismatch(
908                                            top.file_id().copied().unwrap_or_default(),
909                                            expected.source_span().map(|s| s.byte_range()),
910                                            expected.as_ref().to_string(),
911                                            actual_module.file_id().copied().unwrap_or_default(),
912                                            actual.source_span().map(|s| s.byte_range()),
913                                            actual.as_ref().to_string(),
914                                        ))
915                                        .unwrap();
916                                }
917                            }
918                            (Some(expected), None) => {
919                                loader
920                                    .report(&module_version_not_found(
921                                        top.file_id().copied().unwrap_or_default(),
922                                        module_ref.source_span().map(|s| s.byte_range()),
923                                        expected.as_ref().to_string(),
924                                        actual_module.file_id().copied().unwrap_or_default(),
925                                        actual_module.source_span().map(|s| s.byte_range()),
926                                        actual_module.name(),
927                                    ))
928                                    .unwrap();
929                            }
930                        }
931                    } else {
932                        loader
933                            .report(&imported_module_not_found(
934                                top.file_id().copied().unwrap_or_default(),
935                                module_ref.source_span().map(|s| s.byte_range()),
936                                module_ref.name(),
937                            ))
938                            .unwrap();
939                    }
940                }
941                Import::Member(member_ref) => {
942                    let id_ref = member_ref.name();
943                    //let id_ref = member_ref.effective_name();
944                    // TODO: check if this ir correct: id_ref.validate(top, loader);
945                    if let Some(actual_module) = cache.get(id_ref.module()) {
946                        if actual_module.resolve_local(id_ref.member()).is_none() {
947                            loader
948                                .report(&definition_not_found(
949                                    top.file_id().copied().unwrap_or_default(),
950                                    id_ref.source_span().map(|s| s.byte_range()),
951                                    id_ref,
952                                ))
953                                .unwrap();
954                        }
955                    } else {
956                        loader
957                            .report(&imported_module_not_found(
958                                top.file_id().copied().unwrap_or_default(),
959                                id_ref.source_span().map(|s| s.byte_range()),
960                                id_ref,
961                            ))
962                            .unwrap();
963                    }
964                }
965            }
966        }
967    }
968}
969
970impl ImportStatement {
971    // --------------------------------------------------------------------------------------------
972    // Constructors
973    // --------------------------------------------------------------------------------------------
974
975    pub const fn new(imports: Vec<Import>) -> Self {
976        Self {
977            span: None,
978            imports,
979        }
980    }
981
982    pub fn new_module(import: Identifier) -> Self {
983        Self {
984            span: None,
985            imports: vec![Import::from(ModuleImport::from(import))],
986        }
987    }
988
989    pub fn new_module_with_version_uri(import: Identifier, version_uri: Url) -> Self {
990        Self {
991            span: None,
992            imports: vec![Import::from(
993                ModuleImport::from(import).with_version_uri(version_uri.into()),
994            )],
995        }
996    }
997
998    pub fn new_member(import: QualifiedIdentifier) -> Self {
999        Self {
1000            span: None,
1001            imports: vec![Import::from(import)],
1002        }
1003    }
1004
1005    // --------------------------------------------------------------------------------------------
1006    // Fields
1007    // --------------------------------------------------------------------------------------------
1008
1009    pub fn has_imports(&self) -> bool {
1010        !self.imports.is_empty()
1011    }
1012
1013    pub fn imports_len(&self) -> usize {
1014        self.imports.len()
1015    }
1016
1017    pub fn imports(&self) -> impl Iterator<Item = &Import> {
1018        self.imports.iter()
1019    }
1020
1021    pub fn imports_mut(&mut self) -> impl Iterator<Item = &mut Import> {
1022        self.imports.iter_mut()
1023    }
1024
1025    pub fn add_to_imports<I>(&mut self, value: I)
1026    where
1027        I: Into<Import>,
1028    {
1029        self.imports.push(value.into())
1030    }
1031
1032    pub fn extend_imports<I>(&mut self, extension: I)
1033    where
1034        I: IntoIterator<Item = Import>,
1035    {
1036        self.imports.extend(extension)
1037    }
1038
1039    // --------------------------------------------------------------------------------------------
1040
1041    pub fn as_slice(&self) -> &[Import] {
1042        self.imports.as_slice()
1043    }
1044
1045    // --------------------------------------------------------------------------------------------
1046
1047    pub fn imported_modules(&self) -> BTreeSet<&Identifier> {
1048        self.imports()
1049            .map(|imp| match imp {
1050                Import::Module(v) => v.name(),
1051                Import::Member(v) => v.module(),
1052            })
1053            .collect()
1054    }
1055
1056    pub fn imported_module_versions(&self) -> BTreeMap<&Identifier, Option<&HeaderValue<Url>>> {
1057        BTreeMap::from_iter(self.imports().map(|imp| match imp {
1058            Import::Module(v) => (v.name(), v.version_uri()),
1059            Import::Member(v) => (v.module(), None),
1060        }))
1061    }
1062
1063    pub fn imported_types(&self) -> BTreeSet<&QualifiedIdentifier> {
1064        self.imports()
1065            .filter_map(|imp| {
1066                if let Import::Member(imp) = imp {
1067                    Some(imp.name())
1068                } else {
1069                    None
1070                }
1071            })
1072            .collect()
1073    }
1074}
1075
1076// ------------------------------------------------------------------------------------------------
1077
1078impl From<&Identifier> for Import {
1079    fn from(v: &Identifier) -> Self {
1080        Self::Module(ModuleImport::from(v.clone()))
1081    }
1082}
1083
1084impl From<Identifier> for Import {
1085    fn from(v: Identifier) -> Self {
1086        Self::Module(ModuleImport::from(v))
1087    }
1088}
1089
1090impl From<&ModuleImport> for Import {
1091    fn from(v: &ModuleImport) -> Self {
1092        Self::Module(v.clone())
1093    }
1094}
1095
1096impl From<ModuleImport> for Import {
1097    fn from(v: ModuleImport) -> Self {
1098        Self::Module(v)
1099    }
1100}
1101
1102impl From<&QualifiedIdentifier> for Import {
1103    fn from(v: &QualifiedIdentifier) -> Self {
1104        Self::Member(MemberImport::from(v.clone()))
1105    }
1106}
1107
1108impl From<QualifiedIdentifier> for Import {
1109    fn from(v: QualifiedIdentifier) -> Self {
1110        Self::Member(MemberImport::from(v))
1111    }
1112}
1113
1114impl From<&MemberImport> for Import {
1115    fn from(v: &MemberImport) -> Self {
1116        Self::Member(v.clone())
1117    }
1118}
1119
1120impl From<MemberImport> for Import {
1121    fn from(v: MemberImport) -> Self {
1122        Self::Member(v)
1123    }
1124}
1125
1126impl std::fmt::Display for Import {
1127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1128        write!(
1129            f,
1130            "{}",
1131            match self {
1132                Self::Module(v) => v.to_string(),
1133                Self::Member(v) => v.to_string(),
1134            }
1135        )
1136    }
1137}
1138
1139impl HasSourceSpan for Import {
1140    #[inline]
1141    fn with_source_span(self, span: Span) -> Self {
1142        match self {
1143            Self::Module(v) => Self::Module(v.with_source_span(span)),
1144            Self::Member(v) => Self::Member(v.with_source_span(span)),
1145        }
1146    }
1147
1148    #[inline]
1149    fn source_span(&self) -> Option<&Span> {
1150        match self {
1151            Self::Module(v) => v.source_span(),
1152            Self::Member(v) => v.source_span(),
1153        }
1154    }
1155
1156    #[inline]
1157    fn set_source_span(&mut self, span: Span) {
1158        match self {
1159            Self::Module(v) => v.set_source_span(span),
1160            Self::Member(v) => v.set_source_span(span),
1161        }
1162    }
1163
1164    #[inline]
1165    fn unset_source_span(&mut self) {
1166        match self {
1167            Self::Module(v) => v.unset_source_span(),
1168            Self::Member(v) => v.unset_source_span(),
1169        }
1170    }
1171}
1172
1173impl Import {
1174    pub fn module(&self) -> &Identifier {
1175        match self {
1176            Import::Module(v) => v.name(),
1177            Import::Member(v) => v.module(),
1178        }
1179    }
1180    pub fn member(&self) -> Option<&Identifier> {
1181        match self {
1182            Import::Module(_) => None,
1183            Import::Member(v) => Some(v.member()),
1184        }
1185    }
1186}
1187
1188// ------------------------------------------------------------------------------------------------
1189// Implementations ❱ Modules ❱ ModuleImport
1190// ------------------------------------------------------------------------------------------------
1191
1192impl From<&Identifier> for ModuleImport {
1193    fn from(value: &Identifier) -> Self {
1194        Self::new(value.clone())
1195    }
1196}
1197
1198impl From<Identifier> for ModuleImport {
1199    fn from(value: Identifier) -> Self {
1200        Self::new(value)
1201    }
1202}
1203
1204impl PartialEq for ModuleImport {
1205    fn eq(&self, other: &Self) -> bool {
1206        self.name == other.name
1207            && self.version_uri == other.version_uri
1208            && self.renamed_as == other.renamed_as
1209    }
1210}
1211
1212impl Eq for ModuleImport {}
1213
1214impl Hash for ModuleImport {
1215    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1216        // ignore: self.span.hash(state);
1217        self.name.hash(state);
1218        self.version_uri.hash(state);
1219        self.renamed_as.hash(state);
1220    }
1221}
1222
1223impl Display for ModuleImport {
1224    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1225        write!(
1226            f,
1227            "{}{}",
1228            if let Some(version_uri) = self.version_uri() {
1229                format!("{} version {}", self.name(), version_uri)
1230            } else {
1231                self.name().to_string()
1232            },
1233            if let Some(renamed_as) = &self.renamed_as {
1234                format!(" as {renamed_as}")
1235            } else {
1236                String::new()
1237            }
1238        )
1239    }
1240}
1241
1242impl HasSourceSpan for ModuleImport {
1243    fn with_source_span(self, span: Span) -> Self {
1244        let mut self_mut = self;
1245        self_mut.span = Some(span);
1246        self_mut
1247    }
1248
1249    fn source_span(&self) -> Option<&Span> {
1250        self.span.as_ref()
1251    }
1252
1253    fn set_source_span(&mut self, span: Span) {
1254        self.span = Some(span);
1255    }
1256
1257    fn unset_source_span(&mut self) {
1258        self.span = None;
1259    }
1260}
1261
1262impl ModuleImport {
1263    // --------------------------------------------------------------------------------------------
1264    // Constructors
1265    // --------------------------------------------------------------------------------------------
1266    pub const fn new(name: Identifier) -> Self {
1267        Self {
1268            span: None,
1269            name,
1270            version_uri: None,
1271            renamed_as: None,
1272        }
1273    }
1274
1275    pub fn with_version_uri(self, version_uri: HeaderValue<Url>) -> Self {
1276        let mut self_mut = self;
1277        self_mut.version_uri = Some(version_uri);
1278        self_mut
1279    }
1280
1281    pub fn with_rename(self, renamed_as: Identifier) -> Self {
1282        let mut self_mut = self;
1283        self_mut.renamed_as = Some(renamed_as);
1284        self_mut
1285    }
1286
1287    // --------------------------------------------------------------------------------------------
1288    // Fields
1289    // --------------------------------------------------------------------------------------------
1290
1291    pub const fn name(&self) -> &Identifier {
1292        &self.name
1293    }
1294
1295    pub fn set_name(&mut self, name: Identifier) {
1296        self.name = name;
1297    }
1298
1299    // --------------------------------------------------------------------------------------------
1300
1301    pub const fn has_version_uri(&self) -> bool {
1302        self.version_uri.is_some()
1303    }
1304
1305    pub const fn version_uri(&self) -> Option<&HeaderValue<Url>> {
1306        self.version_uri.as_ref()
1307    }
1308
1309    pub fn set_version_uri(&mut self, version_uri: HeaderValue<Url>) {
1310        self.version_uri = Some(version_uri);
1311    }
1312
1313    pub fn unset_version_uri(&mut self) {
1314        self.version_uri = None;
1315    }
1316
1317    // --------------------------------------------------------------------------------------------
1318
1319    pub fn effective_name(&self) -> Identifier {
1320        if let Some(rename) = self.renamed_as() {
1321            rename.clone()
1322        } else {
1323            self.name().clone()
1324        }
1325    }
1326
1327    // --------------------------------------------------------------------------------------------
1328
1329    pub const fn has_been_renamed(&self) -> bool {
1330        self.renamed_as.is_some()
1331    }
1332
1333    pub const fn renamed_as(&self) -> Option<&Identifier> {
1334        self.renamed_as.as_ref()
1335    }
1336
1337    pub fn set_rename_as(&mut self, renamed_as: Identifier) {
1338        self.renamed_as = Some(renamed_as);
1339    }
1340
1341    pub fn unset_rename_as(&mut self) {
1342        self.renamed_as = None;
1343    }
1344
1345    // --------------------------------------------------------------------------------------------
1346    // Helpers
1347    // --------------------------------------------------------------------------------------------
1348
1349    pub fn eq_with_span(&self, other: &Self) -> bool {
1350        self.span == other.span
1351            && self.name == other.name
1352            && self.version_uri == other.version_uri
1353            && self.renamed_as == other.renamed_as
1354    }
1355}
1356
1357// ------------------------------------------------------------------------------------------------
1358// Implementations ❱ Modules ❱ MemberImport
1359// ------------------------------------------------------------------------------------------------
1360
1361impl From<&QualifiedIdentifier> for MemberImport {
1362    fn from(value: &QualifiedIdentifier) -> Self {
1363        Self::new(value.clone())
1364    }
1365}
1366
1367impl From<QualifiedIdentifier> for MemberImport {
1368    fn from(value: QualifiedIdentifier) -> Self {
1369        Self::new(value)
1370    }
1371}
1372
1373impl PartialEq for MemberImport {
1374    fn eq(&self, other: &Self) -> bool {
1375        self.name == other.name && self.renamed_as == other.renamed_as
1376    }
1377}
1378
1379impl Eq for MemberImport {}
1380
1381impl Hash for MemberImport {
1382    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1383        // ignore: self.span.hash(state);
1384        self.name.hash(state);
1385        self.renamed_as.hash(state);
1386    }
1387}
1388
1389impl Display for MemberImport {
1390    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1391        write!(
1392            f,
1393            "{}{}",
1394            self.name().to_string(),
1395            if let Some(renamed_as) = &self.renamed_as {
1396                format!(" as {renamed_as}")
1397            } else {
1398                String::new()
1399            }
1400        )
1401    }
1402}
1403
1404impl HasSourceSpan for MemberImport {
1405    fn with_source_span(self, span: Span) -> Self {
1406        let mut self_mut = self;
1407        self_mut.span = Some(span);
1408        self_mut
1409    }
1410
1411    fn source_span(&self) -> Option<&Span> {
1412        self.span.as_ref()
1413    }
1414
1415    fn set_source_span(&mut self, span: Span) {
1416        self.span = Some(span);
1417    }
1418
1419    fn unset_source_span(&mut self) {
1420        self.span = None;
1421    }
1422}
1423
1424impl MemberImport {
1425    // --------------------------------------------------------------------------------------------
1426    // Constructors
1427    // --------------------------------------------------------------------------------------------
1428    pub const fn new(name: QualifiedIdentifier) -> Self {
1429        Self {
1430            span: None,
1431            name,
1432            renamed_as: None,
1433        }
1434    }
1435
1436    pub fn with_rename(self, renamed_as: Identifier) -> Self {
1437        let mut self_mut = self;
1438        self_mut.renamed_as = Some(renamed_as);
1439        self_mut
1440    }
1441
1442    // --------------------------------------------------------------------------------------------
1443    // Fields
1444    // --------------------------------------------------------------------------------------------
1445
1446    pub const fn name(&self) -> &QualifiedIdentifier {
1447        &self.name
1448    }
1449
1450    pub fn set_name(&mut self, name: QualifiedIdentifier) {
1451        self.name = name;
1452    }
1453
1454    // --------------------------------------------------------------------------------------------
1455
1456    pub const fn module(&self) -> &Identifier {
1457        self.name().module()
1458    }
1459
1460    pub const fn member(&self) -> &Identifier {
1461        &self.name().member()
1462    }
1463
1464    // --------------------------------------------------------------------------------------------
1465
1466    pub fn effective_name(&self) -> IdentifierReference {
1467        if let Some(rename) = self.renamed_as() {
1468            rename.clone().into()
1469        } else {
1470            self.name().clone().into()
1471        }
1472    }
1473
1474    // --------------------------------------------------------------------------------------------
1475
1476    pub const fn has_been_renamed(&self) -> bool {
1477        self.renamed_as.is_some()
1478    }
1479
1480    pub const fn renamed_as(&self) -> Option<&Identifier> {
1481        self.renamed_as.as_ref()
1482    }
1483
1484    pub fn set_rename_as(&mut self, renamed_as: Identifier) {
1485        self.renamed_as = Some(renamed_as);
1486    }
1487
1488    pub fn unset_rename_as(&mut self) {
1489        self.renamed_as = None;
1490    }
1491
1492    // --------------------------------------------------------------------------------------------
1493    // Helpers
1494    // --------------------------------------------------------------------------------------------
1495
1496    pub fn eq_with_span(&self, other: &Self) -> bool {
1497        self.span == other.span && self.name == other.name && self.renamed_as == other.renamed_as
1498    }
1499}