solar_interface/diagnostics/emitter/
mod.rsuse super::{DiagCtxt, Diagnostic, Level};
use crate::SourceMap;
use std::{any::Any, sync::Arc};
mod human;
pub use human::{HumanBufferEmitter, HumanEmitter};
#[cfg(feature = "json")]
mod json;
#[cfg(feature = "json")]
pub use json::JsonEmitter;
mod rustc;
pub type DynEmitter = dyn Emitter + Send;
pub trait Emitter: Any {
fn emit_diagnostic(&mut self, diagnostic: &Diagnostic);
#[inline]
fn source_map(&self) -> Option<&Arc<SourceMap>> {
None
}
#[inline]
fn supports_color(&self) -> bool {
false
}
}
impl DynEmitter {
pub(crate) fn local_buffer(&self) -> Option<&str> {
self.downcast_ref::<HumanBufferEmitter>().map(HumanBufferEmitter::buffer)
}
fn downcast_ref<T: Any>(&self) -> Option<&T> {
if self.type_id() == std::any::TypeId::of::<T>() {
unsafe { Some(&*(self as *const dyn Emitter as *const T)) }
} else {
None
}
}
}
pub struct SilentEmitter {
fatal_dcx: DiagCtxt,
note: Option<String>,
}
impl SilentEmitter {
pub fn new(fatal_dcx: DiagCtxt) -> Self {
Self { fatal_dcx, note: None }
}
pub fn with_note(mut self, note: Option<String>) -> Self {
self.note = note;
self
}
}
impl Emitter for SilentEmitter {
fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
if diagnostic.level != Level::Fatal {
return;
}
let mut diagnostic = diagnostic.clone();
if let Some(note) = &self.note {
diagnostic.note(note.clone());
}
let _ = self.fatal_dcx.emit_diagnostic(diagnostic);
}
}
#[derive(Clone, Debug)]
pub struct LocalEmitter {
diagnostics: Vec<Diagnostic>,
}
impl Default for LocalEmitter {
fn default() -> Self {
Self::new()
}
}
impl LocalEmitter {
pub fn new() -> Self {
Self { diagnostics: Vec::new() }
}
pub fn diagnostics(&self) -> &[Diagnostic] {
&self.diagnostics
}
pub fn into_diagnostics(self) -> Vec<Diagnostic> {
self.diagnostics
}
}
impl Emitter for LocalEmitter {
fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
self.diagnostics.push(diagnostic.clone());
}
}
#[cold]
#[inline(never)]
fn io_panic(error: std::io::Error) -> ! {
panic!("failed to emit diagnostic: {error}");
}