teo_parser/diagnostics/
diagnostics.rs

1use 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}