solar_interface/diagnostics/emitter/
mod.rs1use super::{DiagCtxt, Diagnostic, 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: &Diagnostic);
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.downcast_ref::<HumanBufferEmitter>().map(HumanBufferEmitter::buffer)
39 }
40
41 fn downcast_ref<T: Any>(&self) -> Option<&T> {
43 if self.type_id() == std::any::TypeId::of::<T>() {
44 unsafe { Some(&*(self as *const dyn Emitter as *const T)) }
45 } else {
46 None
47 }
48 }
49}
50
51pub struct SilentEmitter {
53 fatal_dcx: DiagCtxt,
54 note: Option<String>,
55}
56
57impl SilentEmitter {
58 pub fn new(fatal_dcx: DiagCtxt) -> Self {
60 Self { fatal_dcx, note: None }
61 }
62
63 pub fn with_note(mut self, note: Option<String>) -> Self {
65 self.note = note;
66 self
67 }
68}
69
70impl Emitter for SilentEmitter {
71 fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
72 if diagnostic.level != Level::Fatal {
73 return;
74 }
75
76 let mut diagnostic = diagnostic.clone();
77 if let Some(note) = &self.note {
78 diagnostic.note(note.clone());
79 }
80 let _ = self.fatal_dcx.emit_diagnostic(diagnostic);
81 }
82}
83
84#[derive(Clone, Debug)]
86pub struct LocalEmitter {
87 diagnostics: Vec<Diagnostic>,
88}
89
90impl Default for LocalEmitter {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96impl LocalEmitter {
97 pub fn new() -> Self {
99 Self { diagnostics: Vec::new() }
100 }
101
102 pub fn diagnostics(&self) -> &[Diagnostic] {
104 &self.diagnostics
105 }
106
107 pub fn into_diagnostics(self) -> Vec<Diagnostic> {
109 self.diagnostics
110 }
111}
112
113impl Emitter for LocalEmitter {
114 fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
115 self.diagnostics.push(diagnostic.clone());
116 }
117}
118
119#[cold]
120#[inline(never)]
121fn io_panic(error: std::io::Error) -> ! {
122 panic!("failed to emit diagnostic: {error}");
123}