From 84aface8eb8a07f644594b38edda494e9cb32e8f Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Thu, 23 May 2019 23:52:55 +0300 Subject: [PATCH 1/6] Support BooleanLiteralTypeAnnotation --- declarations/babel.js | 1 + src/collector/definitions.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/declarations/babel.js b/declarations/babel.js index a96a823..aff2220 100644 --- a/declarations/babel.js +++ b/declarations/babel.js @@ -550,6 +550,7 @@ declare module '@babel/types' { declare class BooleanLiteralTypeAnnotation extends Node { type: 'BooleanLiteralTypeAnnotation'; + value: boolean; } declare class NullLiteralTypeAnnotation extends Node { diff --git a/src/collector/definitions.js b/src/collector/definitions.js index c4dd86a..dbcfc47 100644 --- a/src/collector/definitions.js +++ b/src/collector/definitions.js @@ -108,6 +108,8 @@ function makeType(ctx: Context, node: FlowTypeAnnotation): ?Type { return t.createLiteral(null); case 'BooleanTypeAnnotation': return t.createBoolean(); + case 'BooleanLiteralTypeAnnotation': + return t.createLiteral(node.value); case 'NumberTypeAnnotation': return t.createNumber('f64'); case 'StringTypeAnnotation': From 870756a440f0c627831f46401c904cc51f847b3e Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Thu, 23 May 2019 23:54:51 +0300 Subject: [PATCH 2/6] Support recursive types --- src/collector/definitions.js | 4 ++++ src/collector/scope.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/collector/definitions.js b/src/collector/definitions.js index dbcfc47..b16a014 100644 --- a/src/collector/definitions.js +++ b/src/collector/definitions.js @@ -31,6 +31,10 @@ import {invariant} from '../utils'; function processTypeAlias(ctx: Context, node: TypeAlias | DeclareTypeAlias) { const {name} = node.id; + + // Forward declaration for the recursive types + ctx.define(name, t.createAny()); + const type = makeType(ctx, node.right); // TODO: support function aliases. diff --git a/src/collector/scope.js b/src/collector/scope.js index 3aa6409..08bb432 100644 --- a/src/collector/scope.js +++ b/src/collector/scope.js @@ -84,7 +84,7 @@ export default class Scope { if (declared) { invariant(decl); - invariant(decl.kind === 'declaration'); + invariant(decl.kind === 'declaration' || decl.kind === 'definition'); } else { invariant(!decl); } From ec681fe6fc625e966fd255e724cf86cbd4d16f1b Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Thu, 23 May 2019 23:53:32 +0300 Subject: [PATCH 3/6] Convert FunctionTypeAnnotation to any to not crash --- src/collector/definitions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/collector/definitions.js b/src/collector/definitions.js index b16a014..9b5c3a9 100644 --- a/src/collector/definitions.js +++ b/src/collector/definitions.js @@ -141,7 +141,7 @@ function makeType(ctx: Context, node: FlowTypeAnnotation): ?Type { case 'MixedTypeAnnotation': return t.createMixed(); case 'FunctionTypeAnnotation': - return null; + return t.createAny(); default: invariant(false, `Unknown node: ${node.type}`); } From 1d0a098c397de6e2be38054cb95e9f46f98452ca Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Mon, 21 Oct 2019 18:56:41 +0300 Subject: [PATCH 4/6] Always translate type named "integer" to json schema "integer" --- src/collector/definitions.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/collector/definitions.js b/src/collector/definitions.js index 9b5c3a9..7fb1b6c 100644 --- a/src/collector/definitions.js +++ b/src/collector/definitions.js @@ -32,15 +32,17 @@ import {invariant} from '../utils'; function processTypeAlias(ctx: Context, node: TypeAlias | DeclareTypeAlias) { const {name} = node.id; - // Forward declaration for the recursive types - ctx.define(name, t.createAny()); + if (name != 'integer') { + // Forward declaration for the recursive types + ctx.define(name, t.createAny()); - const type = makeType(ctx, node.right); + const type = makeType(ctx, node.right); - // TODO: support function aliases. - invariant(type); + // TODO: support function aliases. + invariant(type); - ctx.define(name, type); + ctx.define(name, type); + } } // TODO: type params. @@ -282,6 +284,9 @@ function makeIntersection(ctx: Context, node: IntersectionTypeAnnotation): ?Type function makeReference(ctx: Context, node: GenericTypeAnnotation): ?Type { const {name} = node.id; + if (name == 'integer') { + return t.createNumber('i64'); + } const params = node.typeParameters && wu(node.typeParameters.params).map(n => makeType(ctx, n)).toArray(); From e5afdbcb580f98f6bae7b3c6b88755f0e15a753e Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Mon, 21 Oct 2019 20:00:31 +0300 Subject: [PATCH 5/6] Include leadingComments as $comment --- src/collector/declarations.js | 2 +- src/collector/definitions.js | 16 +++++++++++++++- src/generators/jsonSchema.js | 13 +++++++++++++ src/types.js | 1 + 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/collector/declarations.js b/src/collector/declarations.js index df22ccc..ad1af0d 100644 --- a/src/collector/declarations.js +++ b/src/collector/declarations.js @@ -166,8 +166,8 @@ function extractCommonjsNamedExternals<+T: Node>(nodes: T[], path: string): Exte function processExportNamedDeclaration(ctx: Context, node: ExportNamedDeclaration) { if (isDeclaration(node.declaration)) { + node.declaration.leadingComments = node.leadingComments; const reference = processDeclaration(ctx, node.declaration); - ctx.provide(reference, reference); } diff --git a/src/collector/definitions.js b/src/collector/definitions.js index 7fb1b6c..6916182 100644 --- a/src/collector/definitions.js +++ b/src/collector/definitions.js @@ -4,7 +4,7 @@ import wu from 'wu'; // @see flow#5376. import type { - ArrayTypeAnnotation, ClassDeclaration, ClassProperty, Comment, FlowTypeAnnotation, + Node, ArrayTypeAnnotation, ClassDeclaration, ClassProperty, Comment, FlowTypeAnnotation, GenericTypeAnnotation, InterfaceDeclaration, IntersectionTypeAnnotation, TypeAlias, UnionTypeAnnotation, NullableTypeAnnotation, ObjectTypeIndexer, ObjectTypeProperty, StringLiteralTypeAnnotation, ObjectTypeAnnotation, AnyTypeAnnotation, MixedTypeAnnotation, @@ -37,6 +37,7 @@ function processTypeAlias(ctx: Context, node: TypeAlias | DeclareTypeAlias) { ctx.define(name, t.createAny()); const type = makeType(ctx, node.right); + addComment(node, type); // TODO: support function aliases. invariant(type); @@ -45,6 +46,15 @@ function processTypeAlias(ctx: Context, node: TypeAlias | DeclareTypeAlias) { } } +function addComment(node: Node, type: Type) { + if (node.leadingComments) { + const cmt = node.leadingComments.map(c => c.value).join('\n').trim(); + if (cmt) { + type.comment = cmt; + } + } +} + // TODO: type params. function processInterfaceDeclaration( ctx: Context, @@ -52,6 +62,7 @@ function processInterfaceDeclaration( ) { const {name} = node.id; const type = makeType(ctx, node.body); + addComment(node, type); invariant(type); @@ -215,6 +226,7 @@ function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?Fie invariant(value); type = makeType(ctx, value); + addComment(node, type); } if (!type) { @@ -238,12 +250,14 @@ function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?Fie function makeMap(ctx: Context, node: ObjectTypeIndexer): ?MapType { const keys = makeType(ctx, node.key); const values = makeType(ctx, node.value); + addComment(node, values); return keys && values ? t.createMap(keys, values) : null; } function makeArray(ctx: Context, node: ArrayTypeAnnotation): ?ArrayType { const items = makeType(ctx, node.elementType); + addComment(node, items); return items != null ? t.createArray(items) : null; } diff --git a/src/generators/jsonSchema.js b/src/generators/jsonSchema.js index 9b4ce9c..293ed66 100644 --- a/src/generators/jsonSchema.js +++ b/src/generators/jsonSchema.js @@ -12,6 +12,7 @@ export type Schema = boolean | { id?: string, $ref?: string, $schema?: string, + $comment?: string, title?: string, description?: string, default?: mixed, @@ -45,6 +46,18 @@ export type Schema = boolean | { }; function convert(fund: Fund, type: ?Type): Schema { + let schema = convertType(fund, type); + if (type && type.comment) { + if (schema === true) { + schema = { $comment: type.comment }; + } else { + schema.$comment = type.comment; + } + } + return schema; +} + +function convertType(fund: Fund, type: ?Type): Schema { if (!type) { return { type: 'null', diff --git a/src/types.js b/src/types.js index 34b75d4..51458a8 100644 --- a/src/types.js +++ b/src/types.js @@ -21,6 +21,7 @@ export type TypeId = string[]; export type BaseType = { id?: TypeId, + comment?: string, }; export type RecordType = BaseType & { From 6fe28de2dc82c2b19c50bd580b36157799ed5875 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 23 Oct 2019 17:00:38 +0300 Subject: [PATCH 6/6] Translate null correctly when it is a part of a union type --- src/generators/jsonSchema.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/generators/jsonSchema.js b/src/generators/jsonSchema.js index 293ed66..2476cf1 100644 --- a/src/generators/jsonSchema.js +++ b/src/generators/jsonSchema.js @@ -103,13 +103,13 @@ function convertType(fund: Fund, type: ?Type): Schema { }; case 'union': const enumerate = wu(type.variants) - .filter(variant => variant.kind === 'literal') + .filter(variant => variant.kind === 'literal' && variant.value !== null) .map(literal => (literal: $FlowFixMe).value) .tap(value => invariant(value !== undefined)) .toArray(); const schemas = wu(type.variants) - .filter(variant => variant.kind !== 'literal') + .filter(variant => variant.kind !== 'literal' || variant.value === null) .map(variant => convert(fund, variant)) .toArray();