use crate::{GetSourceLocInfoByHash, diag::*};
use microcad_core::hash::HashSet;
use std::io::IsTerminal;
#[derive(Default)]
pub struct DiagHandler {
pub diagnostics: Diagnostics,
error_limit: Option<u32>,
error_limit_reached: bool,
warnings_as_errors: bool,
pub render_options: DiagRenderOptions,
}
#[derive(Debug)]
pub struct DiagRenderOptions {
pub color: bool,
pub unicode: bool,
}
impl Default for DiagRenderOptions {
fn default() -> Self {
DiagRenderOptions {
color: std::env::var("NO_COLOR").as_deref().unwrap_or("0") == "0",
unicode: std::io::stdout().is_terminal() && std::io::stderr().is_terminal(),
}
}
}
impl DiagRenderOptions {
pub fn theme(&self) -> miette::GraphicalTheme {
match (self.unicode, self.color) {
(true, true) => miette::GraphicalTheme::unicode(),
(true, false) => miette::GraphicalTheme::unicode_nocolor(),
(false, true) => miette::GraphicalTheme::ascii(),
(false, false) => miette::GraphicalTheme::none(),
}
}
}
impl DiagHandler {
pub fn pretty_print(
&self,
f: &mut dyn std::fmt::Write,
source_by_hash: &impl GetSourceLocInfoByHash,
) -> std::fmt::Result {
self.diagnostics
.pretty_print(f, source_by_hash, &self.render_options)
}
pub fn warning_count(&self) -> u32 {
self.diagnostics.warning_count()
}
pub fn error_count(&self) -> u32 {
self.diagnostics.error_count()
}
pub fn error_lines(&self) -> HashSet<u32> {
self.diagnostics.error_lines()
}
pub fn warning_lines(&self) -> HashSet<u32> {
self.diagnostics.warning_lines()
}
pub fn clear(&mut self) {
self.diagnostics.clear();
}
}
impl PushDiag for DiagHandler {
fn push_diag(&mut self, diag: Diagnostic) -> DiagResult<()> {
if let Some(error_limit) = self.error_limit {
if self.error_count() >= error_limit && !self.error_limit_reached {
self.error(&SrcRef::none(), DiagError::ErrorLimitReached(error_limit))?;
self.error_limit_reached = true;
}
return Err(DiagError::ErrorLimitReached(error_limit));
}
let diag = match diag {
Diagnostic::Warning(refer) if self.warnings_as_errors => Diagnostic::Error(refer),
diag => diag,
};
self.diagnostics.push_diag(diag)
}
}