From 7ef7a0d270ab4cbb330bb1f9313bedbc47156181 Mon Sep 17 00:00:00 2001 From: York Yao Date: Wed, 5 Jan 2022 20:07:26 +0800 Subject: [PATCH] feat: support keyof type --- demo/cases.gql | 1 + demo/cases.json | 10 ++- demo/cases.md | 1 + demo/cases.ml | 1 + demo/cases.mongoose.ts | 5 ++ demo/cases.proto | 1 + demo/cases.re | 1 + demo/cases.rs | 1 + demo/cases.ts | 1 + demo/debug.json | 195 ++++++++++++++++++++++------------------- demo/root-type.ts | 1 + demo/typescript.ts | 1 + online/variables.ts | 1 + src/parser.ts | 17 ++++ 14 files changed, 147 insertions(+), 90 deletions(-) diff --git a/demo/cases.gql b/demo/cases.gql index 9e4db16..e07e7a7 100644 --- a/demo/cases.gql +++ b/demo/cases.gql @@ -242,6 +242,7 @@ type EntryType { template3: String! template4: String! template5: String! + keyof: String! } type Mutation { diff --git a/demo/cases.json b/demo/cases.json index 6bef35b..5e78967 100644 --- a/demo/cases.json +++ b/demo/cases.json @@ -151,6 +151,13 @@ "template5": { "type": "string", "pattern": "^\\/api\\/users\\?isAdmin=true|false$" + }, + "keyof": { + "type": "string", + "enum": [ + "member1", + "member2" + ] } }, "required": [ @@ -186,7 +193,8 @@ "template2", "template3", "template4", - "template5" + "template5", + "keyof" ], "additionalProperties": true }, diff --git a/demo/cases.md b/demo/cases.md index d98f59c..39309f2 100644 --- a/demo/cases.md +++ b/demo/cases.md @@ -344,6 +344,7 @@ Field | Required | Type | Description `template3` | `true` | ``/api/users/${number}`` | `template4` | `true` | ``https://${string}.${"png" | "jpg"}`` | `template5` | `true` | ``/api/users?isAdmin=${boolean}`` | +`keyof` | `true` | `"member1" | "member2"` | ## `Mutation` diff --git a/demo/cases.ml b/demo/cases.ml index 7ca6010..1552543 100644 --- a/demo/cases.ml +++ b/demo/cases.ml @@ -233,6 +233,7 @@ type entryType = { template3: string; template4: string; template5: string; + keyof: string; } type mutation = { diff --git a/demo/cases.mongoose.ts b/demo/cases.mongoose.ts index ca687d0..33ded71 100644 --- a/demo/cases.mongoose.ts +++ b/demo/cases.mongoose.ts @@ -827,6 +827,11 @@ export const entryTypeSchema = { type: String, required: true }, + keyof: { + type: Schema.Types.Mixed, + required: true, + enum: ["member1", "member2"] + }, } export const mutationSchema = { diff --git a/demo/cases.proto b/demo/cases.proto index bba3bc2..947223e 100644 --- a/demo/cases.proto +++ b/demo/cases.proto @@ -240,6 +240,7 @@ message EntryType { string template3 = 33; string template4 = 34; string template5 = 35; + string keyof = 36; } message Mutation { diff --git a/demo/cases.re b/demo/cases.re index 3a5baf4..79fcbc9 100644 --- a/demo/cases.re +++ b/demo/cases.re @@ -263,6 +263,7 @@ type entryType = { template3: string, template4: string, template5: string, + keyof: string, }; type mutation = { diff --git a/demo/cases.rs b/demo/cases.rs index acb20fa..5536f6e 100644 --- a/demo/cases.rs +++ b/demo/cases.rs @@ -307,6 +307,7 @@ pub struct EntryType { #[serde(rename = "template3")] pub template_3: String, #[serde(rename = "template4")] pub template_4: String, #[serde(rename = "template5")] pub template_5: String, + pub keyof: String, } #[derive(Serialize, Deserialize, Debug)] diff --git a/demo/cases.ts b/demo/cases.ts index a7c2cd5..32506c5 100644 --- a/demo/cases.ts +++ b/demo/cases.ts @@ -365,6 +365,7 @@ export type EntryType = { template3: `/api/users/${number}` template4: `https://${string}.${'png' | 'jpg'}` template5: `/api/users?isAdmin=${boolean}` + keyof: keyof CreateInput2 } export interface Mutation { diff --git a/demo/debug.json b/demo/debug.json index b0dd7d6..f8dbda0 100644 --- a/demo/debug.json +++ b/demo/debug.json @@ -3142,10 +3142,27 @@ "character": 13 } } + }, + { + "name": "keyof", + "type": { + "kind": "enum", + "type": "string", + "name": "string", + "enums": [ + "member1", + "member2" + ], + "position": { + "file": "demo/cases.ts", + "line": 367, + "character": 9 + } + } } ], - "minProperties": 33, - "maxProperties": 35, + "minProperties": 34, + "maxProperties": 36, "additionalProperties": true, "entry": "cases.json", "position": { @@ -3168,7 +3185,7 @@ "name": "MutationResult", "position": { "file": "demo/cases.ts", - "line": 370, + "line": 371, "character": 38 } }, @@ -3180,7 +3197,7 @@ "name": "CreateInput", "position": { "file": "demo/cases.ts", - "line": 370, + "line": 371, "character": 16 } }, @@ -3193,7 +3210,7 @@ "maxProperties": 0, "position": { "file": "demo/cases.ts", - "line": 369, + "line": 370, "character": 0 } }, @@ -3207,7 +3224,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 374, + "line": 375, "character": 11 } } @@ -3218,7 +3235,7 @@ "kind": "file", "position": { "file": "demo/cases.ts", - "line": 375, + "line": 376, "character": 11 } } @@ -3230,7 +3247,7 @@ "name": "CreateInputMember3", "position": { "file": "demo/cases.ts", - "line": 376, + "line": 377, "character": 11 } } @@ -3240,7 +3257,7 @@ "maxProperties": 3, "position": { "file": "demo/cases.ts", - "line": 373, + "line": 374, "character": 0 } }, @@ -3254,7 +3271,7 @@ "kind": "boolean", "position": { "file": "demo/cases.ts", - "line": 380, + "line": 381, "character": 10 } } @@ -3264,7 +3281,7 @@ "maxProperties": 1, "position": { "file": "demo/cases.ts", - "line": 379, + "line": 380, "character": 0 } }, @@ -3279,7 +3296,7 @@ "name": "GetResult", "position": { "file": "demo/cases.ts", - "line": 384, + "line": 385, "character": 29 } }, @@ -3290,7 +3307,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 384, + "line": 385, "character": 20 } }, @@ -3305,7 +3322,7 @@ "name": "GetResult", "position": { "file": "demo/cases.ts", - "line": 385, + "line": 386, "character": 20 } }, @@ -3316,7 +3333,7 @@ "maxProperties": 0, "position": { "file": "demo/cases.ts", - "line": 383, + "line": 384, "character": 0 } }, @@ -3331,7 +3348,7 @@ "name": "Result", "position": { "file": "demo/cases.ts", - "line": 389, + "line": 390, "character": 10 } } @@ -3341,7 +3358,7 @@ "maxProperties": 1, "position": { "file": "demo/cases.ts", - "line": 388, + "line": 389, "character": 0 } }, @@ -3355,7 +3372,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 393, + "line": 394, "character": 11 } } @@ -3366,7 +3383,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 395, + "line": 396, "character": 26 } }, @@ -3377,7 +3394,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 395, + "line": 396, "character": 17 } }, @@ -3390,7 +3407,7 @@ "maxProperties": 1, "position": { "file": "demo/cases.ts", - "line": 392, + "line": 393, "character": 0 } }, @@ -3404,7 +3421,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 399, + "line": 400, "character": 11 } } @@ -3414,7 +3431,7 @@ "maxProperties": 1, "position": { "file": "demo/cases.ts", - "line": 398, + "line": 399, "character": 0 } }, @@ -3429,7 +3446,7 @@ "name": "Result2", "position": { "file": "demo/cases.ts", - "line": 403, + "line": 404, "character": 10 } } @@ -3439,7 +3456,7 @@ "maxProperties": 1, "position": { "file": "demo/cases.ts", - "line": 402, + "line": 403, "character": 0 } }, @@ -3449,7 +3466,7 @@ "name": "Result3", "position": { "file": "demo/cases.ts", - "line": 406, + "line": 407, "character": 0 } }, @@ -3463,7 +3480,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 409, + "line": 410, "character": 11 } } @@ -3473,7 +3490,7 @@ "maxProperties": 1, "position": { "file": "demo/cases.ts", - "line": 408, + "line": 409, "character": 0 } }, @@ -3488,7 +3505,7 @@ "type": "number", "position": { "file": "demo/cases.ts", - "line": 413, + "line": 414, "character": 7 } }, @@ -3500,7 +3517,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 414, + "line": 415, "character": 8 } } @@ -3513,13 +3530,13 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 415, + "line": 416, "character": 13 } }, "position": { "file": "demo/cases.ts", - "line": 415, + "line": 416, "character": 13 } } @@ -3537,7 +3554,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 416, + "line": 417, "character": 10 } } @@ -3547,7 +3564,7 @@ "maxProperties": 4, "position": { "file": "demo/cases.ts", - "line": 412, + "line": 413, "character": 0 } }, @@ -3559,7 +3576,7 @@ "name": "Pet", "position": { "file": "demo/cases.ts", - "line": 453, + "line": 454, "character": 11 } }, @@ -3577,7 +3594,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 431, + "line": 432, "character": 10 } }, @@ -3595,13 +3612,13 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 436, + "line": 437, "character": 8 } }, "position": { "file": "demo/cases.ts", - "line": 436, + "line": 437, "character": 8 }, "minItems": 1 @@ -3619,7 +3636,7 @@ "name": "Pet", "position": { "file": "demo/cases.ts", - "line": 440, + "line": 441, "character": 7 } }, @@ -3636,7 +3653,7 @@ "type": "integer", "position": { "file": "demo/cases.ts", - "line": 447, + "line": 448, "character": 6 }, "default": 2, @@ -3661,7 +3678,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 452, + "line": 453, "character": 12 }, "default": "asc" @@ -3696,7 +3713,7 @@ "name": "ObjectId", "position": { "file": "demo/cases.ts", - "line": 458, + "line": 459, "character": 12 } } @@ -3708,7 +3725,7 @@ "name": "Date", "position": { "file": "demo/cases.ts", - "line": 459, + "line": 460, "character": 8 } } @@ -3720,7 +3737,7 @@ "name": "Decimal128", "position": { "file": "demo/cases.ts", - "line": 460, + "line": 461, "character": 14 } } @@ -3731,7 +3748,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 464, + "line": 465, "character": 10 } }, @@ -3746,7 +3763,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 468, + "line": 469, "character": 10 } }, @@ -3761,7 +3778,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 477, + "line": 478, "character": 10 }, "lowercase": true, @@ -3782,7 +3799,7 @@ "name": "Buffer", "position": { "file": "demo/cases.ts", - "line": 478, + "line": 479, "character": 10 } } @@ -3792,7 +3809,7 @@ "maxProperties": 7, "position": { "file": "demo/cases.ts", - "line": 457, + "line": 458, "character": 0 } }, @@ -3806,7 +3823,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 484, + "line": 485, "character": 20 } } @@ -3817,7 +3834,7 @@ "kind": "file", "position": { "file": "demo/cases.ts", - "line": 484, + "line": 485, "character": 20 } } @@ -3827,7 +3844,7 @@ "maxProperties": 2, "position": { "file": "demo/cases.ts", - "line": 484, + "line": 485, "character": 20 } }, @@ -3841,13 +3858,13 @@ "name": "Metadata", "position": { "file": "demo/cases.ts", - "line": 487, + "line": 488, "character": 22 } }, "position": { "file": "demo/cases.ts", - "line": 486, + "line": 487, "character": 0 } }, @@ -3859,13 +3876,13 @@ "additionalProperties": { "position": { "file": "demo/cases.ts", - "line": 491, + "line": 492, "character": 17 } }, "position": { "file": "demo/cases.ts", - "line": 490, + "line": 491, "character": 0 } }, @@ -3878,7 +3895,7 @@ "name": "CreateBlog", "position": { "file": "demo/cases.ts", - "line": 495, + "line": 496, "character": 4 } }, @@ -3887,14 +3904,14 @@ "name": "UpdateBlog", "position": { "file": "demo/cases.ts", - "line": 496, + "line": 497, "character": 4 } } ], "position": { "file": "demo/cases.ts", - "line": 494, + "line": 495, "character": 12 }, "objectType": { @@ -3913,7 +3930,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 505, + "line": 506, "character": 8 } } @@ -3924,7 +3941,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 506, + "line": 507, "character": 11 } } @@ -3936,7 +3953,7 @@ "type": "number", "position": { "file": "demo/cases.ts", - "line": 514, + "line": 515, "character": 6 } }, @@ -3947,7 +3964,7 @@ "maxProperties": 3, "position": { "file": "demo/cases.ts", - "line": 494, + "line": 495, "character": 12 } } @@ -3967,7 +3984,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 505, + "line": 506, "character": 8 } } @@ -3978,7 +3995,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 506, + "line": 507, "character": 11 } } @@ -3988,7 +4005,7 @@ "maxProperties": 2, "position": { "file": "demo/cases.ts", - "line": 504, + "line": 505, "character": 0 }, "comments": [ @@ -4010,7 +4027,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 513, + "line": 514, "character": 8 } } @@ -4022,7 +4039,7 @@ "type": "number", "position": { "file": "demo/cases.ts", - "line": 514, + "line": 515, "character": 6 } } @@ -4033,7 +4050,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 515, + "line": 516, "character": 11 } } @@ -4043,7 +4060,7 @@ "maxProperties": 3, "position": { "file": "demo/cases.ts", - "line": 512, + "line": 513, "character": 0 }, "comments": [ @@ -4059,14 +4076,14 @@ "name": "BlogChange", "position": { "file": "demo/cases.ts", - "line": 499, + "line": 500, "character": 4 } } ], "position": { "file": "demo/cases.ts", - "line": 498, + "line": 499, "character": 12 }, "objectType": { @@ -4084,7 +4101,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 522, + "line": 523, "character": 8 } } @@ -4096,7 +4113,7 @@ "type": "number", "position": { "file": "demo/cases.ts", - "line": 523, + "line": 524, "character": 6 } } @@ -4107,7 +4124,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 524, + "line": 525, "character": 11 } } @@ -4117,7 +4134,7 @@ "maxProperties": 3, "position": { "file": "demo/cases.ts", - "line": 498, + "line": 499, "character": 12 } } @@ -4137,7 +4154,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 522, + "line": 523, "character": 8 } } @@ -4149,7 +4166,7 @@ "type": "number", "position": { "file": "demo/cases.ts", - "line": 523, + "line": 524, "character": 6 } } @@ -4160,7 +4177,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 524, + "line": 525, "character": 11 } } @@ -4170,7 +4187,7 @@ "maxProperties": 3, "position": { "file": "demo/cases.ts", - "line": 521, + "line": 522, "character": 0 }, "comments": [ @@ -4186,7 +4203,7 @@ "type": { "position": { "file": "demo/cases.ts", - "line": 529, + "line": 530, "character": 2 } }, @@ -4210,7 +4227,7 @@ "type": "number", "position": { "file": "demo/cases.ts", - "line": 532, + "line": 533, "character": 23 } }, @@ -4230,7 +4247,7 @@ "kind": "string", "position": { "file": "demo/cases.ts", - "line": 533, + "line": 534, "character": 23 } }, @@ -4251,7 +4268,7 @@ "maxProperties": 0, "position": { "file": "demo/cases.ts", - "line": 527, + "line": 528, "character": 0 }, "decorators": [ @@ -4274,7 +4291,7 @@ ], "position": { "file": "demo/cases.ts", - "line": 538, + "line": 539, "character": 5 } }, @@ -4285,7 +4302,7 @@ "kind": "file", "position": { "file": "demo/cases.ts", - "line": 544, + "line": 545, "character": 48 } }, @@ -4304,7 +4321,7 @@ "kind": "void", "position": { "file": "demo/cases.ts", - "line": 550, + "line": 551, "character": 47 } }, @@ -4323,7 +4340,7 @@ "kind": "void", "position": { "file": "demo/cases.ts", - "line": 561, + "line": 562, "character": 12 } }, @@ -4335,7 +4352,7 @@ "kind": "file", "position": { "file": "demo/cases.ts", - "line": 560, + "line": 561, "character": 9 } }, diff --git a/demo/root-type.ts b/demo/root-type.ts index adfc752..dd1e84f 100644 --- a/demo/root-type.ts +++ b/demo/root-type.ts @@ -257,6 +257,7 @@ export interface EntryType { template3: string template4: string template5: string + keyof: string } export interface CreateInput { diff --git a/demo/typescript.ts b/demo/typescript.ts index 927fc5d..382a2b0 100644 --- a/demo/typescript.ts +++ b/demo/typescript.ts @@ -343,6 +343,7 @@ interface EntryType { template3: `/api/users/${number}` template4: `https://${string}.${"png" | "jpg"}` template5: `/api/users?isAdmin=${boolean}` + keyof: "member1" | "member2" [name: string]: unknown } diff --git a/online/variables.ts b/online/variables.ts index 74ff3e5..deb286e 100644 --- a/online/variables.ts +++ b/online/variables.ts @@ -374,6 +374,7 @@ export type EntryType = { template3: \`/api/users/\${number}\` template4: \`https://\${string}.\${'png' | 'jpg'}\` template5: \`/api/users?isAdmin=\${boolean}\` + keyof: keyof CreateInput2 } export interface Mutation { diff --git a/src/parser.ts b/src/parser.ts index fae86b8..5abace4 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -587,6 +587,23 @@ export class Parser { position: this.getPosition(type, sourceFile), } } + if (ts.isParenthesizedTypeNode(type)) { + return this.getType(type.type, sourceFile) + } + if (ts.isTypeOperatorNode(type)) { + if (type.operator === ts.SyntaxKind.KeyOfKeyword && ts.isTypeReferenceNode(type.type)) { + const objectType = this.getTypeOfComplexType(type.type, sourceFile) + if (objectType) { + return { + kind: 'enum', + type: 'string', + name: 'string', + enums: objectType.members.map((m) => m.name), + position: this.getPosition(type, sourceFile), + } + } + } + } const position = this.getPosition(type, sourceFile) if (type.kind !== ts.SyntaxKind.AnyKeyword && !this.disableWarning) { warn(position, 'parser')