Skip to main content

oxc_graphql_parser/
error.rs

1use std::fmt;
2
3/// An `Error` type for operations performed in the lexer and the parser.
4///
5/// Errors get returned alongside the resulting AST if either the lexer or the
6/// parser encounters lexical or syntactical errors respectively.
7///
8/// We encourage you to check for the AST's errors before proceeding to iterate
9/// over the AST's nodes:
10///
11/// ## Example
12/// ```rust
13/// use oxc_graphql_parser::{Allocator, Parser};
14///
15/// let input = "union SearchResult = Photo | Person | Cat | Dog";
16/// let allocator = Allocator::default();
17/// let parser = Parser::new(&allocator, input);
18/// let ast = parser.parse();
19///
20/// assert_eq!(0, ast.errors().len());
21///
22/// let doc = ast.document();
23/// ```
24///
25/// ### Diagnostics
26///
27/// Using something like [ariadne] along with `oxc-graphql-parser` lets you have
28/// more visual diagnostics. [ariadne] and [annotate_snippets] examples guide you
29/// through integrating them with `oxc-graphql-parser`. These are useful if you are
30/// displaying Errors in a terminal-like environment.
31///
32/// [ariadne]: https://github.com/oxc-project/oxc-graphql-parser/blob/main/crates/oxc_graphql_parser/examples/ariadne.rs
33/// [annotate_snippets]: https://github.com/oxc-project/oxc-graphql-parser/blob/main/crates/oxc_graphql_parser/examples/annotate_snippet.rs
34
35#[derive(Debug, PartialEq, Eq, Clone, Hash)]
36pub(crate) enum ErrorData {
37    Eof,
38    LimitExceeded,
39    Text(String),
40}
41
42impl ErrorData {
43    pub fn len(&self) -> usize {
44        match self {
45            Self::Eof | Self::LimitExceeded => 0,
46            Self::Text(text) => text.len(),
47        }
48    }
49}
50
51impl fmt::Display for ErrorData {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        match self {
54            Self::Eof => write!(f, "EOF"),
55            Self::LimitExceeded => Ok(()),
56            Self::Text(text) => write!(f, "{text}"),
57        }
58    }
59}
60
61#[derive(PartialEq, Eq, Clone, Hash, thiserror::Error)]
62#[error("ERROR@{index}:{} {message:?} {data}", .index + .data.len())]
63pub struct Error {
64    pub(crate) message: String,
65    pub(crate) data: ErrorData,
66    pub(crate) index: usize,
67}
68
69impl Error {
70    /// Create a new instance of `Error` with a `Location`.
71    pub fn with_loc<S: Into<String>>(message: S, data: String, index: usize) -> Self {
72        Self { message: message.into(), data: ErrorData::Text(data), index }
73    }
74
75    pub fn limit<S: Into<String>>(message: S, index: usize) -> Self {
76        Self { message: message.into(), data: ErrorData::LimitExceeded, index }
77    }
78
79    pub fn eof<S: Into<String>>(message: S, index: usize) -> Self {
80        Self { message: message.into(), data: ErrorData::Eof, index }
81    }
82
83    /// Get a reference to the error's data. This is usually the token that
84    /// `oxc-graphql-parser` has found to be lexically or syntactically incorrect.
85    pub fn data(&self) -> &str {
86        match &self.data {
87            ErrorData::Text(text) => text,
88            _ => "",
89        }
90    }
91
92    pub fn is_limit(&self) -> bool {
93        matches!(&self.data, ErrorData::LimitExceeded)
94    }
95
96    pub fn is_eof(&self) -> bool {
97        matches!(&self.data, ErrorData::Eof)
98    }
99
100    pub(crate) fn set_data(&mut self, data: String) {
101        self.data = ErrorData::Text(data);
102    }
103
104    /// Get a reference to the error's index. This is where the error begins in
105    /// a given input.
106    pub fn index(&self) -> usize {
107        self.index
108    }
109
110    /// Get a reference to the error's message.
111    pub fn message(&self) -> &str {
112        self.message.as_ref()
113    }
114}
115
116impl fmt::Debug for Error {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        let start = self.index;
119        let end = self.index + self.data.len();
120
121        write!(f, "ERROR@{}:{} {:?} {}", start, end, self.message, self.data)
122    }
123}