Skip to content

Keep case-sensitive globs off DotNet.Glob's global default [patch] - #189

Open
matt-edmondson wants to merge 2 commits into
mainfrom
fix/case-sensitive-glob-options-188
Open

matt-edmondson wants to merge 2 commits into
mainfrom
fix/case-sensitive-glob-options-188

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #188

What changed

ResolveGlob passed its own GlobOptions only on the case-insensitive path. Glob.Parse(pattern) with no options reads DotNet.Glob's static, mutable GlobOptions.Default.

A host that set GlobOptions.Default.Evaluation.CaseInsensitive = true therefore made both the default sensitivity and an explicit CaseSensitive match without regard to case. *.jpg matched IMG.JPG, and -*.jpg hid it. Which patterns were affected depended on whether GlobCache already held them from before the flip.

The case-sensitive branch now parses with a private CaseSensitiveGlobOptions, so TextFilter never reads GlobOptions.Default. Regex mode was never affected.

Tests

GlobDefaultOptionsTests flips GlobOptions.Default.Evaluation.CaseInsensitive to true and restores it in finally. It is marked [DoNotParallelize] and uses patterns no other test parses, so the cache can't mask the bug. It asserts:

  • the default and explicit CaseSensitive sensitivities still treat case as significant
  • an exclusion doesn't hide an item that differs only in case
  • CaseInsensitive still ignores case

With the library change reverted, the test fails on its first assertion. With the change, 268/269 tests pass.

The remaining failure, ReadmeTests.EveryMethodInTheReadmeApiReferenceExistsWithItsDocumentedDefaults, fails identically on main without this change. Open PR #186 addresses it.


Generated by Claude Code

ResolveGlob passed its own options only on the case-insensitive path.
Glob.Parse(pattern) without options reads DotNet.Glob's static, mutable
GlobOptions.Default, so a host that set
GlobOptions.Default.Evaluation.CaseInsensitive = true quietly turned the
default CaseSensitive filters, and explicit CaseSensitive ones,
case-insensitive: `*.jpg` matched `IMG.JPG` and `-*.jpg` hid it. Which
patterns were affected depended on whether they were cached before the
flip. Parse the case-sensitive branch with a private
CaseSensitiveGlobOptions, so TextFilter never reads GlobOptions.Default.

Fixes #188

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW3SsCYipEZieVhB1tG
…from #186)

ReadmeTests fails on main because the EditorBrowsable(Never)
binary-compatibility overloads carry no defaults by design. Ported from
open PR #186 so this PR's CI shows its own result.

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

Copy link
Copy Markdown
Contributor Author

ci / .NET / Test on ubuntu-latest failed on ReadmeTests.EveryMethodInTheReadmeApiReferenceExistsWithItsDocumentedDefaults. That failure doesn't come from this PR: the same test fails on main at 5f420d9 without this change.

The cause is that the [EditorBrowsable(Never)] binary-compatibility overloads of IsMatch/Filter deliberately carry no defaults, and the test checked them against the README anyway.

I've pushed a port of the test-only fix from open PR #186, which checks only the visible overloads. Locally the full suite now passes, 269/269. Whichever of the two PRs merges second should apply cleanly, since the change is identical.


Generated by Claude Code

@sonarqubecloud

sonarqubecloud Bot commented Nov 5, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
E Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Copy link
Copy Markdown
Contributor Author

SonarCloud Code Analysis fails the quality gate with an E maintainability rating. None of the five findings are on lines this PR changes. Its diff to TextFilter.cs is lines 120–123 and 679.

The findings:

Why Sonar counts them as new here: its last analysis of main is at 837b460, from just before #166 (ce92ed1). TextFilter.BinaryCompatibility.cs doesn't exist in that analysis at all, so any PR that touches TextFilter.cs is charged with #166's overlaps. The usual per-PR quality-gate fix can't clear this from here.

Fix: once main is analysed again, which should happen when the next merge to main runs CI, this baseline gap closes. The S3427 overlap is how #166 was designed: the hidden binary-compatibility overloads deliberately carry no defaults, so a call can never be ambiguous between the two sets. If you'd rather the gate stopped flagging it, the overlaps want an accept-or-suppress decision in SonarCloud, not a code change in this PR.

All test jobs are green on the current head (73ce9a0).


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants