Refactor error reports

This commit is contained in:
Jeff 2024-09-02 11:04:08 -04:00
parent 4433c587f5
commit 3c2a70803e
3 changed files with 75 additions and 27 deletions

View File

@ -61,9 +61,13 @@ impl Context {
&self,
identifier: &Identifier,
) -> Result<Option<(ContextData, usize)>, ContextError> {
let associations = self.associations.read()?;
Ok(associations.get(identifier).cloned())
if let Some((variable_data, position)) = self.associations.read()?.get(identifier) {
Ok(Some((variable_data.clone(), *position)))
} else if let Some(parent) = &self.parent {
parent.get(identifier)
} else {
Ok(None)
}
}
/// Returns the type associated with the given identifier.
@ -268,11 +272,9 @@ impl Context {
let mut associations = self.associations.write()?;
if let Some((_, last_position)) = associations.get_mut(identifier) {
if position > *last_position {
log::trace!("Updating {identifier}'s last position to {position:?}");
*last_position = position;
}
Ok(true)
} else {

View File

@ -1,8 +1,8 @@
//! Top-level error handling for the Dust language.
use annotate_snippets::{Level, Renderer, Snippet};
use annotate_snippets::{Level, Message, Renderer, Snippet};
use std::fmt::Display;
use crate::{Span, AnalysisError, ContextError, LexError, ParseError, RuntimeError};
use crate::{AnalysisError, ContextError, LexError, ParseError, RuntimeError, Span};
/// An error that occurred during the execution of the Dust language and its
/// corresponding source code.
@ -79,14 +79,26 @@ impl<'src> DustError<'src> {
}
}
pub fn error_data(&self) -> Vec<(&'static str, Span, String)> {
fn footer(&self) -> Vec<(&'static str, Span, String)> {
match self {
DustError::ContextError(_) => vec![],
DustError::Runtime { runtime_error, .. } => vec![(
DustError::Runtime { runtime_error, .. } => {
let mut error_data = vec![(
"Runtime error",
runtime_error.position(),
runtime_error.to_string(),
)],
)];
if let RuntimeError::Expression { error, position } = runtime_error {
error_data.push((
"Error occured at this expression",
*position,
error.to_string(),
));
}
error_data
}
DustError::Analysis {
analysis_errors, ..
} => analysis_errors
@ -108,13 +120,43 @@ impl<'src> DustError<'src> {
let mut report = String::new();
let renderer = Renderer::styled();
for (title, span, label) in self.error_data() {
let message = Level::Error.title(title).snippet(
Snippet::source(self.source())
.annotation(Level::Info.span(span.0..span.1).label(&label)),
match self {
DustError::ContextError(_) => {
let message = Level::Error.title("Context error");
report.push_str(&renderer.render(message).to_string());
}
DustError::Runtime {
runtime_error,
source,
} => {
let error = runtime_error.root_error();
let position = error.position();
let label = error.to_string();
let message = Level::Error
.title("Runtime error")
.snippet(
Snippet::source(source)
.fold(true)
.annotation(Level::Error.span(position.0..position.1).label(&label)),
)
.footer(
Level::Error
.title("This error occured during the execution of the Dust program."),
);
report.push_str(&format!("{}", renderer.render(message)));
report.push_str(&renderer.render(message).to_string());
report.push('\n');
}
DustError::Analysis {
analysis_errors,
source,
} => todo!(),
DustError::Parse {
parse_error,
source,
} => todo!(),
DustError::Lex { lex_error, source } => todo!(),
}
report

View File

@ -1236,6 +1236,14 @@ impl RuntimeError {
Self::UndefinedField { field_position, .. } => *field_position,
}
}
pub fn root_error(&self) -> &Self {
match self {
Self::Expression { error, .. } => error.root_error(),
Self::Statement { error, .. } => error.root_error(),
error => error,
}
}
}
impl From<ParseError> for RuntimeError {
@ -1264,12 +1272,8 @@ impl Display for RuntimeError {
write!(f, "Function call error at {:?}: {}", position, error)
}
Self::ParseError(parse_error) => write!(f, "{}", parse_error),
Self::Expression { error, position } => {
write!(
f,
"Error while running expression at {:?}: {}",
position, error
)
Self::Expression { .. } => {
write!(f, "Error while running expression")
}
Self::Statement { error, position } => {
write!(