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