use std::collections::HashMap;
use std::io::IsTerminal;
use std::sync::Arc;
use crate::diagnostic::{Diagnostic, DiagnosticCode};
use crate::formatter::{DiagnosticFormatter, RenderOptions};
use crate::DiagnosticEngine;
pub fn print_all_smart<C: DiagnosticCode>(engine: &DiagnosticEngine<C>, color: Option<bool>) {
let color = color.unwrap_or_else(|| std::io::stderr().is_terminal());
eprint!("{}", format_all_smart(engine, color));
}
pub fn format_all_smart<C: DiagnosticCode>(engine: &DiagnosticEngine<C>, color: bool) -> String {
let mut sources: HashMap<Arc<str>, Option<String>> = HashMap::new();
let mut out = String::new();
for d in engine.iter() {
out.push_str(&format_one_smart(d, &mut sources, color));
}
out.push_str(&engine.summary(color));
out
}
fn format_one_smart<C: DiagnosticCode>(
d: &Diagnostic<C>,
cache: &mut HashMap<Arc<str>, Option<String>>,
color: bool,
) -> String {
let Some(label) = d.primary_label() else {
return d.format_compact(color);
};
if label.span.line == 0 {
return d.format_compact(color);
}
let file = label.span.file.clone();
let entry = cache.entry(file.clone()).or_insert_with(|| std::fs::read_to_string(&*file).ok());
match entry {
Some(src) => {
let opts = RenderOptions { color, ..Default::default() };
DiagnosticFormatter::new(d, src).with_options(opts).format()
},
None => d.format_compact(color),
}
}