From dfbd3131520159ad1cc849bc340ac70626c6ce4e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Apr 2026 17:22:43 +0000 Subject: [PATCH 1/3] Initial plan From 49c122fc28f73219c406672e0ff969be966e90c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Apr 2026 17:28:58 +0000 Subject: [PATCH 2/3] feat: add warning when @defaultResponse is used on model with status code or @error Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/2d6ca218-090a-4b98-8bfd-f31ddb57b9c9 Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- packages/openapi/src/decorators.ts | 22 +++++++++++++ packages/openapi/src/lib.ts | 7 +++++ packages/openapi/test/decorators.test.ts | 40 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/packages/openapi/src/decorators.ts b/packages/openapi/src/decorators.ts index fa61100887d..129bf2d9aea 100644 --- a/packages/openapi/src/decorators.ts +++ b/packages/openapi/src/decorators.ts @@ -4,6 +4,7 @@ import { getDoc, getService, getSummary, + isErrorModel, isType, Model, Namespace, @@ -159,6 +160,27 @@ export const $defaultResponse: DefaultResponseDecorator = ( context: DecoratorContext, entity: Model, ) => { + // Warn if the model already has a @statusCode property + for (const prop of entity.properties.values()) { + if (http.isStatusCode(context.program, prop)) { + reportDiagnostic(context.program, { + code: "default-response-with-status-code", + messageId: "statusCode", + target: entity, + }); + break; + } + } + + // Warn if the model is marked with @error + if (isErrorModel(context.program, entity)) { + reportDiagnostic(context.program, { + code: "default-response-with-status-code", + messageId: "error", + target: entity, + }); + } + (http as any).setStatusCode(context.program, entity, ["*"]); context.program.stateSet(defaultResponseKey).add(entity); }; diff --git a/packages/openapi/src/lib.ts b/packages/openapi/src/lib.ts index 889d282b313..4eb56a5b64d 100644 --- a/packages/openapi/src/lib.ts +++ b/packages/openapi/src/lib.ts @@ -34,6 +34,13 @@ export const $lib = createTypeSpecLibrary({ default: paramMessage`@tagMetadata must be used on the service namespace. Did you mean to annotate '${"namespace"}' with '@service'?`, }, }, + "default-response-with-status-code": { + severity: "warning", + messages: { + statusCode: `@defaultResponse should not be used on a model that already has a status code defined. The status code will be ignored in favor of the default response.`, + error: `@defaultResponse should not be used on a model that is marked with @error. Use either @defaultResponse or @error, not both.`, + }, + }, }, state: { tagsMetadata: { description: "State for the @tagMetadata decorator." }, diff --git a/packages/openapi/test/decorators.test.ts b/packages/openapi/test/decorators.test.ts index c4e253f587b..9ca0ad6873b 100644 --- a/packages/openapi/test/decorators.test.ts +++ b/packages/openapi/test/decorators.test.ts @@ -509,4 +509,44 @@ describe("openapi: decorators", () => { deepStrictEqual(getTagsMetadata(program, PetStore), expected); }); }); + + describe("@defaultResponse", () => { + it("emits warning when used on a model with @statusCode", async () => { + const diagnostics = await Tester.diagnose(` + model MyResponse { + @TypeSpec.Http.statusCode _: 500; + message: string; + } + + @defaultResponse + model DefaultError is MyResponse {} + `); + expectDiagnostics(diagnostics, [ + { code: "@typespec/openapi/default-response-with-status-code", message: /status code/ }, + ]); + }); + + it("emits warning when used on a model marked with @error", async () => { + const diagnostics = await Tester.diagnose(` + @error + @defaultResponse + model DefaultError { + message: string; + } + `); + expectDiagnostics(diagnostics, [ + { code: "@typespec/openapi/default-response-with-status-code", message: /\@error/ }, + ]); + }); + + it("does not emit warning when used on a plain model", async () => { + const diagnostics = await Tester.diagnose(` + @defaultResponse + model DefaultError { + message: string; + } + `); + expectDiagnostics(diagnostics, []); + }); + }); }); From c10f3abc18dc9e8dc2ab97440663660c2044b0d0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:00:27 +0000 Subject: [PATCH 3/3] fix: resolve lint error and add changeset for @typespec/openapi Agent-Logs-Url: https://github.com/microsoft/typespec/sessions/8c4a27ca-8f4c-44aa-ab49-14c858ae2835 Co-authored-by: timotheeguerin <1031227+timotheeguerin@users.noreply.github.com> --- .../changes/default-response-warning-2026-4-29-17-59-10.md | 7 +++++++ packages/openapi/test/decorators.test.ts | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .chronus/changes/default-response-warning-2026-4-29-17-59-10.md diff --git a/.chronus/changes/default-response-warning-2026-4-29-17-59-10.md b/.chronus/changes/default-response-warning-2026-4-29-17-59-10.md new file mode 100644 index 00000000000..20150f7385b --- /dev/null +++ b/.chronus/changes/default-response-warning-2026-4-29-17-59-10.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@typespec/openapi" +--- + +Added a warning diagnostic when `@defaultResponse` is used on a model that already has a `@statusCode` property or is marked with `@error`. diff --git a/packages/openapi/test/decorators.test.ts b/packages/openapi/test/decorators.test.ts index 9ca0ad6873b..56fd65f956f 100644 --- a/packages/openapi/test/decorators.test.ts +++ b/packages/openapi/test/decorators.test.ts @@ -535,7 +535,7 @@ describe("openapi: decorators", () => { } `); expectDiagnostics(diagnostics, [ - { code: "@typespec/openapi/default-response-with-status-code", message: /\@error/ }, + { code: "@typespec/openapi/default-response-with-status-code", message: /@error/ }, ]); });