1#![allow(unused_assignments)]
7
8use crate::expression::FiltersetKind;
9use miette::{Diagnostic, SourceSpan};
10use std::fmt;
11use thiserror::Error;
12
13#[derive(Clone, Debug)]
15#[non_exhaustive]
16pub struct FiltersetParseErrors {
17 pub input: String,
19
20 pub errors: Vec<ParseSingleError>,
22}
23
24impl FiltersetParseErrors {
25 pub(crate) fn new(input: impl Into<String>, errors: Vec<ParseSingleError>) -> Self {
26 Self {
27 input: input.into(),
28 errors,
29 }
30 }
31}
32
33#[derive(Clone, Debug, Error, Diagnostic, PartialEq, Eq)]
35#[non_exhaustive]
36pub enum ParseSingleError {
37 #[error("invalid regex")]
39 InvalidRegex {
40 #[label("{}", message)]
42 span: SourceSpan,
43
44 message: String,
46 },
47
48 #[error("invalid glob")]
50 InvalidGlob {
51 #[label("{}", error)]
53 span: SourceSpan,
54
55 error: GlobConstructError,
57 },
58
59 #[error("predicate not allowed in `{kind}` expressions")]
61 BannedPredicate {
62 kind: FiltersetKind,
64
65 #[label("{reason}")]
67 span: SourceSpan,
68
69 reason: BannedPredicateReason,
71 },
72
73 #[error("invalid regex")]
75 InvalidRegexWithoutMessage(#[label("invalid regex")] SourceSpan),
76
77 #[error("expected close regex")]
79 ExpectedCloseRegex(#[label("missing `/`")] SourceSpan),
80
81 #[error("invalid OR operator")]
83 InvalidOrOperator(#[label("expected `|`, `+`, or `or`")] SourceSpan),
84
85 #[error("invalid AND operator")]
87 InvalidAndOperator(#[label("expected `&` or `and`")] SourceSpan),
88
89 #[error("unexpected argument")]
91 UnexpectedArgument(#[label("this set doesn't take an argument")] SourceSpan),
92
93 #[error("unexpected comma")]
95 UnexpectedComma(#[label("this set doesn't take multiple arguments")] SourceSpan),
96
97 #[error("invalid string")]
99 InvalidString(#[label("invalid string")] SourceSpan),
100
101 #[error("expected open parenthesis")]
103 ExpectedOpenParenthesis(#[label("missing `(`")] SourceSpan),
104
105 #[error("expected close parenthesis")]
107 ExpectedCloseParenthesis(#[label("missing `)`")] SourceSpan),
108
109 #[error("invalid escape character")]
111 InvalidEscapeCharacter(#[label("invalid escape character")] SourceSpan),
112
113 #[error("expected expression")]
115 ExpectedExpr(#[label("missing expression")] SourceSpan),
116
117 #[error("expected expression, found `{op}`")]
125 #[diagnostic(help("use `<expr> {suggest} <expr>` instead"))]
126 ExprFoundBinaryOp {
127 op: &'static str,
129
130 suggest: &'static str,
132
133 #[label("`{suggest}` is a binary operator")]
135 span: SourceSpan,
136 },
137
138 #[error("expected expression, found `{op}`")]
143 #[diagnostic(help("use `{suggest} <expr>` instead"))]
144 ExprFoundUnaryOp {
145 op: &'static str,
147
148 suggest: &'static str,
150
151 #[label("`{op}` is not a recognized operator")]
153 span: SourceSpan,
154 },
155
156 #[error("expected end of expression")]
158 ExpectedEndOfExpression(#[label("unparsed input")] SourceSpan),
159
160 #[error("operator didn't match any packages")]
162 NoPackageMatch(#[label("no packages matched this")] SourceSpan),
163
164 #[error("operator didn't match any test groups")]
166 NoGroupMatch(#[label("no test groups matched this")] SourceSpan),
167
168 #[error("operator didn't match any binary IDs")]
170 NoBinaryIdMatch(#[label("no binary IDs matched this")] SourceSpan),
171
172 #[error("operator didn't match any binary names")]
174 NoBinaryNameMatch(#[label("no binary names matched this")] SourceSpan),
175
176 #[error("invalid argument for platform")]
178 InvalidPlatformArgument(#[label("expected \"target\" or \"host\"")] SourceSpan),
179
180 #[error("unsupported expression")]
182 UnsupportedExpression(#[label("contained an unsupported expression")] SourceSpan),
183
184 #[error("unknown parsing error")]
186 Unknown,
187}
188
189impl ParseSingleError {
190 pub(crate) fn invalid_regex(input: &str, start: usize, end: usize) -> Self {
191 match regex_syntax::Parser::new().parse(input) {
193 Ok(_) => {
194 Self::InvalidRegexWithoutMessage((start, end - start).into())
197 }
198 Err(err) => {
199 let (message, span) = match &err {
200 regex_syntax::Error::Parse(err) => (format!("{}", err.kind()), err.span()),
201 regex_syntax::Error::Translate(err) => (format!("{}", err.kind()), err.span()),
202 _ => return Self::InvalidRegexWithoutMessage((start, end - start).into()),
203 };
204
205 let err_start = start + span.start.offset;
207 let err_end = start + span.end.offset;
208
209 Self::InvalidRegex {
210 span: (err_start, err_end - err_start).into(),
211 message,
212 }
213 }
214 }
215 }
216}
217
218#[derive(Clone, Debug, Error, PartialEq, Eq)]
219pub enum GlobConstructError {
220 #[error("{}", .0.kind())]
221 InvalidGlob(globset::Error),
222
223 #[error("{}", .0)]
224 RegexError(String),
225}
226
227#[derive(Debug)]
228pub(crate) struct State<'a> {
229 errors: &'a mut Vec<ParseSingleError>,
231}
232
233impl<'a> State<'a> {
234 pub fn new(errors: &'a mut Vec<ParseSingleError>) -> Self {
235 Self { errors }
236 }
237
238 pub fn report_error(&mut self, error: ParseSingleError) {
239 self.errors.push(error);
240 }
241}
242
243#[derive(Copy, Clone, Debug, PartialEq, Eq)]
244pub enum BannedPredicateReason {
245 DefaultInfiniteRecursion,
247
248 GroupCircularDependency,
251
252 GroupNotAvailableInDefaultFilter,
254
255 GroupNotAvailableInArchive,
257
258 TestNotAvailableInArchive,
260}
261
262impl fmt::Display for BannedPredicateReason {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 match self {
265 BannedPredicateReason::DefaultInfiniteRecursion => {
266 write!(f, "default() causes infinite recursion")
267 }
268 BannedPredicateReason::GroupCircularDependency => {
269 write!(f, "group() creates a circular dependency with overrides")
270 }
271 BannedPredicateReason::GroupNotAvailableInDefaultFilter => {
272 write!(f, "group() is not available in default-filter expressions")
273 }
274 BannedPredicateReason::GroupNotAvailableInArchive => {
275 write!(f, "group() predicates are not supported while archiving")
276 }
277 BannedPredicateReason::TestNotAvailableInArchive => {
278 write!(f, "test() predicates are not supported while archiving")
279 }
280 }
281 }
282}