2024-12-09 12:01:07 +00:00
|
|
|
//! Top-level error for the Dust language API that can create detailed reports with source code
|
|
|
|
//! annotations.
|
2024-12-04 18:31:02 +00:00
|
|
|
use std::fmt::{self, Display, Formatter};
|
|
|
|
|
2024-09-10 05:04:30 +00:00
|
|
|
use annotate_snippets::{Level, Renderer, Snippet};
|
|
|
|
|
2024-12-04 18:31:02 +00:00
|
|
|
use crate::{CompileError, Span, VmError};
|
2024-09-07 08:34:03 +00:00
|
|
|
|
2024-12-09 12:01:07 +00:00
|
|
|
/// A top-level error that can occur during the interpretation of Dust code.
|
2024-09-07 16:15:47 +00:00
|
|
|
#[derive(Debug, PartialEq)]
|
2024-09-07 08:34:03 +00:00
|
|
|
pub enum DustError<'src> {
|
2024-11-06 20:40:37 +00:00
|
|
|
Compile {
|
|
|
|
error: CompileError,
|
2024-09-07 08:34:03 +00:00
|
|
|
source: &'src str,
|
|
|
|
},
|
2024-09-12 04:39:31 +00:00
|
|
|
Runtime {
|
|
|
|
error: VmError,
|
|
|
|
source: &'src str,
|
|
|
|
},
|
2024-09-07 08:34:03 +00:00
|
|
|
}
|
2024-09-10 05:04:30 +00:00
|
|
|
|
|
|
|
impl<'src> DustError<'src> {
|
2024-12-04 18:31:02 +00:00
|
|
|
pub fn compile(error: CompileError, source: &'src str) -> Self {
|
|
|
|
DustError::Compile { error, source }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn runtime(error: VmError, source: &'src str) -> Self {
|
|
|
|
DustError::Runtime { error, source }
|
|
|
|
}
|
|
|
|
|
2024-12-09 12:01:07 +00:00
|
|
|
pub fn report(&self) -> String {
|
2024-12-04 18:31:02 +00:00
|
|
|
let (position, title, description, details) = self.error_data();
|
|
|
|
let label = format!("{}: {}", title, description);
|
|
|
|
let details = details.unwrap_or_else(|| "While parsing this code".to_string());
|
|
|
|
let message = Level::Error.title(&label).snippet(
|
|
|
|
Snippet::source(self.source())
|
|
|
|
.fold(false)
|
|
|
|
.annotation(Level::Error.span(position.0..position.1).label(&details)),
|
|
|
|
);
|
2024-09-10 05:04:30 +00:00
|
|
|
let mut report = String::new();
|
|
|
|
let renderer = Renderer::styled();
|
|
|
|
|
2024-12-04 18:31:02 +00:00
|
|
|
report.push_str(&renderer.render(message).to_string());
|
2024-09-12 04:39:31 +00:00
|
|
|
|
2024-12-04 18:31:02 +00:00
|
|
|
report
|
|
|
|
}
|
2024-09-10 05:04:30 +00:00
|
|
|
|
2024-12-04 18:31:02 +00:00
|
|
|
fn error_data(&self) -> (Span, &str, &str, Option<String>) {
|
|
|
|
match self {
|
|
|
|
Self::Compile { error, .. } => (
|
|
|
|
error.position(),
|
|
|
|
CompileError::title(),
|
|
|
|
error.description(),
|
|
|
|
error.details(),
|
|
|
|
),
|
|
|
|
Self::Runtime { error, .. } => (
|
|
|
|
error.position(),
|
|
|
|
VmError::title(),
|
|
|
|
error.description(),
|
|
|
|
error.details(),
|
|
|
|
),
|
2024-09-10 05:04:30 +00:00
|
|
|
}
|
2024-12-04 18:31:02 +00:00
|
|
|
}
|
2024-09-10 05:04:30 +00:00
|
|
|
|
2024-12-04 18:31:02 +00:00
|
|
|
fn source(&self) -> &str {
|
|
|
|
match self {
|
|
|
|
Self::Compile { source, .. } => source,
|
|
|
|
Self::Runtime { source, .. } => source,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for DustError<'_> {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
2024-12-09 12:01:07 +00:00
|
|
|
write!(f, "{}", self.report())
|
2024-09-10 05:04:30 +00:00
|
|
|
}
|
|
|
|
}
|
2024-09-10 13:26:05 +00:00
|
|
|
|
|
|
|
pub trait AnnotatedError {
|
|
|
|
fn title() -> &'static str;
|
|
|
|
fn description(&self) -> &'static str;
|
|
|
|
fn details(&self) -> Option<String>;
|
|
|
|
fn position(&self) -> Span;
|
|
|
|
}
|