grass/src/error.rs

127 lines
3.1 KiB
Rust
Raw Normal View History

2020-01-06 18:26:07 -05:00
use std::error::Error;
use std::fmt::{self, Display};
use std::io;
use std::string::FromUtf8Error;
2020-04-12 19:37:12 -04:00
use codemap::{Span, SpanLoc};
2020-03-01 14:53:52 -05:00
pub type SassResult<T> = Result<T, SassError>;
2020-04-12 19:37:12 -04:00
#[derive(Debug)]
2020-01-06 18:26:07 -05:00
pub struct SassError {
2020-04-12 19:37:12 -04:00
kind: SassErrorKind,
2020-01-06 18:26:07 -05:00
}
impl SassError {
2020-04-12 19:37:12 -04:00
pub(crate) fn raw(self) -> (String, Span) {
match self.kind {
SassErrorKind::Raw(string, span) => (string, span),
_ => todo!(),
}
}
pub(crate) fn from_loc(message: String, loc: SpanLoc) -> Self {
2020-01-06 19:23:52 -05:00
SassError {
2020-04-12 19:37:12 -04:00
kind: SassErrorKind::ParseError { message, loc },
2020-01-06 19:23:52 -05:00
}
2020-01-06 18:26:07 -05:00
}
}
2020-04-12 19:37:12 -04:00
#[derive(Debug)]
enum SassErrorKind {
/// A raw error with no additional metadata
/// It contains only a `String` message and
/// a span
Raw(String, Span),
ParseError {
message: String,
loc: SpanLoc,
},
IoError(io::Error),
FmtError(fmt::Error),
FromUtf8Error(String),
}
2020-01-06 18:26:07 -05:00
impl Display for SassError {
2020-04-12 19:37:12 -04:00
// TODO: trim whitespace
// TODO: color errors
// TODO: integrate with codemap-diagnostics
2020-01-06 18:26:07 -05:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2020-04-12 19:37:12 -04:00
let (message, loc) = match &self.kind {
SassErrorKind::ParseError { message, loc } => (message, loc),
_ => todo!(),
};
let line = loc.begin.line + 1;
let col = loc.begin.column + 1;
writeln!(f, "Error: {}", message)?;
let padding = vec![' '; format!("{}", line).len() + 1]
.iter()
.collect::<String>();
writeln!(f, "{}|", padding)?;
writeln!(f, "{} | {}", line, loc.file.source_line(loc.begin.line))?;
writeln!(
f,
"{}| {}{}",
padding,
vec![' '; loc.begin.column].iter().collect::<String>(),
vec!['^'; loc.end.column - loc.begin.column]
.iter()
.collect::<String>()
)?;
writeln!(f, "{}|", padding)?;
writeln!(f, "./{}:{}:{}", loc.file.name(), line, col)?;
Ok(())
2020-01-06 18:26:07 -05:00
}
}
impl From<io::Error> for SassError {
fn from(error: io::Error) -> Self {
2020-01-06 19:23:52 -05:00
SassError {
2020-04-12 19:37:12 -04:00
kind: SassErrorKind::IoError(error),
2020-01-06 19:23:52 -05:00
}
2020-01-06 18:26:07 -05:00
}
}
impl From<std::fmt::Error> for SassError {
fn from(error: std::fmt::Error) -> Self {
SassError {
2020-04-12 19:37:12 -04:00
kind: SassErrorKind::FmtError(error),
}
}
}
impl From<FromUtf8Error> for SassError {
fn from(error: FromUtf8Error) -> Self {
SassError {
2020-04-12 19:37:12 -04:00
kind: SassErrorKind::FromUtf8Error(format!(
"Invalid UTF-8 character \"\\x{:X?}\"",
error.as_bytes()[0]
)),
}
}
}
2020-04-12 19:37:12 -04:00
impl From<(&str, Span)> for SassError {
2020-02-16 10:54:25 -05:00
#[inline]
2020-04-12 19:37:12 -04:00
fn from(error: (&str, Span)) -> SassError {
2020-02-16 10:54:25 -05:00
SassError {
2020-04-12 19:37:12 -04:00
kind: SassErrorKind::Raw(error.0.to_owned(), error.1),
2020-02-16 10:54:25 -05:00
}
}
}
2020-04-12 19:37:12 -04:00
impl From<(String, Span)> for SassError {
2020-02-16 10:54:25 -05:00
#[inline]
2020-04-12 19:37:12 -04:00
fn from(error: (String, Span)) -> SassError {
2020-02-16 10:54:25 -05:00
SassError {
2020-04-12 19:37:12 -04:00
kind: SassErrorKind::Raw(error.0, error.1),
2020-02-16 10:54:25 -05:00
}
}
}
2020-01-06 18:26:07 -05:00
impl Error for SassError {
fn description(&self) -> &'static str {
"SASS parsing error"
}
}