Skip to content

Commit

Permalink
fix: true and false can be unioned
Browse files Browse the repository at this point in the history
  • Loading branch information
plantain-00 committed May 4, 2018
1 parent 8257cbb commit 77cfac3
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 47 deletions.
6 changes: 5 additions & 1 deletion demo/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,9 @@
},
{
"type": "null"
},
{
"const": false
}
]
},
Expand Down Expand Up @@ -550,7 +553,8 @@
"enum": [
"foo",
"bar",
null
null,
false
]
},
"InterfaceExtends": {
Expand Down
4 changes: 2 additions & 2 deletions demo/cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ type TypeUnion4 =
typeUnionMember2: string;
}
type TypeUnion5 = TypeLiteral | Interface
type TypeUnion8 = 'foo' | 'bar' | null
type TypeUnion8 = 'foo' | 'bar' | null | false
type TypeUnion = {
typeUnionMember1: TypeUnion1;
typeUnionMember2: TypeUnion2;
typeUnionMember3: TypeUnion3;
typeUnionMember4: TypeUnion4;
typeUnionMember5: TypeUnion5;
typeUnionMember6: string | null;
typeUnionMember6: string | null | false;
typeUnionMember7: 'foo' | 'bar';
typeUnionMember8: TypeUnion8;
}
Expand Down
42 changes: 37 additions & 5 deletions demo/debug.json
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,36 @@
]
},
{
"kind": "string",
"kind": "union",
"name": "TypeUnion8",
"enums": [
"foo",
"bar",
null
"members": [
{
"kind": "enum",
"type": "string",
"name": "string",
"enums": [
"foo"
]
},
{
"kind": "enum",
"type": "string",
"name": "string",
"enums": [
"bar"
]
},
{
"kind": "null"
},
{
"kind": "enum",
"type": "boolean",
"name": "boolean",
"enums": [
false
]
}
]
},
{
Expand Down Expand Up @@ -301,6 +325,14 @@
},
{
"kind": "null"
},
{
"kind": "enum",
"type": "boolean",
"name": "boolean",
"enums": [
false
]
}
]
}
Expand Down
4 changes: 2 additions & 2 deletions online/variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ type TypeUnion4 =
typeUnionMember2: string;
}
type TypeUnion5 = TypeLiteral | Interface
type TypeUnion8 = 'foo' | 'bar' | null
type TypeUnion8 = 'foo' | 'bar' | null | false
type TypeUnion = {
typeUnionMember1: TypeUnion1;
typeUnionMember2: TypeUnion2;
typeUnionMember3: TypeUnion3;
typeUnionMember4: TypeUnion4;
typeUnionMember5: TypeUnion5;
typeUnionMember6: string | null;
typeUnionMember6: string | null | false;
typeUnionMember7: 'foo' | 'bar';
typeUnionMember8: TypeUnion8;
}
Expand Down
26 changes: 22 additions & 4 deletions src/json-schema-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,7 @@ function getJsonSchemaProperty(memberType: Type | ObjectModel | ArrayModel | Uni
} else if (memberType.kind === 'string') {
return getJsonSchemaPropertyOfString(memberType)
} else if (memberType.kind === 'union') {
return {
type: undefined,
anyOf: memberType.members.map(m => getJsonSchemaProperty(m))
}
return getJsonSchemaPropertyOfUnion(memberType as UnionModel)
} else if (memberType.kind === 'null') {
return {
type: 'null'
Expand All @@ -98,6 +95,27 @@ function getJsonSchemaProperty(memberType: Type | ObjectModel | ArrayModel | Uni
}
}

function getJsonSchemaPropertyOfUnion(memberType: UnionModel) {
if (memberType.members.every(m => m.kind === 'enum' || m.kind === 'null')) {
let enums: any[] = []
for (const member of memberType.members) {
if (member.kind === 'enum') {
enums = enums.concat(member.enums)
} else if (member.kind === 'null') {
enums.push(null)
}
}
return {
type: undefined,
enum: enums
}
}
return {
type: undefined,
anyOf: memberType.members.map(m => getJsonSchemaProperty(m))
}
}

function getJsonSchemaPropertyOfString(memberType: StringType) {
if (memberType.enums) {
if (memberType.enums.length === 1) {
Expand Down
92 changes: 65 additions & 27 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import {
NumberType,
StringType,
BooleanType,
ReferenceType
ReferenceType,
NumberModel,
StringModel
} from './utils'

export class Parser {
Expand Down Expand Up @@ -225,38 +227,45 @@ export class Parser {
}

private handleUnionTypeOfLiteralType(unionType: ts.UnionTypeNode, declarationName: ts.Identifier) {
let enumType: 'string' | 'number' | undefined
let enumType: 'string' | 'number' | 'boolean' | undefined
const enums: any[] = []
for (const childType of unionType.types) {
if (childType.kind === ts.SyntaxKind.LiteralType) {
const literalType = childType as ts.LiteralTypeNode
if (literalType.literal.kind === ts.SyntaxKind.StringLiteral) {
enumType = 'string'
enums.push(literalType.literal.text)
} else if (literalType.literal.kind === ts.SyntaxKind.NumericLiteral) {
enumType = 'number'
enums.push(+literalType.literal.text)
const { type, value } = this.getEnumOfLiteralType(childType as ts.LiteralTypeNode)
if (type !== undefined) {
enumType = type
}
if (value !== undefined) {
enums.push(value)
}
} else if (childType.kind === ts.SyntaxKind.NullKeyword) {
enums.push(null)
}
}
if (enumType) {
if (enumType === 'string') {
const model: Model = {
const model: StringModel = {
kind: enumType,
name: declarationName.text,
enums
}
this.models.push(model)
} else {
const model: Model = {
} else if (enumType === 'number') {
const model: NumberModel = {
kind: enumType,
type: enumType,
name: declarationName.text,
enums
}
this.models.push(model)
} else if (enumType === 'boolean') {
const model: Model = {
kind: 'union',
name: declarationName.text,
members: unionType.types.map(e => this.getType(e)),
entry: undefined
}
this.models.push(model)
}
}
}
Expand Down Expand Up @@ -362,15 +371,45 @@ export class Parser {
}
}

private getEnumOfLiteralType(literalType: ts.LiteralTypeNode): { type: 'string' | 'number' | 'boolean' | undefined, value: any } {
if (literalType.literal.kind === ts.SyntaxKind.StringLiteral) {
return {
type: 'string',
value: literalType.literal.text
}
}
if (literalType.literal.kind === ts.SyntaxKind.NumericLiteral) {
return {
type: 'number',
value: +literalType.literal.text
}
}
if (literalType.literal.kind === ts.SyntaxKind.TrueKeyword) {
return {
type: 'boolean',
value: true
}
} else if (literalType.literal.kind === ts.SyntaxKind.FalseKeyword) {
return {
type: 'boolean',
value: false
}
}
return {
type: undefined,
value: undefined
}
}

private getTypeOfLiteralType(literalType: ts.LiteralTypeNode): Type {
let enumType: 'string' | 'number' | undefined
let enumType: 'string' | 'number' | 'boolean' | undefined
const enums: any[] = []
if (literalType.literal.kind === ts.SyntaxKind.StringLiteral) {
enumType = 'string'
enums.push(literalType.literal.text)
} else if (literalType.literal.kind === ts.SyntaxKind.NumericLiteral) {
enumType = 'number'
enums.push(+literalType.literal.text)
const { type, value } = this.getEnumOfLiteralType(literalType)
if (type !== undefined) {
enumType = type
}
if (value !== undefined) {
enums.push(value)
}
if (enumType) {
return {
Expand All @@ -387,16 +426,15 @@ export class Parser {

private getTypeOfUnionType(unionType: ts.UnionTypeNode): Type {
if (unionType.types.every(u => u.kind === ts.SyntaxKind.LiteralType)) {
let enumType: 'string' | 'number' | undefined
let enumType: 'string' | 'number' | 'boolean' | undefined
const enums: any[] = []
for (const childType of unionType.types) {
const literalType = childType as ts.LiteralTypeNode
if (literalType.literal.kind === ts.SyntaxKind.StringLiteral) {
enumType = 'string'
enums.push(literalType.literal.text)
} else if (literalType.literal.kind === ts.SyntaxKind.NumericLiteral) {
enumType = 'number'
enums.push(+literalType.literal.text)
const { type, value } = this.getEnumOfLiteralType(childType as ts.LiteralTypeNode)
if (type !== undefined) {
enumType = type
}
if (value !== undefined) {
enums.push(value)
}
}
if (enumType) {
Expand Down
6 changes: 0 additions & 6 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,10 @@ export type UnionModel = UnionType & {
entry: string | undefined;
}

/**
* @public
*/
export type StringModel = StringType & {
name: string;
}

/**
* @public
*/
export type NumberModel = NumberType & {
name: string;
}
Expand Down

0 comments on commit 77cfac3

Please sign in to comment.