diff --git a/.chronus/changes/feat-fix-union-variant-decorators-2024-4-20-14-27-15.md b/.chronus/changes/feat-fix-union-variant-decorators-2024-4-20-14-27-15.md new file mode 100644 index 000000000..a5d6e21a8 --- /dev/null +++ b/.chronus/changes/feat-fix-union-variant-decorators-2024-4-20-14-27-15.md @@ -0,0 +1,7 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: internal +packages: + - "@typespec/compiler" +--- +Doc diff --git a/.chronus/changes/feat-fix-union-variant-decorators-2024-4-20-14-48-3.md b/.chronus/changes/feat-fix-union-variant-decorators-2024-4-20-14-48-3.md new file mode 100644 index 000000000..836c4235e --- /dev/null +++ b/.chronus/changes/feat-fix-union-variant-decorators-2024-4-20-14-48-3.md @@ -0,0 +1,8 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: fix +packages: + - "@typespec/json-schema" +--- + +Fix decorators application for union variants diff --git a/packages/compiler/src/emitter-framework/type-emitter.ts b/packages/compiler/src/emitter-framework/type-emitter.ts index 236a3a2bc..75e813626 100644 --- a/packages/compiler/src/emitter-framework/type-emitter.ts +++ b/packages/compiler/src/emitter-framework/type-emitter.ts @@ -118,7 +118,7 @@ export type EmitterOutput = EmitEntity | Placeholder | T; * literals, and any type referenced inside anywhere inside the model and any * of the referenced types' references. * - * In both cases, context is an object. It strongly recommended that the context + * In both cases, context is an object. It's strongly recommended that the context * object either contain only primitive types, or else only reference immutable * objects. * diff --git a/packages/json-schema/src/json-schema-emitter.ts b/packages/json-schema/src/json-schema-emitter.ts index 8f566b53c..38fa9f531 100644 --- a/packages/json-schema/src/json-schema-emitter.ts +++ b/packages/json-schema/src/json-schema-emitter.ts @@ -1,7 +1,6 @@ import { BooleanLiteral, DiagnosticTarget, - DuplicateTracker, Enum, EnumMember, IntrinsicType, @@ -52,6 +51,7 @@ import { SourceFileScope, TypeEmitter, } from "@typespec/compiler/emitter-framework"; +import { DuplicateTracker } from "@typespec/compiler/utils"; import { stringify } from "yaml"; import { JsonSchemaDeclaration, @@ -328,7 +328,14 @@ export class JsonSchemaEmitter extends TypeEmitter, JSONSche } unionVariant(variant: UnionVariant): EmitterOutput { - return this.emitter.emitTypeReference(variant.type); + const variantType = this.emitter.emitTypeReference(variant.type); + compilerAssert(variantType.kind === "code", "Unexpected non-code result from emit reference"); + + const result = new ObjectBuilder(variantType.value); + + this.#applyConstraints(variant, result); + + return result; } modelPropertyReference(property: ModelProperty): EmitterOutput { @@ -513,7 +520,7 @@ export class JsonSchemaEmitter extends TypeEmitter, JSONSche } #applyConstraints( - type: Scalar | Model | ModelProperty | Union | Enum, + type: Scalar | Model | ModelProperty | Union | UnionVariant | Enum, schema: ObjectBuilder ) { const applyConstraint = (fn: (p: Program, t: Type) => any, key: string) => { diff --git a/packages/json-schema/test/unions.test.ts b/packages/json-schema/test/unions.test.ts index 244fe2d63..34256aca1 100644 --- a/packages/json-schema/test/unions.test.ts +++ b/packages/json-schema/test/unions.test.ts @@ -87,4 +87,39 @@ describe("emitting unions", () => { const Foo = schemas["Foo.json"]; assert.strictEqual(Foo["x-foo"], true); }); + + it("handles decorators on variants", async () => { + const schemas = await emitSchema(` + union Foo { + @doc("doc text") + @summary("summary text") + @extension("x-key", Json<"x-value">) + bar: string; + + @doc("other model doc") + @summary("other model summary") + @extension("x-key-2", Json<"x-value-2">) + baz: OtherModel; + } + + model OtherModel {} + `); + + const Foo = schemas["Foo.json"]; + + assert.deepStrictEqual(Foo.anyOf, [ + { + description: "doc text", + title: "summary text", + type: "string", + "x-key": "x-value", + }, + { + $ref: "OtherModel.json", + description: "other model doc", + title: "other model summary", + "x-key-2": "x-value-2", + }, + ]); + }); });