Claude: changes for issue #45 #60
No reviewers
Labels
No labels
breaking-change
bug
documentation
duplicate
enhancement
good first issue
help wanted
performance
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/ATProto.NET!60
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/issue-45"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Requested in #45.
Dogfooding `atproto-lexgen csharp` against the published exchange.recipe Lexicons (recipe.exchange) produced C# that did not compile. Fixes all seven reported defects plus three more found while verifying against the 395 official atproto Lexicons: - drop the stray `}` emitted after the file-scoped namespace - rename members that collide with their enclosing type (CS0542), another member, or AtProtoRecord's Type/CreatedAt; sanitize illegal identifiers - disambiguate identically-named defs in sibling documents (CS0101) - emit `using ATProtoNet;`/`using ATProtoNet.Models;`/`System.Text.Json` only when used, plus `#nullable enable`, and root cross-namespace references at `global::` - make optional members nullable (a bare JsonElement serializes as ValueKind.Undefined and throws) - resolve well-known com.atproto.*/app.bsky.* refs to the SDK's own models (SdkTypeMap); unresolvable refs degrade to JsonElement? with a WARN instead of a dangling type name - record defs subclass AtProtoRecord and inherit CreatedAt - unions of object defs become [JsonPolymorphic] base classes with [JsonDerivedType] variants; unions of tokens are typed string - inline object schemas become nested classes (arrays singularize) - token families collapse into one static class of constants (recipe.exchange defs: 101 classes -> 9) - case the `atproto` NSID segment as `AtProto`, and map `"type": "number"` to double Also repeats [JsonPropertyName("$type")] on the Type override everywhere: System.Text.Json does not inherit the attribute onto an override, so the previously documented pattern wrote both "type" and "$type" into records. Verified: unit tests (1010 passing, 15 new in CSharpEmitterTests), and generated output for both the four exchange.recipe schemas and all 395 official atproto Lexicons compiles against the SDK with TreatWarningsAsErrors, with a serialization round-trip through the union. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the task runs.
📝 Retroactive review summary (was stuck as an invisible draft by the APPROVE/APPROVED bug, fixed in v12.2 — verdict was: approve):
Large but well-scoped fix for issue #45: the Lexicon → C# emitter is substantially rewritten (
CSharpEmitter, newEmitPlan/SdkTypeMap,TypeMapperadditions) to fix a long list of real compile-breaking defects (stray closing brace, CS0542 name collisions, CS0101 duplicate types, unqualified SDK refs, non-nullableJsonElementfallbacks,recorddefs not extendingAtProtoRecord,atprotocasing), plus new features (typed unions via[JsonPolymorphic], token-family grouping, nested inline-object classes). The accompanying doc/README/test-fixture updates correctly propagate the[JsonPropertyName("$type")]-on-override fix, which is a legitimate System.Text.Json gotcha (attributes on a base virtual/abstract property are not picked up on the overriding property).I manually traced the non-trivial algorithmic pieces (
EmitPlan's union-signature grouping/overlap handling, sibling-document disambiguation, token-family prefix detection, member/type collision renaming,Shorten/global::qualification) against the 24 new tests inCSharpEmitterTests.csand every case checks out — including subtle ones like thelicenseAllRights/licenseCreativeCommons*common-prefix computation and the_2fa/kebab-caseidentifier sanitization. I was not able to executedotnet testmyself in this sandbox (git worktree/dotnet invocations were blocked by the approval gate), so this is a static review, but the logic is internally consistent and the test coverage is unusually thorough for a change of this size.Two very minor, non-blocking observations not worth a code change on their own: (1)
TypeMapper.ToIdentifier's C#-keyword-escaping branch ("@" + identifier) is unreachable in every actual call site, since all callers pass throughToPascalCasefirst, which capitalizes away every lowercase C# keyword — effectively dead code. (2) A Lexicon union whose refs list includes the very object that declares the union property (self-referential union, not covered by tests) would pass theKind == "object"variant check and could be treated as an owning union member — plausible in principle but an unlikely real-world Lexicon shape, and the overlap-detection logic still degrades gracefully (falls back toJsonElement?with a WARN) in the tested sibling-overlap case.⏱ 3m 27s · 14 turns · tokens: 74.3k in / 17.9k out (+1106.8k cache-read)
📜 Full session transcript
@claude-bot Please fix the small conflict in the changelog.
🤖 On it — follow along in the action run; the reply will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the task runs.
Conflict resolved and pushed to
claude/issue-45(847d266).What was conflicting
Only
CHANGELOG.md— every other file (docs/custom-records.md,tests/ATProtoNet.Tests/RecordCollectionTests.cs) auto-merged. Both sides had appended entries to the[Unreleased]→AddedandFixedsections, so most of it was a straightforward keep-both:Added— main's #41 / #39 / #49 bullets plus main's new### Changedsection, then this PR's typed-unions/tokens bullet.Fixed— the #45 lexgen bullet alongside main's #41 / #49 / #46 bullets.One judgement call worth flagging
This PR's bullet "Hand-written
AtProtoRecordsubclasses serialized bothtypeand$type" describes the same bug as the Issue #49 entry that has since landed on main. #49 fixes it properly at the SDK level (AtProtoJsonDefaults.ApplyRecordTypeDiscriminator, aJsonTypeInfocontract modifier wired into the SDK's own serializer options), so a mechanical keep-both would have left the changelog describing one bug twice, one of the two as if still unfixed.I kept both bullets but reworded this PR's to state what it actually still contributes on top of #49 — the generator, docs, and fixtures now emit
[JsonPropertyName("$type")]on theTypeoverride, so the documented pattern is correct even under hand-builtJsonSerializerOptionsthat don't have the #49 modifier registered. That's genuinely complementary, and #49's own entry already calls that attribute "safe", so the two now read consistently. The PR's code changes were left untouched.Verified
Installed the .NET 10 SDK in the container (it wasn't preinstalled) and ran the canonical pre-merge check against the merged tree:
dotnet build -p:EnableSourceControlManagerQueries=false— 0 errors (1160 warnings, all pre-existing CS1591 missing-XML-doc and NU1902MessagePackadvisories, none from the merge).dotnet test tests/ATProtoNet.Tests/— 1049 passed, 0 failed, 0 skipped.So the semantic overlap between #45 and #49 on
AtProtoRecord.Typedoesn't actually break anything — the emitted attribute and the contract modifier coexist, andRecordCollectionTestspasses with both in play.⏱ 2m 53s · 21 turns · 📜 Full session transcript
(reply recovered from the transcript — the posting step in runs before v12.3 was broken by a shell-quoting bug)