Skip to content

Apply generator fix for extensible enum member normalization collision - #263

Open
David Burg (daviburg) wants to merge 2 commits into
mainfrom
fix/issue-181-enum-member-regeneration
Open

Apply generator fix for extensible enum member normalization collision#263
David Burg (daviburg) wants to merge 2 commits into
mainfrom
fix/issue-181-enum-member-regeneration

Conversation

@daviburg

@daviburg David Burg (daviburg) commented Aug 28, 2026

Copy link
Copy Markdown
Member

Fix Issue #181: Extensible enum normalization collision — Plumsail regenerated

Problem

The generator assigned C# identifiers to swagger enum values in Swagger-definition order without handling normalization collisions (two values that reduce to the same identifier, e.g. Etc/GMT+4 and Etc/GMT-4 both → EtcGMT4). The first claimant silently won; all later claimants were dropped. For reserved struct member names (Equals, GetHashCode, ToString) the generator emitted a property that clashed with mandatory override methods, causing CS0102.

Solution

AzureUX-BPM PR 16971205 (commits d5cb672..07b2718; rebased 2026-08-28, current PR tip 96b674e — git diff 07b2718 96b674e -- src/tools/CodefulSdkGenerator/ empty, generator source identical) introduces a two-phase assignment:

  1. Phase 1: pre-scan all natural names so that suffix-based disambiguation never steals a slot that belongs to another value.
  2. Phase 2: assign in deterministic sorted order (natural name asc, wire value asc), so +4 (lower ASCII) owns EtcGMT4 and -4 gets EtcGMT42.

Empirical audit (Phase 2 methodology)

Built two binaries from the BPM worktree against the same frozen 2026-08-28 ARM swagger cache (99 files, manifest SHA256 ED9C3FB8911D0F28C8D5038CE33ABEE38F7265D186249C8C66CC5C4B7B7CF2C8):

Binary BPM commit SHA256
baseline d5cb6725 (pre-fix: no reserved-name fix, no normalization-collision fix) 61D177482F51C722...
fixed 07b2718 (build source; post-rebase PR tip 96b674e, generator source identical) D22694EB1113337C...

Both ran with --connectors=<100-client-filter>. 97 connectors generated at both commits (MsGraphGroupsAndUsers failed at both; ConnectorNames/ManagedConnectors skipped by filter). 96 clients are byte-identical. One client differs: PlumsailExtensions.cs.

Historical connector audit

The eleven connectors named in the original issue as affected by the reserved-name variant (Blackbaudaltruconsti, Blackbaudcrmconstitu, Dataflows, Documentscorepackapi, Dynamicssmbsaas, Etsy, Iaconnectmsoffice, Meisterplan, Powerassist, Tabscannerreceiptocr, Workpoint365):

Connector In current catalog Reserved-name collision Action
Blackbaudaltruconsti No — not in 2026-08-28 snapshot N/A No change
Blackbaudcrmconstitu No N/A No change
Dataflows No N/A No change
Documentscorepackapi No N/A No change
Dynamicssmbsaas No N/A No change
Etsy Yes — generates identically at d5cb672 and 07b2718 None active No change
Iaconnectmsoffice No N/A No change
Meisterplan No N/A No change
Powerassist No N/A No change
Tabscannerreceiptocr No N/A No change
Workpoint365 No N/A No change

Affected connector: Plumsail

The Plumsail swagger (frozen 2026-08-28) contains both Etc/GMT+N and Etc/GMT-N for the same N. At the true baseline (d5cb672), -N values were first in Swagger order for most entries and claimed the clean identifier; the +N values were silently dropped. The fix recovers 14 dropped values and reassigns 7 identifiers to the correct +N wire value.

PlumsailExtensions.cs SHA256: CE8A13EDEAB683099A0D319A3225ED61AF52AE90E44870EE46038552BAD6F1C8 (generated from BPM 07b2718; BPM PR rebased to 96b674e with identical generator source).

Changes

  • src/Azure.Connectors.Sdk/Generated/PlumsailExtensions.cs: regenerated; 14 new Timezone members added for previously-dropped wire values; 7 existing members (EtcGMT2, EtcGMT3, EtcGMT4, EtcGMT7, EtcGMT8, EtcGMT9, EtcGMT11) now map to the +N wire value (breaking change for callers).
  • tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs: replaced tests that locked the incorrect pre-fix assignment (EtcGMT4"-4") with tests that lock the correct post-fix contract (EtcGMT4"+4", EtcGMT42"-4", EtcGMT62"-6").
  • CHANGELOG.md, release_notes.md: corrected to name Plumsail as the one affected client, document the breaking-change set, true baseline d5cb672, and cache provenance.

Validation

  • Build: 0 warnings, 0 errors
  • Tests: 961 passed, 0 failed
  • dotnet format --verify-no-changes: clean
  • git diff --check: clean

Fixes #181

Copilot AI lite review requested due to automatic review settings August 28, 2026 16:51
@daviburg
David Burg (daviburg) requested a review from a team as a code owner August 28, 2026 16:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Connectors SDK to reflect an upstream CodefulSdkGenerator fix for extensible-enum member name normalization collisions (including reserved struct member names), and adds regression tests to lock the Plumsail Timezone extensible-enum member-to-wire-value mapping.

Changes:

  • Add GeneratedEnumMemberTests covering Plumsail Timezone serialization/deserialization and equality semantics for selected wire values.
  • Update CHANGELOG.md and release_notes.md to document the upstream generator fix and the empirical scan results.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs Adds regression tests asserting stable member↔wire-value mappings for Plumsail Timezone extensible enum.
release_notes.md Documents the generator normalization-collision fix and the empirical scan (no regenerated connectors).
CHANGELOG.md Mirrors the same fix note under [Unreleased] for changelog tracking.
Suppressed comments (1)

tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs:104

  • These tests introduce single-letter local variables (a, b). The repo coding guidelines require descriptive, non-abbreviated identifiers; please rename to meaningful names (e.g., leftTimezone/rightTimezone) to keep tests consistent with the rest of the codebase.
            var a = PlumsailTimezone.EtcGMT6;
            var b = PlumsailTimezone.EtcGMT7;

            Assert.IsTrue(a != b);
            Assert.IsFalse(a.Equals(b));

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread release_notes.md Outdated
Comment thread CHANGELOG.md Outdated
Comment thread tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs Outdated
Copilot AI review requested due to automatic review settings August 28, 2026 17:46
@daviburg
David Burg (daviburg) force-pushed the fix/issue-181-enum-member-regeneration branch from ff79a5b to 6d5bd87 Compare August 28, 2026 17:46
The frozen 2026-08-28 ARM swagger snapshot (cache manifest SHA256
ED9C3FB8911D0F28C8D5038CE33ABEE38F7265D186249C8C66CC5C4B7B7CF2C8)
shows Plumsail's Timezone enum contains both Etc/GMT+N and Etc/GMT-N for
the same N. These normalize to the same C# identifier (EtcGMTN), causing
the pre-fix generator to silently drop the alphabetically-later -N value.

Comparison methodology: BPM worktree built twice — once from true pre-fix
base d5cb672 (no reserved-name fix, no normalization-collision fix; binary
SHA256 61D177482F51C722...) and once from the full-fix tip 07b2718 (binary
SHA256 D22694EB1113337C...). Both ran against the same frozen 99-file cache
with the 100-connector filter matching all checked-in SDK clients. Of the
97 connectors that generated at both commits (MsGraphGroupsAndUsers failed
at both; ConnectorNames/ManagedConnectors skipped by filter), PlumsailExtensions.cs
was the only file with a non-encoding-artifact difference. 96 connector
clients are byte-identical. The eleven historically-affected connectors
(Blackbaudaltruconsti, Blackbaudcrmconstitu, Dataflows, Documentscorepackapi,
Dynamicssmbsaas, Etsy, Iaconnectmsoffice, Meisterplan, Powerassist,
Tabscannerreceiptocr, Workpoint365) are not present in the current catalog.

Changes:
- PlumsailExtensions.cs: regenerated from BPM 07b2718 with frozen cache;
  EtcGMT2-9 and EtcGMT11 now map to +N values (sorted first); 14 new
  members added for previously-dropped -N values; gen SHA256 CE8A13EDEA...
- GeneratedEnumMemberTests.cs: replaced tests that verified the incorrect
  pre-fix assignment (EtcGMT4 -> "-4") with tests that lock the correct
  post-fix mapping (EtcGMT4 -> "+4", EtcGMT42 -> "-4", EtcGMT62 -> "-6")
- CHANGELOG.md, release_notes.md: corrected to name Plumsail as the one
  affected client, document the breaking-change set, true baseline d5cb672,
  and cache provenance; removed incorrect "zero collisions" claim

Fixes: #181

Co-authored-by: Dobby <dobby@microsoft.com>
@daviburg
David Burg (daviburg) force-pushed the fix/issue-181-enum-member-regeneration branch from 6d5bd87 to 11442d2 Compare August 28, 2026 17:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

Suppressed comments (4)

tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs:50

  • Local variable name 'tz' is an abbreviation; prefer a descriptive local name per repo conventions (complete English terms).
            var tz = PlumsailTimezone.EtcGMT42;

            Assert.AreEqual(expected: "Etc/GMT-4", actual: (string)tz);
            var json = JsonSerializer.Serialize(tz, RelaxedEscapeOptions);
            Assert.AreEqual(expected: "\"Etc/GMT-4\"", actual: json);

tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs:104

  • Single-letter locals ('a', 'b') violate the repo naming guideline (no single-letter identifiers). Using descriptive names makes it clearer which value is coming from the known member vs an arbitrary wire value.
            var namedMember = PlumsailTimezone.EtcGMT4;
            var constructedMember = new PlumsailTimezone("Etc/GMT+4");

            Assert.IsTrue(namedMember == constructedMember);
            Assert.IsTrue(namedMember.Equals(constructedMember));

tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs:114

  • Single-letter locals ('a', 'b') violate the repo naming guideline (no single-letter identifiers). Descriptive names also help distinguish the +4 and -4 cases at a glance.
            var plusFour = PlumsailTimezone.EtcGMT4;
            var minusFour = PlumsailTimezone.EtcGMT42;

            Assert.IsTrue(plusFour != minusFour);
            Assert.IsFalse(plusFour.Equals(minusFour));

tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs:62

  • Local variable name 'tz' is an abbreviation; use a descriptive local name (and similarly rename 'json' to reflect what it contains) to align with the repo naming rules.
            var tz = PlumsailTimezone.EtcGMT62;

            Assert.AreEqual(expected: "Etc/GMT-6", actual: (string)tz);
            var json = JsonSerializer.Serialize(tz, RelaxedEscapeOptions);
            Assert.AreEqual(expected: "\"Etc/GMT-6\"", actual: json);

Comment thread tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs
Copilot AI review requested due to automatic review settings August 28, 2026 17:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

Comment thread tests/Azure.Connectors.Sdk.Tests/GeneratedEnumMemberTests.cs
Copilot AI review requested due to automatic review settings August 28, 2026 18:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.

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.

Generator: extensible enum structs with Equals/ToString values cause CS0102 compilation errors

2 participants