use std::slice::Iter;
use crate::{GetSourceLocInfoByHash, diag::*};
#[derive(Debug, Default, Clone)]
pub struct Diagnostics {
error_count: u32,
warning_count: u32,
diagnostics: Vec<Diagnostic>,
}
impl Diagnostics {
pub fn has_errors(&self) -> bool {
self.error_count > 0
}
pub fn has_warnings(&self) -> bool {
self.warning_count > 0
}
pub fn iter(&'_ self) -> Iter<'_, Diagnostic> {
self.diagnostics.iter()
}
pub fn clear(&mut self) {
self.diagnostics.clear();
self.error_count = 0;
self.warning_count = 0;
}
pub fn pretty_print(
&self,
f: &mut dyn std::fmt::Write,
source_by_hash: &impl GetSourceLocInfoByHash,
options: &DiagRenderOptions,
) -> std::fmt::Result {
self.diagnostics
.iter()
.try_for_each(|diag| diag.pretty_print(f, source_by_hash, options))
}
pub fn append(&mut self, mut other: Diagnostics) {
self.error_count += other.error_count;
self.warning_count += other.warning_count;
self.diagnostics.append(&mut other.diagnostics);
}
pub fn warning_count(&self) -> u32 {
self.warning_count
}
pub fn error_count(&self) -> u32 {
self.error_count
}
pub fn error_lines(&self) -> HashSet<u32> {
self.iter()
.filter_map(|d| {
if d.level() == Level::Error {
d.src_ref().line()
} else {
None
}
})
.collect()
}
pub fn warning_lines(&self) -> HashSet<u32> {
self.iter()
.filter_map(|d| {
if d.level() == Level::Warning {
d.src_ref().line()
} else {
None
}
})
.collect()
}
}
impl<R> From<R> for Diagnostics
where
R: Into<Report>,
{
fn from(report: R) -> Self {
Self {
error_count: 1,
warning_count: 0,
diagnostics: vec![Diagnostic::Error(std::rc::Rc::new(Refer::none(
report.into(),
)))],
}
}
}
impl FromIterator<Diagnostics> for Diagnostics {
fn from_iter<I: IntoIterator<Item = Diagnostics>>(iter: I) -> Self {
let mut root = Diagnostics::default();
for other in iter {
root.append(other);
}
root
}
}
impl PushDiag for Diagnostics {
fn push_diag(&mut self, diag: Diagnostic) -> DiagResult<()> {
match &diag {
Diagnostic::Error(_) => {
self.error_count += 1;
}
Diagnostic::Warning(_) => {
self.warning_count += 1;
}
_ => (),
}
self.diagnostics.push(diag);
Ok(())
}
}