From a1e6dbc017a27285f1602a75268fd88b16bd19db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:06:32 +0000 Subject: [PATCH 1/9] Initial plan From d50a2798a3b3d4da67dd95f232f9c94d672b767c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:24:02 +0000 Subject: [PATCH 2/9] Fix: Always use client.apiVersions instead of reading from enum values This fixes the issue where API versions were being lost when adding new versions. The parseApiVersions() function was incorrectly reading from sdkPackage.enums instead of using client.apiVersions, which is the source of truth from TCGC. - Removed logic that reads from apiVersionEnum.values - Simplified parseApiVersions to always use client.apiVersions - Removed unused imports (UsageFlags, containsMultiServiceClient) Fixes microsoft/typespec# Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- .../emitter/src/lib/client-model-builder.ts | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/packages/http-client-csharp/emitter/src/lib/client-model-builder.ts b/packages/http-client-csharp/emitter/src/lib/client-model-builder.ts index 94f1bfd767d..9f95737194f 100644 --- a/packages/http-client-csharp/emitter/src/lib/client-model-builder.ts +++ b/packages/http-client-csharp/emitter/src/lib/client-model-builder.ts @@ -5,7 +5,6 @@ import { SdkClientType, SdkEnumType, SdkHttpOperation, - UsageFlags, } from "@azure-tools/typespec-client-generator-core"; import { CSharpEmitterContext } from "../sdk-context.js"; import { CodeModel } from "../type/code-model.js"; @@ -14,11 +13,7 @@ import { fromSdkClients } from "./client-converter.js"; import { fromSdkNamespaces } from "./namespace-converter.js"; import { processServiceAuthentication } from "./service-authentication.js"; import { fromSdkType } from "./type-converter.js"; -import { - containsMultiServiceClient, - firstLetterToUpperCase, - getClientNamespaceString, -} from "./utils.js"; +import { firstLetterToUpperCase, getClientNamespaceString } from "./utils.js"; /** * Creates the code model from the SDK context. @@ -75,15 +70,10 @@ function parseApiVersions( enums: SdkEnumType[], rootClients: SdkClientType[], ): string[] { - if (containsMultiServiceClient(rootClients)) { - return rootClients[0]?.apiVersions ?? []; - } - - const apiVersionEnum = enums.find((e) => (e.usage & UsageFlags.ApiVersionEnum) !== 0); - if (apiVersionEnum) { - return apiVersionEnum.values.map((v) => v.value as string); - } - + // Always use client.apiVersions as the source of truth. + // TCGC correctly populates this with all versions from the @versioned enum. + // Previously, this function would read from the enum values directly, which could + // miss versions if the enum wasn't fully populated at the time this runs. return rootClients[0]?.apiVersions ?? []; } From d425f272b0a33d5ce0f8467de279577c837f8e51 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:25:30 +0000 Subject: [PATCH 3/9] Add tests for parseApiVersions to verify all versions are preserved Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- .../test/Unit/client-model-builder.test.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts index 611fafc9ec9..f9d1e17aee6 100644 --- a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts @@ -441,3 +441,69 @@ describe("parseApiVersions", () => { ok(barClient.apiVersions.includes("bv2"), "Bar client should include bv2"); }); }); + +describe("parseApiVersions", () => { + let runner: TestHost; + + beforeEach(async () => { + runner = await createEmitterTestHost(); + }); + + it("should include all API versions from @versioned enum", async () => { + const program = await typeSpecCompile( + ` + @service({title: "Test Service"}) + @versioned(Versions) + namespace TestService; + + enum Versions { + v1: "v1", + v2: "v2", + v3: "v3", + } + + @route("/test") + op test(): void; + `, + runner, + ); + const context = createEmitterContext(program); + const sdkContext = await createCSharpSdkContext(context); + const root = createModel(sdkContext); + + // Verify all three versions are present in the root apiVersions + strictEqual(root.apiVersions.length, 3, "Should have 3 apiVersions"); + ok(root.apiVersions.includes("v1"), "Should include v1"); + ok(root.apiVersions.includes("v2"), "Should include v2"); + ok(root.apiVersions.includes("v3"), "Should include v3"); + }); + + it("should preserve version order from TCGC", async () => { + const program = await typeSpecCompile( + ` + @service({title: "Test Service"}) + @versioned(Versions) + namespace TestService; + + enum Versions { + "2023-01-01", + "2024-01-01", + "2025-01-01", + } + + @route("/test") + op test(): void; + `, + runner, + ); + const context = createEmitterContext(program); + const sdkContext = await createCSharpSdkContext(context); + const root = createModel(sdkContext); + + // Verify versions are in the order TCGC provides them + strictEqual(root.apiVersions.length, 3, "Should have 3 apiVersions"); + strictEqual(root.apiVersions[0], "2023-01-01", "First version should be 2023-01-01"); + strictEqual(root.apiVersions[1], "2024-01-01", "Second version should be 2024-01-01"); + strictEqual(root.apiVersions[2], "2025-01-01", "Third version should be 2025-01-01"); + }); +}); From e94b7d719fee13dd7124a055e94a5db4249ce1e0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 18:34:54 +0000 Subject: [PATCH 4/9] Remove namespace declarations from test TypeSpec code to follow existing test patterns Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- .../emitter/test/Unit/client-model-builder.test.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts index f9d1e17aee6..a95fcac33b5 100644 --- a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts @@ -454,8 +454,6 @@ describe("parseApiVersions", () => { ` @service({title: "Test Service"}) @versioned(Versions) - namespace TestService; - enum Versions { v1: "v1", v2: "v2", @@ -483,8 +481,6 @@ describe("parseApiVersions", () => { ` @service({title: "Test Service"}) @versioned(Versions) - namespace TestService; - enum Versions { "2023-01-01", "2024-01-01", From eb4444e8b98bad71f2f905358277c3e146137e54 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 18:38:49 +0000 Subject: [PATCH 5/9] Remove @service decorator from test TypeSpec code to follow existing test patterns Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- .../emitter/test/Unit/client-model-builder.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts index a95fcac33b5..74cb798f224 100644 --- a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts @@ -452,7 +452,6 @@ describe("parseApiVersions", () => { it("should include all API versions from @versioned enum", async () => { const program = await typeSpecCompile( ` - @service({title: "Test Service"}) @versioned(Versions) enum Versions { v1: "v1", @@ -479,7 +478,6 @@ describe("parseApiVersions", () => { it("should preserve version order from TCGC", async () => { const program = await typeSpecCompile( ` - @service({title: "Test Service"}) @versioned(Versions) enum Versions { "2023-01-01", From 4ed0b24a527a931e1ecc2c922c5ee3b798242cd3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 18:41:25 +0000 Subject: [PATCH 6/9] Pass IsVersionNeeded: false to typeSpecCompile since tests define their own version enum Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- .../emitter/test/Unit/client-model-builder.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts index 74cb798f224..d95856cb06b 100644 --- a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts @@ -463,6 +463,7 @@ describe("parseApiVersions", () => { op test(): void; `, runner, + { IsVersionNeeded: false }, ); const context = createEmitterContext(program); const sdkContext = await createCSharpSdkContext(context); @@ -489,6 +490,7 @@ describe("parseApiVersions", () => { op test(): void; `, runner, + { IsVersionNeeded: false }, ); const context = createEmitterContext(program); const sdkContext = await createCSharpSdkContext(context); From 8fa97b9d6ed29a3936fd4b4a71f0d59064758fa2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 18:44:39 +0000 Subject: [PATCH 7/9] Simplify comment in parseApiVersions to be more concise Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- .../http-client-csharp/emitter/src/lib/client-model-builder.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/http-client-csharp/emitter/src/lib/client-model-builder.ts b/packages/http-client-csharp/emitter/src/lib/client-model-builder.ts index 9f95737194f..15c4da86c86 100644 --- a/packages/http-client-csharp/emitter/src/lib/client-model-builder.ts +++ b/packages/http-client-csharp/emitter/src/lib/client-model-builder.ts @@ -71,9 +71,6 @@ function parseApiVersions( rootClients: SdkClientType[], ): string[] { // Always use client.apiVersions as the source of truth. - // TCGC correctly populates this with all versions from the @versioned enum. - // Previously, this function would read from the enum values directly, which could - // miss versions if the enum wasn't fully populated at the time this runs. return rootClients[0]?.apiVersions ?? []; } From 1cbf035565f1fa863c84a55b2cedb73f6e1553de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 19:03:45 +0000 Subject: [PATCH 8/9] Fix tests: Add namespace wrapper and @service decorator for @versioned to work correctly Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- .../emitter/test/Unit/client-model-builder.test.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts index d95856cb06b..c46c15655d1 100644 --- a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts @@ -452,7 +452,12 @@ describe("parseApiVersions", () => { it("should include all API versions from @versioned enum", async () => { const program = await typeSpecCompile( ` + @service(#{ + title: "Test Service", + }) @versioned(Versions) + namespace TestService; + enum Versions { v1: "v1", v2: "v2", @@ -463,7 +468,7 @@ describe("parseApiVersions", () => { op test(): void; `, runner, - { IsVersionNeeded: false }, + { IsNamespaceNeeded: false }, ); const context = createEmitterContext(program); const sdkContext = await createCSharpSdkContext(context); @@ -479,7 +484,12 @@ describe("parseApiVersions", () => { it("should preserve version order from TCGC", async () => { const program = await typeSpecCompile( ` + @service(#{ + title: "Test Service", + }) @versioned(Versions) + namespace TestService; + enum Versions { "2023-01-01", "2024-01-01", @@ -490,7 +500,7 @@ describe("parseApiVersions", () => { op test(): void; `, runner, - { IsVersionNeeded: false }, + { IsNamespaceNeeded: false }, ); const context = createEmitterContext(program); const sdkContext = await createCSharpSdkContext(context); From c4b69ef41c76dc4a670ea59da5d126338fd33317 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 19:11:43 +0000 Subject: [PATCH 9/9] Fix lint error: Remove duplicate parseApiVersions describe block Co-authored-by: JoshLove-msft <54595583+JoshLove-msft@users.noreply.github.com> --- .../emitter/test/Unit/client-model-builder.test.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts index c46c15655d1..054bdde1853 100644 --- a/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/client-model-builder.test.ts @@ -440,14 +440,6 @@ describe("parseApiVersions", () => { ok(barClient.apiVersions.includes("bv1"), "Bar client should include bv1"); ok(barClient.apiVersions.includes("bv2"), "Bar client should include bv2"); }); -}); - -describe("parseApiVersions", () => { - let runner: TestHost; - - beforeEach(async () => { - runner = await createEmitterTestHost(); - }); it("should include all API versions from @versioned enum", async () => { const program = await typeSpecCompile(