Skip to content

Commit

Permalink
chore: Upgrade to Winnow 0.7 (#2109)
Browse files Browse the repository at this point in the history
With 0.7, `ErrMode` is optional. It looks like `cut_err` isn't used but
I held off on migrating from `ModalResult` to `winnow::Result` and
`ModalParser` to `Parser` in case there is a future possibility of using
`ErrMode`.
  • Loading branch information
epage authored Jan 30, 2025
1 parent 5329ab9 commit a734cf2
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 43 deletions.
19 changes: 14 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ unicode-normalization = "0.1.24"
whoami = "1.5.2"
win32job = "2.0.1"
windows-sys = "0.59.0"
winnow = "0.6.24"
winnow = "0.7.0"
xxhash-rust = "0.8.13"
zstd = { version = "0.13.2", features = ["zstdmt"] }

Expand Down
68 changes: 35 additions & 33 deletions nextest-filtering/src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use winnow::{
combinator::{alt, delimited, eof, peek, preceded, repeat, terminated, trace},
stream::{Location, SliceLen, Stream},
token::{literal, take_till},
LocatingSlice, Parser,
LocatingSlice, ModalParser, Parser,
};

mod glob;
Expand All @@ -32,7 +32,7 @@ pub(crate) use unicode_string::DisplayParsedString;

pub(crate) type Span<'a> = winnow::Stateful<LocatingSlice<&'a str>, State<'a>>;
type Error = ();
type PResult<T> = winnow::PResult<T, Error>;
type PResult<T> = winnow::ModalResult<T, Error>;

pub(crate) fn new_span<'a>(input: &'a str, errors: &'a mut Vec<ParseSingleError>) -> Span<'a> {
Span {
Expand Down Expand Up @@ -231,14 +231,14 @@ fn expect_inner<'a, F, T>(
mut parser: F,
make_err: fn(SourceSpan) -> ParseSingleError,
limit: SpanLength,
) -> impl Parser<Span<'a>, Option<T>, Error>
) -> impl ModalParser<Span<'a>, Option<T>, Error>
where
F: Parser<Span<'a>, T, Error>,
F: ModalParser<Span<'a>, T, Error>,
{
move |input: &mut _| match parser.parse_next(input) {
Ok(out) => Ok(Some(out)),
Err(winnow::error::ErrMode::Backtrack(_)) | Err(winnow::error::ErrMode::Cut(_)) => {
let fragment_start = input.location();
let fragment_start = input.current_token_start();
let fragment_length = input.slice_len();
let span = match limit {
SpanLength::Unknown => (fragment_start, fragment_length).into(),
Expand All @@ -265,9 +265,9 @@ where
fn expect<'a, F, T>(
parser: F,
make_err: fn(SourceSpan) -> ParseSingleError,
) -> impl Parser<Span<'a>, Option<T>, Error>
) -> impl ModalParser<Span<'a>, Option<T>, Error>
where
F: Parser<Span<'a>, T, Error>,
F: ModalParser<Span<'a>, T, Error>,
{
expect_inner(parser, make_err, SpanLength::Unknown)
}
Expand All @@ -276,23 +276,23 @@ fn expect_n<'a, F, T>(
parser: F,
make_err: fn(SourceSpan) -> ParseSingleError,
limit: SpanLength,
) -> impl Parser<Span<'a>, Option<T>, Error>
) -> impl ModalParser<Span<'a>, Option<T>, Error>
where
F: Parser<Span<'a>, T, Error>,
F: ModalParser<Span<'a>, T, Error>,
{
expect_inner(parser, make_err, limit)
}

fn expect_char<'a>(
c: char,
make_err: fn(SourceSpan) -> ParseSingleError,
) -> impl Parser<Span<'a>, Option<char>, Error> {
) -> impl ModalParser<Span<'a>, Option<char>, Error> {
expect_inner(ws(c), make_err, SpanLength::Exact(0))
}

fn silent_expect<'a, F, T>(mut parser: F) -> impl Parser<Span<'a>, Option<T>, Error>
fn silent_expect<'a, F, T>(mut parser: F) -> impl ModalParser<Span<'a>, Option<T>, Error>
where
F: Parser<Span<'a>, T, Error>,
F: ModalParser<Span<'a>, T, Error>,
{
move |input: &mut _| match parser.parse_next(input) {
Ok(out) => Ok(Some(out)),
Expand All @@ -301,7 +301,9 @@ where
}
}

fn ws<'a, T, P: Parser<Span<'a>, T, Error>>(mut inner: P) -> impl Parser<Span<'a>, T, Error> {
fn ws<'a, T, P: ModalParser<Span<'a>, T, Error>>(
mut inner: P,
) -> impl ModalParser<Span<'a>, T, Error> {
move |input: &mut Span<'a>| {
let start = input.checkpoint();
() = repeat(
Expand Down Expand Up @@ -344,7 +346,7 @@ fn parse_matcher_text<'i>(input: &mut Span<'i>) -> PResult<Option<String>> {
};

if res.as_ref().map(|s| s.is_empty()).unwrap_or(false) {
let start = input.location();
let start = input.current_token_start();
input
.state
.report_error(ParseSingleError::InvalidString((start..0).into()));
Expand Down Expand Up @@ -447,7 +449,7 @@ fn parse_regex<'i>(input: &mut Span<'i>) -> PResult<Option<NameMatcher>> {
input.reset(&start);
match take_till::<_, _, Error>(0.., ')').parse_next(input) {
Ok(_) => {
let start = input.location();
let start = input.current_token_start();
let err = ParseSingleError::ExpectedCloseRegex((start, 0).into());
input.state.report_error(err);
return Ok(None);
Expand All @@ -462,10 +464,10 @@ fn parse_regex<'i>(input: &mut Span<'i>) -> PResult<Option<NameMatcher>> {
let end = input.checkpoint();

input.reset(&start);
let start = input.location();
let start = input.current_token_start();

input.reset(&end);
let end = input.location();
let end = input.current_token_start();

let err = ParseSingleError::invalid_regex(&res, start, end);
input.state.report_error(err);
Expand Down Expand Up @@ -495,7 +497,7 @@ fn parse_glob_matcher(input: &mut Span<'_>) -> PResult<Option<NameMatcher>> {
// This parse will never fail (because default_matcher won't)
fn set_matcher<'a>(
default_matcher: DefaultMatcher,
) -> impl Parser<Span<'a>, Option<NameMatcher>, Error> {
) -> impl ModalParser<Span<'a>, Option<NameMatcher>, Error> {
ws(alt((
parse_regex_matcher,
parse_glob_matcher,
Expand All @@ -510,7 +512,7 @@ fn recover_unexpected_comma<'i>(input: &mut Span<'i>) -> PResult<()> {
let start = input.checkpoint();
match peek(ws(',')).parse_next(input) {
Ok(_) => {
let pos = input.location();
let pos = input.current_token_start();
input
.state
.report_error(ParseSingleError::UnexpectedComma((pos..0).into()));
Expand All @@ -531,12 +533,12 @@ fn recover_unexpected_comma<'i>(input: &mut Span<'i>) -> PResult<()> {
fn nullary_set_def<'a>(
name: &'static str,
make_set: fn(SourceSpan) -> SetDef,
) -> impl Parser<Span<'a>, Option<SetDef>, Error> {
) -> impl ModalParser<Span<'a>, Option<SetDef>, Error> {
move |i: &mut Span<'_>| {
let start = i.location();
let start = i.current_token_start();
let _ = literal(name).parse_next(i)?;
let _ = expect_char('(', ParseSingleError::ExpectedOpenParenthesis).parse_next(i)?;
let err_loc = i.location();
let err_loc = i.current_token_start();
match take_till::<_, _, Error>(0.., ')').parse_next(i) {
Ok(res) => {
if !res.trim().is_empty() {
Expand All @@ -548,7 +550,7 @@ fn nullary_set_def<'a>(
Err(_) => unreachable!(),
};
let _ = expect_char(')', ParseSingleError::ExpectedCloseParenthesis).parse_next(i)?;
let end = i.location();
let end = i.current_token_start();
Ok(Some(make_set((start, end - start).into())))
}
}
Expand All @@ -562,7 +564,7 @@ enum DefaultMatcher {
}

impl DefaultMatcher {
fn into_parser<'a>(self) -> impl Parser<Span<'a>, Option<NameMatcher>, Error> {
fn into_parser<'a>(self) -> impl ModalParser<Span<'a>, Option<NameMatcher>, Error> {
move |input: &mut _| match self {
Self::Equal => parse_matcher_text
.map(|res: Option<String>| res.map(NameMatcher::implicit_equal))
Expand All @@ -579,13 +581,13 @@ fn unary_set_def<'a>(
name: &'static str,
default_matcher: DefaultMatcher,
make_set: fn(NameMatcher, SourceSpan) -> SetDef,
) -> impl Parser<Span<'a>, Option<SetDef>, Error> {
) -> impl ModalParser<Span<'a>, Option<SetDef>, Error> {
move |i: &mut _| {
let _ = literal(name).parse_next(i)?;
let _ = expect_char('(', ParseSingleError::ExpectedOpenParenthesis).parse_next(i)?;
let start = i.location();
let start = i.current_token_start();
let res = set_matcher(default_matcher).parse_next(i)?;
let end = i.location();
let end = i.current_token_start();
recover_unexpected_comma.parse_next(i)?;
let _ = expect_char(')', ParseSingleError::ExpectedCloseParenthesis).parse_next(i)?;
Ok(res.map(|matcher| make_set(matcher, (start, end - start).into())))
Expand All @@ -595,10 +597,10 @@ fn unary_set_def<'a>(
fn platform_def(i: &mut Span<'_>) -> PResult<Option<SetDef>> {
let _ = "platform".parse_next(i)?;
let _ = expect_char('(', ParseSingleError::ExpectedOpenParenthesis).parse_next(i)?;
let start = i.location();
let start = i.current_token_start();
// Try parsing the argument as a string for better error messages.
let res = ws(parse_matcher_text).parse_next(i)?;
let end = i.location();
let end = i.current_token_start();
recover_unexpected_comma.parse_next(i)?;
let _ = expect_char(')', ParseSingleError::ExpectedCloseParenthesis).parse_next(i)?;

Expand Down Expand Up @@ -642,9 +644,9 @@ fn parse_set_def(input: &mut Span<'_>) -> PResult<Option<SetDef>> {
.parse_next(input)
}

fn expect_expr<'a, P: Parser<Span<'a>, ExprResult, Error>>(
fn expect_expr<'a, P: ModalParser<Span<'a>, ExprResult, Error>>(
inner: P,
) -> impl Parser<Span<'a>, ExprResult, Error> {
) -> impl ModalParser<Span<'a>, ExprResult, Error> {
expect(inner, ParseSingleError::ExpectedExpr).map(|res| res.unwrap_or(ExprResult::Error))
}

Expand Down Expand Up @@ -769,7 +771,7 @@ fn parse_or_operator<'i>(input: &mut Span<'i>) -> PResult<Option<OrOperator>> {
"parse_or_operator",
ws(alt((
|input: &mut Span<'i>| {
let start = input.location();
let start = input.current_token_start();
// This is not a valid OR operator in this position, but catch it to provide a better
// experience.
let op = alt(("||", "OR ")).parse_next(input)?;
Expand Down Expand Up @@ -872,7 +874,7 @@ fn parse_and_or_difference_operator<'i>(
"parse_and_or_difference_operator",
ws(alt((
|input: &mut Span<'i>| {
let start = input.location();
let start = input.current_token_start();
let op = alt(("&&", "AND ")).parse_next(input)?;
// && is not supported in filtersets: suggest using & instead.
let length = op.len();
Expand Down
10 changes: 6 additions & 4 deletions nextest-filtering/src/parsing/glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
errors::{GlobConstructError, ParseSingleError},
NameMatcher,
};
use winnow::{combinator::trace, stream::Location, Parser};
use winnow::{combinator::trace, stream::Location, ModalParser, Parser};

/// A glob pattern.
///
Expand Down Expand Up @@ -58,9 +58,11 @@ impl GenericGlob {
}

// This never returns Err(()) -- instead, it reports an error to the parsing state.
pub(super) fn parse_glob<'i>(implicit: bool) -> impl Parser<Span<'i>, Option<NameMatcher>, Error> {
pub(super) fn parse_glob<'i>(
implicit: bool,
) -> impl ModalParser<Span<'i>, Option<NameMatcher>, Error> {
trace("parse_glob", move |input: &mut Span<'i>| {
let start = input.location();
let start = input.current_token_start();
let res = match parse_matcher_text.parse_next(input) {
Ok(res) => res,
Err(_) => {
Expand All @@ -75,7 +77,7 @@ pub(super) fn parse_glob<'i>(implicit: bool) -> impl Parser<Span<'i>, Option<Nam
match GenericGlob::new(parsed_value) {
Ok(glob) => Ok(Some(NameMatcher::Glob { glob, implicit })),
Err(error) => {
let end = input.location();
let end = input.current_token_start();
let err = ParseSingleError::InvalidGlob {
span: (start, end - start).into(),
error,
Expand Down

0 comments on commit a734cf2

Please sign in to comment.