swc_error_reporters/
lib.rs1use std::fmt::{Debug, Display};
2
3use anyhow::anyhow;
4use handler::{to_pretty_handler, HandlerOpts, ThreadSafetyDiagnostics};
5pub use miette::{GraphicalReportHandler, GraphicalTheme};
6use swc_common::{
7 errors::{Diagnostic, DiagnosticBuilder, Emitter},
8 sync::Lrc,
9};
10
11mod diagnostic;
12pub mod handler;
13pub use diagnostic::{convert_span, to_pretty_source_code, ToPrettyDiagnostic};
14
15pub struct ErrorEmitter {
16 pub diagnostics: ThreadSafetyDiagnostics,
17 pub cm: Lrc<swc_common::SourceMap>,
18 pub opts: HandlerOpts,
19}
20
21impl Emitter for ErrorEmitter {
22 fn emit(&mut self, db: &mut DiagnosticBuilder<'_>) {
23 let d = db.take();
24 self.diagnostics.push(d);
25 }
26
27 fn take_diagnostics(&mut self) -> Vec<String> {
28 let HandlerOpts {
29 color,
30 skip_filename,
31 } = self.opts;
32
33 self.diagnostics
34 .to_pretty_string(&self.cm, skip_filename, color)
35 }
36}
37
38pub struct TWithDiagnosticArray<T: Debug + Display> {
41 inner: Option<T>,
42 diagnostics: Vec<Diagnostic>,
43 cm: Lrc<swc_common::SourceMap>,
44 report_opts: HandlerOpts,
45}
46
47impl<T: Debug + Display> Debug for TWithDiagnosticArray<T> {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 f.debug_struct("TWithDiagnosticArray")
50 .field("inner", &self.inner)
51 .field("diagnostics", &self.diagnostics)
52 .finish()
53 }
54}
55
56impl<T: Debug + Display> Display for TWithDiagnosticArray<T> {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 match self.inner.as_ref() {
59 Some(inner) => {
60 write!(f, "{}\n{}", self.take_pretty_diagnostics(), inner)
61 }
62 None => write!(f, "{}", self.take_pretty_diagnostics()),
63 }
64 }
65}
66
67impl<T: Debug + Display> TWithDiagnosticArray<T> {
68 pub fn new(
71 inner: Option<T>,
72 diagnostics: Vec<Diagnostic>,
73 cm: Lrc<swc_common::SourceMap>,
74 opts: HandlerOpts,
75 ) -> Self {
76 Self {
77 inner,
78 diagnostics,
79 cm,
80 report_opts: opts,
81 }
82 }
83
84 pub fn diagnostics(&self) -> &[Diagnostic] {
86 &self.diagnostics
87 }
88
89 pub fn take_diagnostics(self) -> Vec<Diagnostic> {
92 self.diagnostics
93 }
94
95 fn take_pretty_diagnostics(&self) -> String {
97 let HandlerOpts {
98 color,
99 skip_filename,
100 } = self.report_opts;
101
102 let report_handler = to_pretty_handler(color);
103
104 self.diagnostics
105 .iter()
106 .map(|d| d.to_pretty_string(&self.cm, skip_filename, &report_handler))
107 .collect::<String>()
108 }
109}
110
111impl TWithDiagnosticArray<anyhow::Error> {
112 pub fn to_pretty_error(self) -> anyhow::Error {
115 let pretty_diagnostics = self.take_pretty_diagnostics();
116
117 match self.inner {
118 Some(inner_error) => inner_error.context(pretty_diagnostics),
119 None => {
120 anyhow!(pretty_diagnostics)
121 }
122 }
123 }
124
125 pub fn to_pretty_string(self) -> String {
127 let pretty_error = self.to_pretty_error();
128
129 pretty_error.to_string()
130 }
131}