-
Notifications
You must be signed in to change notification settings - Fork 331
Expand file tree
/
Copy patherror.rs
More file actions
120 lines (105 loc) · 3.39 KB
/
error.rs
File metadata and controls
120 lines (105 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Error types for WIT parsing.
use alloc::boxed::Box;
use alloc::string::{String, ToString};
use core::fmt;
use crate::{SourceMap, Span, ast::lex};
/// Convenience alias for a `Result` whose error type is [`ParseError`].
pub type ParseResult<T, E = ParseError> = Result<T, E>;
/// The category of error that occurred while parsing a WIT package.
#[non_exhaustive]
#[derive(Debug, PartialEq, Eq)]
pub enum ParseErrorKind {
/// Lexer error (invalid character, unterminated comment, etc.)
Lex(lex::Error),
/// Syntactic or semantic error within a single package (duplicate name,
/// invalid attribute, etc.)
Syntax { span: Span, message: String },
/// A type/interface/world references a name that does not exist within
/// the same package.
ItemNotFound {
span: Span,
name: String,
kind: String,
hint: Option<String>,
},
/// A type/interface/world depends on itself.
TypeCycle {
span: Span,
name: String,
kind: String,
},
}
impl ParseErrorKind {
/// Returns the source span associated with this error.
pub fn span(&self) -> Span {
match self {
ParseErrorKind::Lex(e) => Span::new(e.position(), e.position() + 1),
ParseErrorKind::Syntax { span, .. }
| ParseErrorKind::ItemNotFound { span, .. }
| ParseErrorKind::TypeCycle { span, .. } => *span,
}
}
}
impl fmt::Display for ParseErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParseErrorKind::Lex(e) => fmt::Display::fmt(e, f),
ParseErrorKind::Syntax { message, .. } => message.fmt(f),
ParseErrorKind::ItemNotFound {
kind, name, hint, ..
} => {
write!(f, "{kind} `{name}` does not exist")?;
if let Some(hint) = hint {
write!(f, "\n{hint}")?;
}
Ok(())
}
ParseErrorKind::TypeCycle { kind, name, .. } => {
write!(f, "{kind} `{name}` depends on itself")
}
}
}
}
/// A single structured error from parsing a WIT package.
#[derive(Debug, PartialEq, Eq)]
pub struct ParseError(Box<ParseErrorKind>);
impl ParseError {
pub fn new_syntax(span: Span, message: impl Into<String>) -> Self {
ParseErrorKind::Syntax {
span,
message: message.into(),
}
.into()
}
/// Returns the underlying error kind
pub fn kind(&self) -> &ParseErrorKind {
&self.0
}
/// Returns the underlying error kind (mutable).
pub fn kind_mut(&mut self) -> &mut ParseErrorKind {
&mut self.0
}
/// Format this error with source context (file:line:col + snippet)
pub fn highlight(&self, source_map: &SourceMap) -> String {
let e = self.kind();
source_map
.highlight_span(e.span(), e)
.unwrap_or_else(|| e.to_string())
}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.kind(), f)
}
}
impl core::error::Error for ParseError {}
impl From<ParseErrorKind> for ParseError {
fn from(kind: ParseErrorKind) -> Self {
ParseError(Box::new(kind))
}
}
impl From<lex::Error> for ParseError {
fn from(e: lex::Error) -> Self {
ParseErrorKind::Lex(e).into()
}
}