surql_parser/upstream/syn/error/
mod.rs1use crate::upstream::syn::token::Span;
2use std::fmt::Display;
3mod location;
4mod mac;
5mod render;
6pub use location::Location;
7pub(crate) use mac::{bail, syntax_error};
8pub use render::{RenderedError, Snippet};
9#[derive(Debug, Clone, Copy)]
10pub enum MessageKind {
11 Suggestion,
12 Error,
13}
14#[derive(Debug)]
15enum DiagnosticKind {
16 Cause(String),
17 Span {
18 kind: MessageKind,
19 span: Span,
20 label: Option<String>,
21 },
22}
23#[derive(Debug)]
24pub struct Diagnostic {
25 kind: DiagnosticKind,
26 next: Option<Box<Diagnostic>>,
27}
28#[derive(Debug)]
30pub struct SyntaxError {
31 diagnostic: Box<Diagnostic>,
32}
33impl SyntaxError {
34 #[cold]
36 pub fn new<T>(message: T) -> Self
37 where
38 T: Display,
39 {
40 let diagnostic = Diagnostic {
41 kind: DiagnosticKind::Cause(message.to_string()),
42 next: None,
43 };
44 Self {
45 diagnostic: Box::new(diagnostic),
46 }
47 }
48 #[cold]
49 pub fn with_span(mut self, span: Span, kind: MessageKind) -> Self {
50 self.diagnostic = Box::new(Diagnostic {
51 kind: DiagnosticKind::Span {
52 kind,
53 span,
54 label: None,
55 },
56 next: Some(self.diagnostic),
57 });
58 self
59 }
60 #[cold]
61 pub fn with_labeled_span<T: Display>(
62 mut self,
63 span: Span,
64 kind: MessageKind,
65 label: T,
66 ) -> Self {
67 self.diagnostic = Box::new(Diagnostic {
68 kind: DiagnosticKind::Span {
69 kind,
70 span,
71 label: Some(label.to_string()),
72 },
73 next: Some(self.diagnostic),
74 });
75 self
76 }
77 #[cold]
78 pub fn with_cause<T: Display>(mut self, t: T) -> Self {
79 self.diagnostic = Box::new(Diagnostic {
80 kind: DiagnosticKind::Cause(t.to_string()),
81 next: Some(self.diagnostic),
82 });
83 self
84 }
85 pub fn render_on(&self, source: &str) -> RenderedError {
86 let mut res = RenderedError {
87 errors: Vec::new(),
88 snippets: Vec::new(),
89 };
90 Self::render_on_inner(&self.diagnostic, source, &mut res);
91 res
92 }
93 pub fn render_on_bytes(&self, source: &[u8]) -> RenderedError {
94 let source = String::from_utf8_lossy(source);
95 self.render_on(&source)
96 }
97 pub fn update_spans<F: FnMut(&mut Span)>(mut self, mut cb: F) -> Self {
100 let mut cur = &mut *self.diagnostic;
101 loop {
102 match cur.kind {
103 DiagnosticKind::Cause(_) => {}
104 DiagnosticKind::Span { ref mut span, .. } => cb(span),
105 }
106 let Some(next) = cur.next.as_mut() else {
107 break;
108 };
109 cur = &mut *next;
110 }
111 self
112 }
113 fn render_on_inner(diagnostic: &Diagnostic, source: &str, res: &mut RenderedError) {
114 if let Some(ref x) = diagnostic.next {
115 Self::render_on_inner(x, source, res);
116 }
117 match diagnostic.kind {
118 DiagnosticKind::Cause(ref x) => res.errors.push(x.clone()),
119 DiagnosticKind::Span {
120 ref span,
121 ref label,
122 ref kind,
123 } => {
124 let locations = Location::range_of_span(source, *span);
125 let snippet = Snippet::from_source_location_range(
126 source,
127 locations,
128 label.as_ref().map(|x| x.as_str()),
129 *kind,
130 );
131 res.snippets.push(snippet)
132 }
133 }
134 }
135}