teo_parser/diagnostics/
diagnostics.rs1use std::any::TypeId;
2use crate::ast::span::Span;
3
4pub trait DiagnosticsLog {
5 fn span(&self) -> &Span;
6
7 fn message(&self) -> &str;
8
9 fn source_path(&self) -> &str;
10
11 fn into_warning(self) -> DiagnosticsWarning;
12
13 fn into_error(self) -> DiagnosticsError;
14
15 fn is_warning(&self) -> bool;
16
17 fn is_error(&self) -> bool;
18}
19
20#[derive(Debug, Clone)]
21pub struct DiagnosticsError {
22 span: Span,
23 message: String,
24 source_path: String,
25}
26
27impl DiagnosticsLog for DiagnosticsError {
28
29 fn span(&self) -> &Span {
30 &self.span
31 }
32
33 fn message(&self) -> &str {
34 self.message.as_str()
35 }
36
37 fn source_path(&self) -> &str {
38 &self.source_path
39 }
40
41 fn into_warning(self) -> DiagnosticsWarning {
42 panic!("unreachable 8")
43 }
44
45 fn into_error(self) -> DiagnosticsError {
46 self
47 }
48
49 fn is_warning(&self) -> bool {
50 false
51 }
52
53 fn is_error(&self) -> bool {
54 true
55 }
56}
57
58impl DiagnosticsLog for &DiagnosticsError {
59
60 fn span(&self) -> &Span {
61 &self.span
62 }
63
64 fn message(&self) -> &str {
65 self.message.as_str()
66 }
67
68 fn source_path(&self) -> &str {
69 &self.source_path
70 }
71
72 fn into_warning(self) -> DiagnosticsWarning {
73 panic!("unreachable 9")
74 }
75
76 fn into_error(self) -> DiagnosticsError {
77 self.clone()
78 }
79
80 fn is_warning(&self) -> bool {
81 false
82 }
83
84 fn is_error(&self) -> bool {
85 true
86 }
87}
88
89impl DiagnosticsError {
90
91 pub fn new(span: Span, message: impl Into<String>, source_path: impl Into<String>) -> Self {
92 Self { span, message: message.into(), source_path: source_path.into() }
93 }
94}
95
96#[derive(Debug, PartialEq, Eq, Clone)]
97pub struct DiagnosticsWarning {
98 span: Span,
99 message: String,
100 source_path: String,
101}
102
103impl DiagnosticsLog for DiagnosticsWarning {
104
105 fn span(&self) -> &Span {
106 &self.span
107 }
108
109 fn message(&self) -> &str {
110 self.message.as_str()
111 }
112
113 fn source_path(&self) -> &str {
114 &self.source_path
115 }
116
117 fn into_warning(self) -> DiagnosticsWarning {
118 self
119 }
120
121 fn into_error(self) -> DiagnosticsError {
122 panic!("unreachable 9")
123 }
124
125 fn is_warning(&self) -> bool {
126 true
127 }
128
129 fn is_error(&self) -> bool {
130 false
131 }
132}
133
134impl DiagnosticsLog for &DiagnosticsWarning {
135
136 fn span(&self) -> &Span {
137 &self.span
138 }
139
140 fn message(&self) -> &str {
141 self.message.as_str()
142 }
143
144 fn source_path(&self) -> &str {
145 &self.source_path
146 }
147
148 fn into_warning(self) -> DiagnosticsWarning {
149 self.clone()
150 }
151
152 fn into_error(self) -> DiagnosticsError {
153 panic!("unreachable 10")
154 }
155
156 fn is_warning(&self) -> bool {
157 true
158 }
159
160 fn is_error(&self) -> bool {
161 false
162 }
163}
164
165impl DiagnosticsWarning {
166
167 pub fn new(span: Span, message: impl Into<String>, source_path: impl Into<String>) -> Self {
168 Self { span, message: message.into(), source_path: source_path.into() }
169 }
170}
171
172#[derive(Debug, Clone)]
173pub struct Diagnostics {
174 errors: Vec<DiagnosticsError>,
175 warnings: Vec<DiagnosticsWarning>,
176}
177
178impl Diagnostics {
179
180 pub fn new() -> Diagnostics {
181 Diagnostics {
182 errors: Vec::new(),
183 warnings: Vec::new(),
184 }
185 }
186
187 pub fn has_errors(&self) -> bool {
188 !self.errors.is_empty()
189 }
190
191 pub fn has_warnings(&self) -> bool {
192 !self.warnings.is_empty()
193 }
194
195 pub fn warnings(&self) -> &Vec<DiagnosticsWarning> {
196 &self.warnings
197 }
198
199 pub fn errors(&self) -> &Vec<DiagnosticsError> {
200 &self.errors
201 }
202
203 pub fn insert<T>(&mut self, item: T) where T: DiagnosticsLog + 'static {
204 if TypeId::of::<T>() == TypeId::of::<DiagnosticsWarning>() {
205 self.warnings.push(item.into_warning());
206 } else if TypeId::of::<T>() == TypeId::of::<DiagnosticsError>() {
207 self.errors.push(item.into_error());
208 }
209 }
210}
211
212impl Default for Diagnostics {
213 fn default() -> Self {
214 Self::new()
215 }
216}