mod diag_handler;
mod diagnostic;
mod diagnostics;
mod level;
pub use diag_handler::*;
pub use diagnostic::*;
pub use diagnostics::*;
pub use level::*;
use miette::{Diagnostic as MietteDiagnostic, Report};
use thiserror::Error;
use crate::src_ref::*;
use microcad_core::hash::HashSet;
#[derive(Debug, Error, MietteDiagnostic)]
pub enum DiagError {
#[error("Error limit reached: Stopped evaluation after {0} errors")]
ErrorLimitReached(u32),
}
pub type DiagResult<T> = std::result::Result<T, DiagError>;
pub trait PushDiag {
fn push_diag(&mut self, diag: Diagnostic) -> DiagResult<()>;
fn trace(&mut self, src: &impl SrcReferrer, message: String) {
self.push_diag(Diagnostic::Trace(
Refer::new(Report::msg(message), src.src_ref()).into(),
))
.expect("could not push diagnostic trace message");
}
fn info(&mut self, src: &impl SrcReferrer, message: String) {
self.push_diag(Diagnostic::Info(
Refer::new(Report::msg(message), src.src_ref()).into(),
))
.expect("could not push diagnostic info message");
}
fn warning(&mut self, src: &impl SrcReferrer, err: impl Into<Report>) -> DiagResult<()> {
let err = Diagnostic::Warning(Refer::new(err.into(), src.src_ref()).into());
if cfg!(feature = "ansi-color") {
log::warn!("{}", color_print::cformat!("<y,s>{err}</>"));
} else {
log::warn!("{err}");
}
self.push_diag(err)
}
fn error(&mut self, src: &impl SrcReferrer, err: impl Into<Report>) -> DiagResult<()> {
let err = Diagnostic::Error(Refer::new(err.into(), src.src_ref()).into());
if cfg!(feature = "ansi-color") {
log::error!("{}", color_print::cformat!("<r,s>{err}</>"));
} else {
log::error!("{err}");
}
self.push_diag(err)
}
}
pub trait Diag {
fn fmt_diagnosis(&self, f: &mut dyn std::fmt::Write) -> std::fmt::Result;
fn write_diagnosis(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> {
write!(w, "{}", self.diagnosis())
}
fn diagnosis(&self) -> String {
let mut str = String::new();
self.fmt_diagnosis(&mut str).expect("displayable diagnosis");
str
}
fn has_warnings(&self) -> bool {
self.warning_count() > 0
}
fn warning_count(&self) -> u32;
fn has_errors(&self) -> bool {
self.error_count() > 0
}
fn error_count(&self) -> u32;
fn error_lines(&self) -> HashSet<u32>;
fn warning_lines(&self) -> HashSet<u32>;
}