"use strict";
exports.__esModule = true;
exports.generateDocumentation = void 0;
var ts = require("./typescript.js");
var util = require('util');
var log = util.debuglog('fortest');
function generateDocumentation(fileNames, options) {
var program = ts.createProgram(fileNames, options);
var checker = program.getTypeChecker();
var output = [];
var types = [];
var components = [];
for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
var sourceFile = _a[_i];
ts.forEachChild(sourceFile, visit);
}
return [components, types];
function visit(node) {
if (!isNodeExported(node)) {
return;
}
if (ts.isClassDeclaration(node) && node.name) {
var symbol = checker.getSymbolAtLocation(node.name);
if (symbol) {
output.push(serializeClass(symbol));
}
}
else if (ts.isModuleDeclaration(node)) {
ts.forEachChild(node, visit);
}
if (ts.isVariableStatement(node)) {
node.declarationList.declarations.forEach(function (subnode) {
var initializer = subnode.initializer || subnode.type;
if (initializer && initializer.parameters && isFunctionalComponent(initializer)) {
var propsName_1;
initializer.parameters.forEach(function (param) {
var typeNode = param.type;
var typ = checker.getTypeFromTypeNode(typeNode);
var simpleType = typeToSimpleType(typ);
types.push(simpleType);
propsName_1 = simpleType.name;
});
var componentExportedName = exportedNameForSymbol(subnode, node);
var component = {
name: componentExportedName,
propsName: propsName_1
};
components.push(component);
}
});
}
if (ts.isFunctionDeclaration(node)) {
if (isFunctionalComponent(node)) {
var propsName_2;
node.parameters.forEach(function (param) {
var typeNode = param.type;
var typ = checker.getTypeFromTypeNode(typeNode);
var simpleType = typeToSimpleType(typ);
types.push(simpleType);
propsName_2 = simpleType.name;
});
var component = {
name: node.name.escapedText,
propsName: propsName_2
};
components.push(component);
}
}
}
function isFunctionalComponent(node) {
var signatureDeclaration = node;
var isElementSymbolWithJsxParent = function (returnType) {
if (returnType.symbol &&
returnType.symbol.parent &&
returnType.symbol.escapedText === 'Element' &&
returnType.symbol.parent.escapedText === 'JSX') {
return true;
}
if (returnType.symbol &&
returnType.symbol.parent &&
returnType.symbol.escapedName === 'Element' &&
returnType.symbol.parent.escapedName === 'JSX') {
return true;
}
return false;
};
if (ts.isFunctionLike(node)) {
var returnType = checker.getSignatureFromDeclaration(signatureDeclaration).getReturnType();
if (isElementSymbolWithJsxParent(returnType)) {
return true;
}
}
var typeName = node.type.typeName;
if (typeName && ts.isQualifiedName(typeName)) {
if (ts.isIdentifier(typeName.left) &&
typeName.left.escapedText === 'JSX' &&
typeName.right.escapedText === 'Element') {
return true;
}
}
return false;
}
function typeToSimpleType(type) {
var typeName;
if (type.aliasSymbol) {
typeName = type.aliasSymbol.escapedName;
}
if (!typeName) {
typeName = type.symbol.escapedName;
}
var simpleType = {
name: typeName,
properties: []
};
type.symbol.members.forEach(function (symbol, key) {
var checkedType = checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
var intrinsicName = checkedType.intrinsicName;
var optional = checker.isOptionalParameter(symbol.declarations[0]);
var complexType;
if (checkedType.aliasSymbol) {
complexType = checkedType.aliasSymbol.escapedName;
var simpleType_1 = typeToSimpleType(checkedType);
types.push(simpleType_1);
}
var property = {
name: key,
intrinsicType: intrinsicName,
complexType: complexType,
optional: optional
};
simpleType.properties.push(property);
});
return simpleType;
}
function exportedNameForSymbol(symbol, fileNode) {
var localName = symbol.name.escapedText;
var exportedName;
fileNode.parent.symbol.exports.forEach(function (value, key) {
try {
var aliasedSymbol = checker.getAliasedSymbol(value);
if (aliasedSymbol.escapedName === localName) {
exportedName = value.escapedName;
}
}
catch (_a) { }
});
return exportedName || localName;
}
function serializeSymbol(symbol) {
return {
name: symbol.getName(),
documentation: ts.displayPartsToString(symbol.getDocumentationComment(checker)),
type: checker.typeToString(checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration))
};
}
function serializeClass(symbol) {
var details = serializeSymbol(symbol);
var constructorType = checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration);
details.constructors = constructorType
.getConstructSignatures()
.map(serializeSignature);
return details;
}
function serializeSignature(signature) {
return {
parameters: signature.parameters.map(serializeSymbol),
returnType: checker.typeToString(signature.getReturnType()),
documentation: ts.displayPartsToString(signature.getDocumentationComment(checker))
};
}
function isNodeExported(node) {
return ((ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 ||
(!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile));
}
}
exports.generateDocumentation = generateDocumentation;
if (require.main === module) {
var _a = generateDocumentation(process.argv.slice(2), {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.CommonJS
}), components = _a[0], types = _a[1];
var nullPrinter = function (key, value) { return typeof value === 'undefined' ? null : value; };
console.log(JSON.stringify({
"types": types,
"components": components
}, nullPrinter, 4));
}