use alloc::borrow::Cow;
use core::fmt;
use crate::severity::Severity;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Diagnostic {
severity: Severity,
message: Cow<'static, str>,
}
impl Diagnostic {
#[must_use]
pub fn new(severity: Severity, message: impl Into<Cow<'static, str>>) -> Self {
Self {
severity,
message: message.into(),
}
}
#[must_use]
pub fn error(message: impl Into<Cow<'static, str>>) -> Self {
Self::new(Severity::Error, message)
}
#[must_use]
pub fn warning(message: impl Into<Cow<'static, str>>) -> Self {
Self::new(Severity::Warning, message)
}
#[must_use]
pub fn note(message: impl Into<Cow<'static, str>>) -> Self {
Self::new(Severity::Note, message)
}
#[must_use]
#[inline]
pub fn severity(&self) -> Severity {
self.severity
}
#[must_use]
#[inline]
pub fn message(&self) -> &str {
&self.message
}
#[must_use]
#[inline]
pub fn is_error(&self) -> bool {
self.severity.is_error()
}
}
impl fmt::Display for Diagnostic {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.severity, self.message)
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod tests {
use super::*;
use alloc::string::{String, ToString};
#[test]
fn test_new_accepts_literal_and_owned() {
let a = Diagnostic::new(Severity::Error, "x");
let b = Diagnostic::new(Severity::Error, String::from("x"));
assert_eq!(a, b);
}
#[test]
fn test_error_constructor_sets_error_severity() {
let d = Diagnostic::error("boom");
assert_eq!(d.severity(), Severity::Error);
assert!(d.is_error());
}
#[test]
fn test_warning_constructor_is_not_error() {
let d = Diagnostic::warning("hmm");
assert_eq!(d.severity(), Severity::Warning);
assert!(!d.is_error());
}
#[test]
fn test_note_constructor_is_not_error() {
let d = Diagnostic::note("fyi");
assert_eq!(d.severity(), Severity::Note);
assert!(!d.is_error());
}
#[test]
fn test_message_is_preserved() {
assert_eq!(
Diagnostic::error("unexpected token").message(),
"unexpected token"
);
}
#[test]
fn test_display_renders_severity_and_message() {
assert_eq!(Diagnostic::error("boom").to_string(), "error: boom");
assert_eq!(Diagnostic::note("here").to_string(), "note: here");
}
}