Skip to content

Commit

Permalink
Fix microsoft#5001 OkResponse is generated as a model
Browse files Browse the repository at this point in the history
  • Loading branch information
markcowl committed Nov 21, 2024
1 parent c4e7c83 commit b8516ad
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
7 changes: 6 additions & 1 deletion packages/http-server-csharp/src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,8 @@ export async function $onEmit(context: EmitContext<CSharpServiceEmitterOptions>)
}

for (const response of operation.responses) {
this.emitter.emitType(response.type);
if (!isEmptyResponseModel(this.emitter.getProgram(), response.type))
this.emitter.emitType(response.type);
}

return builder.reduce();
Expand Down Expand Up @@ -1207,6 +1208,10 @@ export async function $onEmit(context: EmitContext<CSharpServiceEmitterOptions>)
}
}

function isEmptyResponseModel(program: Program, model: Type): boolean {
if (model.kind !== "Model") return false;
return model.properties.size === 1 && isStatusCode(program, [...model.properties.values()][0]);
}
function processNameSpace(program: Program, target: Namespace, service?: Service | undefined) {
if (!service) service = getService(program, target);
if (service) {
Expand Down
44 changes: 43 additions & 1 deletion packages/http-server-csharp/test/generation.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Program, Type, navigateProgram } from "@typespec/compiler";
import { BasicTestRunner } from "@typespec/compiler/testing";
import assert from "assert";
import assert, { deepStrictEqual } from "assert";
import { beforeEach, it } from "vitest";
import { getPropertySource, getSourceModel } from "../src/utils.js";
import { createCSharpServiceEmitterTestRunner, getStandardService } from "./test-host.js";
Expand Down Expand Up @@ -747,6 +747,48 @@ it("Handles void type in operations", async () => {
);
});

it("Handles empty body 2xx as void", async () => {
await compileAndValidateMultiple(
runner,
`
using TypeSpec.Rest.Resource;
namespace MyService {
model Toy {
@key("toyId")
id: int64;
petId: int64;
name: string;
}
@friendlyName("{name}ListResults", Item)
model ResponsePage<Item> {
items: Item[];
nextLink?: string;
}
@post @route("/foo") op foo(...Toy): OkResponse;
}
`,
[
[
"IMyServiceOperations.cs",
["interface IMyServiceOperations", "Task FooAsync( long id, long petId, string name)"],
],
[
"MyServiceOperationsControllerBase.cs",
[
"public abstract partial class MyServiceOperationsControllerBase: ControllerBase",
"public virtual async Task<IActionResult> Foo(Toy body)",
],
],
["Toy.cs", ["public partial class Toy"]],
],
);
deepStrictEqual([...runner.fs.keys()].filter((k) => k.includes("OkResponse.cs")).length, 0);
});

it("generates appropriate types for literals", async () => {
await compileAndValidateSingleModel(
runner,
Expand Down

0 comments on commit b8516ad

Please sign in to comment.