/* * Copyright (C) 2021 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ import ts from 'typescript'; import {cleanupEmpty} from './util.js'; import {LightweightComment} from './types/lightweight-comment.js'; /** @internal */ export function extractComment(node: ts.Node): LightweightComment | undefined { const jsDocuments = // @ts-expect-error jsDoc exists in reality node.jsDoc as | Array<{ comment?: string; tags?: Array<{comment?: string; tagName?: {escapedText?: string}}>; }> | undefined; const jsDocument = jsDocuments?.[jsDocuments.length - 1]; const comment = jsDocument?.comment?.split('\n\n'); return jsDocument === undefined ? undefined : cleanupEmpty({ shortSummary: comment?.[0], description: comment?.slice(1).join('\n\n'), tags: jsDocument?.tags?.map(tag => cleanupEmpty({ name: tag.tagName?.escapedText ?? 'UNRESOLVED_NAME', parameters: tag.comment?.split(' '), }), ), }); } /** @internal */ export function isProperty( node: ts.ClassElement | ts.TypeElement, ): node is ts.PropertyDeclaration | ts.PropertySignature { return ts.isPropertyDeclaration(node) || ts.isPropertySignature(node); } /** @internal */ export function filterNodeTo( node: ts.NodeArray, check: (node: T) => node is S, ): S[] { return node.filter(check); } /** @internal */ export function filterChildrenTo(node: ts.Node, check: (node: ts.Node) => node is T): T[] { const out: T[] = []; node.forEachChild(child => { if (check(child)) { out.push(child); } }); return out; } /** @internal */ export function getModifiers(text: string, kind: string): string[] { return [ ...text .split(kind)[0] .split(/\s+/) .filter(it => it !== ''), kind, ]; } /** @internal */ export function resolvePropertyName(name?: ts.PropertyName): string | undefined { return name === undefined ? undefined : ts.isComputedPropertyName(name) ? 'UNSUPPORTED_IDENTIFIER_TYPE' : name.getText(); } /** @internal */ export function resolveTypeName(type?: ts.TypeNode): string | undefined { // @ts-expect-error typeName exists in reality return type?.typeName?.escapedText ?? type?.typeName?.right?.escapedText; } /** @internal */ export function isArrayLikeType(typeNode?: ts.TypeNode): typeNode is ts.ArrayTypeNode | ts.TypeReferenceNode { return typeNode !== undefined && (ts.isArrayTypeNode(typeNode) || isArrayReference(typeNode)); } /** @internal */ export function isArrayReference(typeNode: ts.TypeNode): boolean { return ts.isTypeReferenceNode(typeNode) && (typeNode.typeName as ts.Identifier).escapedText === 'Array'; } /** @internal */ export function isClassLikeNode(node: ts.Node): node is ts.ClassDeclaration | ts.InterfaceDeclaration { return ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node); } /** @internal */ export function isEnumLikeNode(node: ts.Node): node is ts.EnumDeclaration | ts.TypeAliasDeclaration { return ts.isEnumDeclaration(node) || ts.isTypeAliasDeclaration(node); }