use std::collections::HashSet;
use std::fmt::Write;
use crate::lint::Diagnostic;
use crate::lint::rule::RuleId;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HelpMode {
#[default]
Auto,
Always,
Never,
}
pub fn render(source: &str, diagnostics: &[Diagnostic]) -> String {
render_with(source, diagnostics, HelpMode::Auto)
}
pub fn render_with(source: &str, diagnostics: &[Diagnostic], help: HelpMode) -> String {
let mut out = String::new();
let (mut e, mut w, mut i) = (0usize, 0usize, 0usize);
let mut help_seen: HashSet<(RuleId, String)> = HashSet::new();
for d in diagnostics {
let (line, col) = if d.has_span() {
(d.span.start.line, d.span.start.column)
} else {
(1, 1)
};
let _ = writeln!(
&mut out,
"{source}:{line}:{col}: {} [{}] {}",
d.severity.as_str(),
d.rule,
d.message
);
if let Some(s) = &d.suggestion {
let show_help = match help {
HelpMode::Always => true,
HelpMode::Never => false,
HelpMode::Auto => help_seen.insert((d.rule, s.clone())),
};
if show_help {
let _ = writeln!(&mut out, "{source}:{line}:{col}: help: {s}");
}
}
match d.severity {
crate::lint::Severity::Error => e += 1,
crate::lint::Severity::Warning => w += 1,
crate::lint::Severity::Info => i += 1,
}
}
let total = diagnostics.len();
if total == 0 {
out.push_str("0 diagnostics\n");
} else {
let _ = writeln!(
&mut out,
"{total} diagnostic{}: {e} error{}, {w} warning{}, {i} info",
if total == 1 { "" } else { "s" },
if e == 1 { "" } else { "s" },
if w == 1 { "" } else { "s" },
);
}
out
}