-
Notifications
You must be signed in to change notification settings - Fork 331
Expand file tree
/
Copy patherror.rs
More file actions
136 lines (122 loc) · 4.54 KB
/
error.rs
File metadata and controls
136 lines (122 loc) · 4.54 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! Error types for WIT package resolution.
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::fmt;
use crate::{PackageName, SourceMap, Span};
/// Convenience alias for a `Result` whose error type is [`ResolveError`].
pub type ResolveResult<T, E = ResolveError> = Result<T, E>;
/// The category of error that occurred while resolving a WIT package.
#[non_exhaustive]
#[derive(Debug, PartialEq, Eq)]
pub enum ResolveErrorKind {
/// A referenced package could not be found among the known packages.
PackageNotFound {
span: Span,
requested: PackageName,
known: Vec<PackageName>,
},
/// An interface has a transitive dependency that creates an incompatible
/// import relationship.
InvalidTransitiveDependency { span: Span, name: String },
/// The same package is defined in two different locations.
DuplicatePackage {
name: PackageName,
span1: Span,
span2: Span,
},
/// Packages form a dependency cycle.
PackageCycle { package: PackageName, span: Span },
/// A semantic error during resolution (type mismatch, invalid use, etc.)
Semantic { span: Span, message: String },
}
impl ResolveErrorKind {
/// Returns the source span associated with this error.
pub fn span(&self) -> Span {
match self {
ResolveErrorKind::PackageNotFound { span, .. }
| ResolveErrorKind::InvalidTransitiveDependency { span, .. }
| ResolveErrorKind::PackageCycle { span, .. }
| ResolveErrorKind::Semantic { span, .. } => *span,
ResolveErrorKind::DuplicatePackage { span1, .. } => *span1,
}
}
}
impl fmt::Display for ResolveErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ResolveErrorKind::PackageNotFound {
requested, known, ..
} => {
if known.is_empty() {
write!(f, "package '{requested}' not found")
} else {
write!(f, "package '{requested}' not found. known packages:")?;
for k in known {
write!(f, "\n {k}")?;
}
Ok(())
}
}
ResolveErrorKind::InvalidTransitiveDependency { name, .. } => write!(
f,
"interface `{name}` transitively depends on an interface in incompatible ways",
),
ResolveErrorKind::DuplicatePackage { name, .. } => {
write!(f, "package `{name}` is defined in two different locations",)
}
ResolveErrorKind::PackageCycle { package, .. } => {
write!(f, "package `{package}` creates a dependency cycle")
}
ResolveErrorKind::Semantic { message, .. } => message.fmt(f),
}
}
}
/// A single structured error from resolving a WIT package.
#[derive(Debug, PartialEq, Eq)]
pub struct ResolveError(Box<ResolveErrorKind>);
impl ResolveError {
/// Creates a [`ResolveError`] with the [`ResolveErrorKind::Semantic`] variant.
pub fn new_semantic(span: Span, message: impl Into<String>) -> Self {
ResolveErrorKind::Semantic {
span,
message: message.into(),
}
.into()
}
/// Returns the underlying error kind.
pub fn kind(&self) -> &ResolveErrorKind {
&self.0
}
/// Returns the underlying error kind (mutable).
pub fn kind_mut(&mut self) -> &mut ResolveErrorKind {
&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();
let msg = e.to_string();
match e {
ResolveErrorKind::DuplicatePackage { name, span1, span2 } => {
let loc1 = source_map.render_location(*span1);
let loc2 = source_map.render_location(*span2);
format!(
"package `{name}` is defined in two different locations:\n * {loc1}\n * {loc2}"
)
}
_ => source_map.highlight_span(e.span(), &msg).unwrap_or(msg),
}
}
}
impl fmt::Display for ResolveError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.kind(), f)
}
}
impl core::error::Error for ResolveError {}
impl From<ResolveErrorKind> for ResolveError {
fn from(kind: ResolveErrorKind) -> Self {
ResolveError(Box::new(kind))
}
}