Refactor error reports
This commit is contained in:
parent
4433c587f5
commit
3c2a70803e
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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!(
|
||||
|
Loading…
Reference in New Issue
Block a user