diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index fe9efcbd8..88b3a684e 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -1084,14 +1084,17 @@ async function addTypesInSchema( emptyTypeAttributes, new Set(itemTypes), ); - } else if (typeof items === "object") { + } else if ( + typeof items === "object" || + typeof items === "boolean" + ) { const itemsLoc = loc.push("items"); itemType = await toType( checkJSONSchema(items, itemsLoc.canonicalRef), itemsLoc, singularAttributes, ); - } else if (items !== undefined && items !== true) { + } else if (items !== undefined) { return messageError( "SchemaArrayItemsMustBeStringOrArray", withRef(loc, { actual: items }), @@ -1396,14 +1399,7 @@ async function addTypesInSchema( let result: TypeRef; if (typeof schema === "boolean") { - // FIXME: Empty union. We'd have to check that it's supported everywhere, - // in particular in union flattening. - messageAssert( - schema === true, - "SchemaFalseNotSupported", - withRef(loc), - ); - result = typeBuilder.getPrimitiveType("any"); + result = typeBuilder.getPrimitiveType(schema ? "any" : "none"); } else { loc = loc.updateWithID(schema.$id); result = await convertToType(schema, loc, typeAttributes); diff --git a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts index a7aeefa83..05b424f43 100644 --- a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts +++ b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts @@ -471,6 +471,15 @@ export function resolveIntersections( return t; } + const noneType = iterableFind(members, (t) => t.kind === "none"); + if (noneType !== undefined) { + return builder.reconstituteType( + noneType, + intersectionAttributes, + forwardingRef, + ); + } + if (members.size === 1) { return builder.reconstituteType( defined(iterableFirst(members)), diff --git a/test/inputs/schema/boolean-subschema.1.fail.json b/test/inputs/schema/boolean-subschema.1.fail.json new file mode 100644 index 000000000..18abda884 --- /dev/null +++ b/test/inputs/schema/boolean-subschema.1.fail.json @@ -0,0 +1,4 @@ +{ + "foo": "hello", + "empty": "not an array" +} diff --git a/test/inputs/schema/boolean-subschema.1.json b/test/inputs/schema/boolean-subschema.1.json new file mode 100644 index 000000000..3dd8cd613 --- /dev/null +++ b/test/inputs/schema/boolean-subschema.1.json @@ -0,0 +1,4 @@ +{ + "foo": "hello", + "empty": [] +} diff --git a/test/inputs/schema/boolean-subschema.schema b/test/inputs/schema/boolean-subschema.schema new file mode 100644 index 000000000..3994e3347 --- /dev/null +++ b/test/inputs/schema/boolean-subschema.schema @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "foo": { "type": "string" }, + "disallowed": false, + "empty": { + "type": "array", + "items": false + }, + "impossible": { + "allOf": [false, { "type": "string" }] + } + }, + "required": ["foo", "empty"], + "additionalProperties": false +} diff --git a/test/languages.ts b/test/languages.ts index c798e154c..33d0a439b 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -630,6 +630,7 @@ export const CJSONLanguage: Language = { /* Enum with invalid values are not checked (for the current implementation, can be added later, should abord parsing and return NULL) */ ...skipsEnumValueValidation, /* Union, Map and Arrays with invalid types are not checked (for the current implementation, can be added later, should abord parsing and return NULL) */ + "boolean-subschema.schema", "class-with-additional.schema", ...skipsMapValueValidation, "multi-type-enum.schema", @@ -1857,6 +1858,7 @@ export const HaskellLanguage: Language = { ...skipsUntypedUnions, // The test driver encodes the Maybe result, so a failed decode prints // "null" and exits 0 — expected-failure samples cannot be detected. + "boolean-subschema.schema", "nested-intersection-union.schema", "prefix-items.schema", "direct-union.schema", @@ -2210,6 +2212,7 @@ export const ElixirLanguage: Language = { // Struct keys cannot be enforced at runtime in Elixir and their values will just be set to null. "strict-optional.schema", "required.schema", + "boolean-subschema.schema", "intersection.schema", // The test incorrectly succeeds due to the emitter being permissive for unions that contain only primitives. A future enhancement diff --git a/test/unit/cjson-enum-default.test.ts b/test/unit/cjson-enum-default.test.ts index b2c02d60e..0ecd24cb9 100644 --- a/test/unit/cjson-enum-default.test.ts +++ b/test/unit/cjson-enum-default.test.ts @@ -28,9 +28,9 @@ describe("cJSON enum invalid value", () => { const output = await cJSONOutput(); expect(output).toContain(`enum Subscription { - SUBSCRIPTION_CONFIG = 1, + SUBSCRIPTION_STATE = 1, + SUBSCRIPTION_CONFIG, SUBSCRIPTION_HEARTBEAT, - SUBSCRIPTION_STATE, };`); expect(output).toContain("enum Subscription x = 0;"); });