sqruff_lib_core/
errors.rs1use std::ops::{Deref, DerefMut, Range};
2
3use fancy_regex::Regex;
4use thiserror::Error;
5
6use super::parser::segments::ErasedSegment;
7use crate::helpers::Config;
8use crate::parser::markers::PositionMarker;
9
10#[derive(Debug, PartialEq, Clone, Default, Error)]
11#[error("{description}")]
12pub struct SQLBaseError {
13 pub fixable: bool,
14 pub line_no: usize,
15 pub line_pos: usize,
16 pub description: String,
17 pub rule: Option<ErrorStructRule>,
18 pub source_slice: Range<usize>,
19}
20
21#[derive(Debug, PartialEq, Clone, Default)]
22pub struct ErrorStructRule {
23 pub name: &'static str,
24 pub code: &'static str,
25}
26
27impl SQLBaseError {
28 pub fn rule_code(&self) -> &'static str {
29 self.rule.as_ref().map_or("????", |rule| rule.code)
30 }
31
32 pub fn set_position_marker(&mut self, position_marker: PositionMarker) {
33 let (line_no, line_pos) = position_marker.source_position();
34
35 self.line_no = line_no;
36 self.line_pos = line_pos;
37
38 self.source_slice = position_marker.source_slice.clone();
39 }
40
41 pub fn desc(&self) -> &str {
42 &self.description
43 }
44}
45
46#[derive(Debug, Clone, Error)]
47#[error(transparent)]
48pub struct SQLLintError {
49 base: SQLBaseError,
50}
51
52impl SQLLintError {
53 pub fn new(description: &str, segment: ErasedSegment, fixable: bool) -> Self {
54 Self {
55 base: SQLBaseError::default().config(|this| {
56 this.description = description.into();
57 this.set_position_marker(segment.get_position_marker().unwrap().clone());
58 this.fixable = fixable;
59 }),
60 }
61 }
62}
63
64impl Deref for SQLLintError {
65 type Target = SQLBaseError;
66
67 fn deref(&self) -> &Self::Target {
68 &self.base
69 }
70}
71
72impl DerefMut for SQLLintError {
73 fn deref_mut(&mut self) -> &mut Self::Target {
74 &mut self.base
75 }
76}
77
78impl From<SQLLintError> for SQLBaseError {
79 fn from(value: SQLLintError) -> Self {
80 value.base
81 }
82}
83
84impl From<SQLBaseError> for SQLLintError {
85 fn from(value: SQLBaseError) -> Self {
86 Self { base: value }
87 }
88}
89
90#[derive(Debug, PartialEq, Clone, Error)]
91#[error("{message}")]
92pub struct SQLTemplaterError {
93 pub message: String,
94}
95
96impl SQLTemplaterError {
97 pub fn new(message: String) -> Self {
98 Self { message }
99 }
100}
101
102impl From<SQLTemplaterError> for SQLBaseError {
103 fn from(value: SQLTemplaterError) -> Self {
104 Self {
105 description: value.message,
106 rule: Some(ErrorStructRule {
107 name: "templater",
108 code: "TMP",
109 }),
110 ..Default::default()
111 }
112 }
113}
114
115#[derive(Debug, Error)]
117#[error("{value}")]
118pub struct SQLFluffUserError {
119 pub value: String,
120}
121
122impl SQLFluffUserError {
123 pub fn new(value: String) -> SQLFluffUserError {
124 SQLFluffUserError { value }
125 }
126}
127
128#[derive(Debug, Error)]
129#[error("{description}")]
130pub struct SQLParseError {
131 pub description: String,
132 pub segment: Option<ErasedSegment>,
133}
134
135impl SQLParseError {
136 pub fn matches(&self, regexp: &str) -> bool {
137 let value = &self.description;
138 let regex = Regex::new(regexp).expect("Invalid regex pattern");
139
140 if let Ok(true) = regex.is_match(value) {
141 true
142 } else {
143 let msg = format!("Regex pattern did not match.\nRegex: {regexp:?}\nInput: {value:?}");
144
145 if regexp == value {
146 panic!("{msg}\nDid you mean to escape the regex?");
147 } else {
148 panic!("{}", msg);
149 }
150 }
151 }
152}
153
154impl From<SQLParseError> for SQLBaseError {
155 fn from(value: SQLParseError) -> Self {
156 let (mut line_no, mut line_pos) = Default::default();
157
158 let pos_marker = value
159 .segment
160 .as_ref()
161 .and_then(|segment| segment.get_position_marker());
162
163 if let Some(pos_marker) = pos_marker {
164 (line_no, line_pos) = pos_marker.source_position();
165 }
166
167 Self::default().config(|this| {
168 this.line_no = line_no;
169 this.line_pos = line_pos;
170 this.description = value.description;
171 })
172 }
173}
174
175#[derive(PartialEq, Eq, Debug, Error)]
176#[error("{message}")]
177pub struct SQLLexError {
178 message: String,
179 position_marker: PositionMarker,
180}
181
182impl SQLLexError {
183 pub fn new(message: String, position_marker: PositionMarker) -> SQLLexError {
184 SQLLexError {
185 message,
186 position_marker,
187 }
188 }
189}
190
191#[derive(Debug, Error)]
192#[error("{value}")]
193pub struct SQLFluffSkipFile {
194 value: String,
195}
196
197impl SQLFluffSkipFile {
198 pub fn new(value: String) -> SQLFluffSkipFile {
199 SQLFluffSkipFile { value }
200 }
201}