re_types_builder/
report.rs1use std::sync::mpsc;
2
3use camino::Utf8Path;
4
5pub fn init() -> (Report, Reporter) {
11 let (errors_tx, errors_rx) = mpsc::channel();
12 let (warnings_tx, warnings_rx) = mpsc::channel();
13 (
14 Report::new(errors_rx, warnings_rx),
15 Reporter::new(errors_tx, warnings_tx),
16 )
17}
18
19#[derive(Clone)]
21pub struct Reporter {
22 errors: mpsc::Sender<String>,
23 warnings: mpsc::Sender<String>,
24}
25
26impl Reporter {
27 fn new(errors: mpsc::Sender<String>, warnings: mpsc::Sender<String>) -> Self {
28 Self { errors, warnings }
29 }
30
31 #[expect(clippy::needless_pass_by_value)] pub fn error_file(&self, path: &Utf8Path, text: impl ToString) {
36 self.errors
37 .send(format!("{path}: {}", text.to_string()))
38 .ok();
39 }
40
41 #[expect(clippy::needless_pass_by_value)] pub fn error(&self, virtpath: &str, fqname: &str, text: impl ToString) {
43 self.errors
44 .send(format!(
45 "{} {fqname}: {}",
46 Self::format_virtpath(virtpath),
47 text.to_string()
48 ))
49 .ok();
50 }
51
52 #[expect(clippy::needless_pass_by_value)] pub fn warn_no_context(&self, text: impl ToString) {
54 self.warnings.send(text.to_string()).ok();
55 }
56
57 #[expect(clippy::needless_pass_by_value)] pub fn warn(&self, virtpath: &str, fqname: &str, text: impl ToString) {
59 self.warnings
60 .send(format!(
61 "{} {fqname}: {}",
62 Self::format_virtpath(virtpath),
63 text.to_string()
64 ))
65 .ok();
66 }
67
68 #[expect(clippy::needless_pass_by_value)] pub fn error_any(&self, text: impl ToString) {
70 self.errors.send(text.to_string()).ok();
71 }
72
73 fn format_virtpath(virtpath: &str) -> String {
75 if let Ok(path) = Utf8Path::new(virtpath).canonicalize() {
76 path.display().to_string()
77 } else if let Ok(path) =
78 Utf8Path::new(&format!("crates/store/re_types/definitions/{virtpath}")).canonicalize()
79 {
80 path.display().to_string()
81 } else {
82 virtpath.to_owned()
83 }
84 }
85}
86
87pub struct Report {
91 errors: mpsc::Receiver<String>,
92 warnings: mpsc::Receiver<String>,
93 _not_send: std::marker::PhantomData<*mut ()>,
94}
95
96impl Report {
97 fn new(errors: mpsc::Receiver<String>, warnings: mpsc::Receiver<String>) -> Self {
98 Self {
99 errors,
100 warnings,
101 _not_send: std::marker::PhantomData,
102 }
103 }
104
105 pub fn finalize(&self, warnings_as_errors: bool) {
107 use colored::Colorize as _;
108
109 let mut any_errors = false;
110
111 while let Ok(warn) = self.warnings.try_recv() {
112 if warnings_as_errors {
113 any_errors = true;
114 eprintln!(
115 "{} {}",
116 "Error (warnings as errors enabled): ".red().bold(),
117 warn
118 );
119 } else {
120 eprintln!("{} {}", "Warning: ".yellow().bold(), warn);
121 }
122 }
123
124 while let Ok(err) = self.errors.try_recv() {
125 any_errors = true;
126 eprintln!("{} {}", "Error: ".red().bold(), err);
127 }
128
129 if any_errors {
130 println!("Some errors occurred.");
131 std::process::exit(1);
132 }
133 }
134}
135
136const _: () = {
137 trait IsNotSend<T> {
156 fn __() {}
157 }
158
159 type False = ();
160
161 struct True;
162
163 struct Check<T: ?Sized>(T);
164
165 impl<T: ?Sized> IsNotSend<True> for Check<T> {}
166
167 impl<T: ?Sized + Send> IsNotSend<False> for Check<T> {}
168
169 let _ = <Check<Report> as IsNotSend<_>>::__;
172
173 fn assert_send<T: Send>() {}
174 let _ = assert_send::<Reporter>;
175};