partiql_cli/
error.rs

1use miette::{Diagnostic, LabeledSpan, SourceCode};
2use partiql_parser::{ParseError, ParserError};
3use partiql_source_map::location::{BytePosition, Location};
4
5use thiserror::Error;
6
7#[derive(Debug, Error, Diagnostic)]
8#[error("Error for query `{query}`")]
9pub struct CLIErrors {
10    query: String,
11    #[related]
12    related: Vec<CLIError>,
13}
14
15impl CLIErrors {
16    pub fn from_parser_error(err: ParserError) -> Self {
17        let query = err.text.to_string();
18
19        let related = err
20            .errors
21            .into_iter()
22            .map(|e| CLIError::from_parse_error(e, &query))
23            .collect();
24        CLIErrors { query, related }
25    }
26}
27
28#[derive(Debug, Error)]
29pub enum CLIError {
30    #[error("PartiQL syntax error:")]
31    SyntaxError {
32        src: String,
33        msg: String,
34        loc: Location<BytePosition>,
35    },
36    #[error("Internal Compiler Error - please report this (https://github.com/partiql/partiql-lang-rust/issues).")]
37    InternalCompilerError { src: String },
38}
39
40impl Diagnostic for CLIError {
41    fn source_code(&self) -> Option<&dyn SourceCode> {
42        match self {
43            CLIError::SyntaxError { src, .. } => Some(src),
44            CLIError::InternalCompilerError { src, .. } => Some(src),
45        }
46    }
47
48    fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
49        match self {
50            CLIError::SyntaxError { msg, loc, .. } => {
51                Some(Box::new(std::iter::once(LabeledSpan::new(
52                    Some(msg.to_string()),
53                    loc.start.0 .0 as usize,
54                    loc.end.0 .0 as usize - loc.start.0 .0 as usize,
55                ))))
56            }
57            CLIError::InternalCompilerError { .. } => None,
58        }
59    }
60}
61
62impl CLIError {
63    pub fn from_parse_error(err: ParseError, source: &str) -> Self {
64        match err {
65            ParseError::SyntaxError(partiql_source_map::location::Located { inner, location }) => {
66                CLIError::SyntaxError {
67                    src: source.to_string(),
68                    msg: format!("Syntax error `{}`", inner),
69                    loc: location,
70                }
71            }
72            ParseError::UnexpectedToken(partiql_source_map::location::Located {
73                inner,
74                location,
75            }) => CLIError::SyntaxError {
76                src: source.to_string(),
77                msg: format!("Unexpected token `{}`", inner.token),
78                loc: location,
79            },
80            ParseError::LexicalError(partiql_source_map::location::Located { inner, location }) => {
81                CLIError::SyntaxError {
82                    src: source.to_string(),
83                    msg: format!("Lexical error `{}`", inner),
84                    loc: location,
85                }
86            }
87            ParseError::Unknown(location) => CLIError::SyntaxError {
88                src: source.to_string(),
89                msg: "Unknown parser error".to_string(),
90                loc: Location {
91                    start: location,
92                    end: location,
93                },
94            },
95            ParseError::IllegalState(_location) => CLIError::InternalCompilerError {
96                src: source.to_string(),
97            },
98            _ => {
99                todo!("Not yet handled {:?}", err);
100            }
101        }
102    }
103}