diff --git a/TextFilter.Test/TextFilterTests.cs b/TextFilter.Test/TextFilterTests.cs index 40ba5c6..6e44b63 100644 --- a/TextFilter.Test/TextFilterTests.cs +++ b/TextFilter.Test/TextFilterTests.cs @@ -608,6 +608,25 @@ public void TheTwoSensitivitiesDoNotCollideInTheGlobCache() Assert.IsFalse(TextFilter.IsMatch("B.MD", "*.md", TextFilterType.Glob, TextFilterMatchOptions.ByWholeString, TextFilterCaseSensitivity.CaseSensitive)); } + [TestMethod] + public void GlobByWholeStringNeedsOnlyOneOptionalTokenToMatch() + { + // The glob hint promises "one of the optional tokens". ByWholeString used to require all of + // them, so a filter of alternatives such as extension globs matched nothing at all. + Assert.IsTrue(TextFilter.IsMatch("photo.jpg", "*.jpg *.png", TextFilterType.Glob, TextFilterMatchOptions.ByWholeString)); + Assert.IsFalse(TextFilter.IsMatch("notes.txt", "*.jpg *.png", TextFilterType.Glob, TextFilterMatchOptions.ByWholeString)); + CollectionAssert.AreEqual( + new List { "a.jpg", "b.png" }, + TextFilter.Filter(["a.jpg", "b.png", "c.txt"], "*.jpg *.png", TextFilterType.Glob, TextFilterMatchOptions.ByWholeString).ToList()); + } + + [TestMethod] + public void GlobByWordAllStillNeedsEveryOptionalTokenToMatch() + { + Assert.IsTrue(TextFilter.IsMatch("red apple", "red* app*", TextFilterType.Glob, TextFilterMatchOptions.ByWordAll)); + Assert.IsFalse(TextFilter.IsMatch("red apple", "red* pear*", TextFilterType.Glob, TextFilterMatchOptions.ByWordAll)); + } + [TestMethod] public void RegexCaseInsensitivityDoesNotDependOnTheCurrentCulture() { diff --git a/TextFilter/TextFilter.cs b/TextFilter/TextFilter.cs index 201095b..ba6ec0e 100644 --- a/TextFilter/TextFilter.cs +++ b/TextFilter/TextFilter.cs @@ -343,9 +343,9 @@ public static bool DoesMatchGlob(string text, string filter, TextFilterMatchOpti return false; // text contains an excluded token } - Func, Func, bool> optionalMatchFunc = textFilterMatchOptions is TextFilterMatchOptions.ByWordAny - ? Enumerable.Any - : Enumerable.All; + Func, Func, bool> optionalMatchFunc = textFilterMatchOptions is TextFilterMatchOptions.ByWordAll + ? Enumerable.All + : Enumerable.Any; bool anyOptionalMatches = optionalMatchFunc(optionalTokens, filterToken => AnyTokenMatchesGlobFilter(filterToken, textTokens, caseSensitivity));