solar_interface/diagnostics/emitter/
mod.rs1use super::{Diag, Level};
2use crate::SourceMap;
3use std::{any::Any, sync::Arc};
4
5mod human;
6pub use human::{HumanBufferEmitter, HumanEmitter};
7
8#[cfg(feature = "json")]
9mod json;
10#[cfg(feature = "json")]
11pub use json::JsonEmitter;
12
13mod rustc;
14
15pub type DynEmitter = dyn Emitter + Send;
17
18pub trait Emitter: Any {
20 fn emit_diagnostic(&mut self, diagnostic: &Diag);
22
23 #[inline]
25 fn source_map(&self) -> Option<&Arc<SourceMap>> {
26 None
27 }
28
29 #[inline]
31 fn supports_color(&self) -> bool {
32 false
33 }
34}
35
36impl DynEmitter {
37 pub(crate) fn local_buffer(&self) -> Option<&str> {
38 (self as &dyn Any).downcast_ref::<HumanBufferEmitter>().map(HumanBufferEmitter::buffer)
39 }
40}
41
42pub struct SilentEmitter {
46 fatal_emitter: Option<Box<DynEmitter>>,
47 note: Option<String>,
48}
49
50impl SilentEmitter {
51 pub fn new(fatal_emitter: impl Emitter + Send) -> Self {
53 Self::new_boxed(Some(Box::new(fatal_emitter)))
54 }
55
56 pub fn new_boxed(fatal_emitter: Option<Box<DynEmitter>>) -> Self {
58 Self { fatal_emitter, note: None }
59 }
60
61 pub fn new_silent() -> Self {
65 Self::new_boxed(None)
66 }
67
68 pub fn with_note(mut self, note: Option<String>) -> Self {
70 self.note = note;
71 self
72 }
73}
74
75impl Emitter for SilentEmitter {
76 fn emit_diagnostic(&mut self, diagnostic: &Diag) {
77 let Some(fatal_emitter) = self.fatal_emitter.as_deref_mut() else { return };
78 if diagnostic.level != Level::Fatal {
79 return;
80 }
81
82 if let Some(note) = &self.note {
83 let mut diagnostic = diagnostic.clone();
84 diagnostic.note(note.clone());
85 fatal_emitter.emit_diagnostic(&diagnostic);
86 } else {
87 fatal_emitter.emit_diagnostic(diagnostic);
88 }
89 }
90}
91
92#[derive(Clone, Debug)]
94pub struct LocalEmitter {
95 diagnostics: Vec<Diag>,
96}
97
98impl Default for LocalEmitter {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104impl LocalEmitter {
105 pub fn new() -> Self {
107 Self { diagnostics: Vec::new() }
108 }
109
110 pub fn diagnostics(&self) -> &[Diag] {
112 &self.diagnostics
113 }
114
115 pub fn into_diagnostics(self) -> Vec<Diag> {
117 self.diagnostics
118 }
119}
120
121impl Emitter for LocalEmitter {
122 fn emit_diagnostic(&mut self, diagnostic: &Diag) {
123 self.diagnostics.push(diagnostic.clone());
124 }
125}
126
127#[cold]
128#[inline(never)]
129fn io_panic(error: std::io::Error) -> ! {
130 panic!("failed to emit diagnostic: {error}");
131}