From b69df720a14ae4fa78f7669f6445009442123d82 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 14 Jul 2026 12:24:07 -0400 Subject: [PATCH 1/2] feat(options): accept just-types in every language that spells it as an enum Most languages spell "generate plain types without (de)serialization helpers" as a `just-types` boolean option, but C# spelled it `--features just-types` and Kotlin, Scala 3, and Smithy4s `--framework just-types`, so the common `--just-types` flag was rejected for them with an option-parsing error. Those four languages now also accept `just-types` (secondary option). When it's set, makeRenderer forces the corresponding enum option to its just-types value before resolving options, so the boolean wins over a conflicting explicit enum value. The enum spellings keep working unchanged. The renderer-options type test that used kotlin + just-types as its "another language's option" compile error now uses rust, which really has no such option. Co-Authored-By: Claude Fable 5 --- .../src/language/CSharp/language.ts | 15 +++++ .../src/language/Kotlin/language.ts | 17 +++++ .../src/language/Scala3/language.ts | 17 +++++ .../src/language/Smithy4s/language.ts | 9 +++ test/unit/just-types-option.test.ts | 66 +++++++++++++++++++ test/unit/renderer-options.test-d.ts | 4 +- 6 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 test/unit/just-types-option.test.ts diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts index d07785dd4a..754c325e95 100644 --- a/packages/quicktype-core/src/language/CSharp/language.ts +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -117,6 +117,14 @@ export const cSharpOptions = { } as const, "complete", ), + // The boolean spelling of `--features just-types`, so that + // `--just-types` works for C# like it does for most other languages. + justTypes: new BooleanOption( + "just-types", + "Plain types only (same as features=just-types)", + false, + "secondary", + ), baseclass: new EnumOption( "base-class", "Base class", @@ -190,6 +198,13 @@ export class CSharpTargetLanguage extends TargetLanguage< renderContext: RenderContext, untypedOptionValues: RendererOptions, ): ConvenienceRenderer { + if (cSharpOptions.justTypes.getValue(untypedOptionValues)) { + untypedOptionValues = { + ...untypedOptionValues, + features: "just-types", + } as RendererOptions; + } + const options = getOptionValues(cSharpOptions, untypedOptionValues); switch (options.framework) { diff --git a/packages/quicktype-core/src/language/Kotlin/language.ts b/packages/quicktype-core/src/language/Kotlin/language.ts index c434958149..854d232432 100644 --- a/packages/quicktype-core/src/language/Kotlin/language.ts +++ b/packages/quicktype-core/src/language/Kotlin/language.ts @@ -1,6 +1,7 @@ import type { ConvenienceRenderer } from "../../ConvenienceRenderer.js"; import type { RenderContext } from "../../Renderer.js"; import { + BooleanOption, EnumOption, StringOption, getOptionValues, @@ -27,6 +28,15 @@ export const kotlinOptions = { } as const, "klaxon", ), + // The boolean spelling of `--framework just-types`, so that + // `--just-types` works for Kotlin like it does for most other + // languages. + justTypes: new BooleanOption( + "just-types", + "Plain types only (same as framework=just-types)", + false, + "secondary", + ), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; @@ -60,6 +70,13 @@ export class KotlinTargetLanguage extends TargetLanguage< renderContext: RenderContext, untypedOptionValues: RendererOptions, ): ConvenienceRenderer { + if (kotlinOptions.justTypes.getValue(untypedOptionValues)) { + untypedOptionValues = { + ...untypedOptionValues, + framework: "just-types", + } as RendererOptions; + } + const options = getOptionValues(kotlinOptions, untypedOptionValues); switch (options.framework) { diff --git a/packages/quicktype-core/src/language/Scala3/language.ts b/packages/quicktype-core/src/language/Scala3/language.ts index 3f98d37177..aba0075e4c 100644 --- a/packages/quicktype-core/src/language/Scala3/language.ts +++ b/packages/quicktype-core/src/language/Scala3/language.ts @@ -1,6 +1,7 @@ import type { ConvenienceRenderer } from "../../ConvenienceRenderer.js"; import type { RenderContext } from "../../Renderer.js"; import { + BooleanOption, EnumOption, StringOption, getOptionValues, @@ -24,6 +25,15 @@ export const scala3Options = { } as const, "just-types", ), + // The boolean spelling of `--framework just-types`, so that + // `--just-types` works for Scala like it does for most other + // languages. + justTypes: new BooleanOption( + "just-types", + "Plain types only (same as framework=just-types)", + false, + "secondary", + ), packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; @@ -56,6 +66,13 @@ export class Scala3TargetLanguage extends TargetLanguage< renderContext: RenderContext, untypedOptionValues: RendererOptions, ): ConvenienceRenderer { + if (scala3Options.justTypes.getValue(untypedOptionValues)) { + untypedOptionValues = { + ...untypedOptionValues, + framework: "just-types", + } as RendererOptions; + } + const options = getOptionValues(scala3Options, untypedOptionValues); switch (options.framework) { diff --git a/packages/quicktype-core/src/language/Smithy4s/language.ts b/packages/quicktype-core/src/language/Smithy4s/language.ts index 1213c92fd0..114362f9b9 100644 --- a/packages/quicktype-core/src/language/Smithy4s/language.ts +++ b/packages/quicktype-core/src/language/Smithy4s/language.ts @@ -1,6 +1,7 @@ import type { ConvenienceRenderer } from "../../ConvenienceRenderer.js"; import type { RenderContext } from "../../Renderer.js"; import { + BooleanOption, EnumOption, StringOption, getOptionValues, @@ -23,6 +24,14 @@ export const smithyOptions = { { "just-types": Framework.None } as const, "just-types", ), + // Smithy only ever generates plain types; the flag is accepted for + // consistency with the other languages. + justTypes: new BooleanOption( + "just-types", + "Plain types only (the only mode Smithy supports)", + false, + "secondary", + ), packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; diff --git a/test/unit/just-types-option.test.ts b/test/unit/just-types-option.test.ts new file mode 100644 index 0000000000..b417d8fb90 --- /dev/null +++ b/test/unit/just-types-option.test.ts @@ -0,0 +1,66 @@ +// Most languages spell "generate plain types without (de)serialization +// helpers" as a `just-types` boolean option, but C# spelled it +// `features=just-types` and Kotlin/Scala/Smithy `framework=just-types`, so +// the CLI's `--just-types` flag was rejected for those languages. They now +// also accept `just-types`, which forces the corresponding enum option. +import { describe, expect, test } from "vitest"; + +import { + InputData, + type LanguageName, + type RendererOptions, + jsonInputForTargetLanguage, + quicktype, +} from "quicktype-core"; + +async function linesFor( + lang: LanguageName, + rendererOptions: RendererOptions, +): Promise { + const jsonInput = jsonInputForTargetLanguage(lang); + await jsonInput.addSource({ + name: "Person", + samples: ['{"name": "Alice", "age": 37}'], + }); + const inputData = new InputData(); + inputData.addInput(jsonInput); + const result = await quicktype({ inputData, lang, rendererOptions }); + return result.lines.join("\n"); +} + +describe("just-types is accepted by every enum-spelled language", () => { + test("C#: just-types matches features=just-types", async () => { + const viaBoolean = await linesFor("csharp", { "just-types": true }); + const viaEnum = await linesFor("csharp", { features: "just-types" }); + expect(viaBoolean).toEqual(viaEnum); + expect(viaBoolean).not.toContain("JsonConverter"); + }); + + test("Kotlin: just-types matches framework=just-types", async () => { + const viaBoolean = await linesFor("kotlin", { "just-types": true }); + const viaEnum = await linesFor("kotlin", { framework: "just-types" }); + expect(viaBoolean).toEqual(viaEnum); + expect(viaBoolean).not.toContain("Klaxon"); + }); + + test("Scala: just-types matches framework=just-types", async () => { + const viaBoolean = await linesFor("scala3", { "just-types": true }); + const viaEnum = await linesFor("scala3", { framework: "just-types" }); + expect(viaBoolean).toEqual(viaEnum); + }); + + test("Smithy: just-types is accepted", async () => { + const viaBoolean = await linesFor("smithy4a", { "just-types": true }); + const viaDefault = await linesFor("smithy4a", {}); + expect(viaBoolean).toEqual(viaDefault); + }); + + test("the boolean wins over a conflicting enum value", async () => { + const viaBoolean = await linesFor("kotlin", { + "just-types": true, + framework: "jackson", + }); + const plain = await linesFor("kotlin", { framework: "just-types" }); + expect(viaBoolean).toEqual(plain); + }); +}); diff --git a/test/unit/renderer-options.test-d.ts b/test/unit/renderer-options.test-d.ts index f86fcde9c3..33fd010369 100644 --- a/test/unit/renderer-options.test-d.ts +++ b/test/unit/renderer-options.test-d.ts @@ -52,8 +52,8 @@ describe("rendererOptions typing", () => { test("rejects another language's option name", () => { void quicktype({ inputData, - lang: "kotlin", - // @ts-expect-error `just-types` is a C#/TypeScript spelling; Kotlin has no such option + lang: "rust", + // @ts-expect-error Rust has no `just-types` option rendererOptions: { "just-types": "true" }, }); }); From 23511bac63e7d0f7a3228b46d33a0805c2f060ef Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 14 Jul 2026 14:47:50 -0400 Subject: [PATCH 2/2] feat(options)!: make --just-types the only spelling, everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: the enum spellings of "plain types" are gone. C# loses `--features just-types` and `--features just-types-and-namespace` (their value maps were identical); Kotlin and Scala 3 lose `--framework just-types`; Smithy4s loses its single-value `--framework` option entirely. Every language now spells it the way the other 15 always have: the boolean `--just-types`, which wins over a conflicting explicit `--features`/`--framework`. Scala 3's default changes with this: a bare `quicktype -l scala3` now generates circe (de)serialization instead of plain case classes — plain types now require asking for `--just-types`, like in every other language. The VS Code extension's per-language special-casing collapses into a single check for whether the target language has a `just-types` option (fixing a bug where its "just types" commands silently did nothing for languages other than C# and Kotlin), and the Smithy4s test fixture migrates to the boolean spelling. Co-Authored-By: Claude Fable 5 --- .../CSharp/NewtonSoftCSharpRenderer.ts | 6 +- .../CSharp/SystemTextJsonCSharpRenderer.ts | 6 +- .../src/language/CSharp/language.ts | 26 +--- .../src/language/Kotlin/language.ts | 25 +--- .../src/language/Scala3/language.ts | 27 +--- .../src/language/Smithy4s/language.ts | 37 ++--- packages/quicktype-vscode/src/extension.ts | 19 +-- test/languages.ts | 2 +- test/unit/just-types-option.test.ts | 128 ++++++++++++++---- 9 files changed, 137 insertions(+), 139 deletions(-) diff --git a/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts index 0df4b758f2..c69107ebd9 100644 --- a/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts +++ b/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts @@ -68,8 +68,10 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { private readonly _options: OptionValues, ) { super(targetLanguage, renderContext, _options); - this._needHelpers = _options.features.helpers; - this._needAttributes = _options.features.attributes; + // `--just-types` wins over whatever `--features` says. + this._needHelpers = _options.features.helpers && !_options.justTypes; + this._needAttributes = + _options.features.attributes && !_options.justTypes; this._needNamespaces = _options.features.namespaces; } diff --git a/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts index 8eb22b14b6..34204577b4 100644 --- a/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts +++ b/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts @@ -69,8 +69,10 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { >, ) { super(targetLanguage, renderContext, _options); - this._needHelpers = _options.features.helpers; - this._needAttributes = _options.features.attributes; + // `--just-types` wins over whatever `--features` says. + this._needHelpers = _options.features.helpers && !_options.justTypes; + this._needAttributes = + _options.features.attributes && !_options.justTypes; this._needNamespaces = _options.features.namespaces; } diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts index 754c325e95..0b0c7235f5 100644 --- a/packages/quicktype-core/src/language/CSharp/language.ts +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -104,27 +104,10 @@ export const cSharpOptions = { helpers: false, attributes: true, }, - "just-types-and-namespace": { - namespaces: true, - helpers: false, - attributes: false, - }, - "just-types": { - namespaces: true, - helpers: false, - attributes: false, - }, } as const, "complete", ), - // The boolean spelling of `--features just-types`, so that - // `--just-types` works for C# like it does for most other languages. - justTypes: new BooleanOption( - "just-types", - "Plain types only (same as features=just-types)", - false, - "secondary", - ), + justTypes: new BooleanOption("just-types", "Plain types only", false), baseclass: new EnumOption( "base-class", "Base class", @@ -198,13 +181,6 @@ export class CSharpTargetLanguage extends TargetLanguage< renderContext: RenderContext, untypedOptionValues: RendererOptions, ): ConvenienceRenderer { - if (cSharpOptions.justTypes.getValue(untypedOptionValues)) { - untypedOptionValues = { - ...untypedOptionValues, - features: "just-types", - } as RendererOptions; - } - const options = getOptionValues(cSharpOptions, untypedOptionValues); switch (options.framework) { diff --git a/packages/quicktype-core/src/language/Kotlin/language.ts b/packages/quicktype-core/src/language/Kotlin/language.ts index 854d232432..f806d423f9 100644 --- a/packages/quicktype-core/src/language/Kotlin/language.ts +++ b/packages/quicktype-core/src/language/Kotlin/language.ts @@ -17,26 +17,17 @@ import { KotlinRenderer } from "./KotlinRenderer.js"; import { KotlinXRenderer } from "./KotlinXRenderer.js"; export const kotlinOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), framework: new EnumOption( "framework", "Serialization framework", { - "just-types": "None", jackson: "Jackson", klaxon: "Klaxon", kotlinx: "KotlinX", } as const, "klaxon", ), - // The boolean spelling of `--framework just-types`, so that - // `--just-types` works for Kotlin like it does for most other - // languages. - justTypes: new BooleanOption( - "just-types", - "Plain types only (same as framework=just-types)", - false, - "secondary", - ), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; @@ -70,18 +61,14 @@ export class KotlinTargetLanguage extends TargetLanguage< renderContext: RenderContext, untypedOptionValues: RendererOptions, ): ConvenienceRenderer { - if (kotlinOptions.justTypes.getValue(untypedOptionValues)) { - untypedOptionValues = { - ...untypedOptionValues, - framework: "just-types", - } as RendererOptions; - } - const options = getOptionValues(kotlinOptions, untypedOptionValues); + // `--just-types` wins over whatever `--framework` says. + if (options.justTypes) { + return new KotlinRenderer(this, renderContext, options); + } + switch (options.framework) { - case "None": - return new KotlinRenderer(this, renderContext, options); case "Jackson": return new KotlinJacksonRenderer(this, renderContext, options); case "Klaxon": diff --git a/packages/quicktype-core/src/language/Scala3/language.ts b/packages/quicktype-core/src/language/Scala3/language.ts index aba0075e4c..f1e8d10630 100644 --- a/packages/quicktype-core/src/language/Scala3/language.ts +++ b/packages/quicktype-core/src/language/Scala3/language.ts @@ -15,24 +15,15 @@ import { Scala3Renderer } from "./Scala3Renderer.js"; import { UpickleRenderer } from "./UpickleRenderer.js"; export const scala3Options = { + justTypes: new BooleanOption("just-types", "Plain types only", false), framework: new EnumOption( "framework", "Serialization framework", { - "just-types": "None", circe: "Circe", upickle: "Upickle", } as const, - "just-types", - ), - // The boolean spelling of `--framework just-types`, so that - // `--just-types` works for Scala like it does for most other - // languages. - justTypes: new BooleanOption( - "just-types", - "Plain types only (same as framework=just-types)", - false, - "secondary", + "circe", ), packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; @@ -66,18 +57,14 @@ export class Scala3TargetLanguage extends TargetLanguage< renderContext: RenderContext, untypedOptionValues: RendererOptions, ): ConvenienceRenderer { - if (scala3Options.justTypes.getValue(untypedOptionValues)) { - untypedOptionValues = { - ...untypedOptionValues, - framework: "just-types", - } as RendererOptions; - } - const options = getOptionValues(scala3Options, untypedOptionValues); + // `--just-types` wins over whatever `--framework` says. + if (options.justTypes) { + return new Scala3Renderer(this, renderContext, options); + } + switch (options.framework) { - case "None": - return new Scala3Renderer(this, renderContext, options); case "Upickle": return new UpickleRenderer(this, renderContext, options); case "Circe": diff --git a/packages/quicktype-core/src/language/Smithy4s/language.ts b/packages/quicktype-core/src/language/Smithy4s/language.ts index 114362f9b9..5376a3a6a4 100644 --- a/packages/quicktype-core/src/language/Smithy4s/language.ts +++ b/packages/quicktype-core/src/language/Smithy4s/language.ts @@ -2,36 +2,18 @@ import type { ConvenienceRenderer } from "../../ConvenienceRenderer.js"; import type { RenderContext } from "../../Renderer.js"; import { BooleanOption, - EnumOption, StringOption, getOptionValues, } from "../../RendererOptions/index.js"; -import { assertNever } from "../../support/Support.js"; import { TargetLanguage } from "../../TargetLanguage.js"; import type { LanguageName, RendererOptions } from "../../types.js"; import { Smithy4sRenderer } from "./Smithy4sRenderer.js"; -export enum Framework { - None = "None", -} - export const smithyOptions = { - // FIXME: why does this exist - framework: new EnumOption( - "framework", - "Serialization framework", - { "just-types": Framework.None } as const, - "just-types", - ), - // Smithy only ever generates plain types; the flag is accepted for - // consistency with the other languages. - justTypes: new BooleanOption( - "just-types", - "Plain types only (the only mode Smithy supports)", - false, - "secondary", - ), + // Plain types is the only mode Smithy supports; the flag is accepted + // for consistency with the other languages. + justTypes: new BooleanOption("just-types", "Plain types only", false), packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; @@ -64,13 +46,10 @@ export class SmithyTargetLanguage extends TargetLanguage< renderContext: RenderContext, untypedOptionValues: RendererOptions, ): ConvenienceRenderer { - const options = getOptionValues(smithyOptions, untypedOptionValues); - - switch (options.framework) { - case Framework.None: - return new Smithy4sRenderer(this, renderContext, options); - default: - return assertNever(options.framework); - } + return new Smithy4sRenderer( + this, + renderContext, + getOptionValues(smithyOptions, untypedOptionValues), + ); } } diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts index 08f5e011d9..506efb9d97 100644 --- a/packages/quicktype-vscode/src/extension.ts +++ b/packages/quicktype-vscode/src/extension.ts @@ -106,19 +106,12 @@ async function runQuicktype( vscode.workspace.getConfiguration(configurationSection); const justTypes = forceJustTypes || configuration.justTypes; - const rendererOptions: RendererOptions = {}; - if (justTypes) { - // FIXME: The target language should have a property to return these options. - if (lang.name === "csharp") { - (rendererOptions as RendererOptions<"csharp">).features = - "just-types"; - } else if (lang.name === "kotlin") { - (rendererOptions as RendererOptions<"kotlin">).framework = - "just-types"; - } else if ("just-types" in rendererOptions) { - rendererOptions["just-types"] = "true"; - } - } + // Not every language has a `just-types` option — JSON Schema, for + // example, has no serialization helpers to leave out. + const rendererOptions: RendererOptions = + justTypes && lang.optionDefinitions.some((o) => o.name === "just-types") + ? ({ "just-types": "true" } as RendererOptions) + : {}; const inputData = new InputData(); switch (kind) { diff --git a/test/languages.ts b/test/languages.ts index b064f74c8d..a03ef19e2c 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -1083,7 +1083,7 @@ I havea no idea how to encode these tests correctly. ], skipSchema: [], skipMiscJSON: false, - rendererOptions: { framework: "just-types" }, + rendererOptions: { "just-types": "true" }, quickTestRendererOptions: [], sourceFiles: ["src/language/Smithy4s/index.ts"], }; diff --git a/test/unit/just-types-option.test.ts b/test/unit/just-types-option.test.ts index b417d8fb90..8ae56e317a 100644 --- a/test/unit/just-types-option.test.ts +++ b/test/unit/just-types-option.test.ts @@ -1,8 +1,8 @@ -// Most languages spell "generate plain types without (de)serialization -// helpers" as a `just-types` boolean option, but C# spelled it -// `features=just-types` and Kotlin/Scala/Smithy `framework=just-types`, so -// the CLI's `--just-types` flag was rejected for those languages. They now -// also accept `just-types`, which forces the corresponding enum option. +// Every quicktype language spells "generate plain types without +// (de)serialization helpers" as the boolean `just-types` option. C#'s +// `features=just-types` / `features=just-types-and-namespace` and Kotlin's, +// Scala 3's, and Smithy4s's `framework=just-types` are gone; the boolean +// wins over a conflicting explicit enum value. import { describe, expect, test } from "vitest"; import { @@ -15,7 +15,7 @@ import { async function linesFor( lang: LanguageName, - rendererOptions: RendererOptions, + rendererOptions: RendererOptions = {}, ): Promise { const jsonInput = jsonInputForTargetLanguage(lang); await jsonInput.addSource({ @@ -28,39 +28,111 @@ async function linesFor( return result.lines.join("\n"); } -describe("just-types is accepted by every enum-spelled language", () => { - test("C#: just-types matches features=just-types", async () => { - const viaBoolean = await linesFor("csharp", { "just-types": true }); - const viaEnum = await linesFor("csharp", { features: "just-types" }); - expect(viaBoolean).toEqual(viaEnum); - expect(viaBoolean).not.toContain("JsonConverter"); +describe("just-types generates plain types in every language", () => { + test("C#: no attributes, no helpers, but a namespace", async () => { + const output = await linesFor("csharp", { "just-types": true }); + expect(output).toContain("namespace QuickType"); + expect(output).toContain("public partial class Person"); + expect(output).not.toContain("JsonConverter"); + expect(output).not.toContain("JsonProperty"); }); - test("Kotlin: just-types matches framework=just-types", async () => { - const viaBoolean = await linesFor("kotlin", { "just-types": true }); - const viaEnum = await linesFor("kotlin", { framework: "just-types" }); - expect(viaBoolean).toEqual(viaEnum); - expect(viaBoolean).not.toContain("Klaxon"); + test("Kotlin: plain data classes, no Klaxon", async () => { + const output = await linesFor("kotlin", { "just-types": true }); + expect(output).toContain("data class Person"); + expect(output).not.toContain("Klaxon"); }); - test("Scala: just-types matches framework=just-types", async () => { - const viaBoolean = await linesFor("scala3", { "just-types": true }); - const viaEnum = await linesFor("scala3", { framework: "just-types" }); - expect(viaBoolean).toEqual(viaEnum); + test("Scala 3: plain case classes, no circe", async () => { + const output = await linesFor("scala3", { "just-types": true }); + expect(output).toContain("case class Person"); + expect(output).not.toContain("circe"); }); - test("Smithy: just-types is accepted", async () => { + test("Smithy: accepted (plain types is the only mode)", async () => { const viaBoolean = await linesFor("smithy4a", { "just-types": true }); - const viaDefault = await linesFor("smithy4a", {}); - expect(viaBoolean).toEqual(viaDefault); + expect(viaBoolean).toContain("structure Person"); + expect(viaBoolean).toEqual(await linesFor("smithy4a")); }); +}); + +describe("the removed enum spellings are errors", () => { + // The old spellings aren't valid `RendererOptions` anymore, which is + // the point: they must also fail for API callers who evade the types. + test("C#: features=just-types", async () => { + const options = { features: "just-types" } as RendererOptions; + await expect(linesFor("csharp", options)).rejects.toThrow( + "Unknown value just-types for option features", + ); + }); + + test("C#: features=just-types-and-namespace", async () => { + const options = { + features: "just-types-and-namespace", + } as RendererOptions; + await expect(linesFor("csharp", options)).rejects.toThrow( + "Unknown value just-types-and-namespace for option features", + ); + }); + + test("Kotlin: framework=just-types", async () => { + const options = { framework: "just-types" } as RendererOptions; + await expect(linesFor("kotlin", options)).rejects.toThrow( + "Unknown value just-types for option framework", + ); + }); + + test("Scala 3: framework=just-types", async () => { + const options = { framework: "just-types" } as RendererOptions; + await expect(linesFor("scala3", options)).rejects.toThrow( + "Unknown value just-types for option framework", + ); + }); +}); - test("the boolean wins over a conflicting enum value", async () => { - const viaBoolean = await linesFor("kotlin", { +describe("just-types wins over a conflicting enum option", () => { + test("C#: just-types beats features=attributes-only", async () => { + const output = await linesFor("csharp", { + "just-types": true, + features: "attributes-only", + }); + expect(output).toEqual( + await linesFor("csharp", { "just-types": true }), + ); + expect(output).not.toContain("JsonProperty"); + }); + + test("Kotlin: just-types beats framework=jackson", async () => { + const output = await linesFor("kotlin", { "just-types": true, framework: "jackson", }); - const plain = await linesFor("kotlin", { framework: "just-types" }); - expect(viaBoolean).toEqual(plain); + expect(output).toEqual( + await linesFor("kotlin", { "just-types": true }), + ); + expect(output).not.toContain("jackson"); + }); + + test("Scala 3: just-types beats framework=upickle", async () => { + const output = await linesFor("scala3", { + "just-types": true, + framework: "upickle", + }); + expect(output).toEqual( + await linesFor("scala3", { "just-types": true }), + ); + expect(output).not.toContain("upickle"); + }); +}); + +describe("framework defaults", () => { + test("Scala 3 defaults to circe", async () => { + const output = await linesFor("scala3"); + expect(output).toContain("io.circe"); + }); + + test("Kotlin defaults to Klaxon", async () => { + const output = await linesFor("kotlin"); + expect(output).toContain("com.beust.klaxon"); }); });