Skip to content

Let a regex that spans whitespace match under ByWordAny [patch] - #125

Merged
matt-edmondson merged 1 commit into
mainfrom
claude/textfilter-122-regex-spans-words
Sep 28, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
claude/textfilter-122-regex-spans-words

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #122

Problem

For ByWordAny and ByWordAll, DoesMatchRegex split the text into words and ran the pattern against each word separately. No word contains whitespace, so any pattern that has to match across it could never match. That includes hello world, o\sw and New York. ByWordAny is the default for Filter and IsMatch, so in a regex filter box with default options, typing a phrase hid every item.

Change

All in TextFilter/TextFilter.cs:

  • Whole text first under ByWordAny: the pattern is now tried against the whole text, then against each word, which is the fix the triage suggested. Word-anchored patterns like ^world still match hello world through the per-word pass.
  • Same timeout handling for both passes: the per-token try/catch (RegexMatchTimeoutException) moved into a private IsMatchWithinTimeout. The whole-text evaluation and the per-word evaluations share it, so a pattern that times out on the whole text still reports no match rather than throwing.
  • ByWordAll unchanged: it keeps its per-word meaning. The DoesMatchRegex remarks now say that a pattern spanning whitespace needs ByWholeString there. That is the "document it" option from the triage, and it doesn't change behaviour for existing ByWordAll callers.
  • Blank text still returns false before either pass runs.

Timeout budget: for ByWordAny, one catastrophic pattern now costs up to one extra timeout per item: the whole-text attempt on top of the per-word attempts. #118 tracks the per-word timeout budget, and fixing it there covers this evaluation too.

Tests

  • IsMatchRegexSpanningWhitespaceMatchesUnderTheDefaults covers the two acceptance cases from the issue (hello world and o\sw), plus o w, New York and \d+\s+items.
  • FilterRegexSpanningWhitespaceKeepsMatchingItemsUnderTheDefaults
  • IsMatchRegexByWordAnyStillMatchesAWordAnchoredPattern checks that ^world and hello$ still match, and that a phrase with a doubled space doesn't.
  • DoesMatchRegexByWordAllStillRequiresEveryWordToMatchOnItsOwn pins the documented ByWordAll behaviour.

With the change to TextFilter.cs reverted, the 6 whitespace-spanning cases fail. With it, the full suite passes (123/123 on net10.0), and the library builds for every target.

This PR also edits DoesMatchRegex, like #121, but on different lines. Whichever of the two merges second may need a trivial rebase.

🤖 Generated with Claude Code

https://claude.ai/code/session_01M9aefrfAYJpanQVrUuFpJh


Generated by Claude Code

DoesMatchRegex split the text into words for ByWordAny and ByWordAll
and ran the pattern against each word. No word contains whitespace, so a
pattern such as "hello world", "o\sw" or "New York" could never match,
and ByWordAny is the default for Filter and IsMatch.

Under ByWordAny the pattern is now tried against the whole text first,
then against each word, so word-anchored patterns like "^world" still
match. Both evaluations share the existing timeout handling. ByWordAll
keeps its per-word meaning, and the remarks now say that a pattern
spanning whitespace needs ByWholeString there.

Fixes #122

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M9aefrfAYJpanQVrUuFpJh
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 6967c0d into main Sep 28, 2026
12 checks passed
@matt-edmondson
matt-edmondson deleted the claude/textfilter-122-regex-spans-words branch September 28, 2026 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regex filters containing a space or \s never match under the default ByWordAny option ("hello world" doesn't match "hello world")

2 participants