use std::path::PathBuf;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("File system error: {message}")]
FileSystem {
message: String,
path: Option<PathBuf>,
#[source]
source: Option<std::io::Error>,
},
#[error("Parse error in {file}:{line}:{column}: {message}")]
Parse {
file: PathBuf,
line: usize,
column: usize,
message: String,
},
#[error("Analysis error: {0}")]
Analysis(String),
#[error("Configuration error: {0}")]
Configuration(String),
#[error("Unsupported: {0}")]
Unsupported(String),
#[error("Validation error: {0}")]
Validation(String),
#[error("Dependency error: {0}")]
Dependency(String),
#[error("Concurrency error: {0}")]
Concurrency(String),
#[error("{context}: {message}")]
WithContext { context: String, message: String },
#[error(transparent)]
External(#[from] anyhow::Error),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Json(#[from] serde_json::Error),
#[error(transparent)]
Pattern(#[from] glob::PatternError),
}
impl Error {
pub fn file_system(message: impl Into<String>, path: impl Into<PathBuf>) -> Self {
Self::FileSystem {
message: message.into(),
path: Some(path.into()),
source: None,
}
}
pub fn parse(
file: impl Into<PathBuf>,
line: usize,
column: usize,
message: impl Into<String>,
) -> Self {
Self::Parse {
file: file.into(),
line,
column,
message: message.into(),
}
}
pub fn with_context(self, context: impl Into<String>) -> Self {
Self::WithContext {
context: context.into(),
message: self.to_string(),
}
}
}
pub type Result<T> = std::result::Result<T, Error>;
pub trait ResultExt<T> {
fn context(self, context: impl Into<String>) -> Result<T>;
}
impl<T> ResultExt<T> for Result<T> {
fn context(self, context: impl Into<String>) -> Result<T> {
self.map_err(|e| e.with_context(context))
}
}