Skip to content

docs: correct five claims the code had already outgrown - #73

Merged
Reefact merged 1 commit into
mainfrom
claude/five-false-claims
Aug 11, 2026
Merged

docs: correct five claims the code had already outgrown#73
Reefact merged 1 commit into
mainfrom
claude/five-false-claims

Conversation

@Reefact

@Reefact Reefact commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Summary

Five statements in the repository are false. Each was verified by measurement before being rewritten, and one of them is a diagnostic message a user reads.

1. EMN0005's message, false on half the shapes it reports

Both the analyzer's wording and EnumContractException's said the shadowed member was "only reachable through a different casing". Measured against System.Text.Json:

shape Blue blue claim
[JsonStringEnumMemberName("Blue")] Red beside Blue Red Blue true — the member loses its own spelling
[JsonStringEnumMemberName("blue")] Red beside Blue Blue Red false — it keeps its own spelling and loses blue

The member loses the declared spelling and keeps every other casing, which is true either way. The oracle has to be the serializer, because this package refuses both shapes outright and there is no contract to ask — which is also why the claim went unchecked so long: a message describing a shape nothing can build is a sentence no test was reaching for. the_shadowed_member_loses_the_declared_spelling_and_no_other is that test now.

The rule pages are left alone: they state it of their own example, which is the same-casing one, and already describe the mirror correctly. Only the generic wordings were wrong — the two messages, two remarks, and the changelog's summary of the rule.

2. "the one input where a channel and the body disagree"

The binder's remark said that; the paragraph directly below it already contradicted it, and so did the test suite two methods apart — a_flags_combination_naming_no_member_is_refused_too says in its own text "which is what makes this a divergence". There are at least three: the non-[Flags] combination, the [Flags] one refused by a different platform test, and a declared name carrying a character a route or a header cannot transport, which is what EMN0006 exists to report. The test that named itself ..._is_the_one_thing_only_the_body_accepts is renamed with it.

3. EMN0001 on alias writing

It still said the first-declared alias name is used when writing. It is the first in Enum.GetNames order, which is neither declaration order nor the arithmetic one — the correction that went into the value-to-name map never reached that page, in either language.

4. The README on link generation

ASP.NET Core formats route values without the value's own ToString(), so a link built from the enum value carries the C# name

Self-contradictory: the C# name is what ToString() returns. Measured — ProductStatus.OutOfStock.ToString() and Convert.ToString(…, InvariantCulture) both give "OutOfStock", and /status/link-raw in the suite produces that path. It formats them with it, which is the whole reason the workaround exists.

5. limitations on who refuses an undefined value

It credited the refusal to EnumTypeModelBinder and called it "not reachable from here". This package registers its binder ahead of the provider ASP.NET Core uses for enums, so EnumTypeModelBinder never sees the value: the check is reproduced here, deliberately — as the binder's own remark says — and the refusal a caller meets is this package's own. Both halves rewritten, in both languages.

Type of change

  • Bug fix
  • New feature
  • Breaking change to the public API
  • Refactoring
  • Analyzer / diagnostic change
  • Tests
  • Documentation
  • Build / CI / tooling

Testing

  • dotnet build -c Release — clean, warnings are errors here
  • dotnet test -c Release — 956 passed, 0 failed
  • tests/PackageSmokeTest/run.sh — run because the analyzer's resources changed; "The published package behaves as documented."

Also run: tools/style/lint-layout.sh (nothing to report).

Public API

  • No change to the public surface
  • The surface changed and the baseline was updated in the same commit

Two diagnostic message strings change; no symbol does.

Documentation

  • README / docs/ updated
  • The French counterpart was updated to match
  • CHANGELOG.md and docs/for-users/CHANGELOG.fr.md both updated
  • No documentation change required

🤖 Generated with Claude Code

https://claude.ai/code/session_01M5U2BZXpHQr7YcfNHVx9dA


Generated by Claude Code

EMN0005's message was false on half the shapes it reports. Both the
analyzer's wording and EnumContractException's said the shadowed member
was "only reachable through a different casing". That holds when the
declared name is spelled like the C# name it shadows, and not otherwise:
on [JsonStringEnumMemberName("blue")] beside a Blue member, Blue still
answers to Blue and it is blue it loses. The member loses the declared
spelling and keeps every other casing, which is true either way.

Measured against System.Text.Json, since this package refuses both
shapes and has no contract to ask — which is also why the claim went
unchecked: a message describing a shape nothing can build is a sentence
no test was reaching for. There is a test now. The rule pages were
already right, and are left alone: they state it of their own example,
which is the same-casing one, and describe the mirror correctly.

The binder called the undefined-value refusal "the one input where a
channel and the body disagree". The paragraph below it already
contradicted that, and so did the test suite two methods apart: the
[Flags] half is a second input and a name carrying a character a route
or a header cannot transport is a third, which is what EMN0006 reports.
The test that named itself "the one thing only the body accepts" is
renamed with it.

EMN0001 still said the first-declared alias name is used when writing.
It is the first in Enum.GetNames order — the correction that went into
the value-to-name map never reached that page, in either language.

The README said ASP.NET Core formats route values without the value's
own ToString(), then explained that the link therefore carries the C#
name, which is what ToString() returns. It formats them with it.

limitations credited the refusal to EnumTypeModelBinder and called it
"not reachable from here". This package registers its binder ahead of
the provider ASP.NET Core uses for enums, so EnumTypeModelBinder never
sees the value: the check is reproduced here, deliberately, and the
refusal a caller meets is this package's own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M5U2BZXpHQr7YcfNHVx9dA
@Reefact
Reefact merged commit a3637ee into main Aug 11, 2026
10 checks passed
@Reefact
Reefact deleted the claude/five-false-claims branch August 11, 2026 19:25
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