better error reporting
This commit is contained in:
parent
8405d01303
commit
d12d129eb8
4 changed files with 90 additions and 13 deletions
|
@ -1,9 +1,10 @@
|
|||
use eww_config::{ast::*, config::*};
|
||||
use eww_config::{ast::*, config::*, format_diagnostic::ToDiagnostic};
|
||||
|
||||
fn main() {
|
||||
let mut files = codespan_reporting::files::SimpleFiles::new();
|
||||
|
||||
let input = r#"(hi :bar 22 :baz {"hi" asdfasdf * 2} (foo) (baz))"#;
|
||||
let input = r#"
|
||||
(hi :bar 22 :baz {(foo == bar ? 12.K : 12)} (foo) (baz))"#;
|
||||
|
||||
let file_id = files.add("foo.eww", input);
|
||||
let ast = eww_config::parse_string(file_id, input);
|
||||
|
@ -12,10 +13,12 @@ fn main() {
|
|||
println!("{:?}", ast);
|
||||
}
|
||||
Err(err) => {
|
||||
let diag = err.pretty_diagnostic(&files);
|
||||
dbg!(&err);
|
||||
let diag = err.to_diagnostic(&files);
|
||||
use codespan_reporting::term;
|
||||
let config = term::Config::default();
|
||||
let mut writer = term::termcolor::StandardStream::stderr(term::termcolor::ColorChoice::Always);
|
||||
term::emit(&mut writer, &term::Config::default(), &files, &diag).unwrap();
|
||||
term::emit(&mut writer, &config, &files, &diag).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,15 +30,6 @@ impl AstError {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pretty_diagnostic(&self, files: &files::SimpleFiles<&str, &str>) -> diagnostic::Diagnostic<usize> {
|
||||
let diag = diagnostic::Diagnostic::error().with_message(format!("{}", self));
|
||||
if let Some(span) = self.get_span() {
|
||||
diag.with_labels(vec![diagnostic::Label::primary(span.2, span.0..span.1)])
|
||||
} else {
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_parse_error(
|
||||
file_id: usize,
|
||||
err: lalrpop_util::ParseError<usize, lexer::Token, parse_error::ParseError>,
|
||||
|
|
81
src/format_diagnostic.rs
Normal file
81
src/format_diagnostic.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
use codespan_reporting::{diagnostic, files};
|
||||
use simplexpr::dynval;
|
||||
|
||||
use crate::{ast::Span, error::AstError, parse_error};
|
||||
use diagnostic::*;
|
||||
|
||||
fn span_to_label(span: Span) -> Label<usize> {
|
||||
Label::primary(span.2, span.0..span.1)
|
||||
}
|
||||
|
||||
pub trait ToDiagnostic {
|
||||
fn to_diagnostic(&self, files: &files::SimpleFiles<&str, &str>) -> Diagnostic<usize>;
|
||||
}
|
||||
|
||||
impl ToDiagnostic for AstError {
|
||||
fn to_diagnostic(&self, files: &files::SimpleFiles<&str, &str>) -> Diagnostic<usize> {
|
||||
let diag = Diagnostic::error();
|
||||
if let Some(span) = self.get_span() {
|
||||
use lalrpop_util::ParseError::*;
|
||||
match self {
|
||||
AstError::InvalidDefinition(_) => todo!(),
|
||||
|
||||
AstError::MissingNode(_, expected) => diag
|
||||
.with_message(format!("Missing {}", expected))
|
||||
.with_labels(vec![span_to_label(span).with_message(format!("Expected `{}` here", expected))]),
|
||||
|
||||
AstError::WrongExprType(_, expected, actual) => diag
|
||||
.with_message("Wrong type of expression")
|
||||
.with_notes(vec![format!("Expected: {}\nGot: {}", expected, actual)])
|
||||
.with_labels(vec![span_to_label(span).with_message(format!("Expected a `{}` here", expected))]),
|
||||
|
||||
AstError::ParseError { file_id, source } => {
|
||||
lalrpop_error_to_diagnostic(source, diag, span, move |diag, error| match error {
|
||||
parse_error::ParseError::SimplExpr(_, error) => simplexpr_error_to_diagnostic(error, diag, span),
|
||||
parse_error::ParseError::LexicalError(_) => diag
|
||||
.with_message("Invalid token")
|
||||
.with_labels(vec![span_to_label(span).with_message("Invalid token")]),
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
diag.with_message(format!("{}", self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lalrpop_error_to_diagnostic<T: std::fmt::Display, E>(
|
||||
error: &lalrpop_util::ParseError<usize, T, E>,
|
||||
diag: Diagnostic<usize>,
|
||||
span: Span,
|
||||
handle_user_error: impl FnOnce(Diagnostic<usize>, &E) -> Diagnostic<usize>,
|
||||
) -> Diagnostic<usize> {
|
||||
use lalrpop_util::ParseError::*;
|
||||
match error {
|
||||
InvalidToken { location } => diag.with_message("Invalid token").with_labels(vec![span_to_label(span)]),
|
||||
UnrecognizedEOF { location, expected } => diag
|
||||
.with_message("Input ended unexpectedly. Check if you have any unclosed delimiters")
|
||||
.with_labels(vec![span_to_label(span)]),
|
||||
UnrecognizedToken { token, expected } => diag
|
||||
.with_message(format!("Unexpected token `{}` encoutered", token.1))
|
||||
.with_labels(vec![span_to_label(span).with_message("Token unexpected")]),
|
||||
|
||||
ExtraToken { token } => diag.with_message(format!("Extra token encountered: `{}`", token.1)),
|
||||
User { error } => handle_user_error(diag, error),
|
||||
}
|
||||
}
|
||||
|
||||
fn simplexpr_error_to_diagnostic(error: &simplexpr::error::Error, diag: Diagnostic<usize>, span: Span) -> Diagnostic<usize> {
|
||||
match error {
|
||||
simplexpr::error::Error::ParseError { source } => lalrpop_error_to_diagnostic(source, diag, span, move |diag, error| {
|
||||
diag.with_message("Invalid token").with_labels(vec![span_to_label(span).with_message("Invalid token")])
|
||||
}),
|
||||
simplexpr::error::Error::ConversionError(dynval::ConversionError { value, target_type, source }) => diag
|
||||
.with_message(format!("{}", error))
|
||||
.with_labels(vec![span_to_label(span).with_message(format!("{} is not of type `{}`", value, target_type))])
|
||||
.with_notes(source.as_ref().map(|x| vec![format!("{}", x)]).unwrap_or_default()),
|
||||
simplexpr::error::Error::Spanned(..) => todo!(),
|
||||
simplexpr::error::Error::Eval(error) => diag.with_message(format!("{}", error)).with_labels(vec![span_to_label(span)]),
|
||||
simplexpr::error::Error::Other(error) => diag.with_message(format!("{}", error)).with_labels(vec![span_to_label(span)]),
|
||||
}
|
||||
}
|
|
@ -5,9 +5,11 @@
|
|||
pub mod ast;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod format_diagnostic;
|
||||
mod lexer;
|
||||
mod parse_error;
|
||||
pub mod value;
|
||||
|
||||
use ast::Ast;
|
||||
use error::{AstError, AstResult};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue