blob: ac3629bf8f733e2ef65605f86170c04f05e2b561 [file] [log] [blame] [edit]
use std::path::Path;
use miette::{Diagnostic, LabeledSpan, NamedSource, SourceOffset};
#[derive(Debug)]
pub struct ErrorReport {
src: Option<NamedSource>,
message: String,
location: Option<LabeledSpan>,
}
impl Diagnostic for ErrorReport {
fn source_code(&self) -> Option<&dyn miette::SourceCode> {
self.src.as_ref().map(|x| x as _)
}
fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
self.location
.as_ref()
.map(|loc| Box::new(std::iter::once(loc.clone())) as _)
}
}
impl std::fmt::Display for ErrorReport {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for ErrorReport {}
impl ErrorReport {
pub fn message(message: impl Into<String>) -> Self {
ErrorReport {
src: None,
message: message.into(),
location: None,
}
}
pub fn from_error_src(error: &syn::Error, path: &Path, text: String) -> Self {
let message = error.to_string();
let span = error.span();
let start = span.start();
// we add + 1 to these offsets because of weird upstream behaviour I'm too lazy
// to try and land a fix for. If spans are off-by-one, delete these + 1s :)
let start = SourceOffset::from_location(&text, start.line, start.column + 1);
let end = span.end();
let end = SourceOffset::from_location(&text, end.line, end.column + 1);
let start_off = start.offset();
let len = end.offset() - start_off;
let location = LabeledSpan::new(Some(message), start_off, len);
let src = NamedSource::new(path.to_string_lossy(), text);
ErrorReport {
message: "parsing failed".into(),
src: Some(src),
location: Some(location),
}
}
}