microcad_lang_base/diag/
mod.rs1mod diag_handler;
14mod diagnostic;
15mod diagnostics;
16mod level;
17
18pub use diag_handler::*;
19pub use diagnostic::*;
20pub use diagnostics::*;
21pub use level::*;
22use miette::{Diagnostic as MietteDiagnostic, Report};
23
24use thiserror::Error;
25
26use crate::src_ref::*;
27use microcad_core::hash::HashSet;
28
29#[derive(Debug, Error, MietteDiagnostic)]
31pub enum DiagError {
32 #[error("Error limit reached: Stopped evaluation after {0} errors")]
34 ErrorLimitReached(u32),
35}
36
37pub type DiagResult<T> = std::result::Result<T, DiagError>;
39
40pub trait PushDiag {
42 fn push_diag(&mut self, diag: Diagnostic) -> DiagResult<()>;
44
45 fn trace(&mut self, src: &impl SrcReferrer, message: String) {
47 self.push_diag(Diagnostic::Trace(
48 Refer::new(Report::msg(message), src.src_ref()).into(),
49 ))
50 .expect("could not push diagnostic trace message");
51 }
52 fn info(&mut self, src: &impl SrcReferrer, message: String) {
54 self.push_diag(Diagnostic::Info(
55 Refer::new(Report::msg(message), src.src_ref()).into(),
56 ))
57 .expect("could not push diagnostic info message");
58 }
59 fn warning(&mut self, src: &impl SrcReferrer, err: impl Into<Report>) -> DiagResult<()> {
61 let err = Diagnostic::Warning(Refer::new(err.into(), src.src_ref()).into());
62 if cfg!(feature = "ansi-color") {
63 log::warn!("{}", color_print::cformat!("<y,s>{err}</>"));
64 } else {
65 log::warn!("{err}");
66 }
67 self.push_diag(err)
68 }
69 fn error(&mut self, src: &impl SrcReferrer, err: impl Into<Report>) -> DiagResult<()> {
71 let err = Diagnostic::Error(Refer::new(err.into(), src.src_ref()).into());
72 if cfg!(feature = "ansi-color") {
73 log::error!("{}", color_print::cformat!("<r,s>{err}</>"));
74 } else {
75 log::error!("{err}");
76 }
77 self.push_diag(err)
78 }
79}
80
81pub trait Diag {
83 fn fmt_diagnosis(&self, f: &mut dyn std::fmt::Write) -> std::fmt::Result;
85
86 fn write_diagnosis(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> {
88 write!(w, "{}", self.diagnosis())
89 }
90
91 fn diagnosis(&self) -> String {
93 let mut str = String::new();
94 self.fmt_diagnosis(&mut str).expect("displayable diagnosis");
95 str
96 }
97
98 fn has_warnings(&self) -> bool {
100 self.warning_count() > 0
101 }
102
103 fn warning_count(&self) -> u32;
105
106 fn has_errors(&self) -> bool {
108 self.error_count() > 0
109 }
110
111 fn error_count(&self) -> u32;
113
114 fn error_lines(&self) -> HashSet<u32>;
116
117 fn warning_lines(&self) -> HashSet<u32>;
119}