driver_lang/severity.rs
1//! How serious a [`Diagnostic`](crate::Diagnostic) is.
2
3use core::fmt;
4
5/// The seriousness of a [`Diagnostic`](crate::Diagnostic).
6///
7/// A driver runs a program through a chain of stages, and each stage reports
8/// what it found by emitting diagnostics into the [`Session`](crate::Session).
9/// The severity is what tells the driver — and the person reading the output —
10/// whether a diagnostic is a hard failure that should stop compilation, a
11/// heads-up that something looks wrong, or a neutral remark that adds context.
12///
13/// Only [`Error`](Severity::Error) counts toward
14/// [`Session::error_count`](crate::Session::error_count); a warning or a note is
15/// recorded and rendered but never trips
16/// [`Session::abort_if_errors`](crate::Session::abort_if_errors). Ordering the
17/// variants by seriousness — error first — mirrors that: `Error < Warning < Note`
18/// is *not* the intent, so the type intentionally does not derive `Ord`. Compare
19/// with [`is_error`](Severity::is_error) instead of relying on a numeric rank.
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize))]
22#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
23pub enum Severity {
24 /// A hard failure. Counts toward the session's error total and makes
25 /// [`Session::abort_if_errors`](crate::Session::abort_if_errors) stop the
26 /// build.
27 Error,
28 /// Something suspicious that does not by itself stop compilation.
29 Warning,
30 /// Neutral context attached to the output — a hint, a location, a reminder.
31 Note,
32}
33
34impl Severity {
35 /// Whether this is [`Severity::Error`] — the only severity that counts as a
36 /// build failure.
37 ///
38 /// # Examples
39 ///
40 /// ```
41 /// use driver_lang::Severity;
42 ///
43 /// assert!(Severity::Error.is_error());
44 /// assert!(!Severity::Warning.is_error());
45 /// assert!(!Severity::Note.is_error());
46 /// ```
47 #[must_use]
48 #[inline]
49 pub fn is_error(self) -> bool {
50 matches!(self, Severity::Error)
51 }
52
53 /// The lowercase label used when a diagnostic is rendered
54 /// (`"error"`, `"warning"`, `"note"`).
55 ///
56 /// # Examples
57 ///
58 /// ```
59 /// use driver_lang::Severity;
60 ///
61 /// assert_eq!(Severity::Error.as_str(), "error");
62 /// assert_eq!(Severity::Warning.as_str(), "warning");
63 /// assert_eq!(Severity::Note.as_str(), "note");
64 /// ```
65 #[must_use]
66 #[inline]
67 pub fn as_str(self) -> &'static str {
68 match self {
69 Severity::Error => "error",
70 Severity::Warning => "warning",
71 Severity::Note => "note",
72 }
73 }
74}
75
76impl fmt::Display for Severity {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 f.write_str(self.as_str())
79 }
80}
81
82#[cfg(test)]
83#[allow(clippy::unwrap_used, clippy::expect_used)]
84mod tests {
85 use super::*;
86 use alloc::string::ToString;
87
88 #[test]
89 fn test_is_error_only_true_for_error() {
90 assert!(Severity::Error.is_error());
91 assert!(!Severity::Warning.is_error());
92 assert!(!Severity::Note.is_error());
93 }
94
95 #[test]
96 fn test_as_str_matches_variant() {
97 assert_eq!(Severity::Error.as_str(), "error");
98 assert_eq!(Severity::Warning.as_str(), "warning");
99 assert_eq!(Severity::Note.as_str(), "note");
100 }
101
102 #[test]
103 fn test_display_matches_as_str() {
104 assert_eq!(Severity::Warning.to_string(), "warning");
105 }
106}