UNPKG

@microsoft/api-extractor

Version:

Validate, document, and review the exported API for a TypeScript library

142 lines (140 loc) 4.99 kB
"use strict"; // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. Object.defineProperty(exports, "__esModule", { value: true }); /* tslint:disable:no-bitwise */ const ts = require("typescript"); /** * Some helper functions for formatting certain TypeScript Compiler API expressions. */ class PrettyPrinter { /** * Used for debugging only. This dumps the TypeScript Compiler's abstract syntax tree. */ static dumpTree(node, indent = '') { const kindName = ts.SyntaxKind[node.kind]; let trimmedText; try { trimmedText = node.getText() .replace(/[\r\n]/g, ' ') .replace(/\s+/g, ' ') .trim(); if (trimmedText.length > 100) { trimmedText = trimmedText.substr(0, 97) + '...'; } } catch (e) { trimmedText = '(error getting text)'; } console.log(`${indent}${kindName}: [${trimmedText}]`); try { for (const childNode of node.getChildren()) { PrettyPrinter.dumpTree(childNode, indent + ' '); } } catch (e) { // sometimes getChildren() throws an exception } } /** * Returns a text representation of the enum flags. */ static getSymbolFlagsString(flags) { return PrettyPrinter._getFlagsString(flags, PrettyPrinter._getSymbolFlagString); } /** * Returns a text representation of the enum flags. */ static getTypeFlagsString(flags) { return PrettyPrinter._getFlagsString(flags, PrettyPrinter._getTypeFlagString); } /** * Returns the first line of a potentially nested declaration. * For example, for a class definition this might return * "class Blah<T> extends BaseClass" without the curly braces. * For example, for a function definition, this might return * "test(): void;" without the curly braces. */ static getDeclarationSummary(node) { let result = ''; let previousSyntaxKind = ts.SyntaxKind.Unknown; for (const childNode of node.getChildren()) { switch (childNode.kind) { case ts.SyntaxKind.JSDocComment: break; case ts.SyntaxKind.Block: result += ';'; break; default: if (PrettyPrinter._wantSpaceAfter(previousSyntaxKind) && PrettyPrinter._wantSpaceBefore(childNode.kind)) { result += ' '; } result += childNode.getText(); previousSyntaxKind = childNode.kind; break; } } return result; } /** * Throws an exception. Use this only for unexpected errors, as it may ungracefully terminate the process; * AstItem.reportError() is generally a better option. */ static throwUnexpectedSyntaxError(errorNode, message) { throw new Error(PrettyPrinter.formatFileAndLineNumber(errorNode) + ': ' + message); } /** * Returns a string such as this, based on the context information in the provided node: * "[C:\Folder\File.ts#123]" */ static formatFileAndLineNumber(node) { const sourceFile = node.getSourceFile(); const lineAndCharacter = sourceFile.getLineAndCharacterOfPosition(node.getStart()); return `[${sourceFile.fileName}#${lineAndCharacter.line}]`; } static _getSymbolFlagString(flag) { return ts.SymbolFlags[flag]; } static _getTypeFlagString(flag) { return ts.TypeFlags[flag]; } static _getFlagsString(flags, func) { /* tslint:disable:no-any */ let result = ''; let flag = 1; for (let bit = 0; bit < 32; ++bit) { if (flags & flag) { if (result !== '') { result += ', '; } result += func(flag); } flag <<= 1; } return result === '' ? '???' : result; /* tslint:enable:no-any */ } static _wantSpaceAfter(syntaxKind) { switch (syntaxKind) { case ts.SyntaxKind.Unknown: case ts.SyntaxKind.OpenParenToken: case ts.SyntaxKind.CloseParenToken: return false; } return true; } static _wantSpaceBefore(syntaxKind) { switch (syntaxKind) { case ts.SyntaxKind.Unknown: case ts.SyntaxKind.OpenParenToken: case ts.SyntaxKind.CloseParenToken: case ts.SyntaxKind.ColonToken: case ts.SyntaxKind.SemicolonToken: return false; } return true; } } exports.default = PrettyPrinter; //# sourceMappingURL=PrettyPrinter.js.map