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("SQLTemplaterError")]
92pub struct SQLTemplaterError;
93
94#[derive(Debug, Error)]
96#[error("{value}")]
97pub struct SQLFluffUserError {
98 pub value: String,
99}
100
101impl SQLFluffUserError {
102 pub fn new(value: String) -> SQLFluffUserError {
103 SQLFluffUserError { value }
104 }
105}
106
107#[derive(Debug, Error)]
108#[error("{description}")]
109pub struct SQLParseError {
110 pub description: String,
111 pub segment: Option<ErasedSegment>,
112}
113
114impl SQLParseError {
115 pub fn matches(&self, regexp: &str) -> bool {
116 let value = &self.description;
117 let regex = Regex::new(regexp).expect("Invalid regex pattern");
118
119 if let Ok(true) = regex.is_match(value) {
120 true
121 } else {
122 let msg = format!("Regex pattern did not match.\nRegex: {regexp:?}\nInput: {value:?}");
123
124 if regexp == value {
125 panic!("{msg}\nDid you mean to escape the regex?");
126 } else {
127 panic!("{}", msg);
128 }
129 }
130 }
131}
132
133impl From<SQLParseError> for SQLBaseError {
134 fn from(value: SQLParseError) -> Self {
135 let (mut line_no, mut line_pos) = Default::default();
136
137 let pos_marker = value
138 .segment
139 .as_ref()
140 .and_then(|segment| segment.get_position_marker());
141
142 if let Some(pos_marker) = pos_marker {
143 (line_no, line_pos) = pos_marker.source_position();
144 }
145
146 Self::default().config(|this| {
147 this.line_no = line_no;
148 this.line_pos = line_pos;
149 this.description = value.description;
150 })
151 }
152}
153
154#[derive(PartialEq, Eq, Debug, Error)]
155#[error("{message}")]
156pub struct SQLLexError {
157 message: String,
158 position_marker: PositionMarker,
159}
160
161impl SQLLexError {
162 pub fn new(message: String, position_marker: PositionMarker) -> SQLLexError {
163 SQLLexError {
164 message,
165 position_marker,
166 }
167 }
168}
169
170#[derive(Debug, Error)]
171#[error("{value}")]
172pub struct SQLFluffSkipFile {
173 value: String,
174}
175
176impl SQLFluffSkipFile {
177 pub fn new(value: String) -> SQLFluffSkipFile {
178 SQLFluffSkipFile { value }
179 }
180}