From 26a9c0db4168687b4fa659fcede085e65b04302c Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Wed, 25 Nov 2020 17:53:06 -0700 Subject: [PATCH] fix: JSON schema had incorrect value types Resolves #1389 --- src/lib/converter/symbols.ts | 1 - src/lib/serialization/index.ts | 1 - src/lib/serialization/schema.ts | 43 ++++++----- src/lib/serialization/serializer.ts | 12 +++- .../serializers/reflections/abstract.ts | 37 ++-------- .../serializers/reflections/container.ts | 34 ++------- .../serializers/reflections/declaration.ts | 66 +++++------------ .../serializers/reflections/index.ts | 1 - .../serializers/reflections/parameter.ts | 10 +-- .../serializers/reflections/project.ts | 25 ------- .../serializers/reflections/signature.ts | 30 +++----- .../serializers/reflections/type-parameter.ts | 15 ++-- .../serializers/types/predicate.ts | 6 +- .../class/specs-with-lump-categories.json | 60 ++++++++-------- src/test/converter/class/specs.json | 60 ++++++++-------- src/test/converter/interface/specs.json | 72 +++++++++---------- src/test/converter/variables/specs.json | 18 ++--- src/test/converter/variables/specs.nodoc.json | 18 ++--- 18 files changed, 203 insertions(+), 306 deletions(-) delete mode 100644 src/lib/serialization/serializers/reflections/project.ts diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index 62bf318ea..54636e5bb 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -21,7 +21,6 @@ import { convertDefaultValue } from "./convert-expression"; import { ConverterEvents } from "./converter-events"; import { createSignature } from "./factories/signature"; -// TODO: implementationOf / overwrites // TODO: Index signatures function getSymbolExportsWithFlag(symbol: ts.Symbol, flag: ts.SymbolFlags) { diff --git a/src/lib/serialization/index.ts b/src/lib/serialization/index.ts index fe44a2f49..406545af3 100644 --- a/src/lib/serialization/index.ts +++ b/src/lib/serialization/index.ts @@ -17,7 +17,6 @@ export { IntrinsicTypeSerializer, LiteralTypeSerializer, ParameterReflectionSerializer, - ProjectReflectionSerializer, ReferenceTypeSerializer, ReflectionCategorySerializer, ReflectionGroupSerializer, diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index 4833d1b3f..13b7f599c 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -143,8 +143,15 @@ export interface SignatureReflection extends Reflection, S< M.SignatureReflection, - "type" | "overwrites" | "inheritedFrom" | "implementationOf" - > {} + | "parameters" + | "type" + | "overwrites" + | "inheritedFrom" + | "implementationOf" + > { + // Weird not to call this typeParameters... preserving backwards compatibility for now. + typeParameter?: ModelToObject; +} export interface ParameterReflection extends Reflection, @@ -155,15 +162,26 @@ export interface DeclarationReflection S< M.DeclarationReflection, | "type" + | "signatures" + | "indexSignature" | "defaultValue" | "overwrites" | "inheritedFrom" + | "implementationOf" | "extendedTypes" | "extendedBy" | "implementedTypes" | "implementedBy" - | "implementationOf" - > {} + > { + // Weird not to call this typeParameters... preserving backwards compatibility for now. + typeParameter?: ModelToObject; + + // Yep... backwards compatibility. This is an optional one-tuple. + getSignature?: [ModelToObject]; + + // Yep... backwards compatibility. This is an optional one-tuple. + setSignature?: [ModelToObject]; +} export interface TypeParameterReflection extends Reflection, @@ -174,32 +192,19 @@ export interface ProjectReflection extends ContainerReflection {} export interface ContainerReflection extends Reflection, - S { + S { sources?: ModelToObject; } -/** - * If a 3rd party serializer creates a loop when serializing, a pointer will be created - * instead of re-serializing the [[DeclarationReflection]] - */ -export interface ReflectionPointer extends S {} - export interface Reflection extends S< M.Reflection, "id" | "name" | "kind" | "kindString" | "comment" | "decorates" > { + /** Will not be present if name === originalName */ originalName?: M.Reflection["originalName"]; flags: ReflectionFlags; decorators?: ModelToObject; - - children?: ModelToObject[]; - parameters?: ModelToObject[]; - typeParameter?: ModelToObject[]; - signatures?: ModelToObject[]; - indexSignature?: ModelToObject[]; - getSignature?: ModelToObject[]; - setSignature?: ModelToObject[]; } // Types diff --git a/src/lib/serialization/serializer.ts b/src/lib/serialization/serializer.ts index db3eb883e..12bcc8ae3 100644 --- a/src/lib/serialization/serializer.ts +++ b/src/lib/serialization/serializer.ts @@ -44,6 +44,17 @@ export class Serializer extends EventDispatcher { } toObject(value: T, init: object = {}): ModelToObject { + if (value == null || typeof value !== "object") { + return value as any; // Serializing some primitive + } + + if (Array.isArray(value)) { + if (value.length === 0) { + return undefined as any; + } + return value.map((val) => this.toObject(val)) as any; + } + // Note: This type *could* potentially lie, if a serializer declares a partial type but fails to provide // the defined property, but the benefit of being mostly typed is probably worth it. // TypeScript errors out if init is correctly typed as `Partial>` @@ -117,7 +128,6 @@ const serializerComponents: (new (owner: Serializer) => SerializerComponent< S.ContainerReflectionSerializer, S.DeclarationReflectionSerializer, S.ParameterReflectionSerializer, - S.ProjectReflectionSerializer, S.SignatureReflectionSerializer, S.TypeParameterReflectionSerializer, diff --git a/src/lib/serialization/serializers/reflections/abstract.ts b/src/lib/serialization/serializers/reflections/abstract.ts index e7e103512..04797cd4e 100644 --- a/src/lib/serialization/serializers/reflections/abstract.ts +++ b/src/lib/serialization/serializers/reflections/abstract.ts @@ -1,8 +1,8 @@ -import { Reflection, TraverseProperty } from "../../../models"; +import { Reflection } from "../../../models"; import { ReflectionSerializerComponent } from "../../components"; import { DecoratorWrapper } from "../models"; -import { Reflection as JSONReflection } from "../../schema"; +import type { Reflection as JSONReflection } from "../../schema"; export class ReflectionSerializer extends ReflectionSerializerComponent< Reflection @@ -24,16 +24,17 @@ export class ReflectionSerializer extends ReflectionSerializerComponent< kind: reflection.kind, kindString: reflection.kindString, flags: {}, + comment: this.owner.toObject(reflection.comment), + decorates: this.owner.toObject(reflection.decorates), + decorators: this.owner.toObject( + reflection.decorators?.map((d) => new DecoratorWrapper(d)) + ), }; if (reflection.originalName !== reflection.name) { result.originalName = reflection.originalName; } - if (reflection.comment) { - result.comment = this.owner.toObject(reflection.comment); - } - const flags = [ "isPrivate", "isProtected", @@ -56,30 +57,6 @@ export class ReflectionSerializer extends ReflectionSerializerComponent< } } - if (reflection.decorates && reflection.decorates.length > 0) { - result.decorates = reflection.decorates.map((t) => - this.owner.toObject(t) - ); - } - - if (reflection.decorators && reflection.decorators.length > 0) { - result.decorators = reflection.decorators.map((d) => - this.owner.toObject(new DecoratorWrapper(d)) - ); - } - - reflection.traverse((child, property) => { - if (property === TraverseProperty.TypeLiteral) { - return; - } - let name = TraverseProperty[property]; - name = name[0].toLowerCase() + name.substr(1); - if (!(result as any)[name]) { - (result as any)[name] = []; - } - (result as any)[name].push(this.owner.toObject(child)); - }); - return result; } } diff --git a/src/lib/serialization/serializers/reflections/container.ts b/src/lib/serialization/serializers/reflections/container.ts index 62b79de8f..a653115e1 100644 --- a/src/lib/serialization/serializers/reflections/container.ts +++ b/src/lib/serialization/serializers/reflections/container.ts @@ -23,34 +23,14 @@ export class ContainerReflectionSerializer extends ReflectionSerializerComponent container: ContainerReflection, obj: JSONReflection ): JSONContainerReflection { - const result: JSONContainerReflection = { + return { ...obj, + children: this.owner.toObject(container.children), + groups: this.owner.toObject(container.groups), + categories: this.owner.toObject(container.categories), + sources: this.owner.toObject( + container.sources?.map((s) => new SourceReferenceWrapper(s)) + ), }; - - if (container.groups && container.groups.length > 0) { - result.groups = container.groups.map((group) => - this.owner.toObject(group) - ); - } - - if (container.categories && container.categories.length > 0) { - result.categories = container.categories.map((category) => - this.owner.toObject(category) - ); - } - - if (container.sources && container.sources.length > 0) { - result.sources = container.sources.map((source) => - this.owner.toObject( - new SourceReferenceWrapper({ - fileName: source.fileName, - line: source.line, - character: source.character, - }) - ) - ); - } - - return result; } } diff --git a/src/lib/serialization/serializers/reflections/declaration.ts b/src/lib/serialization/serializers/reflections/declaration.ts index 9aee9a46e..d263487d7 100644 --- a/src/lib/serialization/serializers/reflections/declaration.ts +++ b/src/lib/serialization/serializers/reflections/declaration.ts @@ -17,61 +17,33 @@ export class DeclarationReflectionSerializer extends ReflectionSerializerCompone } toObject( - declaration: DeclarationReflection, + d: DeclarationReflection, obj: JSONContainerReflection ): JSONDeclarationReflection { const result: JSONDeclarationReflection = { ...obj, + typeParameter: this.owner.toObject(d.typeParameters), + type: this.owner.toObject(d.type), + signatures: this.owner.toObject(d.signatures), + indexSignature: this.owner.toObject(d.indexSignature), }; - if (declaration.type) { - result.type = this.owner.toObject(declaration.type); + if (d.getSignature) { + result.getSignature = [this.owner.toObject(d.getSignature)]; } - - if (declaration.defaultValue) { - result.defaultValue = declaration.defaultValue; - } - - if (declaration.overwrites) { - result.overwrites = this.owner.toObject(declaration.overwrites); - } - - if (declaration.inheritedFrom) { - result.inheritedFrom = this.owner.toObject( - declaration.inheritedFrom - ); - } - - if (declaration.extendedTypes) { - result.extendedTypes = declaration.extendedTypes.map((t) => - this.owner.toObject(t) - ); - } - - if (declaration.extendedBy) { - result.extendedBy = declaration.extendedBy.map((t) => - this.owner.toObject(t) - ); - } - - if (declaration.implementedTypes) { - result.implementedTypes = declaration.implementedTypes.map((t) => - this.owner.toObject(t) - ); - } - - if (declaration.implementedBy) { - result.implementedBy = declaration.implementedBy.map((t) => - this.owner.toObject(t) - ); - } - - if (declaration.implementationOf) { - result.implementationOf = this.owner.toObject( - declaration.implementationOf - ); + if (d.setSignature) { + result.setSignature = [this.owner.toObject(d.setSignature)]; } - return result; + return Object.assign(result, { + defaultValue: this.owner.toObject(d.defaultValue), + overwrites: this.owner.toObject(d.overwrites), + inheritedFrom: this.owner.toObject(d.inheritedFrom), + implementationOf: this.owner.toObject(d.implementationOf), + extendedTypes: this.owner.toObject(d.extendedTypes), + extendedBy: this.owner.toObject(d.extendedBy), + implementedTypes: this.owner.toObject(d.implementedTypes), + implementedBy: this.owner.toObject(d.implementedBy), + }); } } diff --git a/src/lib/serialization/serializers/reflections/index.ts b/src/lib/serialization/serializers/reflections/index.ts index 8467164f0..0ebc4d94b 100644 --- a/src/lib/serialization/serializers/reflections/index.ts +++ b/src/lib/serialization/serializers/reflections/index.ts @@ -2,7 +2,6 @@ export * from "./abstract"; export * from "./container"; export * from "./declaration"; export * from "./parameter"; -export * from "./project"; export * from "./reference"; export * from "./signature"; export * from "./type-parameter"; diff --git a/src/lib/serialization/serializers/reflections/parameter.ts b/src/lib/serialization/serializers/reflections/parameter.ts index 252c69c5a..d5ba83ab6 100644 --- a/src/lib/serialization/serializers/reflections/parameter.ts +++ b/src/lib/serialization/serializers/reflections/parameter.ts @@ -19,16 +19,10 @@ export class ParameterReflectionSerializer extends ReflectionSerializerComponent ): JSONParameterReflection { const result: JSONParameterReflection = { ...obj, + type: this.owner.toObject(parameter.type), + defaultValue: this.owner.toObject(parameter.defaultValue), }; - if (parameter.type) { - result.type = this.owner.toObject(parameter.type); - } - - if (parameter.defaultValue) { - result.defaultValue = parameter.defaultValue; - } - return result; } } diff --git a/src/lib/serialization/serializers/reflections/project.ts b/src/lib/serialization/serializers/reflections/project.ts deleted file mode 100644 index 4a46c1d41..000000000 --- a/src/lib/serialization/serializers/reflections/project.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ProjectReflection } from "../../../models"; - -import { ReflectionSerializerComponent } from "../../components"; -import { ContainerReflectionSerializer } from "./container"; -import { - ProjectReflection as JSONProjectReflection, - ContainerReflection as JSONContainerReflection, -} from "../../schema"; - -export class ProjectReflectionSerializer extends ReflectionSerializerComponent< - ProjectReflection -> { - static PRIORITY = ContainerReflectionSerializer.PRIORITY - 1; // mimic inheritance, run after parent - - supports(t: unknown) { - return t instanceof ProjectReflection; - } - - toObject( - _container: ProjectReflection, - obj: JSONContainerReflection - ): JSONProjectReflection { - return obj; - } -} diff --git a/src/lib/serialization/serializers/reflections/signature.ts b/src/lib/serialization/serializers/reflections/signature.ts index 80dbefbe0..d30297fc2 100644 --- a/src/lib/serialization/serializers/reflections/signature.ts +++ b/src/lib/serialization/serializers/reflections/signature.ts @@ -17,26 +17,14 @@ export class SignatureReflectionSerializer extends ReflectionSerializerComponent signature: SignatureReflection, obj: JSONReflection ): JSONSignatureReflection { - const result: JSONSignatureReflection = { ...obj }; - - if (signature.type) { - result.type = this.owner.toObject(signature.type); - } - - if (signature.overwrites) { - result.overwrites = this.owner.toObject(signature.overwrites); - } - - if (signature.inheritedFrom) { - result.inheritedFrom = this.owner.toObject(signature.inheritedFrom); - } - - if (signature.implementationOf) { - result.implementationOf = this.owner.toObject( - signature.implementationOf - ); - } - - return result; + return { + ...obj, + typeParameter: this.owner.toObject(signature.typeParameters), + parameters: this.owner.toObject(signature.parameters), + type: this.owner.toObject(signature.type), + overwrites: this.owner.toObject(signature.overwrites), + inheritedFrom: this.owner.toObject(signature.inheritedFrom), + implementationOf: this.owner.toObject(signature.implementationOf), + }; } } diff --git a/src/lib/serialization/serializers/reflections/type-parameter.ts b/src/lib/serialization/serializers/reflections/type-parameter.ts index 64feb75d6..fa2eeb29d 100644 --- a/src/lib/serialization/serializers/reflections/type-parameter.ts +++ b/src/lib/serialization/serializers/reflections/type-parameter.ts @@ -17,15 +17,10 @@ export class TypeParameterReflectionSerializer extends ReflectionSerializerCompo typeParameter: TypeParameterReflection, obj: JSONReflection ): JSONTypeParameterReflection { - const result: JSONTypeParameterReflection = { ...obj }; - - if (typeParameter.type) { - result.type = this.owner.toObject(typeParameter.type); - } - if (typeParameter.default) { - result.default = this.owner.toObject(typeParameter.default); - } - - return result; + return { + ...obj, + type: this.owner.toObject(typeParameter.type), + default: this.owner.toObject(typeParameter.default), + }; } } diff --git a/src/lib/serialization/serializers/types/predicate.ts b/src/lib/serialization/serializers/types/predicate.ts index 8c63b475f..5f80400d2 100644 --- a/src/lib/serialization/serializers/types/predicate.ts +++ b/src/lib/serialization/serializers/types/predicate.ts @@ -1,5 +1,6 @@ import { PredicateType } from "../../../models"; import { TypeSerializerComponent } from "../../components"; +import { PredicateType as JSONPredicateType } from "../../schema"; export class PredicateTypeSerializer extends TypeSerializerComponent< PredicateType @@ -8,7 +9,10 @@ export class PredicateTypeSerializer extends TypeSerializerComponent< return t instanceof PredicateType; } - toObject(type: PredicateType, obj?: any): any { + toObject( + type: PredicateType, + obj: Pick + ): JSONPredicateType { return { ...obj, name: type.name, diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 5c58cc8d3..f58ce0314 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -2671,18 +2671,6 @@ "comment": { "shortText": "GenericClass short text." }, - "typeParameter": [ - { - "id": 172, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {}, - "comment": { - "shortText": "Generic parameter.\n" - } - } - ], "children": [ { "id": 164, @@ -2817,6 +2805,18 @@ ] } ], + "typeParameter": [ + { + "id": 172, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {}, + "comment": { + "shortText": "Generic parameter.\n" + } + } + ], "extendedBy": [ { "type": "reference", @@ -3293,24 +3293,6 @@ "kind": 128, "kindString": "Class", "flags": {}, - "typeParameter": [ - { - "id": 212, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {}, - "type": { - "type": "typeOperator", - "operator": "keyof", - "target": { - "type": "reference", - "id": 202, - "name": "TestClass" - } - } - } - ], "children": [ { "id": 208, @@ -3382,6 +3364,24 @@ 211 ] } + ], + "typeParameter": [ + { + "id": 212, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {}, + "type": { + "type": "typeOperator", + "operator": "keyof", + "target": { + "type": "reference", + "id": 202, + "name": "TestClass" + } + } + } ] }, { diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index b8f6d3f5f..5641e699f 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -2667,18 +2667,6 @@ "comment": { "shortText": "GenericClass short text." }, - "typeParameter": [ - { - "id": 172, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {}, - "comment": { - "shortText": "Generic parameter.\n" - } - } - ], "children": [ { "id": 164, @@ -2813,6 +2801,18 @@ ] } ], + "typeParameter": [ + { + "id": 172, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {}, + "comment": { + "shortText": "Generic parameter.\n" + } + } + ], "extendedBy": [ { "type": "reference", @@ -3289,24 +3289,6 @@ "kind": 128, "kindString": "Class", "flags": {}, - "typeParameter": [ - { - "id": 212, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {}, - "type": { - "type": "typeOperator", - "operator": "keyof", - "target": { - "type": "reference", - "id": 202, - "name": "TestClass" - } - } - } - ], "children": [ { "id": 208, @@ -3378,6 +3360,24 @@ 211 ] } + ], + "typeParameter": [ + { + "id": 212, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {}, + "type": { + "type": "typeOperator", + "operator": "keyof", + "target": { + "type": "reference", + "id": 202, + "name": "TestClass" + } + } + } ] }, { diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index 57e1b8fae..409fb6a2a 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -333,15 +333,6 @@ } ] }, - "typeParameter": [ - { - "id": 87, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {} - } - ], "children": [ { "id": 68, @@ -653,6 +644,15 @@ ] } ], + "typeParameter": [ + { + "id": 87, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {} + } + ], "implementedTypes": [ { "type": "reference", @@ -673,15 +673,6 @@ "kind": 128, "kindString": "Class", "flags": {}, - "typeParameter": [ - { - "id": 49, - "name": "V", - "kind": 131072, - "kindString": "Type parameter", - "flags": {} - } - ], "children": [ { "id": 36, @@ -911,6 +902,15 @@ ] } ], + "typeParameter": [ + { + "id": 49, + "name": "V", + "kind": 131072, + "kindString": "Type parameter", + "flags": {} + } + ], "implementedTypes": [ { "type": "reference", @@ -934,15 +934,6 @@ "comment": { "shortText": "The main interface of the event system.\nAn IEventDispatcher is an object that keeps a list of listeners, and sends dispatches events of a certain type to them.\nThis might otherwise be known as a Signal." }, - "typeParameter": [ - { - "id": 66, - "name": "U", - "kind": 131072, - "kindString": "Type parameter", - "flags": {} - } - ], "children": [ { "id": 51, @@ -1144,6 +1135,15 @@ ] } ], + "typeParameter": [ + { + "id": 66, + "name": "U", + "kind": 131072, + "kindString": "Type parameter", + "flags": {} + } + ], "implementedBy": [ { "type": "reference", @@ -1212,15 +1212,6 @@ "comment": { "shortText": "Encapsulates a subscription to an event dispatcher, and allows for unsubscribing" }, - "typeParameter": [ - { - "id": 34, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {} - } - ], "children": [ { "id": 31, @@ -1304,6 +1295,15 @@ ] } ], + "typeParameter": [ + { + "id": 34, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {} + } + ], "implementedBy": [ { "type": "reference", diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index c92347282..b14f55b96 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -20,15 +20,6 @@ "comment": { "shortText": "A custom array class." }, - "typeParameter": [ - { - "id": 6, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {} - } - ], "children": [ { "id": 3, @@ -70,6 +61,15 @@ ] } ], + "typeParameter": [ + { + "id": 6, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {} + } + ], "extendedBy": [ { "type": "reference", diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index c92347282..b14f55b96 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -20,15 +20,6 @@ "comment": { "shortText": "A custom array class." }, - "typeParameter": [ - { - "id": 6, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {} - } - ], "children": [ { "id": 3, @@ -70,6 +61,15 @@ ] } ], + "typeParameter": [ + { + "id": 6, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {} + } + ], "extendedBy": [ { "type": "reference",