@microsoft/api-extractor
Version:
Validate, document, and review the exported API for a TypeScript library
142 lines (140 loc) • 4.99 kB
JavaScript
;
// 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