1use crate::source::SourceId;
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4
5mod display;
6mod from_std;
7mod source;
8
9pub type LexResult<T> = Result<T, OakError>;
15
16pub type ParseResult<T> = Result<T, OakError>;
22
23#[derive(Debug)]
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
33pub struct OakDiagnostics<T> {
34 pub result: Result<T, OakError>,
37 pub diagnostics: Vec<OakError>,
39}
40
41impl<T: Clone> Clone for OakDiagnostics<T> {
42 fn clone(&self) -> Self {
43 Self { result: self.result.clone(), diagnostics: self.diagnostics.clone() }
44 }
45}
46
47impl<T> OakDiagnostics<T> {
48 pub fn new(result: Result<T, OakError>) -> Self {
50 Self { result, diagnostics: Vec::new() }
51 }
52
53 pub fn success(value: T) -> Self {
55 Self { result: Ok(value), diagnostics: Vec::new() }
56 }
57
58 pub fn error(error: OakError) -> Self {
60 Self { result: Err(error), diagnostics: Vec::new() }
61 }
62
63 pub fn has_errors(&self) -> bool {
65 self.result.is_err() || !self.diagnostics.is_empty()
66 }
67}
68
69impl<'a, L: crate::Language> OakDiagnostics<&'a crate::tree::GreenNode<'a, L>> {
70 pub fn green(&self) -> &'a crate::tree::GreenNode<'a, L> {
72 self.result.as_ref().expect("Failed to get green node from parse output")
73 }
74}
75
76#[derive(Clone)]
82#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
83pub struct OakError {
84 kind: Box<OakErrorKind>,
86}
87
88impl OakError {
89 pub fn new(kind: OakErrorKind) -> Self {
91 Self { kind: Box::new(kind) }
92 }
93
94 pub fn custom_error(message: impl Into<String>) -> Self {
96 Self::new(OakErrorKind::CustomError { message: message.into() })
97 }
98}
99
100impl std::fmt::Debug for OakError {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 std::fmt::Display::fmt(self, f)
103 }
104}
105
106#[cfg(feature = "serde")]
107impl serde::ser::Error for OakError {
108 fn custom<T: std::fmt::Display>(msg: T) -> Self {
109 OakError::serde_error(msg.to_string())
110 }
111}
112
113#[cfg(feature = "serde")]
114impl serde::de::Error for OakError {
115 fn custom<T: std::fmt::Display>(msg: T) -> Self {
116 OakError::deserialize_error(msg.to_string())
117 }
118}
119
120#[cfg(feature = "serde")]
121mod serde_io_error {
122 use serde::{Deserialize, Deserializer, Serialize, Serializer};
123
124 pub fn serialize<S>(error: &std::io::Error, serializer: S) -> Result<S::Ok, S::Error>
125 where
126 S: Serializer,
127 {
128 error.to_string().serialize(serializer)
129 }
130
131 pub fn deserialize<'de, D>(deserializer: D) -> Result<std::io::Error, D::Error>
132 where
133 D: Deserializer<'de>,
134 {
135 let s = String::deserialize(deserializer)?;
136 Ok(std::io::Error::new(std::io::ErrorKind::Other, s))
137 }
138}
139
140#[derive(Debug)]
146#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
147pub enum OakErrorKind {
148 IoError {
150 #[cfg_attr(feature = "serde", serde(with = "crate::errors::serde_io_error"))]
152 error: std::io::Error,
153 source_id: Option<SourceId>,
155 },
156 SyntaxError {
158 message: String,
160 offset: usize,
162 source_id: Option<SourceId>,
164 },
165 UnexpectedCharacter {
167 character: char,
169 offset: usize,
171 source_id: Option<SourceId>,
173 },
174
175 UnexpectedToken {
177 token: String,
179 offset: usize,
181 source_id: Option<SourceId>,
183 },
184
185 UnexpectedEof {
187 offset: usize,
189 source_id: Option<SourceId>,
191 },
192
193 CustomError {
195 message: String,
197 },
198
199 InvalidTheme {
201 message: String,
203 },
204
205 UnsupportedFormat {
207 format: String,
209 },
210
211 ColorParseError {
213 color: String,
215 },
216
217 FormatError {
219 message: String,
221 },
222
223 SemanticError {
225 message: String,
227 },
228
229 ProtocolError {
231 message: String,
233 },
234
235 ExpectedToken {
237 expected: String,
239 offset: usize,
241 source_id: Option<SourceId>,
243 },
244
245 ExpectedName {
247 name_kind: String,
249 offset: usize,
251 source_id: Option<SourceId>,
253 },
254
255 TrailingCommaNotAllowed {
257 offset: usize,
259 source_id: Option<SourceId>,
261 },
262
263 TestFailure {
265 path: std::path::PathBuf,
267 expected: String,
269 actual: String,
271 },
272
273 TestRegenerated {
275 path: std::path::PathBuf,
277 },
278
279 SerdeError {
281 message: String,
283 },
284
285 DeserializeError {
287 message: String,
289 },
290
291 XmlError {
293 message: String,
295 },
296
297 ZipError {
299 message: String,
301 },
302
303 ParseError {
305 message: String,
307 },
308
309 InternalError {
311 message: String,
313 },
314}
315
316impl OakErrorKind {
317 pub fn key(&self) -> &'static str {
319 match self {
320 OakErrorKind::IoError { .. } => "error.io",
321 OakErrorKind::SyntaxError { .. } => "error.syntax",
322 OakErrorKind::UnexpectedCharacter { .. } => "error.unexpected_character",
323 OakErrorKind::UnexpectedToken { .. } => "error.unexpected_token",
324 OakErrorKind::UnexpectedEof { .. } => "error.unexpected_eof",
325 OakErrorKind::CustomError { .. } => "error.custom",
326 OakErrorKind::InvalidTheme { .. } => "error.invalid_theme",
327 OakErrorKind::UnsupportedFormat { .. } => "error.unsupported_format",
328 OakErrorKind::ColorParseError { .. } => "error.color_parse",
329 OakErrorKind::FormatError { .. } => "error.format",
330 OakErrorKind::SemanticError { .. } => "error.semantic",
331 OakErrorKind::ProtocolError { .. } => "error.protocol",
332 OakErrorKind::ExpectedToken { .. } => "error.expected_token",
333 OakErrorKind::ExpectedName { .. } => "error.expected_name",
334 OakErrorKind::TrailingCommaNotAllowed { .. } => "error.trailing_comma_not_allowed",
335 OakErrorKind::TestFailure { .. } => "error.test_failure",
336 OakErrorKind::TestRegenerated { .. } => "error.test_regenerated",
337 OakErrorKind::SerdeError { .. } => "error.serde",
338 OakErrorKind::DeserializeError { .. } => "error.deserialize",
339 OakErrorKind::XmlError { .. } => "error.xml",
340 OakErrorKind::ZipError { .. } => "error.zip",
341 OakErrorKind::ParseError { .. } => "error.parse",
342 OakErrorKind::InternalError { .. } => "error.internal",
343 }
344 }
345}
346
347impl OakError {
348 pub fn kind(&self) -> &OakErrorKind {
350 &self.kind
351 }
352
353 pub fn test_failure(path: std::path::PathBuf, expected: String, actual: String) -> Self {
355 OakErrorKind::TestFailure { path, expected, actual }.into()
356 }
357
358 pub fn test_regenerated(path: std::path::PathBuf) -> Self {
360 OakErrorKind::TestRegenerated { path }.into()
361 }
362
363 pub fn io_error(error: std::io::Error, source_id: SourceId) -> Self {
381 OakErrorKind::IoError { error, source_id: Some(source_id) }.into()
382 }
383
384 pub fn syntax_error(message: impl Into<String>, offset: usize, source_id: Option<SourceId>) -> Self {
400 OakErrorKind::SyntaxError { message: message.into(), offset, source_id }.into()
401 }
402
403 pub fn unexpected_character(character: char, offset: usize, source_id: Option<SourceId>) -> Self {
419 OakErrorKind::UnexpectedCharacter { character, offset, source_id }.into()
420 }
421
422 pub fn unexpected_token(token: impl Into<String>, offset: usize, source_id: Option<SourceId>) -> Self {
424 OakErrorKind::UnexpectedToken { token: token.into(), offset, source_id }.into()
425 }
426
427 pub fn unexpected_eof(offset: usize, source_id: Option<SourceId>) -> Self {
429 OakErrorKind::UnexpectedEof { offset, source_id }.into()
430 }
431
432 pub fn expected_token(expected: impl Into<String>, offset: usize, source_id: Option<SourceId>) -> Self {
434 OakErrorKind::ExpectedToken { expected: expected.into(), offset, source_id }.into()
435 }
436
437 pub fn expected_name(name_kind: impl Into<String>, offset: usize, source_id: Option<SourceId>) -> Self {
439 OakErrorKind::ExpectedName { name_kind: name_kind.into(), offset, source_id }.into()
440 }
441
442 pub fn trailing_comma_not_allowed(offset: usize, source_id: Option<SourceId>) -> Self {
444 OakErrorKind::TrailingCommaNotAllowed { offset, source_id }.into()
445 }
446
447 pub fn invalid_theme(message: impl Into<String>) -> Self {
449 OakErrorKind::InvalidTheme { message: message.into() }.into()
450 }
451
452 pub fn unsupported_format(format: impl Into<String>) -> Self {
454 OakErrorKind::UnsupportedFormat { format: format.into() }.into()
455 }
456
457 pub fn color_parse_error(color: impl Into<String>) -> Self {
459 OakErrorKind::ColorParseError { color: color.into() }.into()
460 }
461
462 pub fn format_error(message: impl Into<String>) -> Self {
464 OakErrorKind::FormatError { message: message.into() }.into()
465 }
466
467 pub fn semantic_error(message: impl Into<String>) -> Self {
469 OakErrorKind::SemanticError { message: message.into() }.into()
470 }
471
472 pub fn protocol_error(message: impl Into<String>) -> Self {
474 OakErrorKind::ProtocolError { message: message.into() }.into()
475 }
476
477 pub fn serde_error(message: impl Into<String>) -> Self {
479 OakErrorKind::SerdeError { message: message.into() }.into()
480 }
481
482 pub fn deserialize_error(message: impl Into<String>) -> Self {
484 OakErrorKind::DeserializeError { message: message.into() }.into()
485 }
486
487 pub fn xml_error(message: impl Into<String>) -> Self {
489 OakErrorKind::XmlError { message: message.into() }.into()
490 }
491
492 pub fn zip_error(message: impl Into<String>) -> Self {
494 OakErrorKind::ZipError { message: message.into() }.into()
495 }
496
497 pub fn parse_error(message: impl Into<String>) -> Self {
499 OakErrorKind::ParseError { message: message.into() }.into()
500 }
501
502 pub fn internal_error(message: impl Into<String>) -> Self {
504 OakErrorKind::InternalError { message: message.into() }.into()
505 }
506
507 pub fn with_source_id(mut self, source_id: SourceId) -> Self {
509 match self.kind.as_mut() {
510 OakErrorKind::IoError { source_id: u, .. } => *u = Some(source_id),
511 OakErrorKind::SyntaxError { source_id: u, .. } => *u = Some(source_id),
512 OakErrorKind::UnexpectedCharacter { source_id: u, .. } => *u = Some(source_id),
513 OakErrorKind::UnexpectedToken { source_id: u, .. } => *u = Some(source_id),
514 OakErrorKind::ExpectedToken { source_id: u, .. } => *u = Some(source_id),
515 OakErrorKind::ExpectedName { source_id: u, .. } => *u = Some(source_id),
516 OakErrorKind::TrailingCommaNotAllowed { source_id: u, .. } => *u = Some(source_id),
517 _ => {}
518 }
519 self
520 }
521}
522
523impl Clone for OakErrorKind {
524 fn clone(&self) -> Self {
525 match self {
526 OakErrorKind::IoError { error, source_id } => {
527 let new_error = std::io::Error::new(error.kind(), error.to_string());
529 OakErrorKind::IoError { error: new_error, source_id: *source_id }
530 }
531 OakErrorKind::SyntaxError { message, offset, source_id } => OakErrorKind::SyntaxError { message: message.clone(), offset: *offset, source_id: *source_id },
532 OakErrorKind::UnexpectedCharacter { character, offset, source_id } => OakErrorKind::UnexpectedCharacter { character: *character, offset: *offset, source_id: *source_id },
533 OakErrorKind::UnexpectedToken { token, offset, source_id } => OakErrorKind::UnexpectedToken { token: token.clone(), offset: *offset, source_id: *source_id },
534 OakErrorKind::UnexpectedEof { offset, source_id } => OakErrorKind::UnexpectedEof { offset: *offset, source_id: *source_id },
535 OakErrorKind::ExpectedToken { expected, offset, source_id } => OakErrorKind::ExpectedToken { expected: expected.clone(), offset: *offset, source_id: *source_id },
536 OakErrorKind::ExpectedName { name_kind, offset, source_id } => OakErrorKind::ExpectedName { name_kind: name_kind.clone(), offset: *offset, source_id: *source_id },
537 OakErrorKind::TrailingCommaNotAllowed { offset, source_id } => OakErrorKind::TrailingCommaNotAllowed { offset: *offset, source_id: *source_id },
538 OakErrorKind::CustomError { message } => OakErrorKind::CustomError { message: message.clone() },
539 OakErrorKind::InvalidTheme { message } => OakErrorKind::InvalidTheme { message: message.clone() },
540 OakErrorKind::UnsupportedFormat { format } => OakErrorKind::UnsupportedFormat { format: format.clone() },
541 OakErrorKind::ColorParseError { color } => OakErrorKind::ColorParseError { color: color.clone() },
542 OakErrorKind::FormatError { message } => OakErrorKind::FormatError { message: message.clone() },
543 OakErrorKind::SemanticError { message } => OakErrorKind::SemanticError { message: message.clone() },
544 OakErrorKind::ProtocolError { message } => OakErrorKind::ProtocolError { message: message.clone() },
545 OakErrorKind::TestFailure { path, expected, actual } => OakErrorKind::TestFailure { path: path.clone(), expected: expected.clone(), actual: actual.clone() },
546 OakErrorKind::TestRegenerated { path } => OakErrorKind::TestRegenerated { path: path.clone() },
547 OakErrorKind::SerdeError { message } => OakErrorKind::SerdeError { message: message.clone() },
548 OakErrorKind::DeserializeError { message } => OakErrorKind::DeserializeError { message: message.clone() },
549 OakErrorKind::XmlError { message } => OakErrorKind::XmlError { message: message.clone() },
550 OakErrorKind::ZipError { message } => OakErrorKind::ZipError { message: message.clone() },
551 OakErrorKind::ParseError { message } => OakErrorKind::ParseError { message: message.clone() },
552 OakErrorKind::InternalError { message } => OakErrorKind::InternalError { message: message.clone() },
553 }
554 }
555}