Skip to content

feat(guard): guard C# - #789

Merged
mick-gsk merged 1 commit into
mainfrom
feat/guard-csharp
Jul 29, 2026
Merged

mick-gsk merged 1 commit into
mainfrom
feat/guard-csharp

Conversation

@mick-gsk

Copy link
Copy Markdown
Owner

Eight file types in one index. Measured: serilog 0.9 % of 216 files, Newtonsoft.Json 2.5 % of 945.

One thing C# needed that nothing else did

Every other matcher anchors to column zero — that is what makes "top level" cheap to express without a parser. C# breaks it: a block-scoped namespace X { ... } indents the entire file by one level. Types are matched at up to four leading spaces; the modern file-scoped namespace X; form needs no allowance, and both are tested.

using A.B.C; becomes A/B/C, and the trailing-segment resolver written for Go in #786 finds it unchanged, because a .NET project mirrors its namespace in the directory tree — the same assumption Java relies on.

*.csproj had to become a glob rather than a name: a .NET project file is called after its project, so the directory is searched instead of probed.

Two exclusion rules the measurement produced

Both general, neither specific to this corpus.

.NET names a test project after the project it covers, so the path segment is never exactly tests. Src/Newtonsoft.Json.Tests/ slipped straight through a filter that only matched the bare word — and supplied most of what the guard would have said. Any segment ending .Tests, .Test, .Specs or .Spec now counts.

Generated code restates whatever produced it, and nobody edits it. Model.designer.cs, Api.g.cs and schema_pb2.py are excluded by filename.

before after
Newtonsoft.Json 5.1 % 2.5 %

No regression

axios 5.6 %, flask 4.8 %, gin 2.0 %, gson 0.0 %, ripgrep 7.3 %.

Verification

170 guard tests (11 new), all nine gates, nine repositories across eight file types within the noise budget, ruff and mypy clean, markdownlint clean.

🤖 Generated with Claude Code

Eight file types in one index. Measured: serilog 0.9 % of 216 files,
Newtonsoft.Json 2.5 % of 945.

C# needed one thing no other language here did. Every other matcher anchors to
column zero, which is what makes "top level" cheap to express — but a
block-scoped `namespace X { ... }` indents the whole file by one level. Types
are matched at up to four leading spaces; the file-scoped `namespace X;` form
needs no allowance. `using A.B.C;` becomes `A/B/C`, and the trailing-segment
resolver written for Go finds it, because a .NET project mirrors its namespace
in the directory tree.

`*.csproj` had to be a glob rather than a name: a .NET project file is called
after its project, so the directory is searched instead of probed.

Two exclusion rules came out of the measurement, both general rather than
specific to this corpus.

.NET names a test project after the project it covers, so the segment is never
exactly `tests` — `Src/Newtonsoft.Json.Tests/` slipped through a filter that
only matched the bare word, and supplied most of what the guard would have
said. Any segment ending `.Tests`, `.Test`, `.Specs` or `.Spec` now counts.

Generated code restates whatever produced it and nobody edits it, so
`Model.designer.cs`, `Api.g.cs` and `schema_pb2.py` are excluded by filename.

    Newtonsoft.Json  5.1 % -> 2.5 %

No regression: axios 5.6 %, flask 4.8 %, gin 2.0 %, gson 0.0 %, ripgrep 7.3 %.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mick-gsk
mick-gsk merged commit fe02396 into main Jul 29, 2026
1 check failed
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@mick-gsk
mick-gsk deleted the feat/guard-csharp branch July 29, 2026 23:29
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.

2 participants