use std::ops::Range;
use gpui::{Hsla, SharedString};
use crate::theme::Theme;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Severity {
Hint,
Info,
Warning,
Error,
}
impl Severity {
pub fn color(self, t: &Theme) -> Hsla {
match self {
Severity::Error => t.danger().hsla(),
Severity::Warning => t.warning().hsla(),
Severity::Info => t.info().hsla(),
Severity::Hint => t.dimmed().hsla(),
}
}
}
#[derive(Debug, Clone)]
pub struct Diagnostic {
pub line: usize,
pub cols: Range<usize>,
pub severity: Severity,
pub message: SharedString,
}
impl Diagnostic {
pub fn new(
line: usize,
cols: Range<usize>,
severity: Severity,
message: impl Into<SharedString>,
) -> Self {
Diagnostic {
line,
cols,
severity,
message: message.into(),
}
}
pub fn line_wide(line: usize, severity: Severity, message: impl Into<SharedString>) -> Self {
Diagnostic::new(line, 0..0, severity, message)
}
}
pub(crate) fn line_severity(diagnostics: &[Diagnostic], line: usize) -> Option<Severity> {
diagnostics
.iter()
.filter(|d| d.line == line)
.map(|d| d.severity)
.max()
}
pub(crate) fn line_message(diagnostics: &[Diagnostic], line: usize) -> Option<&Diagnostic> {
diagnostics
.iter()
.filter(|d| d.line == line)
.max_by_key(|d| d.severity)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn severity_orders_worst_last() {
assert!(Severity::Error > Severity::Warning);
assert!(Severity::Warning > Severity::Info);
assert!(Severity::Info > Severity::Hint);
}
#[test]
fn line_lookups_pick_the_worst() {
let diags = vec![
Diagnostic::new(2, 0..4, Severity::Warning, "unused"),
Diagnostic::new(2, 6..9, Severity::Error, "type mismatch"),
Diagnostic::line_wide(5, Severity::Hint, "style"),
];
assert_eq!(line_severity(&diags, 2), Some(Severity::Error));
assert_eq!(line_severity(&diags, 5), Some(Severity::Hint));
assert_eq!(line_severity(&diags, 0), None);
assert_eq!(line_message(&diags, 2).unwrap().message.as_ref(), "type mismatch");
}
#[test]
fn line_wide_uses_an_empty_range() {
let d = Diagnostic::line_wide(3, Severity::Error, "boom");
assert!(d.cols.is_empty());
assert_eq!(d.line, 3);
}
}