topiary_config/
error.rs

1use std::{error, fmt, io, path, result};
2
3pub type TopiaryConfigResult<T> = result::Result<T, TopiaryConfigError>;
4
5#[derive(Debug)]
6pub enum TopiaryConfigError {
7    FileNotFound(path::PathBuf),
8    UnknownLanguage(String),
9    UnknownExtension(String),
10    NoExtension(path::PathBuf),
11    #[cfg(not(target_arch = "wasm32"))]
12    QueryFileNotFound(path::PathBuf),
13    Io(io::Error),
14    Missing,
15    TreeSitterFacade(topiary_tree_sitter_facade::LanguageError),
16    Nickel(nickel_lang_core::error::Error),
17    NickelDeserialization(nickel_lang_core::deserialize::RustDeserializationError),
18    #[cfg(not(target_arch = "wasm32"))]
19    Fetching(TopiaryConfigFetchingError),
20}
21
22#[derive(Debug)]
23/// Topiary can fetch an compile grammars, doing so may create errors.
24/// Usually, this error would be part of the `TopiaryConfigError`, however, that enum also includes `nickel_lang_core::error::Error`, which does not implement Sync/Send.
25/// Since fetching an compilation is something that can easily be parallelized, we create a special error that DOES implement Sync/Send.
26#[cfg(not(target_arch = "wasm32"))]
27pub enum TopiaryConfigFetchingError {
28    Git(anyhow::Error),
29    Build(anyhow::Error),
30    Io(io::Error),
31    LibLoading(libloading::Error),
32    GrammarFileNotFound(path::PathBuf),
33}
34
35impl fmt::Display for TopiaryConfigError {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            TopiaryConfigError::FileNotFound(path) => write!(f, "We tried to find your configuration file at {}, but failed to do so. Make sure the file exists.", path.to_string_lossy()),
39            TopiaryConfigError::UnknownLanguage(lang) => write!(f, "You were looking for language \"{lang}\", but we do not know that language."),
40            TopiaryConfigError::UnknownExtension(ext) => write!(f, "You tried to format a file with extension: \"{ext}\", but we do not know that extension. Make sure the extension is in your configuration file!"),
41            TopiaryConfigError::NoExtension(path) => write!(f, "You tried to format {} without specifying a language, but we cannot automatically detect the language because we can't find the filetype extension.", path.to_string_lossy()),
42            #[cfg(not(target_arch = "wasm32"))]
43            TopiaryConfigError::QueryFileNotFound(path) => write!(f, "We could not find the query file: \"{}\" anywhere. If you use the TOPIARY_LANGUAGE_DIR environment variable, make sure it set set correctly.", path.to_string_lossy()),
44            TopiaryConfigError::Io(error) => write!(f, "We encountered an io error: {error}"),
45            TopiaryConfigError::Missing => write!(f, "A configuration file is missing. If you passed a configuration file, make sure it exists."),
46            TopiaryConfigError::TreeSitterFacade(_) => write!(f, "We could not load the grammar for the given language"),
47            TopiaryConfigError::Nickel(e) => write!(f, "Nickel error: {:#?}\n\nDid you forget to add a \"priority\" annotation in your config file?", e),
48            TopiaryConfigError::NickelDeserialization(e) => write!(f, "Nickel error: {:#?}", e),
49            #[cfg(not(target_arch = "wasm32"))]
50            TopiaryConfigError::Fetching(e) => write!(f, "Error Fetching Language: {}", e),
51        }
52    }
53}
54
55#[cfg(not(target_arch = "wasm32"))]
56impl fmt::Display for TopiaryConfigFetchingError {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        match self {
59            TopiaryConfigFetchingError::Git(e) => write!(f, "Git error: {:?}", e),
60            TopiaryConfigFetchingError::Build(e) => {
61                write!(f, "Compilation error: {e},")
62            }
63            TopiaryConfigFetchingError::Io(error) => {
64                write!(f, "We encountered an io error: {error}")
65            }
66            TopiaryConfigFetchingError::LibLoading(e) => write!(f, "Libloading error: {:?}", e),
67            TopiaryConfigFetchingError::GrammarFileNotFound(path) => write!(
68                f,
69                "Attempted to load grammar at `{}`, but no file found",
70                path.to_string_lossy()
71            ),
72        }
73    }
74}
75
76impl From<nickel_lang_core::deserialize::RustDeserializationError> for TopiaryConfigError {
77    fn from(e: nickel_lang_core::deserialize::RustDeserializationError) -> Self {
78        Self::NickelDeserialization(e)
79    }
80}
81
82impl From<nickel_lang_core::error::Error> for TopiaryConfigError {
83    fn from(e: nickel_lang_core::error::Error) -> Self {
84        Self::Nickel(e)
85    }
86}
87
88#[cfg(not(target_arch = "wasm32"))]
89impl From<TopiaryConfigFetchingError> for TopiaryConfigError {
90    fn from(e: TopiaryConfigFetchingError) -> Self {
91        Self::Fetching(e)
92    }
93}
94
95impl From<io::Error> for TopiaryConfigError {
96    fn from(e: io::Error) -> Self {
97        Self::Io(e)
98    }
99}
100
101#[cfg(not(target_arch = "wasm32"))]
102impl From<io::Error> for TopiaryConfigFetchingError {
103    fn from(e: io::Error) -> Self {
104        Self::Io(e)
105    }
106}
107
108impl From<topiary_tree_sitter_facade::LanguageError> for TopiaryConfigError {
109    fn from(e: topiary_tree_sitter_facade::LanguageError) -> Self {
110        Self::TreeSitterFacade(e)
111    }
112}
113
114#[cfg(not(target_arch = "wasm32"))]
115impl From<libloading::Error> for TopiaryConfigFetchingError {
116    fn from(e: libloading::Error) -> Self {
117        Self::LibLoading(e)
118    }
119}
120
121impl error::Error for TopiaryConfigError {
122    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
123        match self {
124            #[cfg(not(target_arch = "wasm32"))]
125            TopiaryConfigError::Io(e) => e.source(),
126            _ => None,
127        }
128    }
129}