iowo/src/error/mod.rs

92 lines
2.9 KiB
Rust

use codespan_reporting::{
diagnostic::{Diagnostic, Label},
files::SimpleFiles,
};
use crate::Span;
#[derive(Debug)]
pub struct Errors {
pub kind: ErrorKind,
pub locs: Vec<Span>,
}
#[derive(Debug)]
pub enum ErrorKind {
InvalidToken,
SyntaxError(SyntaxErrorKind),
CommandNotFound,
}
#[derive(Debug)]
pub enum SyntaxErrorKind {
/// `MissingStreamer` means, that the pipeline starts with a Pipe (`|`), so it has no streamer as input in front of it.
MissingStreamer,
/// `MissingSink` means, that the pipeline ends with a Pipe (`|`), meaning that the output can't go anywhere
MissingSink,
/// This indicates a missing filter somewhere in the pipeline, meaning that there's 2 pipes after one another
MissingFilter,
/// A literal cannot be a sink
LiteralAsSink,
/// A literal can't be a filter either
LiteralAsFilter,
/// A literal acting as streamer cannot take arguments
LiteralWithArgs,
}
impl Errors {
pub fn new(kind: ErrorKind, locs: Vec<Span>) -> Self {
Self { kind, locs }
}
pub fn new_single(kind: ErrorKind, loc: Span) -> Self {
Self {
kind,
locs: vec![loc],
}
}
pub fn into_diag(
&self,
file_id: usize,
_file_db: &SimpleFiles<&str, String>,
) -> Diagnostic<usize> {
let Errors { kind, locs } = self;
match kind {
ErrorKind::InvalidToken => simple_diag(locs.clone(), file_id, "invalid tokens"),
ErrorKind::SyntaxError(syntax_error) => match syntax_error {
SyntaxErrorKind::MissingStreamer => simple_diag(
locs.clone(),
file_id,
"pipeline is missing an input provider",
),
SyntaxErrorKind::MissingSink => {
simple_diag(locs.clone(), file_id, "pipeline is missing a sink")
}
SyntaxErrorKind::MissingFilter => {
simple_diag(locs.clone(), file_id, "missing filters in pipeline")
}
SyntaxErrorKind::LiteralAsSink => {
simple_diag(locs.clone(), file_id, "pipelines can't end in a literal")
}
SyntaxErrorKind::LiteralAsFilter => {
simple_diag(locs.clone(), file_id, "literals can't filter data")
}
SyntaxErrorKind::LiteralWithArgs => {
simple_diag(locs.clone(), file_id, "literals can't take arguments")
}
},
ErrorKind::CommandNotFound => simple_diag(locs.clone(), file_id, "command not found"),
}
}
}
fn simple_diag(spans: Vec<Span>, file_id: usize, msg: &str) -> Diagnostic<usize> {
Diagnostic::error().with_message(msg).with_labels(
spans
.into_iter()
.map(|span| Label::primary(file_id, span))
.collect(),
)
}