feat: starting to get pretty error messages

This commit is contained in:
rvcas 2022-10-11 13:55:38 -04:00 committed by Lucas
parent 59d7b54473
commit da89e9902c
8 changed files with 103 additions and 12 deletions

1
Cargo.lock generated
View File

@ -78,6 +78,7 @@ dependencies = [
"internment",
"miette",
"pretty_assertions",
"thiserror",
"vec1",
]

View File

@ -1,18 +1,80 @@
use std::{io, path::PathBuf};
use std::{
fmt::{Debug, Display},
io,
path::PathBuf,
};
use aiken_lang::error::ParseError;
use miette::{EyreContext, LabeledSpan, MietteHandlerOpts, RgbColors, SourceCode};
#[allow(dead_code)]
#[derive(Debug, thiserror::Error, miette::Diagnostic)]
#[derive(thiserror::Error)]
pub enum Error {
#[error("file operation failed")]
FileIo { path: PathBuf, error: io::Error },
#[error("failed to parse Aiken source code")]
#[error("failed to parse")]
Parse {
path: PathBuf,
src: String,
#[source]
error: Box<ParseError>,
},
#[error("list of errors")]
/// Useful for returning many [`Error::Parse`] at once
#[error("a list of errors")]
List(Vec<Self>),
}
impl Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let miette_handler = MietteHandlerOpts::new()
// For better support of terminal themes use the ANSI coloring
.rgb_colors(RgbColors::Never)
// If ansi support is disabled in the config disable the eye-candy
.color(true)
.unicode(true)
.terminal_links(true)
.build();
// Ignore error to prevent format! panics. This can happen if span points at some
// inaccessible location, for example by calling `report_error()` with wrong working set.
let _ = miette_handler.debug(self, f);
Ok(())
}
}
impl miette::Diagnostic for Error {
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
match self {
Error::Parse { .. } => Some(Box::new("aiken::parser".to_string())),
Error::FileIo { .. } => None,
Error::List(_) => None,
}
}
fn source_code(&self) -> Option<&dyn SourceCode> {
match self {
Error::Parse { src, .. } => Some(src),
Error::FileIo { .. } => None,
Error::List(_) => None,
}
}
fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
match self {
Error::Parse { error, .. } => error.labels(),
Error::FileIo { .. } => None,
Error::List(_) => None,
}
}
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
match self {
Error::Parse { error, .. } => error.kind.help(),
Error::FileIo { .. } => None,
Error::List(_) => None,
}
}
}

View File

@ -16,13 +16,15 @@ use uplc::{
},
};
use aiken::{config::Config, project::Project};
use aiken::{config::Config, error, project::Project};
mod args;
use args::{Args, TxCommand, UplcCommand};
fn main() -> miette::Result<()> {
miette::set_panic_hook();
let args = Args::default();
match args {
@ -47,7 +49,16 @@ fn main() -> miette::Result<()> {
let mut project = Project::new(config, project_path);
project.build()?;
if let Err(err) = project.build() {
match err {
error::Error::List(errors) => {
for error in errors {
eprintln!("Error: {:?}", error)
}
}
rest => Err(rest)?,
}
};
}
Args::Dev => {

View File

@ -17,6 +17,7 @@ pub struct Source {
}
#[derive(Debug)]
#[allow(dead_code)]
struct ParsedModule {
path: PathBuf,
name: String,

View File

@ -14,6 +14,7 @@ authors = ["Lucas Rosa <x@rvcas.dev>", "Kasey White <kwhitemsg@gmail.com>"]
chumsky = "0.8.0"
internment = "0.7.0"
miette = "5.2.0"
thiserror = "1.0.37"
vec1 = "1.8.0"
[dev-dependencies]

View File

@ -498,6 +498,12 @@ pub struct Span {
pub end: usize,
}
impl From<Span> for miette::SourceSpan {
fn from(span: Span) -> Self {
Self::new(span.start.into(), span.end.into())
}
}
impl Span {
pub fn empty() -> Self {
use chumsky::Span;

View File

@ -1,11 +1,15 @@
use std::{collections::HashSet, fmt};
use miette::Diagnostic;
use crate::{ast::Span, token::Token};
#[derive(Debug)]
#[derive(Debug, Diagnostic, thiserror::Error)]
#[error("{}", .kind)]
pub struct ParseError {
kind: ErrorKind,
span: Span,
pub kind: ErrorKind,
#[label]
pub span: Span,
#[allow(dead_code)]
while_parsing: Option<(Span, &'static str)>,
expected: HashSet<Pattern>,
@ -63,19 +67,24 @@ impl<T: Into<Pattern>> chumsky::Error<T> for ParseError {
}
}
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Diagnostic, thiserror::Error)]
pub enum ErrorKind {
#[error("unexpected end")]
UnexpectedEnd,
#[error("unexpected {0}")]
#[diagnostic(help("try removing it"))]
Unexpected(Pattern),
#[error("unclosed {start}")]
Unclosed {
start: Pattern,
before_span: Span,
before: Option<Pattern>,
},
#[error("no end branch")]
NoEndBranch,
}
#[derive(Debug, PartialEq, Eq, Hash)]
#[derive(Debug, PartialEq, Eq, Hash, Diagnostic, thiserror::Error)]
pub enum Pattern {
Char(char),
Token(Token),

View File

@ -5,7 +5,7 @@ pub type Datum {
}
pub type Redeemer {
Buy
Buy,
Sell
}