use crate::source::SourceSpan;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DiagnosticCode(&'static str);
impl DiagnosticCode {
#[must_use]
pub const fn new(value: &'static str) -> Self {
Self(value)
}
#[must_use]
pub const fn as_str(self) -> &'static str {
self.0
}
}
impl fmt::Display for DiagnosticCode {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Severity {
Error,
Warning,
Note,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LabelKind {
Primary,
Secondary,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DiagnosticLabel {
kind: LabelKind,
span: SourceSpan,
message: String,
}
impl DiagnosticLabel {
#[must_use]
pub fn primary(span: SourceSpan, message: impl Into<String>) -> Self {
Self {
kind: LabelKind::Primary,
span,
message: message.into(),
}
}
#[must_use]
pub fn secondary(span: SourceSpan, message: impl Into<String>) -> Self {
Self {
kind: LabelKind::Secondary,
span,
message: message.into(),
}
}
#[must_use]
pub const fn kind(&self) -> LabelKind {
self.kind
}
#[must_use]
pub const fn span(&self) -> SourceSpan {
self.span
}
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Diagnostic {
code: DiagnosticCode,
severity: Severity,
message: String,
labels: Vec<DiagnosticLabel>,
notes: Vec<String>,
}
impl Diagnostic {
#[must_use]
pub fn new(code: DiagnosticCode, severity: Severity, message: impl Into<String>) -> Self {
Self {
code,
severity,
message: message.into(),
labels: Vec::new(),
notes: Vec::new(),
}
}
#[must_use]
pub fn with_label(mut self, label: DiagnosticLabel) -> Self {
self.labels.push(label);
self
}
#[must_use]
pub fn with_note(mut self, note: impl Into<String>) -> Self {
self.notes.push(note.into());
self
}
#[must_use]
pub const fn code(&self) -> DiagnosticCode {
self.code
}
#[must_use]
pub const fn severity(&self) -> Severity {
self.severity
}
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
#[must_use]
pub fn labels(&self) -> &[DiagnosticLabel] {
&self.labels
}
#[must_use]
pub fn notes(&self) -> &[String] {
&self.notes
}
}