You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A glob class whose only range is reversed (file[%-!]) matches every item, while the letter/digit equivalent (file[9-0]) matches none #173
When a glob class contains only reversed ranges, or expands past MaxGlobClassMembers (4096), ToGlobCharacterList (TextFilter/TextFilter.cs) returns null:
the reversed-range case: the for (member = first; member <= last; …) loop adds nothing, so members.Count == 0 returns null (around line 600)
the over-cap case: around line 587
ResolveGlob caches that null, and DoesMatchGlob then treats the token as unparseable, half-typed input:
around line 378, unparseable optional tokens are dropped
with none left, around line 382, no optional constraint applies, so every item passes
Letter and digit ranges take a different path: IsNativeGlobRange (around line 559) sends them to DotNet.Glob, where a reversed range correctly matches nothing. So whether the same mistake hides everything or shows everything depends on which characters the range uses.
Failure scenario
Filter(["alpha.cs", "beta.txt", "gamma.md"], "file[%-!]") returns all three items. Expected: none, because the class is empty.
Filter(..., "file[9-0]") correctly returns none.
IsMatch("hello", "x[?-!]") returns true, as does IsMatch("hello", "x[\u0001-�]y") (over the cap). Both should be false.
The pattern is complete and well-formed, so this isn't the "user is still typing" case that the drop-unparseable rule exists for. It is the same symptom that #110 and #130 fixed for half-typed ranges: a filter that should narrow the list instead shows everything.
Suggested fix / acceptance criteria
Keep the "unparseable → drop" path for genuinely incomplete input only, such as [a- or an unclosed [.
For a complete class that has no members, produce a token that never matches. A reversed range then behaves the same for punctuation as it does for letters and digits.
For a class that expands past the cap, either keep it as a native range when DotNet.Glob can express it, raise the cap, or treat it as never-matching. It must not match everything.
Add tests:
file[%-!] and x[?-!] match nothing, under both Filter and IsMatch, in both case-sensitivity modes
an over-cap class doesn't match unrelated text
Related: #110 and #130 (closed; half-typed ranges), #167 (notes that a native reversed range matches nothing).
Area / suggested owner: Glob handling in TextFilter/TextFilter.cs: ToGlobCharacterList (null returns for an empty class or an over-cap class), the ResolveGlob cache, and the drop-unparseable path in DoesMatchGlob. IsNativeGlobRange is the reference for the letter/digit behaviour.
Activity
matt-edmondson commentedon Oct 31, 2026
Triage
file[a-]is treated as unparseable: as a filter it shows every item, as an exclusion it hides nothing #130 fixed for half-typed ranges. Only reversed punctuation ranges and classes over the 4096-member cap trigger it, so it's an edge case, but the result is the opposite of what the pattern asks for.TextFilter/TextFilter.cs:ToGlobCharacterList(null returns for an empty class or an over-cap class), theResolveGlobcache, and the drop-unparseable path inDoesMatchGlob.IsNativeGlobRangeis the reference for the letter/digit behaviour.file[a-]is treated as unparseable: as a filter it shows every item, as an exclusion it hides nothing #130 (closed) and Case-insensitive glob matches less than case-sensitive for mixed-case ranges: [A-z] stops matching "_", [Z-a] stops matching "a" #167. Open PRs Match an unclosed glob bracket literally [patch] #165, Match a mixed-case glob range the same under both case sensitivities [patch] #168, Match a whole-string glob containing a space against the whole text [patch] #169 and Require a separator after a glob ** joined to a preceding literal [patch] #171 change nearby glob-class code (unclosed brackets, mixed-case ranges, spaces,**) but none of them fixes empty or over-cap classes. Expect merge conflicts inToGlobCharacterList, so sequence this one after those land.Generated by Claude Code