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}