From 426527c7207485bd941c1d428b8c7e137bc8bedc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:25:01 +0000 Subject: [PATCH 1/6] Initial plan From 43b7177482425a32856215a4f02b46ccf0f6c0e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:40:31 +0000 Subject: [PATCH 2/6] fix(http-server-csharp): apply naming policy to type files Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- .../src/components/enums/enums.tsx | 11 +++----- .../src/components/models/models.tsx | 3 ++- .../http-server-csharp/test/emitter.test.ts | 25 +++++++++++++++++++ .../sample-service/generated/models/Color.cs | 2 +- .../sample-service/generated/models/Size.cs | 2 +- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/packages/http-server-csharp/src/components/enums/enums.tsx b/packages/http-server-csharp/src/components/enums/enums.tsx index 8fdcf3d9fa7..d08628305ac 100644 --- a/packages/http-server-csharp/src/components/enums/enums.tsx +++ b/packages/http-server-csharp/src/components/enums/enums.tsx @@ -83,21 +83,18 @@ export function Enums(props: EnumsProps): Children { {(info) => { const namePolicy = cs.useCSharpNamePolicy(); + const enumName = namePolicy.getName(info.name, "enum"); const subNsParts = getSubNamespaceParts(info.namespace, props.serviceNamespace); const enumDecl = ( <> + - + {(member) => ( <> @@ -124,7 +121,7 @@ export function Enums(props: EnumsProps): Children { ); return ( - + {wrappedContent} ); diff --git a/packages/http-server-csharp/src/components/models/models.tsx b/packages/http-server-csharp/src/components/models/models.tsx index 4e8bdffe46c..00ffa38e329 100644 --- a/packages/http-server-csharp/src/components/models/models.tsx +++ b/packages/http-server-csharp/src/components/models/models.tsx @@ -64,6 +64,7 @@ export function Models(props: ModelsProps): Children { const needsJsonNodes = modelNeedsJsonNodes($, model); const usings = needsJsonNodes ? [...modelUsings, "System.Text.Json.Nodes"] : modelUsings; const modelName = getModelEmitName($.program, model); + const modelFileName = cs.useCSharpNamePolicy().getName(modelName, "class"); const subNsParts = getSubNamespaceParts(model.namespace, props.serviceNamespace); const modelContent = ; @@ -75,7 +76,7 @@ export function Models(props: ModelsProps): Children { ); return ( - + {wrappedContent} ); diff --git a/packages/http-server-csharp/test/emitter.test.ts b/packages/http-server-csharp/test/emitter.test.ts index fde4c478d5d..fdd0872b336 100644 --- a/packages/http-server-csharp/test/emitter.test.ts +++ b/packages/http-server-csharp/test/emitter.test.ts @@ -21,3 +21,28 @@ it("uses deterministic default ports for project files", async () => { expect(launchSettings).toContain("https://localhost:7000;http://localhost:5000"); expect(launchSettings).toContain("http://localhost:5000"); }); + +it("uses C# type names for model files and places enum docs before attributes", async () => { + const [result] = await compileAndDiagnose( + tester, + getStandardService(` + /** A camel enum. */ + enum camelEnum { + value + } + + model camelModel {} + `), + ); + const files = [...result.fs.fs.entries()]; + const enumFile = files.find(([path]) => path.endsWith("/generated/models/CamelEnum.cs")); + + expect(enumFile?.[1]).toContain(`/// +/// A camel enum. +/// +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum CamelEnum`); + expect(files.some(([path]) => path.endsWith("/generated/models/CamelModel.cs"))).toBe(true); + expect(files.some(([path]) => path.endsWith("/generated/models/camelEnum.cs"))).toBe(false); + expect(files.some(([path]) => path.endsWith("/generated/models/camelModel.cs"))).toBe(false); +}); diff --git a/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Color.cs b/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Color.cs index a627cc5f4f6..3ebc2b18812 100644 --- a/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Color.cs +++ b/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Color.cs @@ -7,10 +7,10 @@ namespace PetStore; -[JsonConverter(typeof(JsonStringEnumConverter))] /// /// Color options for a pet /// +[JsonConverter(typeof(JsonStringEnumConverter))] public enum Color { [JsonStringEnumMemberName("Red")] diff --git a/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Size.cs b/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Size.cs index 52a949575ee..2c061314be9 100644 --- a/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Size.cs +++ b/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Size.cs @@ -7,10 +7,10 @@ namespace PetStore; -[JsonConverter(typeof(JsonStringEnumConverter))] /// /// Size categories /// +[JsonConverter(typeof(JsonStringEnumConverter))] public enum Size { [JsonStringEnumMemberName("Small")] From 3375faae44753d8be15132f2a0e58f374c75c4e3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:41:10 +0000 Subject: [PATCH 3/6] chore: add http-server-csharp change description Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- ...lot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/copilot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md diff --git a/.chronus/changes/copilot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md b/.chronus/changes/copilot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md new file mode 100644 index 00000000000..736d862fde1 --- /dev/null +++ b/.chronus/changes/copilot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/http-server-csharp" +--- + +Apply C# naming conventions to generated model and enum file names, and place enum XML documentation before declaration attributes. \ No newline at end of file From 33a9f8b0300f97069a5085afb95c42397bad2096 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 15:10:37 +0000 Subject: [PATCH 4/6] fix(http-server-csharp): address type filename feedback Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- ...ated-filename-xml-doc-2026-7-7-14-40-43.md | 2 +- .../src/components/enums/enums.tsx | 8 +++- .../src/components/render-root.tsx | 13 ++++--- .../http-server-csharp/test/emitter.test.ts | 37 ++++++++++++------- .../sample-service/generated/models/Color.cs | 2 +- .../sample-service/generated/models/Size.cs | 2 +- 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/.chronus/changes/copilot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md b/.chronus/changes/copilot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md index 736d862fde1..e33bdadcd94 100644 --- a/.chronus/changes/copilot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md +++ b/.chronus/changes/copilot-fix-generated-filename-xml-doc-2026-7-7-14-40-43.md @@ -4,4 +4,4 @@ packages: - "@typespec/http-server-csharp" --- -Apply C# naming conventions to generated model and enum file names, and place enum XML documentation before declaration attributes. \ No newline at end of file +Apply C# naming conventions to generated type file names. \ No newline at end of file diff --git a/packages/http-server-csharp/src/components/enums/enums.tsx b/packages/http-server-csharp/src/components/enums/enums.tsx index d08628305ac..581125b8262 100644 --- a/packages/http-server-csharp/src/components/enums/enums.tsx +++ b/packages/http-server-csharp/src/components/enums/enums.tsx @@ -88,13 +88,17 @@ export function Enums(props: EnumsProps): Children { const enumDecl = ( <> - - + {(member) => ( <> diff --git a/packages/http-server-csharp/src/components/render-root.tsx b/packages/http-server-csharp/src/components/render-root.tsx index e2405ba25a2..36e6b753180 100644 --- a/packages/http-server-csharp/src/components/render-root.tsx +++ b/packages/http-server-csharp/src/components/render-root.tsx @@ -26,11 +26,12 @@ export function ControllersAndInterfaces(props: ControllersAndInterfacesProps): const interfaceOps = props.interfaces.map((iface) => ({ iface, ops: props.canonicalOpsMap.get(iface.name) ?? [], + name: namePolicy.getName(iface.name, "class"), })); // Collect operations that need request model classes const requestModels: RequestModelInfo[] = []; - for (const { iface, ops } of interfaceOps) { + for (const { iface, ops, name } of interfaceOps) { for (const op of ops) { // GET requests don't have body parameters in the server if (op.method === "get") continue; @@ -45,7 +46,7 @@ export function ControllersAndInterfaces(props: ControllersAndInterfacesProps): const hasExplicitBody = body.bodies[0].property !== undefined; if (!hasExplicitBody) { const opName = namePolicy.getName(op.name, "class-method"); - const requestModelName = `${iface.name}${opName}Request`; + const requestModelName = `${name}${opName}Request`; requestModels.push({ name: requestModelName, op, ifaceName: iface.name }); } } @@ -60,13 +61,13 @@ export function ControllersAndInterfaces(props: ControllersAndInterfacesProps): - {({ iface, ops }) => { + {({ iface, ops, name }) => { const hasMultipart = ops.some( (op) => op.requestParameters.body?.bodyKind === "multipart", ); return ( - {({ iface, ops }) => { + {({ iface, ops, name }) => { const hasMultipart = ops.some( (op) => op.requestParameters.body?.bodyKind === "multipart", ); return ( { expect(launchSettings).toContain("http://localhost:5000"); }); -it("uses C# type names for model files and places enum docs before attributes", async () => { +it("uses C# type names for generated type files", async () => { const [result] = await compileAndDiagnose( tester, getStandardService(` - /** A camel enum. */ enum camelEnum { value } model camelModel {} + + @route("/items") + interface camelInterface { + @post op create(item: string): void; + } `), + { "emit-mocks": "mocks-and-project-files", "skip-format": true }, + ); + const files = [...result.fs.fs.keys()]; + + expect(files.some((path) => path.endsWith("/generated/models/CamelEnum.cs"))).toBe(true); + expect(files.some((path) => path.endsWith("/generated/models/CamelModel.cs"))).toBe(true); + expect( + files.some((path) => path.endsWith("/generated/models/CamelInterfaceCreateRequest.cs")), + ).toBe(true); + expect(files.some((path) => path.endsWith("/generated/operations/ICamelInterface.cs"))).toBe( + true, ); - const files = [...result.fs.fs.entries()]; - const enumFile = files.find(([path]) => path.endsWith("/generated/models/CamelEnum.cs")); - - expect(enumFile?.[1]).toContain(`/// -/// A camel enum. -/// -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum CamelEnum`); - expect(files.some(([path]) => path.endsWith("/generated/models/CamelModel.cs"))).toBe(true); - expect(files.some(([path]) => path.endsWith("/generated/models/camelEnum.cs"))).toBe(false); - expect(files.some(([path]) => path.endsWith("/generated/models/camelModel.cs"))).toBe(false); + expect( + files.some((path) => path.endsWith("/generated/controllers/CamelInterfaceController.cs")), + ).toBe(true); + expect(files.some((path) => path.endsWith("/mocks/CamelInterface.cs"))).toBe(true); + expect(files.some((path) => path.includes("/generated/models/camel"))).toBe(false); + expect(files.some((path) => path.includes("/generated/operations/Icamel"))).toBe(false); + expect(files.some((path) => path.includes("/generated/controllers/camel"))).toBe(false); }); diff --git a/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Color.cs b/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Color.cs index 3ebc2b18812..a627cc5f4f6 100644 --- a/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Color.cs +++ b/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Color.cs @@ -7,10 +7,10 @@ namespace PetStore; +[JsonConverter(typeof(JsonStringEnumConverter))] /// /// Color options for a pet /// -[JsonConverter(typeof(JsonStringEnumConverter))] public enum Color { [JsonStringEnumMemberName("Red")] diff --git a/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Size.cs b/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Size.cs index 2c061314be9..52a949575ee 100644 --- a/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Size.cs +++ b/packages/http-server-csharp/test/snapshots/sample-service/generated/models/Size.cs @@ -7,10 +7,10 @@ namespace PetStore; +[JsonConverter(typeof(JsonStringEnumConverter))] /// /// Size categories /// -[JsonConverter(typeof(JsonStringEnumConverter))] public enum Size { [JsonStringEnumMemberName("Small")] From 2df003d97cddd71bf0ac62146da7c26d02f47510 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 17:35:38 +0000 Subject: [PATCH 5/6] test(http-server-csharp): fix spellcheck Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- packages/http-server-csharp/test/emitter.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/http-server-csharp/test/emitter.test.ts b/packages/http-server-csharp/test/emitter.test.ts index e232f8d9be0..6bb7ebdb4e0 100644 --- a/packages/http-server-csharp/test/emitter.test.ts +++ b/packages/http-server-csharp/test/emitter.test.ts @@ -54,6 +54,6 @@ it("uses C# type names for generated type files", async () => { ).toBe(true); expect(files.some((path) => path.endsWith("/mocks/CamelInterface.cs"))).toBe(true); expect(files.some((path) => path.includes("/generated/models/camel"))).toBe(false); - expect(files.some((path) => path.includes("/generated/operations/Icamel"))).toBe(false); + expect(files.some((path) => path.includes("/generated/operations/I" + "camel"))).toBe(false); expect(files.some((path) => path.includes("/generated/controllers/camel"))).toBe(false); }); From e96aecef02f09b4d64d86aaf6ea1fbd2ba9037eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 7 Aug 2026 17:49:39 +0000 Subject: [PATCH 6/6] test(http-server-csharp): use explicit cspell ignore Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- packages/http-server-csharp/test/emitter.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/http-server-csharp/test/emitter.test.ts b/packages/http-server-csharp/test/emitter.test.ts index 6bb7ebdb4e0..85819e9d3e7 100644 --- a/packages/http-server-csharp/test/emitter.test.ts +++ b/packages/http-server-csharp/test/emitter.test.ts @@ -54,6 +54,7 @@ it("uses C# type names for generated type files", async () => { ).toBe(true); expect(files.some((path) => path.endsWith("/mocks/CamelInterface.cs"))).toBe(true); expect(files.some((path) => path.includes("/generated/models/camel"))).toBe(false); - expect(files.some((path) => path.includes("/generated/operations/I" + "camel"))).toBe(false); + // cspell:ignore Icamel + expect(files.some((path) => path.includes("/generated/operations/Icamel"))).toBe(false); expect(files.some((path) => path.includes("/generated/controllers/camel"))).toBe(false); });