From 0609c577bd175294d92c8d40affd29d7ab15cefa Mon Sep 17 00:00:00 2001 From: Miguel Varela Ramos Date: Fri, 22 May 2026 10:39:16 +0100 Subject: [PATCH] feat: support go 1.24 ignore directives --- src/lib.rs | 76 +++++++++++++++++++++++++++++++++++++++++++ src/parser.rs | 37 +++++++++++++++++++++ tests/data/ignore.mod | 11 +++++++ tests/parse.rs | 17 ++++++++++ 4 files changed, 141 insertions(+) create mode 100644 tests/data/ignore.mod diff --git a/src/lib.rs b/src/lib.rs index 6034f5f..ca99ee2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,7 @@ pub struct GoMod { pub exclude: Vec, pub replace: Vec, pub retract: Vec, + pub ignore: Vec, } impl std::str::FromStr for GoMod { @@ -73,6 +74,7 @@ impl std::str::FromStr for GoMod { Directive::Exclude(d) => res.exclude.append(d), Directive::Replace(d) => res.replace.append(d), Directive::Retract(d) => res.retract.append(d), + Directive::Ignore(d) => res.ignore.append(d), } } @@ -284,6 +286,80 @@ mod tests { ); } + #[test] + fn test_ignore_single() { + let input = indoc! {r#" + module github.com/ignore-single + + go 1.24 + + ignore ./testdata + "#}; + + let go_mod = GoMod::from_str(input).unwrap(); + + assert_eq!(go_mod.ignore, vec!["./testdata".to_string()]); + } + + #[test] + fn test_ignore_multi() { + let input = indoc! {r#" + module github.com/ignore-multi + + go 1.24 + + ignore ( + ./testdata + ./vendor/temp + ./node_modules + ) + "#}; + + let go_mod = GoMod::from_str(input).unwrap(); + + assert_eq!( + go_mod.ignore, + vec![ + "./testdata".to_string(), + "./vendor/temp".to_string(), + "./node_modules".to_string(), + ] + ); + } + + #[test] + fn test_ignore_repeated_singles() { + let input = indoc! {r#" + module github.com/ignore-repeated + + go 1.24 + + ignore ./testdata + ignore ./vendor/temp + "#}; + + let go_mod = GoMod::from_str(input).unwrap(); + + assert_eq!( + go_mod.ignore, + vec!["./testdata".to_string(), "./vendor/temp".to_string()] + ); + } + + #[test] + fn test_no_line_ending_after_ignore() { + let input = indoc! {r#" + module github.com/no-line-ending + + ignore ( + ./testdata + )"#}; + + let go_mod = GoMod::from_str(input).unwrap(); + + assert_eq!(go_mod.ignore, vec!["./testdata".to_string()]); + } + #[test] fn test_comments() { let input = indoc! {r#" diff --git a/src/parser.rs b/src/parser.rs index 19ece9d..75c399e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -22,6 +22,7 @@ pub(crate) enum Directive<'a> { Exclude(Vec), Replace(Vec), Retract(Vec), + Ignore(Vec), } pub(crate) fn gomod<'a>(input: &mut &'a str) -> Result>> { @@ -44,6 +45,7 @@ fn directive<'a>(input: &mut &'a str) -> Result> { "exclude" => exclude, "replace" => replace, "retract" => retract, + "ignore" => ignore, _ => fail, ) .parse_next(input) @@ -294,3 +296,38 @@ fn retract_multi(input: &mut &str) -> Result> { Ok(res.into_iter().flatten().collect::>()) } + +fn ignore<'a>(input: &mut &'a str) -> Result> { + let res = preceded( + ("ignore", space1), + dispatch! {peek(any); + '(' => ignore_multi, + _ => ignore_single, + }, + ) + .parse_next(input)?; + let _ = take_while(0.., CRLF).parse_next(input)?; + + Ok(Directive::Ignore(res)) +} + +fn ignore_single(input: &mut &str) -> Result> { + // terminate, if `)` is found + peek(not(')')).parse_next(input)?; + + let path = take_till(1.., WHITESPACES).parse_next(input)?; + + // remove any comments added to the same line + let _ = opt(comment).parse_next(input)?; + + Ok(vec![path.to_string()]) +} + +fn ignore_multi(input: &mut &str) -> Result> { + let _ = ("(", multispace1).parse_next(input)?; + let res: Vec> = + repeat(1.., terminated(ignore_single, multispace0)).parse_next(input)?; + let _ = (")", multispace0).parse_next(input)?; + + Ok(res.into_iter().flatten().collect::>()) +} diff --git a/tests/data/ignore.mod b/tests/data/ignore.mod new file mode 100644 index 0000000..610e193 --- /dev/null +++ b/tests/data/ignore.mod @@ -0,0 +1,11 @@ +module github.com/example/ignore + +go 1.24 + +ignore ./build + +ignore ( + ./testdata + ./vendor/temp + ./node_modules +) diff --git a/tests/parse.rs b/tests/parse.rs index e2b681a..ba6a21b 100644 --- a/tests/parse.rs +++ b/tests/parse.rs @@ -91,6 +91,23 @@ fn test_parse_tool() { ); } +#[test] +fn test_parse_ignore() { + let file_content = get_test_file_content("ignore.mod"); + let gomod = file_content.parse::().unwrap(); + + assert_eq!(gomod.module, "github.com/example/ignore".to_string()); + assert_eq!( + gomod.ignore, + vec![ + "./build".to_string(), + "./testdata".to_string(), + "./vendor/temp".to_string(), + "./node_modules".to_string(), + ] + ); +} + #[test] fn test_carriage_return() { let file_content = get_test_file_content("compress.mod")