sdml_core/model/
modules.rs

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