nextest_filtering/
errors.rs1#![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 end of expression")]
119 ExpectedEndOfExpression(#[label("unparsed input")] SourceSpan),
120
121 #[error("operator didn't match any packages")]
123 NoPackageMatch(#[label("no packages matched this")] SourceSpan),
124
125 #[error("operator didn't match any binary IDs")]
127 NoBinaryIdMatch(#[label("no binary IDs matched this")] SourceSpan),
128
129 #[error("operator didn't match any binary names")]
131 NoBinaryNameMatch(#[label("no binary names matched this")] SourceSpan),
132
133 #[error("invalid argument for platform")]
135 InvalidPlatformArgument(#[label("expected \"target\" or \"host\"")] SourceSpan),
136
137 #[error("unsupported expression")]
139 UnsupportedExpression(#[label("contained an unsupported expression")] SourceSpan),
140
141 #[error("unknown parsing error")]
143 Unknown,
144}
145
146impl ParseSingleError {
147 pub(crate) fn invalid_regex(input: &str, start: usize, end: usize) -> Self {
148 match regex_syntax::Parser::new().parse(input) {
150 Ok(_) => {
151 Self::InvalidRegexWithoutMessage((start, end - start).into())
154 }
155 Err(err) => {
156 let (message, span) = match &err {
157 regex_syntax::Error::Parse(err) => (format!("{}", err.kind()), err.span()),
158 regex_syntax::Error::Translate(err) => (format!("{}", err.kind()), err.span()),
159 _ => return Self::InvalidRegexWithoutMessage((start, end - start).into()),
160 };
161
162 let err_start = start + span.start.offset;
164 let err_end = start + span.end.offset;
165
166 Self::InvalidRegex {
167 span: (err_start, err_end - err_start).into(),
168 message,
169 }
170 }
171 }
172 }
173}
174
175#[derive(Clone, Debug, Error, PartialEq, Eq)]
176pub enum GlobConstructError {
177 #[error("{}", .0.kind())]
178 InvalidGlob(globset::Error),
179
180 #[error("{}", .0)]
181 RegexError(String),
182}
183
184#[derive(Debug)]
185pub(crate) struct State<'a> {
186 errors: &'a mut Vec<ParseSingleError>,
188}
189
190impl<'a> State<'a> {
191 pub fn new(errors: &'a mut Vec<ParseSingleError>) -> Self {
192 Self { errors }
193 }
194
195 pub fn report_error(&mut self, error: ParseSingleError) {
196 self.errors.push(error);
197 }
198}
199
200#[derive(Copy, Clone, Debug, PartialEq, Eq)]
201pub enum BannedPredicateReason {
202 InfiniteRecursion,
204 Unsupported,
206}
207
208impl fmt::Display for BannedPredicateReason {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 match self {
211 BannedPredicateReason::InfiniteRecursion => {
212 write!(f, "this predicate causes infinite recursion")
213 }
214 BannedPredicateReason::Unsupported => {
215 write!(f, "test() predicates are not supported while archiving")
216 }
217 }
218 }
219}