Explorar o código

feat(docs): Generate docs for enums

Relates to #89
Michael Bromley %!s(int64=6) %!d(string=hai) anos
pai
achega
70a14544ee

+ 7 - 2
scripts/docs/typescript-docgen-types.ts

@@ -53,6 +53,11 @@ export interface TypeAliasInfo extends DeclarationInfo {
     type: ts.TypeNode;
 }
 
-export type ParsedDeclaration = TypeAliasInfo | ClassInfo | InterfaceInfo;
-export type ValidDeclaration = ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.ClassDeclaration;
+export interface EnumInfo extends DeclarationInfo {
+    kind: 'enum';
+    members: PropertyInfo[];
+}
+
+export type ParsedDeclaration = TypeAliasInfo | ClassInfo | InterfaceInfo | EnumInfo;
+export type ValidDeclaration = ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.ClassDeclaration | ts.EnumDeclaration;
 export type TypeMap = Map<string, string>;

+ 15 - 6
scripts/docs/typescript-docs-parser.ts

@@ -73,7 +73,7 @@ export class TypescriptDocsParser {
         statement: ts.Statement,
         sourceFile: string,
         sourceLine: number,
-    ): InterfaceInfo | TypeAliasInfo | ClassInfo | undefined {
+    ): ParsedDeclaration | undefined {
         if (!this.isValidDeclaration(statement)) {
             return;
         }
@@ -123,6 +123,12 @@ export class TypescriptDocsParser {
                 extends: this.getHeritageClauseText(statement, ts.SyntaxKind.ExtendsKeyword),
                 implements: this.getHeritageClauseText(statement, ts.SyntaxKind.ImplementsKeyword),
             };
+        } else if (ts.isEnumDeclaration(statement)) {
+            return {
+                ...info,
+                kind: 'enum' as 'enum',
+                members: this.parseMembers(statement.members) as PropertyInfo[],
+            };
         }
     }
 
@@ -150,7 +156,7 @@ export class TypescriptDocsParser {
     private getDeclarationFullText(declaration: ValidDeclaration): string {
         const name = declaration.name ? declaration.name.getText() : 'anonymous';
         let typeParams = '';
-        if (declaration.typeParameters) {
+        if (!ts.isEnumDeclaration(declaration) && declaration.typeParameters) {
             typeParams = '<' + declaration.typeParameters.map(tp => tp.getText()).join(', ') + '>';
         }
         return name + typeParams;
@@ -169,7 +175,7 @@ export class TypescriptDocsParser {
      * Parses an array of inteface members into a simple object which can be rendered into markdown.
      */
     private parseMembers(
-        members: ts.NodeArray<ts.TypeElement | ts.ClassElement>,
+        members: ts.NodeArray<ts.TypeElement | ts.ClassElement | ts.EnumMember>,
     ): Array<PropertyInfo | MethodInfo> {
         const result: Array<PropertyInfo | MethodInfo> = [];
 
@@ -182,7 +188,9 @@ export class TypescriptDocsParser {
                     ts.isMethodSignature(member) ||
                     ts.isPropertyDeclaration(member) ||
                     ts.isMethodDeclaration(member) ||
-                    ts.isConstructorDeclaration(member))
+                    ts.isConstructorDeclaration(member) ||
+                    ts.isEnumMember(member)
+                )
             ) {
                 const name = member.name ? member.name.getText() : 'constructor';
                 let description = '';
@@ -202,7 +210,7 @@ export class TypescriptDocsParser {
                     example: tag => (description += this.formatExampleCode(tag.comment)),
                     default: tag => (defaultValue = tag.comment || ''),
                 });
-                if (member.type) {
+                if (!ts.isEnumMember(member) && member.type) {
                     type = member.type.getText();
                 }
                 const memberInfo: MemberInfo = {
@@ -279,7 +287,8 @@ export class TypescriptDocsParser {
         return (
             ts.isInterfaceDeclaration(statement) ||
             ts.isTypeAliasDeclaration(statement) ||
-            ts.isClassDeclaration(statement)
+            ts.isClassDeclaration(statement) ||
+            ts.isEnumDeclaration(statement)
         );
     }
 

+ 35 - 2
scripts/docs/typescript-docs-renderer.ts

@@ -7,7 +7,7 @@ import ts from 'typescript';
 import { assertNever } from '../../packages/common/src/shared-utils';
 
 import { deleteGeneratedDocs, generateFrontMatter } from './docgen-utils';
-import { ClassInfo, DeclarationInfo, InterfaceInfo, ParsedDeclaration, TypeAliasInfo, TypeMap } from './typescript-docgen-types';
+import { ClassInfo, DeclarationInfo, EnumInfo, InterfaceInfo, ParsedDeclaration, TypeAliasInfo, TypeMap } from './typescript-docgen-types';
 
 export class TypescriptDocsRenderer {
 
@@ -28,6 +28,9 @@ export class TypescriptDocsRenderer {
                 case 'class':
                     markdown = this.renderInterfaceOrClass(info, typeMap, docsUrl);
                     break;
+                case 'enum':
+                    markdown = this.renderEnum(info, typeMap, docsUrl);
+                    break;
                 default:
                     assertNever(info);
             }
@@ -85,6 +88,18 @@ export class TypescriptDocsRenderer {
         return output;
     }
 
+    private renderEnum(enumInfo: EnumInfo, knownTypeMap: TypeMap, docsUrl: string): string {
+        const { title, weight, description, fullText } = enumInfo;
+        let output = '';
+        output += generateFrontMatter(title, weight);
+        output += `\n\n# ${title}\n\n`;
+        output += this.renderGenerationInfoShortcode(enumInfo);
+        output += `${this.renderDescription(description, knownTypeMap, docsUrl)}\n\n`;
+        output += `## Signature\n\n`;
+        output += this.renderEnumSignature(enumInfo);
+        return output;
+    }
+
     /**
      * Generates a markdown code block string for the interface signature.
      */
@@ -156,7 +171,25 @@ export class TypescriptDocsRenderer {
         return output;
     }
 
-    private renderMembers(info: InterfaceInfo | ClassInfo | TypeAliasInfo, knownTypeMap: TypeMap, docsUrl: string): string {
+    private renderEnumSignature(enumInfo: EnumInfo): string {
+        const { fullText, members } = enumInfo;
+        let output = '';
+        output += `\`\`\`TypeScript\n`;
+        output += `enum ${fullText} `;
+        if (members) {
+            output += `{\n`;
+            output += members.map(member => {
+                let line = member.description ? `  // ${member.description}\n` : '';
+                line += `  ${member.fullText}`;
+                return line;
+            }).join(`\n`);
+            output += `\n}\n`;
+        }
+        output += `\`\`\`\n`;
+        return output;
+    }
+
+    private renderMembers(info: InterfaceInfo | ClassInfo | TypeAliasInfo | EnumInfo, knownTypeMap: TypeMap, docsUrl: string): string {
         const { members, title } = info;
         let output = '';
         for (const member of members || []) {