Skip to main content

sql_fun_sqlast/sem/
error.rs

1use std::{
2    convert::Infallible,
3    io::ErrorKind,
4    path::{Path, PathBuf},
5};
6
7use crate::sem::{AnalysisProblem, ParseContext, TypeReference};
8
9/// error
10#[derive(Debug, thiserror::Error)]
11pub enum AnalysisError {
12    /// unknown errror
13    #[error("{0}")]
14    GenericError(#[source] Box<dyn std::error::Error>),
15
16    /// serde
17    #[error(transparent)]
18    SerdeJson(#[from] serde_json::Error),
19
20    /// IO Error
21    #[error(transparent)]
22    Io(#[from] std::io::Error),
23
24    /// Unexpected None
25    #[error("unexpected None with {0}")]
26    UnexpectedNone(String),
27
28    /// Unexpeced input value
29    #[error("unexpected input :{0}")]
30    UnexpectedInput(String),
31
32    /// Type name is invalid
33    #[error("invalid type name ")]
34    TypeNameFormat(String),
35
36    /// extension schema not found
37    #[error("schema for extension {0} not found")]
38    ExtensionSchemaNotFound(String),
39
40    /// argument related errors
41    #[error(transparent)]
42    Arg(#[from] sql_fun_core::SqlFunArgsError),
43
44    /// metadata related errors
45    #[error(transparent)]
46    Meta(#[from] sql_fun_core::MetadataError),
47
48    /// highlighter theme replated errors
49    #[error(transparent)]
50    HighlighterTheme(#[from] sql_fun_core::HighlighterThemeError),
51
52    /// file not found
53    #[error("file not found : {0}")]
54    FileNotFound(PathBuf),
55
56    /// formatting error
57    #[error(transparent)]
58    FormattingError(#[from] std::fmt::Error),
59}
60
61impl AnalysisError {
62    /// raise `UnexpectedNone` error
63    pub fn raise_unexpected_none<T>(message: &str) -> Result<T, Self> {
64        Err(AnalysisError::UnexpectedNone(String::from(message)))
65    }
66
67    /// raise `UnexpectedInput` error
68    #[track_caller]
69    pub fn raise_unexpected_input<T>(message: &str) -> Result<T, Self> {
70        #[cfg(test)]
71        panic!("unexpected input {message}");
72
73        #[cfg_attr(test, expect(unreachable_code))]
74        Err(AnalysisError::UnexpectedInput(String::from(message)))
75    }
76
77    /// type name is invalid format
78    pub fn type_name_format<E: std::fmt::Debug>(value: &E) -> Self {
79        Self::TypeNameFormat(format!("{value:?}"))
80    }
81
82    /// wraps `std::error::Error`
83    #[track_caller]
84    pub fn generic_error<E: std::error::Error + 'static + Send>(error: E) -> Self {
85        #[cfg(test)]
86        panic!("generic error {error}");
87
88        #[cfg_attr(test, expect(unreachable_code))]
89        Self::GenericError(Box::new(error))
90    }
91
92    /// inconsistent type reference
93    #[track_caller]
94    #[must_use]
95    pub fn type_canonicalize_failed(_expr_type: &TypeReference) -> Self {
96        todo!()
97    }
98
99    /// regitering dynamic type to context
100    pub fn raise_register_dynamic_type(
101        _create_comp_type: &super::CreateCompositType,
102    ) -> Result<Infallible, Self> {
103        todo!()
104    }
105
106    /// file not found
107    pub fn file_not_found<P>(file_path: P) -> Result<Infallible, Self>
108    where
109        P: AsRef<Path>,
110    {
111        Err(Self::FileNotFound(file_path.as_ref().to_path_buf()))
112    }
113
114    /// never returns from this
115    pub fn never() -> ! {
116        unreachable!("this function calls with Ok(Infallble) instanciated")
117    }
118
119    /// unexpected eof error
120    pub fn unexpected_eof() -> Self {
121        AnalysisError::Io(std::io::Error::new(
122            ErrorKind::UnexpectedEof,
123            "unexpected eof",
124        ))
125    }
126}
127
128/// problem like error, internal error for Analysis
129#[derive(Debug, thiserror::Error)]
130pub enum ProblemLikeError {
131    /// invalid operator name
132    #[error("invalid operator name {0:?}")]
133    InvalidOperatorName(Vec<String>),
134}
135
136impl ProblemLikeError {
137    pub fn invalid_operator_name(value: Vec<String>) -> Self {
138        Self::InvalidOperatorName(value)
139    }
140
141    pub fn into_problem(self) -> AnalysisProblem {
142        match self {
143            Self::InvalidOperatorName(v) => AnalysisProblem::operator_name_syntax(&v),
144        }
145    }
146
147    pub fn report_problem_to<TParseContext>(
148        self,
149        context: &mut TParseContext,
150    ) -> Result<(), AnalysisError>
151    where
152        TParseContext: ParseContext,
153    {
154        context.report_problem(self.into_problem())?;
155        Ok(())
156    }
157}