kodept_macros/error/
traits.rs1use crate::error::report::{Report, ReportMessage};
2use crate::error::ErrorReported;
3use codespan_reporting::diagnostic::{Diagnostic, Severity};
4use codespan_reporting::files::{Error, Files};
5use codespan_reporting::term::termcolor::WriteColor;
6use codespan_reporting::term::Config;
7use extend::ext;
8use kodept_core::file_relative::{CodePath, FileRelative};
9
10#[derive(Clone)]
11pub struct CodespanSettings<S> {
12 pub config: Config,
13 pub stream: S,
14}
15
16pub trait Reportable {
17 type FileId;
18
19 fn emit<'f, W: WriteColor, F: Files<'f, FileId = Self::FileId>>(
20 self,
21 settings: &mut CodespanSettings<W>,
22 source: &'f F,
23 ) -> Result<(), Error>;
24}
25
26impl<FileId> Reportable for Diagnostic<FileId> {
27 type FileId = FileId;
28
29 fn emit<'f, W: WriteColor, F: Files<'f, FileId = Self::FileId>>(
30 self,
31 settings: &mut CodespanSettings<W>,
32 source: &'f F,
33 ) -> Result<(), Error> {
34 codespan_reporting::term::emit(&mut settings.stream, &settings.config, source, &self)
35 }
36}
37
38impl Reportable for Report {
39 type FileId = ();
40
41 fn emit<'f, W: WriteColor, F: Files<'f, FileId = Self::FileId>>(
42 self,
43 settings: &mut CodespanSettings<W>,
44 source: &'f F,
45 ) -> Result<(), Error> {
46 self.into_diagnostic().emit(settings, source)
47 }
48}
49
50impl<E: std::error::Error> Reportable for FileRelative<&E> {
51 type FileId = ();
52
53 fn emit<'f, W: WriteColor, F: Files<'f, FileId = Self::FileId>>(
54 self,
55 settings: &mut CodespanSettings<W>,
56 source: &'f F,
57 ) -> Result<(), Error> {
58 let report = Report::new(
59 &self.filepath,
60 vec![],
61 ReportMessage::new(Severity::Error, "external", self.value.to_string()),
62 );
63 report.emit(settings, source)
64 }
65}
66
67impl<R: Reportable> Reportable for Vec<R> {
68 type FileId = R::FileId;
69
70 fn emit<'f, W: WriteColor, F: Files<'f, FileId = Self::FileId>>(
71 self,
72 settings: &mut CodespanSettings<W>,
73 source: &'f F,
74 ) -> Result<(), Error> {
75 self.into_iter()
76 .try_for_each(|it| it.emit(settings, source))
77 }
78}
79
80#[ext]
81pub impl<T, R: Reportable> Result<T, R> {
82 fn or_emit<'f, W: WriteColor, F: Files<'f, FileId = R::FileId>>(
83 self,
84 settings: &mut CodespanSettings<W>,
85 source: &'f F,
86 ) -> Result<T, ErrorReported> {
87 match self {
88 Ok(x) => Ok(x),
89 Err(e) => {
90 e.emit(settings, source).expect("Cannot emit diagnostics");
91 Err(ErrorReported::new())
92 }
93 }
94 }
95}
96
97#[ext]
98pub impl<T, E: std::error::Error + Send + Sync + 'static> Result<T, E> {
99 fn or_emit<'f, W: WriteColor, F: Files<'f, FileId = ()>>(
100 self,
101 settings: &mut CodespanSettings<W>,
102 source: &'f F,
103 filepath: CodePath,
104 ) -> Result<T, ErrorReported> {
105 match self {
106 Ok(x) => Ok(x),
107 Err(e) => {
108 let file_relative = FileRelative {
109 value: &e,
110 filepath,
111 };
112 file_relative
113 .emit(settings, source)
114 .expect("Cannot emit diagnostics");
115 Err(ErrorReported::with_cause(e))
116 }
117 }
118 }
119}