diff --git a/src/quicktype-core/Transformers.ts b/src/quicktype-core/Transformers.ts index 7f40294b..172beace 100644 --- a/src/quicktype-core/Transformers.ts +++ b/src/quicktype-core/Transformers.ts @@ -922,6 +922,10 @@ class TransformationTypeAttributeKind extends TypeAttributeKind super("transformation"); } + appliesToTypeKind(_kind: TypeKind): boolean { + return true; + } + get inIdentity(): boolean { return true; } diff --git a/src/quicktype-core/TypeAttributes.ts b/src/quicktype-core/TypeAttributes.ts index 183569a7..85cc0cf9 100644 --- a/src/quicktype-core/TypeAttributes.ts +++ b/src/quicktype-core/TypeAttributes.ts @@ -2,12 +2,16 @@ import stringHash = require("string-hash"); import { mapFilterMap, mapFilter, mapTranspose, mapMap } from "collection-utils"; import { panic, assert } from "./support/Support"; -import { Type } from "./Type"; +import { Type, TypeKind } from "./Type"; import { BaseGraphRewriteBuilder } from "./GraphRewriting"; export class TypeAttributeKind { constructor(readonly name: string) {} + appliesToTypeKind(kind: TypeKind): boolean { + return kind !== "any"; + } + combine(_attrs: T[]): T { return panic(`Cannot combine type attribute ${this.name}`); } diff --git a/src/quicktype-core/TypeBuilder.ts b/src/quicktype-core/TypeBuilder.ts index 0838a6e8..302ad04b 100644 --- a/src/quicktype-core/TypeBuilder.ts +++ b/src/quicktype-core/TypeBuilder.ts @@ -35,7 +35,8 @@ import { TypeIdentity, TransformedStringTypeKind, isPrimitiveStringTypeKind, - transformedStringTypeKinds + transformedStringTypeKinds, + TypeKind } from "./Type"; import { TypeGraph, TypeRef, makeTypeRef, derefTypeRef, typeRefIndex, assertTypeRefGraph } from "./TypeGraph"; import { TypeAttributes, combineTypeAttributes, TypeAttributeKind, emptyTypeAttributes } from "./TypeAttributes"; @@ -49,6 +50,10 @@ class ProvenanceTypeAttributeKind extends TypeAttributeKind> { super("provenance"); } + appliesToTypeKind(_kind: TypeKind): boolean { + return true; + } + combine(arr: Set[]): Set { return setUnionManyInto(new Set(), arr); } @@ -144,6 +149,14 @@ export class TypeBuilder { trefs.forEach(tref => this.assertTypeRefGraph(tref)); } + private filterTypeAttributes(t: Type, attributes: TypeAttributes): TypeAttributes { + const filtered = mapFilter(attributes, (_, k) => k.appliesToTypeKind(t.kind)); + if (attributes.size !== filtered.size) { + this.setLostTypeAttributes(); + } + return filtered; + } + private commitType(tref: TypeRef, t: Type): void { this.assertTypeRefGraph(tref); const index = typeRefIndex(tref); @@ -151,6 +164,7 @@ export class TypeBuilder { // console.log(`committing ${t.kind}${name} to ${index}`); assert(this.types[index] === undefined, "A type index was committed twice"); this.types[index] = t; + this.typeAttributes[index] = this.filterTypeAttributes(t, this.typeAttributes[index]); } protected addType( @@ -199,6 +213,10 @@ export class TypeBuilder { }), "Can't add different identity type attributes to an existing type" ); + const maybeType = this.types[index]; + if (maybeType !== undefined) { + attributes = this.filterTypeAttributes(maybeType, attributes); + } const nonIdentityAttributes = mapFilter(attributes, (_, k) => !k.inIdentity); this.typeAttributes[index] = combineTypeAttributes("union", existingAttributes, nonIdentityAttributes); }