feat: starting to get pretty error messages
This commit is contained in:
parent
59d7b54473
commit
da89e9902c
|
@ -78,6 +78,7 @@ dependencies = [
|
|||
"internment",
|
||||
"miette",
|
||||
"pretty_assertions",
|
||||
"thiserror",
|
||||
"vec1",
|
||||
]
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -17,6 +17,7 @@ pub struct Source {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
struct ParsedModule {
|
||||
path: PathBuf,
|
||||
name: String,
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -5,7 +5,7 @@ pub type Datum {
|
|||
}
|
||||
|
||||
pub type Redeemer {
|
||||
Buy
|
||||
Buy,
|
||||
Sell
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue