From 218ee7087a3de04c2bf6fc3c30d7546a7bd5d09b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 14 Jan 2026 03:51:31 +0000 Subject: [PATCH 1/3] Fix enum usage bug with convenientAPI(false) Remove generateConvenient check for HTTP operation parameters so that types referenced in query, header, and path parameters always get Input usage, even when convenientAPI is false. This ensures enums and other types are included in the generated output. The check is still kept for method parameters and body parameters as intended. Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com> --- .../src/types.ts | 6 +- .../test/decorators/convenient-api.test.ts | 104 +++++++++++++++++- 2 files changed, 105 insertions(+), 5 deletions(-) diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index a52e10662d..f15055d379 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -1615,9 +1615,9 @@ function updateTypesFromOperation( for (const param of httpOperation.parameters.parameters) { if (isNeverOrVoidType(param.param.type)) continue; const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, param.param, operation)); - if (generateConvenient) { - diagnostics.pipe(updateUsageOrAccess(context, UsageFlags.Input, sdkType)); - } + // Always update input usage for HTTP operation parameters (header, query, path) + // even when generateConvenient is false, so that types like enums are included + diagnostics.pipe(updateUsageOrAccess(context, UsageFlags.Input, sdkType)); const access = getAccessOverride(context, operation) ?? "public"; diagnostics.pipe(updateUsageOrAccess(context, access, sdkType)); } diff --git a/packages/typespec-client-generator-core/test/decorators/convenient-api.test.ts b/packages/typespec-client-generator-core/test/decorators/convenient-api.test.ts index 402ec7c1cd..615d5917db 100644 --- a/packages/typespec-client-generator-core/test/decorators/convenient-api.test.ts +++ b/packages/typespec-client-generator-core/test/decorators/convenient-api.test.ts @@ -1,7 +1,8 @@ -import { Operation } from "@typespec/compiler"; -import { strictEqual } from "assert"; +import { Enum, Operation } from "@typespec/compiler"; +import { ok, strictEqual } from "assert"; import { beforeEach, describe, it } from "vitest"; import { shouldGenerateConvenient, shouldGenerateProtocol } from "../../src/decorators.js"; +import { UsageFlags } from "../../src/interfaces.js"; import { SdkTestRunner, createSdkContextTestHelper, createSdkTestRunner } from "../test-host.js"; let runner: SdkTestRunner; @@ -345,3 +346,102 @@ describe("@protocolAPI and @convenientAPI with scope", () => { } }); }); + +describe("@convenientAPI(false) with enum parameters", () => { + it("enum in query parameter should have Input usage even with convenientAPI(false)", async () => { + const { IncludeEnum } = (await runner.compile(` + @service + namespace TestService { + enum IncludeEnum { + file_search_call_results: "file_search_call.results", + web_search_call_results: "web_search_call.results", + } + + model ItemResult { + id: string; + content: string; + } + + @route("/conversations/{conversation_id}/items/{item_id}") + @convenientAPI(false) + op getConversationItem( + @path conversation_id: string, + @path item_id: string, + @query(#{explode: true}) include?: IncludeEnum[], + ): ItemResult; + } + `)) as { IncludeEnum: Enum }; + + const sdkPackage = runner.context.sdkPackage; + ok(sdkPackage.enums); + const includeEnum = sdkPackage.enums.find((e) => e.name === "IncludeEnum"); + ok(includeEnum, "IncludeEnum should be in the enums list"); + ok( + includeEnum.usage & UsageFlags.Input, + "IncludeEnum should have Input usage even with convenientAPI(false)", + ); + }); + + it("enum in header parameter should have Input usage even with convenientAPI(false)", async () => { + const { StatusEnum } = (await runner.compile(` + @service + namespace TestService { + enum StatusEnum { + active: "active", + inactive: "inactive", + } + + model Response { + data: string; + } + + @route("/data") + @convenientAPI(false) + op getData( + @header status: StatusEnum, + ): Response; + } + `)) as { StatusEnum: Enum }; + + const sdkPackage = runner.context.sdkPackage; + ok(sdkPackage.enums); + const statusEnum = sdkPackage.enums.find((e) => e.name === "StatusEnum"); + ok(statusEnum, "StatusEnum should be in the enums list"); + ok( + statusEnum.usage & UsageFlags.Input, + "StatusEnum should have Input usage even with convenientAPI(false)", + ); + }); + + it("enum in path parameter should have Input usage even with convenientAPI(false)", async () => { + const { ResourceType } = (await runner.compile(` + @service + namespace TestService { + enum ResourceType { + users: "users", + groups: "groups", + } + + model Resource { + id: string; + } + + @route("/resources/{type}/{id}") + @convenientAPI(false) + op getResource( + @path type: ResourceType, + @path id: string, + ): Resource; + } + `)) as { ResourceType: Enum }; + + const sdkPackage = runner.context.sdkPackage; + ok(sdkPackage.enums); + const resourceType = sdkPackage.enums.find((e) => e.name === "ResourceType"); + ok(resourceType, "ResourceType should be in the enums list"); + ok( + resourceType.usage & UsageFlags.Input, + "ResourceType should have Input usage even with convenientAPI(false)", + ); + }); +}); From 2b7c75d2b553010e9759b8668d31956ce43dcc43 Mon Sep 17 00:00:00 2001 From: tadelesh Date: Wed, 14 Jan 2026 13:34:57 +0800 Subject: [PATCH 2/3] changeset --- ...x-dotnet-client-compilation-issue-2026-0-14-13-34-47.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/copilot-fix-dotnet-client-compilation-issue-2026-0-14-13-34-47.md diff --git a/.chronus/changes/copilot-fix-dotnet-client-compilation-issue-2026-0-14-13-34-47.md b/.chronus/changes/copilot-fix-dotnet-client-compilation-issue-2026-0-14-13-34-47.md new file mode 100644 index 0000000000..fdceb952f1 --- /dev/null +++ b/.chronus/changes/copilot-fix-dotnet-client-compilation-issue-2026-0-14-13-34-47.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-client-generator-core" +--- + +Fix enum type exclusion in protocol methods when `@convenientAPI(false)`. \ No newline at end of file From d79dc9005dab6c23c10bc2adcf4fc65b39977e75 Mon Sep 17 00:00:00 2001 From: tadelesh Date: Wed, 14 Jan 2026 15:53:41 +0800 Subject: [PATCH 3/3] fix tests --- .../test/decorators/convenient-api.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/typespec-client-generator-core/test/decorators/convenient-api.test.ts b/packages/typespec-client-generator-core/test/decorators/convenient-api.test.ts index 615d5917db..4340ce888c 100644 --- a/packages/typespec-client-generator-core/test/decorators/convenient-api.test.ts +++ b/packages/typespec-client-generator-core/test/decorators/convenient-api.test.ts @@ -1,4 +1,4 @@ -import { Enum, Operation } from "@typespec/compiler"; +import { Operation } from "@typespec/compiler"; import { ok, strictEqual } from "assert"; import { beforeEach, describe, it } from "vitest"; import { shouldGenerateConvenient, shouldGenerateProtocol } from "../../src/decorators.js"; @@ -349,7 +349,7 @@ describe("@protocolAPI and @convenientAPI with scope", () => { describe("@convenientAPI(false) with enum parameters", () => { it("enum in query parameter should have Input usage even with convenientAPI(false)", async () => { - const { IncludeEnum } = (await runner.compile(` + await runner.compile(` @service namespace TestService { enum IncludeEnum { @@ -370,7 +370,7 @@ describe("@convenientAPI(false) with enum parameters", () => { @query(#{explode: true}) include?: IncludeEnum[], ): ItemResult; } - `)) as { IncludeEnum: Enum }; + `); const sdkPackage = runner.context.sdkPackage; ok(sdkPackage.enums); @@ -383,7 +383,7 @@ describe("@convenientAPI(false) with enum parameters", () => { }); it("enum in header parameter should have Input usage even with convenientAPI(false)", async () => { - const { StatusEnum } = (await runner.compile(` + await runner.compile(` @service namespace TestService { enum StatusEnum { @@ -401,7 +401,7 @@ describe("@convenientAPI(false) with enum parameters", () => { @header status: StatusEnum, ): Response; } - `)) as { StatusEnum: Enum }; + `); const sdkPackage = runner.context.sdkPackage; ok(sdkPackage.enums); @@ -414,7 +414,7 @@ describe("@convenientAPI(false) with enum parameters", () => { }); it("enum in path parameter should have Input usage even with convenientAPI(false)", async () => { - const { ResourceType } = (await runner.compile(` + await runner.compile(` @service namespace TestService { enum ResourceType { @@ -433,7 +433,7 @@ describe("@convenientAPI(false) with enum parameters", () => { @path id: string, ): Resource; } - `)) as { ResourceType: Enum }; + `); const sdkPackage = runner.context.sdkPackage; ok(sdkPackage.enums);