nyar_error/undefined/
mod.rs

1use crate::{NyarError, NyarErrorKind};
2use diagnostic::{Color, Diagnostic, Label, ReportKind, SourceID, SourceSpan};
3use std::{
4    error::Error,
5    fmt::{Debug, Display, Formatter},
6    ops::Range,
7};
8
9#[derive(Clone, Debug, Eq, PartialEq)]
10pub struct MissingError {
11    pub(crate) kind: MissingErrorKind,
12    pub(crate) span: SourceSpan,
13}
14
15#[derive(Clone, Debug, Eq, PartialEq)]
16pub(crate) enum MissingErrorKind {
17    /// empty symbol
18    EmptyPath,
19    /// undefined symbol
20    Undefined(Box<str>),
21}
22
23impl Error for MissingError {}
24
25impl Display for MissingError {
26    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
27        Display::fmt(&self.kind, f)
28    }
29}
30
31impl Display for MissingErrorKind {
32    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
33        match self {
34            Self::EmptyPath => write!(f, "Empty symbol"),
35            Self::Undefined(v) => write!(f, "Undefined symbol `{}`", v),
36        }
37    }
38}
39
40impl From<MissingError> for NyarError {
41    fn from(value: MissingError) -> Self {
42        value.as_error(ReportKind::Error)
43    }
44}
45
46impl MissingError {
47    pub fn empty() -> Self {
48        Self { kind: MissingErrorKind::EmptyPath, span: SourceSpan::default() }
49    }
50    pub fn undefined(symbol: &str) -> Self {
51        Self { kind: MissingErrorKind::Undefined(Box::from(symbol)), span: SourceSpan::default() }
52    }
53    pub fn with_span(self, span: SourceSpan) -> Self {
54        Self { span, ..self }
55    }
56    pub fn with_range(self, range: Range<u32>) -> Self {
57        Self { span: self.span.with_range(range), ..self }
58    }
59    pub fn with_file(self, file: SourceID) -> Self {
60        Self { span: self.span.with_file(file), ..self }
61    }
62    pub fn as_error(self, kind: ReportKind) -> NyarError {
63        NyarErrorKind::Missing(self).as_error(kind)
64    }
65    pub fn as_report(&self, kind: ReportKind) -> Diagnostic {
66        let mut report = Diagnostic::new(kind).with_location(self.span.get_file(), Some(self.span.get_start()));
67        report.set_message(self.to_string());
68        match self.kind {
69            MissingErrorKind::EmptyPath => {
70                report.add_label(Label::new(self.span).with_message("Symbol path cannot be empty").with_color(Color::Red))
71            }
72            MissingErrorKind::Undefined(_) => report.add_label(
73                Label::new(self.span).with_message("You need to declare this symbol by `let` first").with_color(Color::Red),
74            ),
75        }
76        report.finish()
77    }
78}