From a79c31113125e3d85a2b04d9386326a35659fd47 Mon Sep 17 00:00:00 2001 From: vitoo <32278696+vitoUwu@users.noreply.github.com> Date: Tue, 5 Nov 2024 12:59:31 -0400 Subject: [PATCH] JsDocs in anonymous types (#868) * fix: anonymous types jsdoc assign * fix: unix type name --- engine/schema/comments.ts | 36 ++++++- engine/schema/schemeable.test.ts | 135 +++++++++++++++++++++++++ engine/schema/schemeable.test.types.ts | 21 ++++ 3 files changed, 190 insertions(+), 2 deletions(-) diff --git a/engine/schema/comments.ts b/engine/schema/comments.ts index 41efb6856..8747264b5 100644 --- a/engine/schema/comments.ts +++ b/engine/schema/comments.ts @@ -30,9 +30,41 @@ export type Spannable = | ExportNamedDeclarationSpannable; const getChildren = (s: Spannable) => { - return (s as any)?.declaration?.body?.body ?? (s as any)?.body?.body ?? + const children = (s as any)?.declaration?.body?.body ?? + (s as any)?.body?.body ?? (s as ModuleSpannable)?.body ?? (s as ImportDeclarationSpannable)?.specifiers; + + if (children) { + return children; + } + + if ((s as any)?.type === "TsPropertySignature") { + const typeAnnotation = (s as any)?.typeAnnotation?.typeAnnotation as any; + if ( + typeAnnotation?.type === "TsTypeLiteral" && + typeAnnotation?.members?.length + ) { + return typeAnnotation.members; + } + + if ( + typeAnnotation?.type === "TsArrayType" && + typeAnnotation?.elemType?.type === "TsTypeLiteral" && + typeAnnotation?.elemType?.members?.length + ) { + return typeAnnotation.elemType.members; + } + + if ( + typeAnnotation?.type === "TsTypeReference" && + typeAnnotation?.typeName?.value === "Array" && + typeAnnotation?.typeParams?.params?.[0]?.type === "TsTypeLiteral" && + typeAnnotation?.typeParams?.params?.[0]?.members?.length + ) { + return typeAnnotation.typeParams.params[0].members; + } + } }; const isSpannableArray = (child: any): child is Spannable[] => { @@ -44,7 +76,7 @@ const isSpannableArray = (child: any): child is Spannable[] => { * This function allocate comments where it should be placed. * When a program is parsed all comments are ignored meaning that it will not be part of the code AST. * The problem is that we use comments to enrich JSONSchema based on the JsDoc attribute. - * As comments are treat as a separate array of strings containing only the information of which characeter it starts and ends (spannable). + * As comments are treat as a separate array of strings containing only the information of which character it starts and ends (spannable). * This code distribute it based on the span attribute of the comments, matching with the body span attribute. * * So it basically starts with all comments of the module, and then distribute it into body items, it recursively do the same thing inside a body item declaration if it is a TsInterface declaration, diff --git a/engine/schema/schemeable.test.ts b/engine/schema/schemeable.test.ts index 52accb482..c053bff73 100644 --- a/engine/schema/schemeable.test.ts +++ b/engine/schema/schemeable.test.ts @@ -896,3 +896,138 @@ Deno.test("Wellknown in types generation", async () => { assertSpyCalls(genId, 9); }); + +Deno.test("Anonymous types generation", async () => { + const transformed = await getSchemeableFor("WithAnonTypes"); + if (!transformed) { + fail("TypeAlias should exists"); + } + + const isWindows = Deno.build.os === "windows"; + // TODO: get name for unix systems + const cardName = isWindows ? "tl@1586-1845" : "tl@1516-1761"; + const buttonName = isWindows ? "tl@1698-1838" : "tl@1622-1755"; + + assertEquals(transformed, { + file: path, + name: "WithAnonTypes", + extends: [], + jsDocSchema: {}, + type: "object", + value: { + items: { + title: "Items", + jsDocSchema: { title: "Cards" }, + schemeable: { + file: path, + type: "array", + name: `[${cardName}]`, + value: { + file: path, + name: cardName, + type: "object", + value: { + title: { + title: "Title", + jsDocSchema: {}, + schemeable: { + type: "inline", + name: "string", + value: { type: "string" }, + }, + required: true, + }, + description: { + title: "Description", + jsDocSchema: { format: "rich-text" }, + schemeable: { + type: "inline", + name: "string", + value: { type: "string" }, + }, + required: true, + }, + buttons: { + title: "Buttons", + jsDocSchema: {}, + schemeable: { + type: "array", + name: `[${buttonName}]`, + file: path, + value: { + file: path, + name: buttonName, + type: "object", + value: { + label: { + title: "Label", + jsDocSchema: {}, + schemeable: { + type: "inline", + name: "string", + value: { type: "string" }, + }, + required: true, + }, + url: { + title: "Url", + jsDocSchema: { format: "url" }, + schemeable: { + type: "inline", + name: "string", + value: { type: "string" }, + }, + required: true, + }, + position: { + title: "Position", + jsDocSchema: {}, + schemeable: { + file: undefined, + type: "union", + name: "left|right|center", + value: [ + { + type: "inline", + name: "left", + value: { + type: "string", + const: "left", + default: "left", + }, + }, + { + type: "inline", + name: "right", + value: { + type: "string", + const: "right", + default: "right", + }, + }, + { + type: "inline", + name: "center", + value: { + type: "string", + const: "center", + default: "center", + }, + }, + ], + }, + required: true, + }, + }, + }, + }, + required: true, + }, + }, + }, + }, + required: true, + }, + }, + }); +}); diff --git a/engine/schema/schemeable.test.types.ts b/engine/schema/schemeable.test.types.ts index 605205025..212f4b4b0 100644 --- a/engine/schema/schemeable.test.types.ts +++ b/engine/schema/schemeable.test.types.ts @@ -63,3 +63,24 @@ export interface TypeWithExtendsOmit extends Omit { } export { type MyDataUriType } from "data:text/tsx,export interface MyDataUriType { a: string; };"; + +export interface WithAnonTypes { + /** + * @title Cards + */ + items: { + title: string; + /** + * @format rich-text + */ + description: string; + buttons: Array<{ + label: string; + /** + * @format url + */ + url: string; + position: "left" | "right" | "center"; + }>; + }[]; +}