Skip to content

Instantly share code, notes, and snippets.

@g4rcez
Created May 31, 2021 21:56
Show Gist options
  • Save g4rcez/5dd4593fcd8ce024ac46180f2d437cfa to your computer and use it in GitHub Desktop.
Save g4rcez/5dd4593fcd8ce024ac46180f2d437cfa to your computer and use it in GitHub Desktop.
import fs from "fs";
import ts from "typescript";
const isType = (node: ts.Node) =>
ts.isTypeAliasDeclaration(node) ||
(ts.isInterfaceDeclaration(node) && node.name && node.name);
type DocEntry = {
name?: string;
fileName?: string;
documentation?: string;
type?: string;
constructors?: DocEntry[];
parameters?: DocEntry[];
returnType?: string;
};
const output: DocEntry[] = [];
const program = ts.createProgram(["./src/types.ts"], {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.CommonJS,
});
const checker = program.getTypeChecker();
function visit(node: ts.Node) {
if (!isNodeExported(node)) {
return;
}
if (isType(node)) {
const NODE: ts.TypeAliasDeclaration = node as never;
let symbol = checker.getSymbolAtLocation(NODE.name);
if (symbol) {
output.push(serializeType(symbol));
}
} else if (ts.isModuleDeclaration(node)) {
ts.forEachChild(node, visit);
}
}
/** Serialize a symbol into a json object */
function serializeSymbol(symbol: ts.Symbol): DocEntry {
return {
name: symbol.getName(),
documentation: ts.displayPartsToString(
symbol.getDocumentationComment(checker)
),
type: checker.typeToString(
checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration!)
),
};
}
function serializeType(symbol: ts.Symbol): DocEntry {
let details = serializeSymbol(symbol);
let constructorType = checker.getTypeOfSymbolAtLocation(
symbol,
symbol.valueDeclaration!
);
console.log(constructorType);
details.constructors = constructorType
.getConstructSignatures()
.map(serializeSignature);
return {
constructors: details.constructors,
documentation: symbol
.getDocumentationComment(checker)
.map((x) => x.text)
.join(" "),
fileName: "",
name: symbol.name,
};
}
/** Serialize a class symbol information */
function serializeClass(symbol: ts.Symbol) {
let details = serializeSymbol(symbol);
// Get the construct signatures
let constructorType = checker.getTypeOfSymbolAtLocation(
symbol,
symbol.valueDeclaration!
);
details.constructors = constructorType
.getConstructSignatures()
.map(serializeSignature);
return details;
}
/** Serialize a signature (call or construct) */
function serializeSignature(signature: ts.Signature) {
return {
parameters: signature.parameters.map(serializeSymbol),
returnType: checker.typeToString(signature.getReturnType()),
documentation: ts.displayPartsToString(
signature.getDocumentationComment(checker)
),
};
}
/** True if this is visible outside this file, false otherwise */
function isNodeExported(node: ts.Node): boolean {
return (
(ts.getCombinedModifierFlags(node as ts.Declaration) &
ts.ModifierFlags.Export) !==
0 ||
(!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile)
);
}
for (const sourceFile of program.getSourceFiles()) {
if (!sourceFile.isDeclarationFile) {
// Walk the tree to search for classes
ts.forEachChild(sourceFile, visit);
}
}
fs.writeFileSync("classes.json", JSON.stringify(output, undefined, 4));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment