1use std::borrow::Cow;
2
3use miette::SourceSpan;
4use nu_protocol::Span;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
7pub enum Severity {
8 Info,
9 Warning,
10 Error,
11}
12
13impl std::fmt::Display for Severity {
14 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15 match self {
16 Severity::Error => write!(f, "error"),
17 Severity::Warning => write!(f, "warning"),
18 Severity::Info => write!(f, "info"),
19 }
20 }
21}
22
23#[derive(Debug, Clone)]
25pub struct RuleViolation {
26 pub rule_id: Cow<'static, str>,
27 pub message: Cow<'static, str>,
28 pub span: Span,
29 pub suggestion: Option<Cow<'static, str>>,
30 pub fix: Option<Fix>,
31}
32
33impl RuleViolation {
34 #[must_use]
36 pub const fn new_static(rule_id: &'static str, message: &'static str, span: Span) -> Self {
37 Self {
38 rule_id: Cow::Borrowed(rule_id),
39 message: Cow::Borrowed(message),
40 span,
41 suggestion: None,
42 fix: None,
43 }
44 }
45
46 #[must_use]
48 pub fn new_dynamic(rule_id: &'static str, message: String, span: Span) -> Self {
49 Self {
50 rule_id: Cow::Borrowed(rule_id),
51 message: Cow::Owned(message),
52 span,
53 suggestion: None,
54 fix: None,
55 }
56 }
57
58 #[must_use]
60 pub fn with_suggestion_static(mut self, suggestion: &'static str) -> Self {
61 self.suggestion = Some(Cow::Borrowed(suggestion));
62 self
63 }
64
65 #[must_use]
67 pub fn with_suggestion_dynamic(mut self, suggestion: String) -> Self {
68 self.suggestion = Some(Cow::Owned(suggestion));
69 self
70 }
71
72 #[must_use]
74 pub fn with_fix(mut self, fix: Fix) -> Self {
75 self.fix = Some(fix);
76 self
77 }
78
79 #[must_use]
81 pub fn into_violation(self, severity: Severity) -> Violation {
82 Violation {
83 rule_id: self.rule_id,
84 severity,
85 message: self.message,
86 span: self.span,
87 suggestion: self.suggestion,
88 fix: self.fix,
89 file: None,
90 }
91 }
92}
93
94#[derive(Debug, Clone)]
96pub struct Violation {
97 pub rule_id: Cow<'static, str>,
98 pub severity: Severity,
99 pub message: Cow<'static, str>,
100 pub span: Span,
101 pub suggestion: Option<Cow<'static, str>>,
102 pub fix: Option<Fix>,
103 pub file: Option<Cow<'static, str>>,
104}
105
106impl Violation {
107 #[must_use]
109 pub const fn new_static(
110 rule_id: &'static str,
111 severity: Severity,
112 message: &'static str,
113 span: Span,
114 ) -> Self {
115 Self {
116 rule_id: Cow::Borrowed(rule_id),
117 severity,
118 message: Cow::Borrowed(message),
119 span,
120 suggestion: None,
121 fix: None,
122 file: None,
123 }
124 }
125
126 #[must_use]
128 pub fn new_dynamic(
129 rule_id: &'static str,
130 severity: Severity,
131 message: String,
132 span: Span,
133 ) -> Self {
134 Self {
135 rule_id: Cow::Borrowed(rule_id),
136 severity,
137 message: Cow::Owned(message),
138 span,
139 suggestion: None,
140 fix: None,
141 file: None,
142 }
143 }
144
145 #[must_use]
147 pub fn with_suggestion_static(mut self, suggestion: &'static str) -> Self {
148 self.suggestion = Some(Cow::Borrowed(suggestion));
149 self
150 }
151
152 #[must_use]
154 pub fn with_suggestion_dynamic(mut self, suggestion: String) -> Self {
155 self.suggestion = Some(Cow::Owned(suggestion));
156 self
157 }
158
159 #[must_use]
161 pub fn with_fix(mut self, fix: Fix) -> Self {
162 self.fix = Some(fix);
163 self
164 }
165
166 #[must_use]
167 pub fn to_source_span(&self) -> SourceSpan {
168 SourceSpan::from((self.span.start, self.span.end - self.span.start))
169 }
170}
171
172#[derive(Debug, Clone)]
173pub struct Fix {
174 pub description: Cow<'static, str>,
175 pub replacements: Vec<Replacement>,
176}
177
178impl Fix {
179 #[must_use]
181 pub fn new_static(description: &'static str, replacements: Vec<Replacement>) -> Self {
182 Self {
183 description: Cow::Borrowed(description),
184 replacements,
185 }
186 }
187
188 #[must_use]
190 pub fn new_dynamic(description: String, replacements: Vec<Replacement>) -> Self {
191 Self {
192 description: Cow::Owned(description),
193 replacements,
194 }
195 }
196}
197
198#[derive(Debug, Clone)]
199pub struct Replacement {
200 pub span: Span,
201 pub new_text: Cow<'static, str>,
202}
203
204impl Replacement {
205 #[must_use]
207 pub const fn new_static(span: Span, new_text: &'static str) -> Self {
208 Self {
209 span,
210 new_text: Cow::Borrowed(new_text),
211 }
212 }
213
214 #[must_use]
216 pub fn new_dynamic(span: Span, new_text: String) -> Self {
217 Self {
218 span,
219 new_text: Cow::Owned(new_text),
220 }
221 }
222}