From 8eb6644c1cb34f2a98ddc6f5a51cd7e75c59a584 Mon Sep 17 00:00:00 2001 From: Luv Kapur Date: Wed, 18 Sep 2024 19:57:40 -0400 Subject: [PATCH] feat(schema): add ability to view complete signature of every api node including docs (#9206) --- .../entities/semantic-schema/api-schema.ts | 50 ++++++++++++++++- .../entities/semantic-schema/schema-node.ts | 6 +- .../schemas/array-literal-expression.ts | 5 ++ .../entities/semantic-schema/schemas/class.ts | 56 +++++++++++++++++-- .../schemas/conditional-type.ts | 9 +++ .../semantic-schema/schemas/decorator.ts | 15 ++++- .../semantic-schema/schemas/docs/doc.ts | 20 +++++++ .../schemas/docs/property-like-tag.ts | 6 ++ .../schemas/docs/return-tag.ts | 6 ++ .../semantic-schema/schemas/docs/tag.ts | 4 ++ .../semantic-schema/schemas/enum-member.ts | 16 ++++++ .../entities/semantic-schema/schemas/enum.ts | 30 +++++++++- .../semantic-schema/schemas/export.ts | 46 +++++++++++++-- .../schemas/expression-with-arguments.ts | 11 ++++ .../semantic-schema/schemas/function-like.ts | 41 ++++++++++++-- .../semantic-schema/schemas/get-accessor.ts | 17 +++++- .../semantic-schema/schemas/ignored.ts | 4 ++ .../schemas/index-signature.ts | 7 +++ .../schemas/indexed-access-type.ts | 7 +++ .../semantic-schema/schemas/inference-type.ts | 16 ++++++ .../semantic-schema/schemas/interface.ts | 44 ++++++++++++++- .../semantic-schema/schemas/keyword-type.ts | 4 ++ .../semantic-schema/schemas/literal-type.ts | 4 ++ .../semantic-schema/schemas/literal-value.ts | 4 ++ .../semantic-schema/schemas/module.ts | 30 ++++++++-- .../semantic-schema/schemas/named-tuple.ts | 8 ++- .../schemas/object-literal-expression.ts | 13 ++++- .../semantic-schema/schemas/parameter.ts | 40 +++++++++++++ .../schemas/parenthesized-type.ts | 8 ++- .../schemas/property-assignment.ts | 18 +++++- .../semantic-schema/schemas/set-accessor.ts | 5 ++ .../schemas/template-literal-type-span.ts | 8 ++- .../schemas/template-literal-type.ts | 9 ++- .../semantic-schema/schemas/this-type.ts | 4 ++ .../semantic-schema/schemas/tuple-type.ts | 8 ++- .../semantic-schema/schemas/type-array.ts | 8 ++- .../schemas/type-intersection.ts | 8 ++- .../semantic-schema/schemas/type-literal.ts | 22 ++++++++ .../semantic-schema/schemas/type-operator.ts | 8 ++- .../semantic-schema/schemas/type-predicate.ts | 17 +++++- .../semantic-schema/schemas/type-query.ts | 8 ++- .../semantic-schema/schemas/type-ref.ts | 29 ++++++++-- .../semantic-schema/schemas/type-union.ts | 15 ++++- .../entities/semantic-schema/schemas/type.ts | 18 +++++- .../schemas/unimplemented-schema.ts | 4 ++ .../semantic-schema/schemas/unknown-schema.ts | 4 ++ .../schemas/unresolved-schema.ts | 4 ++ .../semantic-schema/schemas/variable-like.ts | 22 +++++++- scopes/react/react/react.schema.ts | 26 +++++++-- 49 files changed, 703 insertions(+), 69 deletions(-) diff --git a/components/entities/semantic-schema/api-schema.ts b/components/entities/semantic-schema/api-schema.ts index 3355dcc24322..a5e96e698531 100644 --- a/components/entities/semantic-schema/api-schema.ts +++ b/components/entities/semantic-schema/api-schema.ts @@ -78,7 +78,7 @@ export class APISchema extends SchemaNode { return ''; } - return `${chalk.green.bold(sectionName)}\n${objects.map((c) => c.toString()).join('\n')}\n\n`; + return `${chalk.green.bold(sectionName)}\n${objects.map((c) => c.toString({ color: true })).join('\n')}\n\n`; }; return ( @@ -95,6 +95,54 @@ export class APISchema extends SchemaNode { ); } + toFullSignature(options: { showDocs?: boolean; showTitles?: boolean } = { showDocs: true }): string { + const title = `API Schema of ${this.componentId.toString()}\n\n`; + + const exportGroups: { [key: string]: SchemaNode[] } = {}; + + for (const exp of this.module.exports) { + const node = ExportSchema.isExportSchema(exp) ? exp.exportNode : exp; + const constructorName = node.constructor.name; + + if (!exportGroups[constructorName]) { + exportGroups[constructorName] = []; + } + + exportGroups[constructorName].push(exp); + } + + let output = options.showTitles ? title : ''; + + for (const [sectionName, exports] of Object.entries(exportGroups)) { + const readableSectionName = options.showTitles ? this.getReadableSectionName(sectionName) : ''; + + output += `${readableSectionName}\n\n`; + + const sectionBody = exports.map((exp) => exp.toFullSignature(options)).join('\n\n'); + + output += `${sectionBody}\n\n`; + } + + return output.trim(); + } + + private getReadableSectionName(constructorName: string): string { + const sectionNameMap: { [key: string]: string } = { + ModuleSchema: 'Namespaces', + ClassSchema: 'Classes', + InterfaceSchema: 'Interfaces', + FunctionLikeSchema: 'Functions', + VariableLikeSchema: 'Variables', + TypeSchema: 'Types', + EnumSchema: 'Enums', + TypeRefSchema: 'Type References', + UnresolvedSchema: 'Unresolved', + ReactSchema: 'React Components', + }; + + return sectionNameMap[constructorName] || constructorName; + } + listSignatures() { return this.module.exports.map((exp) => exp.signature); } diff --git a/components/entities/semantic-schema/schema-node.ts b/components/entities/semantic-schema/schema-node.ts index 69b04f8003d0..914ff13e72f7 100644 --- a/components/entities/semantic-schema/schema-node.ts +++ b/components/entities/semantic-schema/schema-node.ts @@ -8,7 +8,8 @@ export interface ISchemaNode { signature?: string; name?: string; toObject(): Record; - toString(): string; + toString(options?: { color?: boolean }): string; + toFullSignature(options?: { showDocs?: boolean }): string; getNodes(): SchemaNode[]; findNode(predicate: (node: SchemaNode) => boolean, visitedNodes?: Set): SchemaNode | undefined; getAllNodesRecursively(visitedNodes?: Set): SchemaNode[]; @@ -44,7 +45,8 @@ export abstract class SchemaNode implements ISchemaNode { ); } - abstract toString(): string; + abstract toString(options?: { color?: boolean }): string; + abstract toFullSignature(options?: { showDocs?: boolean }): string; getNodes(): SchemaNode[] { return [this]; diff --git a/components/entities/semantic-schema/schemas/array-literal-expression.ts b/components/entities/semantic-schema/schemas/array-literal-expression.ts index c4e189b4e8fe..f25cb99569d2 100644 --- a/components/entities/semantic-schema/schemas/array-literal-expression.ts +++ b/components/entities/semantic-schema/schemas/array-literal-expression.ts @@ -22,4 +22,9 @@ export class ArrayLiteralExpressionSchema extends SchemaNode { toString(): string { return `[${this.members.join(', ')}]`; } + + toFullSignature(options?: { showDocs?: boolean }): string { + const membersStr = this.members.map((member) => member.toFullSignature(options)).join(', '); + return `[${membersStr}]`; + } } diff --git a/components/entities/semantic-schema/schemas/class.ts b/components/entities/semantic-schema/schemas/class.ts index 52dbf60b7ce6..046130e068f8 100644 --- a/components/entities/semantic-schema/schemas/class.ts +++ b/components/entities/semantic-schema/schemas/class.ts @@ -28,10 +28,58 @@ export class ClassSchema extends SchemaNode { return this.members; } - toString() { - const membersStr = this.members.map((m) => `* ${m.toString()}`).join('\n'); - const decoratorsStr = this.decorators?.map((decorator) => decorator.toString()).join('\n'); - return `${this.decorators ? `${decoratorsStr}\n` : ''}${chalk.bold.underline(this.name)}\n${membersStr}`; + toString(options?: { color?: boolean }): string { + const boldUnderline = options?.color ? chalk.bold.underline : (str: string) => str; + const membersStr = this.members.map((m) => `* ${m.toString(options)}`).join('\n'); + const decoratorsStr = this.decorators?.map((decorator) => decorator.toString(options)).join('\n'); + return `${this.decorators ? `${decoratorsStr}\n` : ''}${boldUnderline(this.name)}\n${membersStr}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + let result = ''; + + if (options?.showDocs && this.doc) { + result += `${this.doc.toFullSignature()}\n`; + } + + const decoratorsStr = this.decorators?.map((decorator) => decorator.toFullSignature(options)).join('\n'); + if (decoratorsStr) { + result += `${decoratorsStr}\n`; + } + + let classDeclaration = `class ${this.name}`; + + if (this.typeParams && this.typeParams.length > 0) { + classDeclaration += `<${this.typeParams.join(', ')}>`; + } + + if (this.extendsNodes && this.extendsNodes.length > 0) { + const extendsStr = this.extendsNodes.map((node) => node.toFullSignature(options)).join(', '); + classDeclaration += ` extends ${extendsStr}`; + } + + if (this.implementNodes && this.implementNodes.length > 0) { + const implementsStr = this.implementNodes.map((node) => node.toFullSignature(options)).join(', '); + classDeclaration += ` implements ${implementsStr}`; + } + + result += `${classDeclaration} {\n`; + + const membersStr = this.members + .map((member) => { + const memberStr = member.toFullSignature(options); + return memberStr + .split('\n') + .map((line) => ` ${line}`) + .join('\n'); + }) + .join('\n'); + + result += `${membersStr}\n`; + + result += `}`; + + return result; } toObject() { diff --git a/components/entities/semantic-schema/schemas/conditional-type.ts b/components/entities/semantic-schema/schemas/conditional-type.ts index e10fa8342626..78328c0672e9 100644 --- a/components/entities/semantic-schema/schemas/conditional-type.ts +++ b/components/entities/semantic-schema/schemas/conditional-type.ts @@ -33,6 +33,15 @@ export class ConditionalTypeSchema extends SchemaNode { return `${this.checkType.toString()} extends ${this.extendsType.toString()} ? ${this.trueType.toString()} : ${this.falseType.toString()}`; } + toFullSignature(options?: { showDocs?: boolean }): string { + const checkTypeStr = this.checkType.toFullSignature(options); + const extendsTypeStr = this.extendsType.toFullSignature(options); + const trueTypeStr = this.trueType.toFullSignature(options); + const falseTypeStr = this.falseType.toFullSignature(options); + + return `${checkTypeStr} extends ${extendsTypeStr} ? ${trueTypeStr} : ${falseTypeStr}`; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/decorator.ts b/components/entities/semantic-schema/schemas/decorator.ts index c8e730018d6b..4d46a006205e 100644 --- a/components/entities/semantic-schema/schemas/decorator.ts +++ b/components/entities/semantic-schema/schemas/decorator.ts @@ -17,11 +17,24 @@ export class DecoratorSchema extends SchemaNode { } toString() { - // name and args const argsStr = this.args?.map((arg) => arg.toString()).join(', '); return `@${this.name}${argsStr ? `(${argsStr})` : ''}`; } + toFullSignature(options?: { showDocs?: boolean }): string { + let result = ''; + + if (options?.showDocs && this.doc) { + result += `${this.doc.toFullSignature()}\n`; + } + + const argsStr = this.args?.map((arg) => arg.toFullSignature(options)).join(', '); + + result += `@${this.name}${argsStr ? `(${argsStr})` : ''}`; + + return result; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/docs/doc.ts b/components/entities/semantic-schema/schemas/docs/doc.ts index 755031555057..ecbc45948c7a 100644 --- a/components/entities/semantic-schema/schemas/docs/doc.ts +++ b/components/entities/semantic-schema/schemas/docs/doc.ts @@ -16,6 +16,26 @@ export class DocSchema extends SchemaNode { return `${comment}${tags}`; } + toFullSignature(): string { + const lines: string[] = []; + + if (this.comment) { + lines.push(...this.comment.split('\n').map((line) => ` * ${line.trim()}`)); + } + + if (this.tags && this.tags.length > 0) { + for (const tag of this.tags) { + lines.push(` * ${tag.toString().trim()}`); + } + } + + if (lines.length === 0) { + return ''; + } + + return `/**\n${lines.join('\n')}\n */`; + } + hasTag(tagName: TagName) { return Boolean(this.findTag(tagName)); } diff --git a/components/entities/semantic-schema/schemas/docs/property-like-tag.ts b/components/entities/semantic-schema/schemas/docs/property-like-tag.ts index 2c5c6d2f4f51..1e0db54a98b3 100644 --- a/components/entities/semantic-schema/schemas/docs/property-like-tag.ts +++ b/components/entities/semantic-schema/schemas/docs/property-like-tag.ts @@ -18,6 +18,12 @@ export class PropertyLikeTagSchema extends TagSchema { return `@${this.tagName} ${this.name}${type} ${comment}`; } + toFullSignature(options?: { showDocs?: boolean }): string { + const typeStr = this.type ? ` {${this.type.toFullSignature(options)}} ` : ''; + const comment = this.comment ? ` ${this.comment}` : ''; + return `@${this.tagName} ${this.name}${typeStr}${comment}`; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/docs/return-tag.ts b/components/entities/semantic-schema/schemas/docs/return-tag.ts index c3f3b6d1263a..30617fcc7ca2 100644 --- a/components/entities/semantic-schema/schemas/docs/return-tag.ts +++ b/components/entities/semantic-schema/schemas/docs/return-tag.ts @@ -18,6 +18,12 @@ export class ReturnTagSchema extends TagSchema { return `@${this.tagName}${comment}`; } + toFullSignature(options?: { showDocs?: boolean }): string { + const typeStr = this.type ? ` {${this.type.toFullSignature(options)}}` : ''; + const comment = this.comment ? ` ${this.comment}` : ''; + return `@${this.tagName}${typeStr}${comment}`; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/docs/tag.ts b/components/entities/semantic-schema/schemas/docs/tag.ts index e1124697a852..d00d1fb1e1d9 100644 --- a/components/entities/semantic-schema/schemas/docs/tag.ts +++ b/components/entities/semantic-schema/schemas/docs/tag.ts @@ -13,6 +13,10 @@ export class TagSchema extends SchemaNode { return `@${this.tagName}${comment}`; } + toFullSignature(): string { + return this.toString(); + } + static fromObject(obj: Record): TagSchema { const location = obj.location; const tagName = obj.tagName; diff --git a/components/entities/semantic-schema/schemas/enum-member.ts b/components/entities/semantic-schema/schemas/enum-member.ts index c68812a8b478..96ad291a3509 100644 --- a/components/entities/semantic-schema/schemas/enum-member.ts +++ b/components/entities/semantic-schema/schemas/enum-member.ts @@ -20,6 +20,22 @@ export class EnumMemberSchema extends SchemaNode { return `${this.name}=${this.value}`; } + toFullSignature(options?: { showDocs?: boolean }): string { + let result = ''; + + if (options?.showDocs && this.doc) { + result += `${this.doc.toFullSignature()}\n`; + } + + if (this.value !== undefined) { + result += `${this.name} = ${this.value}`; + } else { + result += `${this.name}`; + } + + return result; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/enum.ts b/components/entities/semantic-schema/schemas/enum.ts index 2754fced9d4d..704f923c80b3 100644 --- a/components/entities/semantic-schema/schemas/enum.ts +++ b/components/entities/semantic-schema/schemas/enum.ts @@ -23,9 +23,33 @@ export class EnumSchema extends SchemaNode { return this.members; } - toString() { - const membersStr = this.members.map((m) => `* ${m.toString()}`).join('\n'); - return `${chalk.bold.underline(this.name)}\n${membersStr}`; + toString(options) { + const boldUnderline = options?.color ? chalk.bold.underline : (str: string) => str; + const membersStr = this.members.map((m) => `* ${m.toString(options)}`).join('\n'); + return `${boldUnderline(this.name)}\n${membersStr}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + let result = ''; + + if (options?.showDocs && this.doc) { + result += `${this.doc.toFullSignature()}\n`; + } + + result += `enum ${this.name} {\n`; + + const membersStr = this.members + .map((member) => { + const memberStr = member.toFullSignature(options); + return ` ${memberStr}`; + }) + .join(',\n'); + + result += `${membersStr}\n`; + + result += `}`; + + return result; } toObject() { diff --git a/components/entities/semantic-schema/schemas/export.ts b/components/entities/semantic-schema/schemas/export.ts index 1f3307455e8b..5bf5733220e4 100644 --- a/components/entities/semantic-schema/schemas/export.ts +++ b/components/entities/semantic-schema/schemas/export.ts @@ -6,6 +6,7 @@ export class ExportSchema extends SchemaNode { alias?: string; exportNode: SchemaNode; readonly doc?: DocSchema; + readonly signature?: string; constructor( readonly location: SchemaLocation, @@ -18,13 +19,50 @@ export class ExportSchema extends SchemaNode { this.exportNode = exportNode; this.alias = alias; this.doc = doc; + this.signature = exportNode.signature || this.toFullSignature(); } - toString() { - if (this.alias) { - return `${this.name} as ${this.alias}`; + toString(options?: { color?: boolean }): string { + let signature = ''; + + const alias = this.alias || this.name; + const originalName = this.exportNode.name || this.name; + + if (alias !== originalName) { + signature += `export { ${originalName} as ${alias} };\n`; + } else { + signature += `export { ${originalName} };\n`; } - return `${this.name}`; + + const exportNodeSignature = this.exportNode.toString(options); + + signature += `\n${exportNodeSignature}`; + + return signature; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + let signature = ''; + + if (options?.showDocs && this.doc) { + const docString = this.doc.toFullSignature(); + signature += `${docString}\n`; + } + + const alias = this.alias || this.name; + const originalName = this.exportNode.name || this.name; + + if (alias !== originalName) { + signature += `export { ${originalName} as ${alias} };\n`; + } else { + signature += `export { ${originalName} };\n`; + } + + const exportNodeSignature = this.exportNode.toFullSignature(options); + + signature += `\n${exportNodeSignature}`; + + return signature; } toObject() { diff --git a/components/entities/semantic-schema/schemas/expression-with-arguments.ts b/components/entities/semantic-schema/schemas/expression-with-arguments.ts index 7c2a598d25c4..a757d9d82752 100644 --- a/components/entities/semantic-schema/schemas/expression-with-arguments.ts +++ b/components/entities/semantic-schema/schemas/expression-with-arguments.ts @@ -20,6 +20,17 @@ export class ExpressionWithTypeArgumentsSchema extends SchemaNode { return this.name; } + toFullSignature(options?: { showDocs?: boolean }): string { + let result = this.name; + + if (this.typeArgs && this.typeArgs.length > 0) { + const typeArgsStr = this.typeArgs.map((arg) => arg.toFullSignature(options)).join(', '); + result += `<${typeArgsStr}>`; + } + + return result; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/function-like.ts b/components/entities/semantic-schema/schemas/function-like.ts index 854335155d9f..af3e7b5df357 100644 --- a/components/entities/semantic-schema/schemas/function-like.ts +++ b/components/entities/semantic-schema/schemas/function-like.ts @@ -47,13 +47,46 @@ export class FunctionLikeSchema extends SchemaNode { return [...this.params, this.returnType, ...(this.decorators || [])]; } - toString() { + toString({ color }) { + const bold = color ? chalk.bold : (text: string) => text; const paramsStr = this.params.map((param) => param.toString()).join(', '); const typeParamsStr = this.typeParams ? `<${this.typeParams.join(', ')}>` : ''; - const decoratorsStr = this.decorators?.map((decorator) => decorator.toString()).join('\n'); - return `${this.decorators ? `${decoratorsStr}\n` : ''}${this.modifiersToString()}${typeParamsStr}${chalk.bold( + const decoratorsStr = this.decorators?.map((decorator) => decorator.toString({ color })).join('\n'); + return `${this.decorators ? `${decoratorsStr}\n` : ''}${this.modifiersToString()}${typeParamsStr}${bold( this.name - )}(${paramsStr}): ${this.returnType.toString()}`; + )}(${paramsStr}): ${this.returnType.toString({ color })}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + let result = ''; + if (options?.showDocs && this.doc) { + result += `${this.doc.toFullSignature()}\n`; + } + const decoratorsStr = this.decorators?.map((decorator) => decorator.toString()).join('\n'); + if (decoratorsStr) { + result += `${decoratorsStr}\n`; + } + const modifiersStr = this.modifiersToString(); + const typeParamsStr = this.typeParams ? `<${this.typeParams.join(', ')}>` : ''; + const paramsStr = this.params + .map((param) => { + let paramStr = ''; + if (param.isSpread) { + paramStr += '...'; + } + paramStr += param.name; + if (param.isOptional) { + paramStr += '?'; + } + paramStr += `: ${param.type.toString()}`; + if (param.defaultValue !== undefined) { + paramStr += ` = ${param.defaultValue}`; + } + return paramStr; + }) + .join(', '); + result += `${modifiersStr}${this.name}${typeParamsStr}(${paramsStr}): ${this.returnType.toString()}`; + return result; } isDeprecated(): boolean { diff --git a/components/entities/semantic-schema/schemas/get-accessor.ts b/components/entities/semantic-schema/schemas/get-accessor.ts index 05cfd4bb6b76..48cf7ed479c6 100644 --- a/components/entities/semantic-schema/schemas/get-accessor.ts +++ b/components/entities/semantic-schema/schemas/get-accessor.ts @@ -16,8 +16,21 @@ export class GetAccessorSchema extends SchemaNode { return [this.type]; } - toString() { - return `get ${chalk.bold(this.name)}(): ${this.type.toString()}`; + toString(options?: { color?: boolean }): string { + const bold = options?.color ? chalk.bold : (x: string) => x; + return `get ${bold(this.name)}(): ${this.type.toString(options)}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + let result = ''; + + if (options?.showDocs && this.doc) { + result += `${this.doc.toFullSignature()}\n`; + } + + result += `get ${this.name}(): ${this.type.toFullSignature(options)}`; + + return result; } toObject() { diff --git a/components/entities/semantic-schema/schemas/ignored.ts b/components/entities/semantic-schema/schemas/ignored.ts index 93079f02045d..6e8cba03ebca 100644 --- a/components/entities/semantic-schema/schemas/ignored.ts +++ b/components/entities/semantic-schema/schemas/ignored.ts @@ -25,6 +25,10 @@ export class IgnoredSchema extends SchemaNode { return ''; } + toFullSignature(): string { + return ''; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/index-signature.ts b/components/entities/semantic-schema/schemas/index-signature.ts index e85eba4b7bc5..076bd0975de0 100644 --- a/components/entities/semantic-schema/schemas/index-signature.ts +++ b/components/entities/semantic-schema/schemas/index-signature.ts @@ -20,6 +20,13 @@ export class IndexSignatureSchema extends SchemaNode { return `[${this.keyType.toString()}]: ${this.valueType.toString()}`; } + toFullSignature(options?: { showDocs?: boolean }): string { + const keyTypeStr = this.keyType.toFullSignature(options); + const valueTypeStr = this.valueType.toFullSignature(options); + + return `[${keyTypeStr}]: ${valueTypeStr}`; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/indexed-access-type.ts b/components/entities/semantic-schema/schemas/indexed-access-type.ts index df36c658f799..c43c99bc30c0 100644 --- a/components/entities/semantic-schema/schemas/indexed-access-type.ts +++ b/components/entities/semantic-schema/schemas/indexed-access-type.ts @@ -19,6 +19,13 @@ export class IndexedAccessSchema extends SchemaNode { return `${this.objectType.toString()}[${this.indexType.toString()}]`; } + toFullSignature(options?: { showDocs?: boolean }): string { + const objectTypeStr = this.objectType.toFullSignature(options); + const indexTypeStr = this.indexType.toFullSignature(options); + + return `${objectTypeStr}[${indexTypeStr}]`; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/inference-type.ts b/components/entities/semantic-schema/schemas/inference-type.ts index f30673d42c7b..cde5b0c0915c 100644 --- a/components/entities/semantic-schema/schemas/inference-type.ts +++ b/components/entities/semantic-schema/schemas/inference-type.ts @@ -22,6 +22,22 @@ export class InferenceTypeSchema extends SchemaNode { return this.type; } + toFullSignature(): string { + let result = ''; + + if (this.name && this.name !== this.type) { + result += `${this.name}: `; + } + + result += this.type; + + if (this.defaultValue !== undefined) { + result += ` = ${this.defaultValue}`; + } + + return result; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/interface.ts b/components/entities/semantic-schema/schemas/interface.ts index a6a7bdf88c27..38f73ec84c40 100644 --- a/components/entities/semantic-schema/schemas/interface.ts +++ b/components/entities/semantic-schema/schemas/interface.ts @@ -26,9 +26,47 @@ export class InterfaceSchema extends SchemaNode { return this.members; } - toString() { - const membersStr = this.members.map((m) => `* ${m.toString()}`).join('\n'); - return `${chalk.bold.underline(this.name)}\n${membersStr}`; + toString(options?: { color?: boolean }): string { + const boldUnderline = options?.color ? chalk.bold.underline : (str: string) => str; + const membersStr = this.members.map((m) => `* ${m.toString(options)}`).join('\n'); + return `${boldUnderline(this.name)}\n${membersStr}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + let result = ''; + + if (options?.showDocs && this.doc) { + result += `${this.doc.toFullSignature()}\n`; + } + + let interfaceDeclaration = `interface ${this.name}`; + + if (this.typeParams && this.typeParams.length > 0) { + interfaceDeclaration += `<${this.typeParams.join(', ')}>`; + } + + if (this.extendsNodes && this.extendsNodes.length > 0) { + const extendsStr = this.extendsNodes.map((node) => node.toFullSignature(options)).join(', '); + interfaceDeclaration += ` extends ${extendsStr}`; + } + + result += `${interfaceDeclaration} {\n`; + + const membersStr = this.members + .map((member) => { + const memberStr = member.toFullSignature(options); + return memberStr + .split('\n') + .map((line) => ` ${line}`) + .join('\n'); + }) + .join('\n'); + + result += `${membersStr}\n`; + + result += `}`; + + return result; } toObject() { diff --git a/components/entities/semantic-schema/schemas/keyword-type.ts b/components/entities/semantic-schema/schemas/keyword-type.ts index e7ccd8954f04..bff602de7351 100644 --- a/components/entities/semantic-schema/schemas/keyword-type.ts +++ b/components/entities/semantic-schema/schemas/keyword-type.ts @@ -12,6 +12,10 @@ export class KeywordTypeSchema extends SchemaNode { return this.name; } + toFullSignature(): string { + return this.toString(); + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/literal-type.ts b/components/entities/semantic-schema/schemas/literal-type.ts index ba690ffc5790..28a29771a837 100644 --- a/components/entities/semantic-schema/schemas/literal-type.ts +++ b/components/entities/semantic-schema/schemas/literal-type.ts @@ -19,6 +19,10 @@ export class LiteralTypeSchema extends SchemaNode { return this.name; } + toFullSignature(): string { + return this.toString(); + } + static fromObject(obj: Record): LiteralTypeSchema { const location = obj.location; const name = obj.name; diff --git a/components/entities/semantic-schema/schemas/literal-value.ts b/components/entities/semantic-schema/schemas/literal-value.ts index 218149ea891c..13a4868eb91f 100644 --- a/components/entities/semantic-schema/schemas/literal-value.ts +++ b/components/entities/semantic-schema/schemas/literal-value.ts @@ -10,6 +10,10 @@ export class LiteralValueSchema extends SchemaNode { return this.value; } + toFullSignature(): string { + return this.toString(); + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/module.ts b/components/entities/semantic-schema/schemas/module.ts index 392ecf730f9d..c4ad967d332f 100644 --- a/components/entities/semantic-schema/schemas/module.ts +++ b/components/entities/semantic-schema/schemas/module.ts @@ -5,11 +5,11 @@ import { ExportSchema } from './export'; export class ModuleSchema extends SchemaNode { // exports could either be re exports (export declarations) or nodes with export modifier - exports: (ExportSchema | SchemaNode)[]; + exports: SchemaNode[]; internals: SchemaNode[]; namespace?: string; - constructor(readonly location: SchemaLocation, exports: (ExportSchema | SchemaNode)[], internals: SchemaNode[]) { + constructor(readonly location: SchemaLocation, exports: SchemaNode[], internals: SchemaNode[]) { super(); this.exports = exports; this.internals = internals; @@ -30,13 +30,33 @@ export class ModuleSchema extends SchemaNode { }, [] as (ExportSchema | SchemaNode)[]); } - toString() { + toString(options?: { color?: boolean }) { if (!this.namespace) throw new Error( 'toString() should not be called on a module without namespace, make sure this.flatExportsRecursively() is called' ); - const exportsStr = this.exports.map((m) => `* ${m.toString()}`).join('\n'); - return `${chalk.bold.underline(this.namespace)}\n${exportsStr}`; + const boldUnderline = options?.color ? chalk.bold.underline : (str: string) => str; + + const exportsStr = this.exports.map((m) => `* ${m.toString(options)}`).join('\n'); + return `${boldUnderline(this.namespace)}\n${exportsStr}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + if (!this.namespace) + throw new Error( + 'toFullSignature() should not be called on a module without namespace; make sure this.flatExportsRecursively() is called' + ); + + const exportsSignatures = this.exports.map((m) => m.toFullSignature(options)).join('\n'); + + let signature = `${this.namespace}\n${exportsSignatures}`; + + if (options?.showDocs && this.doc) { + const docString = this.doc.toFullSignature(); + signature = `${docString}\n${signature}`; + } + + return signature; } toObject() { diff --git a/components/entities/semantic-schema/schemas/named-tuple.ts b/components/entities/semantic-schema/schemas/named-tuple.ts index 6368ada5e38f..26b4c2286e5f 100644 --- a/components/entities/semantic-schema/schemas/named-tuple.ts +++ b/components/entities/semantic-schema/schemas/named-tuple.ts @@ -10,8 +10,12 @@ export class NamedTupleSchema extends SchemaNode { return [this.type]; } - toString() { - return `${this.name}: ${this.type.toString()}`; + toString(options?: { color?: boolean }): string { + return `${this.name}: ${this.type.toString(options)}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + return `${this.name}: ${this.type.toFullSignature(options)}`; } toObject() { diff --git a/components/entities/semantic-schema/schemas/object-literal-expression.ts b/components/entities/semantic-schema/schemas/object-literal-expression.ts index 836dfb55303c..281b22223878 100644 --- a/components/entities/semantic-schema/schemas/object-literal-expression.ts +++ b/components/entities/semantic-schema/schemas/object-literal-expression.ts @@ -10,8 +10,17 @@ export class ObjectLiteralExpressionSchema extends SchemaNode { return this.members; } - toString(): string { - return `{\n${this.members.map((member) => `\t${member.toString()}`).join('\n')}\n}`; + toString(options?: { color?: boolean }): string { + return `{\n${this.members.map((member) => `\t${member.toString(options)}`).join('\n')}\n}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + const membersStr = this.members.map((member) => member.toFullSignature(options)).join(',\n'); + + return `{\n${membersStr + .split('\n') + .map((line) => ` ${line}`) + .join('\n')}\n}`; } toObject() { diff --git a/components/entities/semantic-schema/schemas/parameter.ts b/components/entities/semantic-schema/schemas/parameter.ts index 3ab681a9d762..5851fa622058 100644 --- a/components/entities/semantic-schema/schemas/parameter.ts +++ b/components/entities/semantic-schema/schemas/parameter.ts @@ -25,6 +25,46 @@ export class ParameterSchema extends SchemaNo return `${this.name}${this.isOptional ? '?' : ''}: ${this.type.toString()}`; } + toFullSignature(options?: { showDocs?: boolean }): string { + let paramStr = ''; + + if (options?.showDocs && this.description) { + paramStr += `/** ${this.description} */\n`; + } + + if (this.isSpread) { + paramStr += '...'; + } + + let paramName = ''; + + if (this.objectBindingNodes && this.objectBindingNodes.length > 0) { + const bindingsStr = this.objectBindingNodes.map((node) => node.toFullSignature(options)).join(', '); + paramName += `{ ${bindingsStr} }`; + } else { + paramName += this.name; + } + + if (this.isOptional) { + paramName += '?'; + } + + paramStr += `${paramName}`; + + if (this.type && typeof this.type.toString === 'function') { + const typeName = this.type.toString(); + if (typeName) { + paramStr += `: ${typeName}`; + } + } + + if (this.defaultValue !== undefined) { + paramStr += ` = ${this.defaultValue}`; + } + + return paramStr; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/parenthesized-type.ts b/components/entities/semantic-schema/schemas/parenthesized-type.ts index 4a73866697ac..06b3b23c3804 100644 --- a/components/entities/semantic-schema/schemas/parenthesized-type.ts +++ b/components/entities/semantic-schema/schemas/parenthesized-type.ts @@ -16,8 +16,12 @@ export class ParenthesizedTypeSchema extends SchemaNode { return [this.type]; } - toString() { - return `(${this.type.toString()})`; + toString(options?: { color?: boolean }): string { + return `(${this.type.toString(options)})`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + return `(${this.type.toFullSignature(options)})`; } toObject() { diff --git a/components/entities/semantic-schema/schemas/property-assignment.ts b/components/entities/semantic-schema/schemas/property-assignment.ts index 5256e298428a..8fc27c1d6356 100644 --- a/components/entities/semantic-schema/schemas/property-assignment.ts +++ b/components/entities/semantic-schema/schemas/property-assignment.ts @@ -12,8 +12,22 @@ export class PropertyAssignmentSchema extends SchemaNode { super(); } - toString() { - return `${this.name}: ${this.value.toString()}`; + toString(options?: { color?: boolean }): string { + return `${this.name}: ${this.value.toString(options)}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + let result = ''; + + if (options?.showDocs && this.doc) { + result += `${this.doc.toFullSignature()}\n`; + } + + const valueStr = this.value.toFullSignature(options); + + result += `${this.name}: ${valueStr}`; + + return result; } toObject() { diff --git a/components/entities/semantic-schema/schemas/set-accessor.ts b/components/entities/semantic-schema/schemas/set-accessor.ts index 8e1c0b15bb2c..2ce520637444 100644 --- a/components/entities/semantic-schema/schemas/set-accessor.ts +++ b/components/entities/semantic-schema/schemas/set-accessor.ts @@ -23,6 +23,11 @@ export class SetAccessorSchema extends SchemaNode { return `set ${chalk.bold(this.name)}(${this.param.toString()})`; } + toFullSignature(options?: { showDocs?: boolean }): string { + const paramStr = this.param.toFullSignature(options); + return `set ${this.name}(${paramStr})`; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/template-literal-type-span.ts b/components/entities/semantic-schema/schemas/template-literal-type-span.ts index f7ff315ab545..7fb5e40e42e3 100644 --- a/components/entities/semantic-schema/schemas/template-literal-type-span.ts +++ b/components/entities/semantic-schema/schemas/template-literal-type-span.ts @@ -13,8 +13,12 @@ export class TemplateLiteralTypeSpanSchema extends SchemaNode { return [this.type]; } - toString() { - return `${this.type.toString()} ${this.literal}`; + toString(options?: { color?: boolean }) { + return `${this.type.toString(options)} ${this.literal}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + return `${this.type.toFullSignature(options)} ${this.literal}`; } toObject() { diff --git a/components/entities/semantic-schema/schemas/template-literal-type.ts b/components/entities/semantic-schema/schemas/template-literal-type.ts index 78a84e816fe2..55d1e2f8dae7 100644 --- a/components/entities/semantic-schema/schemas/template-literal-type.ts +++ b/components/entities/semantic-schema/schemas/template-literal-type.ts @@ -13,11 +13,16 @@ export class TemplateLiteralTypeSchema extends SchemaNode { this.templateSpans = templateSpans; } - toString() { - const spans = this.templateSpans.map((span) => span.toString()).join(''); + toString(options?: { color?: boolean }) { + const spans = this.templateSpans.map((span) => span.toString(options)).join(''); return `${this.head}${spans}`; } + toFullSignature(options?: { showDocs?: boolean }): string { + const spans = this.templateSpans.map((span) => span.toFullSignature(options)).join(''); + return `\`${this.head}${spans}\``; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/this-type.ts b/components/entities/semantic-schema/schemas/this-type.ts index 3729def3039a..4874721e30a0 100644 --- a/components/entities/semantic-schema/schemas/this-type.ts +++ b/components/entities/semantic-schema/schemas/this-type.ts @@ -12,6 +12,10 @@ export class ThisTypeSchema extends SchemaNode { return this.name; } + toFullSignature() { + return this.toString(); + } + static fromObject(obj: Record): ThisTypeSchema { const location = obj.location; const name = obj.name; diff --git a/components/entities/semantic-schema/schemas/tuple-type.ts b/components/entities/semantic-schema/schemas/tuple-type.ts index c696f17faa97..81b82389030a 100644 --- a/components/entities/semantic-schema/schemas/tuple-type.ts +++ b/components/entities/semantic-schema/schemas/tuple-type.ts @@ -9,8 +9,12 @@ export class TupleTypeSchema extends SchemaNode { this.elements = elements; } - toString() { - return `[${this.elements.map((elem) => elem.toString()).join(', ')}]`; + toString(options?: { color?: boolean }) { + return `[${this.elements.map((elem) => elem.toString(options)).join(', ')}]`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + return `[${this.elements.map((elem) => elem.toFullSignature(options)).join(', ')}]`; } toObject() { diff --git a/components/entities/semantic-schema/schemas/type-array.ts b/components/entities/semantic-schema/schemas/type-array.ts index a55ba3d9450b..57acd0cafd89 100644 --- a/components/entities/semantic-schema/schemas/type-array.ts +++ b/components/entities/semantic-schema/schemas/type-array.ts @@ -13,8 +13,12 @@ export class TypeArraySchema extends SchemaNode { return [this.type]; } - toString() { - return `${this.type.toString()}[]`; + toString(options?: { color?: boolean }) { + return `${this.type.toString(options)}[]`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + return `${this.type.toFullSignature(options)}[]`; } toObject() { diff --git a/components/entities/semantic-schema/schemas/type-intersection.ts b/components/entities/semantic-schema/schemas/type-intersection.ts index 4049beca1cf1..9da469bf4c0f 100644 --- a/components/entities/semantic-schema/schemas/type-intersection.ts +++ b/components/entities/semantic-schema/schemas/type-intersection.ts @@ -13,8 +13,12 @@ export class TypeIntersectionSchema extends SchemaNode { return this.types; } - toString() { - return `${this.types.map((type) => type.toString()).join(' & ')}`; + toString(options?: { color?: boolean }) { + return `${this.types.map((type) => type.toString(options)).join(' & ')}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + return this.types.map((type) => type.toFullSignature(options)).join(' & '); } toObject() { diff --git a/components/entities/semantic-schema/schemas/type-literal.ts b/components/entities/semantic-schema/schemas/type-literal.ts index 8191002476dd..cefe4154d616 100644 --- a/components/entities/semantic-schema/schemas/type-literal.ts +++ b/components/entities/semantic-schema/schemas/type-literal.ts @@ -20,6 +20,28 @@ export class TypeLiteralSchema extends SchemaNode { return `{ ${this.members.map((type) => type.toString()).join('; ')} }`; } + toFullSignature(options?: { showDocs?: boolean }): string { + const indent = (level: number) => ' '.repeat(level); + const level = 0; + let signature = ''; + + signature += '{\n'; + + this.members.forEach((member) => { + const memberSignature = member.toFullSignature(options); + + const memberLines = memberSignature.split('\n'); + + const indentedLines = memberLines.map((line) => indent(level + 1) + line); + + signature += indentedLines.join('\n') + '\n'; + }); + + signature += indent(level) + '}'; + + return signature; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/type-operator.ts b/components/entities/semantic-schema/schemas/type-operator.ts index 174d5d274517..e14770603661 100644 --- a/components/entities/semantic-schema/schemas/type-operator.ts +++ b/components/entities/semantic-schema/schemas/type-operator.ts @@ -12,8 +12,12 @@ export class TypeOperatorSchema extends SchemaNode { return [this.type]; } - toString() { - return `${this.name} ${this.type.toString()}`; + toString(options?: { color?: boolean }) { + return `${this.name} ${this.type.toString(options)}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + return `${this.name} ${this.type.toFullSignature(options)}`; } toObject() { diff --git a/components/entities/semantic-schema/schemas/type-predicate.ts b/components/entities/semantic-schema/schemas/type-predicate.ts index c02aa5bf56a6..e502303313b8 100644 --- a/components/entities/semantic-schema/schemas/type-predicate.ts +++ b/components/entities/semantic-schema/schemas/type-predicate.ts @@ -26,12 +26,25 @@ export class TypePredicateSchema extends SchemaNode { this.type = type; } - toString() { + toString(options?: { color?: boolean }) { const assertsKeyword = this.hasAssertsModifier ? 'asserts ' : ''; - const typeStr = this.type ? ` is ${this.type.toString()}` : ''; + const typeStr = this.type ? ` is ${this.type.toString(options)}` : ''; return assertsKeyword + this.name + typeStr; } + toFullSignature(options?: { showDocs?: boolean }): string { + const assertsKeyword = this.hasAssertsModifier ? 'asserts ' : ''; + const typeSignature = this.type ? ` is ${this.type.toFullSignature(options)}` : ''; + let signature = `${assertsKeyword}${this.name}${typeSignature}`; + + if (options?.showDocs && this.doc) { + const docString = this.doc.toFullSignature(); + signature = `${docString}\n${signature}`; + } + + return signature; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/type-query.ts b/components/entities/semantic-schema/schemas/type-query.ts index 90cea95e213b..d9980f4d107f 100644 --- a/components/entities/semantic-schema/schemas/type-query.ts +++ b/components/entities/semantic-schema/schemas/type-query.ts @@ -20,8 +20,12 @@ export class TypeQuerySchema extends SchemaNode { return this.signature; } - toString() { - return `typeof ${this.type.toString()}`; + toString(options?: { color?: boolean }) { + return `typeof ${this.type.toString(options)}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + return `typeof ${this.type.toFullSignature(options)}`; } toObject() { diff --git a/components/entities/semantic-schema/schemas/type-ref.ts b/components/entities/semantic-schema/schemas/type-ref.ts index 520dd9af01ab..78a80179a4ba 100644 --- a/components/entities/semantic-schema/schemas/type-ref.ts +++ b/components/entities/semantic-schema/schemas/type-ref.ts @@ -52,27 +52,44 @@ export class TypeRefSchema extends SchemaNode { return this; } - toString() { - const name = this.nameToString(); + toString(options?: { color?: boolean }) { + const name = this.nameToString(options); if (!this.typeArgs) { return name; } - const args = this.typeArgs.map((arg) => arg.toString()).join(', '); + const args = this.typeArgs.map((arg) => arg.toString(options)).join(', '); return `${name}<${args}>`; } - private nameToString() { + private nameToString(options?: { color?: boolean }) { + const dim = options?.color ? chalk.dim : (str: string) => str; if (this.componentId) { - const compStr = chalk.dim(`(component: ${this.componentId.toStringWithoutVersion()})`); + const compStr = dim(`(component: ${this.componentId.toStringWithoutVersion()})`); return `${compStr} ${this.name}`; } if (this.packageName) { - const pkgStr = chalk.dim(`(package: ${this.packageName})`); + const pkgStr = dim(`(package: ${this.packageName})`); return `${pkgStr} ${this.name}`; } return this.name; } + toFullSignature(options?: { showDocs?: boolean }): string { + let signature = this.name; + + if (this.typeArgs && this.typeArgs.length > 0) { + const argsSignatures = this.typeArgs.map((arg) => arg.toFullSignature(options)).join(', '); + signature += `<${argsSignatures}>`; + } + + if (options?.showDocs && this.doc) { + const docString = this.doc.toFullSignature(); + signature = `${docString}\n${signature}`; + } + + return signature; + } + /** * whether this type was already exported in this component */ diff --git a/components/entities/semantic-schema/schemas/type-union.ts b/components/entities/semantic-schema/schemas/type-union.ts index 79a041c0a3d0..a165dc2228a0 100644 --- a/components/entities/semantic-schema/schemas/type-union.ts +++ b/components/entities/semantic-schema/schemas/type-union.ts @@ -7,8 +7,19 @@ export class TypeUnionSchema extends SchemaNode { super(); this.types = types; } - toString() { - return `${this.types.map((type) => type.toString()).join(' | ')}`; + toString(options?: { color?: boolean }) { + return `${this.types.map((type) => type.toString(options)).join(' | ')}`; + } + toFullSignature(options?: { showDocs?: boolean }): string { + const typeSignatures = this.types.map((type) => type.toFullSignature(options)); + let signature = typeSignatures.join(' | '); + + if (options?.showDocs && this.doc) { + const docString = this.doc.toFullSignature(); + signature = `${docString}\n${signature}`; + } + + return signature; } getNodes() { return this.types; diff --git a/components/entities/semantic-schema/schemas/type.ts b/components/entities/semantic-schema/schemas/type.ts index fcb4941d1eb6..679ee318506d 100644 --- a/components/entities/semantic-schema/schemas/type.ts +++ b/components/entities/semantic-schema/schemas/type.ts @@ -19,8 +19,22 @@ export class TypeSchema extends SchemaNode { this.doc = doc; } - toString() { - return `${chalk.bold(this.name)}: ${this.type.toString()}`; + toString(options?: { color?: boolean }) { + const bold = options?.color ? chalk.bold : (str: string) => str; + return `${bold(this.name)}: ${this.type.toString(options)}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + const typeSignature = this.type.toFullSignature(options); + + let signature = `${this.name}: ${typeSignature}`; + + if (options?.showDocs && this.doc) { + const docString = this.doc.toFullSignature(); + signature = `${docString}\n${signature}`; + } + + return signature; } getNodes() { diff --git a/components/entities/semantic-schema/schemas/unimplemented-schema.ts b/components/entities/semantic-schema/schemas/unimplemented-schema.ts index d2af97e56cb9..106802f364a0 100644 --- a/components/entities/semantic-schema/schemas/unimplemented-schema.ts +++ b/components/entities/semantic-schema/schemas/unimplemented-schema.ts @@ -9,6 +9,10 @@ export class UnImplementedSchema extends SchemaNode { return `<>`; } + toFullSignature(): string { + return `<>`; + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/unknown-schema.ts b/components/entities/semantic-schema/schemas/unknown-schema.ts index e224ce47b0e8..9bc84dfc5db4 100644 --- a/components/entities/semantic-schema/schemas/unknown-schema.ts +++ b/components/entities/semantic-schema/schemas/unknown-schema.ts @@ -14,6 +14,10 @@ export class UnknownSchema extends SchemaNode { return `<>`; } + toFullSignature(): string { + return this.toString(); + } + toObject() { return { ...super.toObject(), diff --git a/components/entities/semantic-schema/schemas/unresolved-schema.ts b/components/entities/semantic-schema/schemas/unresolved-schema.ts index 2ce725867b43..328603dd167a 100644 --- a/components/entities/semantic-schema/schemas/unresolved-schema.ts +++ b/components/entities/semantic-schema/schemas/unresolved-schema.ts @@ -13,6 +13,10 @@ export class UnresolvedSchema extends SchemaNode { return this.name; } + toFullSignature(): string { + return this.toString(); + } + toObject() { return super.toObject(); } diff --git a/components/entities/semantic-schema/schemas/variable-like.ts b/components/entities/semantic-schema/schemas/variable-like.ts index 769901c446be..bfffce89b61d 100644 --- a/components/entities/semantic-schema/schemas/variable-like.ts +++ b/components/entities/semantic-schema/schemas/variable-like.ts @@ -28,8 +28,26 @@ export class VariableLikeSchema extends SchemaNode { return [this.type]; } - toString() { - return `${chalk.bold(this.name)}${this.isOptional ? '?' : ''}: ${this.type.toString()}`; + toString(options?: { color?: boolean }) { + const bold = options?.color ? chalk.bold : (str: string) => str; + return `${bold(this.name)}${this.isOptional ? '?' : ''}: ${this.type.toString(options)}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + const namePart = `${this.name}${this.isOptional ? '?' : ''}`; + const typeSignature = this.type.toFullSignature(options); + let signature = `${namePart}: ${typeSignature}`; + + if (this.defaultValue !== undefined) { + signature += ` = ${this.defaultValue}`; + } + + if (options?.showDocs && this.doc) { + const docString = this.doc.toFullSignature(); + signature = `${docString}\n${signature}`; + } + + return signature; } toObject() { diff --git a/scopes/react/react/react.schema.ts b/scopes/react/react/react.schema.ts index 17df1ed6589d..b85314afccfc 100644 --- a/scopes/react/react/react.schema.ts +++ b/scopes/react/react/react.schema.ts @@ -45,12 +45,30 @@ export class ReactSchema extends SchemaNode { return compact([this.props, this.returnType]); } - toString() { + toString(options?: { color?: boolean }): string { + const bold = options?.color ? chalk.bold : (x: string) => x; + const paramsStr = this.props?.toString(); const typeParamsStr = this.typeParams ? `<${this.typeParams.join(', ')}>` : ''; - return `${this.modifiersToString()}${typeParamsStr}${chalk.bold( - this.name - )}(${paramsStr}): ${this.returnType.toString()}`; + return `${this.modifiersToString()}${typeParamsStr}${bold(this.name)}(${paramsStr}): ${this.returnType.toString()}`; + } + + toFullSignature(options?: { showDocs?: boolean }): string { + let signature = ''; + + if (this.doc && options?.showDocs) { + signature += `${this.doc.toFullSignature()}\n`; + } + + const modifiersStr = this.modifiersToString(); + const typeParamsStr = this.typeParams ? `<${this.typeParams.join(', ')}>` : ''; + const paramsStr = this.props ? this.props.toFullSignature() : ''; + + const returnTypeStr = this.returnType.toFullSignature(); + + signature += `${modifiersStr}const ${this.name}${typeParamsStr} = (${paramsStr}): ${returnTypeStr};`; + + return signature; } isDeprecated(): boolean {