FEATURE: Better attribution of errors to their file.

This commit is contained in:
Jeremy Wall 2019-01-23 21:21:13 -06:00
parent 3f69896a08
commit 2409f0c64e
2 changed files with 35 additions and 8 deletions

View File

@ -17,9 +17,8 @@ use std::error;
use std::fmt;
use std::fmt::Debug;
use abortable_parser::Positioned;
use crate::ast::*;
use crate::iter::FilePositioned;
/// ErrorType defines the various types of errors that can result from compiling UCG into an
/// output format.
@ -76,10 +75,14 @@ impl BuildError {
}
fn render(&self, w: &mut fmt::Formatter) -> fmt::Result {
let file = match self.pos.file {
Some(ref pb) => pb.to_string_lossy().to_string(),
None => "<eval>".to_string(),
};
write!(
w,
"{} at line: {} column: {}\nCaused By:\n\t{} ",
self.err_type, self.pos.line, self.pos.column, self.msg
"{} at {} line: {} column: {}\nCaused By:\n\t{} ",
self.err_type, file, self.pos.line, self.pos.column, self.msg
)?;
Ok(())
}
@ -104,11 +107,11 @@ impl error::Error for BuildError {
}
#[derive(Debug)]
pub struct StackPrinter<C: Positioned> {
pub struct StackPrinter<C: FilePositioned> {
pub err: abortable_parser::Error<C>,
}
impl<C: Positioned> StackPrinter<C> {
impl<C: FilePositioned> StackPrinter<C> {
pub fn render(&self, w: &mut fmt::Formatter) -> fmt::Result {
let mut curr_err = Some(&self.err);
let mut tabstop = "";
@ -118,11 +121,16 @@ impl<C: Positioned> StackPrinter<C> {
None => break,
Some(err) => {
let context = err.get_context();
let file = match context.file() {
Some(ref pb) => pb.to_string_lossy().to_string(),
None => "<eval>".to_string(),
};
write!(
w,
"{}{}: line: {}, column: {}\n",
"{}{}: at {} line: {}, column: {}\n",
tabstop,
err.get_msg(),
file,
context.line(),
context.column(),
)?;
@ -138,7 +146,7 @@ impl<C: Positioned> StackPrinter<C> {
}
}
impl<C: Positioned> fmt::Display for StackPrinter<C> {
impl<C: FilePositioned> fmt::Display for StackPrinter<C> {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
self.render(w)
}

View File

@ -121,3 +121,22 @@ impl<'a> From<&'a OffsetStrIter<'a>> for Position {
}
}
}
pub trait FilePositioned: Positioned {
fn file(&self) -> Option<&PathBuf>;
}
impl<'a> FilePositioned for OffsetStrIter<'a> {
fn file(&self) -> Option<&PathBuf> {
self.source_file.as_ref()
}
}
impl<'a> FilePositioned for SliceIter<'a, Token> {
fn file(&self) -> Option<&PathBuf> {
match self.peek_next() {
Some(t) => t.pos.file.as_ref(),
None => None,
}
}
}