sardines-compile-time-tools
Version:
sardines.compile-time-tools.js is part of the sardines.io project
302 lines (301 loc) • 13.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.gatherExports = exports.illegalExportTypes = exports.legalExportTypes = void 0;
var ts = require("typescript");
var fs = require("fs");
var builtInTypes = ['Promise', 'Map', 'Array', 'Set', 'void', 'any', 'null', 'undefined', 'object', 'number', 'string', 'boolean'];
exports.legalExportTypes = [
ts.SyntaxKind.FunctionExpression,
ts.SyntaxKind.FunctionDeclaration,
ts.SyntaxKind.ArrowFunction,
ts.SyntaxKind.InterfaceDeclaration,
ts.SyntaxKind.ObjectLiteralExpression,
ts.SyntaxKind.ArrayLiteralExpression,
ts.SyntaxKind.PropertyAccessExpression,
ts.SyntaxKind.EnumDeclaration,
];
exports.illegalExportTypes = [
ts.SyntaxKind.ClassDeclaration,
];
function gatherExports(sourceFilePath) {
var sourceFile = ts.createSourceFile(sourceFilePath, fs.readFileSync(sourceFilePath).toString(), ts.ScriptTarget.ES2015, true);
var idnetifiers = new Map();
var referencedTypes = [];
var importedIds = [];
var proxyIds = [];
var storeSyntax = function (syntax) {
if (syntax.name) {
if (idnetifiers.has(syntax.name)) {
throw "duplicated identifier: " + syntax.name;
}
else if (syntax.isExport && exports.illegalExportTypes.indexOf(syntax.type) >= 0) {
throw "illegal export type: " + ts.SyntaxKind[syntax.type] + " for syntax [" + syntax.name + "]";
}
else {
idnetifiers.set(syntax.name, syntax);
}
}
};
var storeReferencedTypes = function (types) {
for (var _i = 0, types_1 = types; _i < types_1.length; _i++) {
var t = types_1[_i];
if (referencedTypes.indexOf(t) < 0)
referencedTypes.push(t);
}
};
var storeImportedOrExportedIds = function (ids, source, isImport) {
if (isImport === void 0) { isImport = true; }
if (!source)
return;
for (var _i = 0, ids_1 = ids; _i < ids_1.length; _i++) {
var item_1 = ids_1[_i];
var line = item_1 + "|" + source;
if (isImport && importedIds.indexOf(line) < 0)
importedIds.push(line);
else if (!isImport && proxyIds.indexOf(line) < 0)
proxyIds.push(line);
}
};
var checkSyntaxType = function (node, type) {
if (type === void 0) { type = ts.SyntaxKind.ExportKeyword; }
if (node.kind === type)
return true;
var result = false;
if (node.getChildCount() > 0) {
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
var child = _a[_i];
if (checkSyntaxType(child, type)) {
result = true;
break;
}
}
}
return result;
};
var printNode = function (node, prefix) {
if (prefix === void 0) { prefix = ''; }
console.log(prefix, ts.SyntaxKind[node.kind], node.getText());
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
var item_2 = _a[_i];
printNode(item_2, prefix + ' ');
}
};
var getTypeRefInParam = function (param) {
var result = [];
for (var _i = 0, _a = param.getChildren(); _i < _a.length; _i++) {
var item_3 = _a[_i];
var digIn = true;
if (item_3.kind === ts.SyntaxKind.TypeReference) {
var text = item_3.getText();
if (text.indexOf('<') < 0 && builtInTypes.indexOf(text) < 0 && text.indexOf('|') < 0) {
result.push(text);
digIn = false;
}
}
if (digIn) {
var subResult = getTypeRefInParam(item_3);
for (var _b = 0, subResult_1 = subResult; _b < subResult_1.length; _b++) {
var t = subResult_1[_b];
if (result.indexOf(t) < 0) {
result.push(t);
}
}
}
}
return result;
};
var getParamSyntax = function (node) {
var paramSyntax = null, pre = null, preBeforePre = null;
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
var item_4 = _a[_i];
if (item_4.kind === ts.SyntaxKind.CloseParenToken) {
if (pre && pre.kind !== ts.SyntaxKind.OpenParenToken && preBeforePre && preBeforePre.kind === ts.SyntaxKind.OpenParenToken) {
paramSyntax = pre;
}
break;
}
preBeforePre = pre;
pre = item_4;
}
var params = [];
if (paramSyntax) {
for (var _b = 0, _c = paramSyntax.getChildren(); _b < _c.length; _b++) {
var item_5 = _c[_b];
if (item_5.kind === ts.SyntaxKind.Parameter) {
var paramName = null;
for (var _d = 0, _e = item_5.getChildren(); _d < _e.length; _d++) {
var subItem = _e[_d];
if (subItem.kind === ts.SyntaxKind.Identifier) {
paramName = subItem.getText();
}
}
if (paramName) {
var paramObj = {
name: paramName,
type: item_5.kind,
typeStr: ts.SyntaxKind[item_5.kind],
isExport: false,
isAsync: false,
text: item_5.getText()
};
params.push(paramObj);
}
}
}
return params;
}
return null;
};
var getReturnType = function (node) {
var preBeforePre = null, pre = null, returnType = null;
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
var child = _a[_i];
if (pre && preBeforePre && preBeforePre.kind === ts.SyntaxKind.ColonToken)
if (child.kind === ts.SyntaxKind.EqualsGreaterThanToken || child.kind === ts.SyntaxKind.Block) {
returnType = pre.getText();
}
preBeforePre = pre;
pre = child;
}
return returnType;
};
var parseParamsIntoSyntax = function (node, syntax) {
syntax.param = getParamSyntax(node);
if (syntax.param) {
syntax.typeRef = getTypeRefInParam(node);
if (syntax.typeRef.length > 0)
storeReferencedTypes(syntax.typeRef);
}
syntax.isAsync = checkSyntaxType(node, ts.SyntaxKind.AsyncKeyword);
var returnType = getReturnType(node);
if (!returnType)
returnType = 'any';
else if (syntax.isAsync && returnType.indexOf('Promise<') === 0) {
returnType = returnType.substr(8);
returnType = returnType.substr(0, returnType.length - 1);
}
syntax.returnType = returnType;
return syntax;
};
var getNamedImportsOrExports = function (node) {
var importedOrExportedIds = [];
var source = null, isSource = false;
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
var item_6 = _a[_i];
if (item_6.kind === ts.SyntaxKind.ImportSpecifier || item_6.kind === ts.SyntaxKind.ExportSpecifier) {
var children = item_6.getChildren();
if (children.length === 1) {
importedOrExportedIds.push(children[0].getText());
}
else if (children.length === 3 && children[1].kind === ts.SyntaxKind.AsKeyword) {
importedOrExportedIds.push(children[0].getText() + ':' + children[2].getText());
}
}
else if (item_6.kind === ts.SyntaxKind.FromKeyword) {
isSource = true;
}
else if (item_6.kind === ts.SyntaxKind.StringLiteral && isSource) {
source = item_6.getText();
}
else {
var _b = getNamedImportsOrExports(item_6), subIds = _b[0], subSource = _b[1];
for (var _c = 0, subIds_1 = subIds; _c < subIds_1.length; _c++) {
var subId = subIds_1[_c];
if (importedOrExportedIds.indexOf(subId) < 0)
importedOrExportedIds.push(subId);
}
if (subSource) {
if (!source)
source = subSource;
}
}
}
return [importedOrExportedIds, source];
};
var analyzeNode = function (node) {
if (node.kind === ts.SyntaxKind.SourceFile) {
ts.forEachChild(node, analyzeNode);
return;
}
var name = '', isAsync = false, isExport = checkSyntaxType(node), text = node.getText().replace(/export +/g, ''), syntax = { name: name, isAsync: isAsync, isExport: isExport, type: node.kind, typeStr: ts.SyntaxKind[node.kind], text: text };
switch (node.kind) {
case ts.SyntaxKind.VariableStatement:
for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) {
var item_7 = _a[_i];
analyzeNode(item_7);
}
break;
case ts.SyntaxKind.ExportDeclaration:
case ts.SyntaxKind.ImportDeclaration:
var _b = getNamedImportsOrExports(node), importedIds_1 = _b[0], source = _b[1];
storeImportedOrExportedIds(importedIds_1, source, node.kind === ts.SyntaxKind.ImportDeclaration);
break;
case ts.SyntaxKind.ExportAssignment:
throw 'export default is not supported';
case ts.SyntaxKind.InterfaceDeclaration:
syntax.name = node.name.text;
break;
case ts.SyntaxKind.EnumDeclaration:
syntax.name = node.name.text;
break;
case ts.SyntaxKind.ClassDeclaration:
syntax.name = node.name.text;
break;
case ts.SyntaxKind.ArrowFunction:
syntax.name = node.name;
syntax.isExport = checkSyntaxType(node, ts.SyntaxKind.ExportKeyword);
parseParamsIntoSyntax(node, syntax);
break;
case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.FunctionExpression:
syntax.name = node.name.text;
syntax.isExport = checkSyntaxType(node, ts.SyntaxKind.ExportKeyword);
parseParamsIntoSyntax(node, syntax);
break;
case ts.SyntaxKind.VariableDeclaration:
isExport = checkSyntaxType(node.parent.parent);
name = node.name.getText();
var isValueSyntax = false;
for (var _c = 0, _d = node.getChildren(); _c < _d.length; _c++) {
var item_8 = _d[_c];
if (isValueSyntax) {
var sourceId = item_8.getText();
if (item_8.kind === ts.SyntaxKind.Identifier && idnetifiers.has(sourceId)) {
var tmpSyntax = Object.assign({}, idnetifiers.get(sourceId));
tmpSyntax.name = name;
tmpSyntax.isExport = isExport;
storeSyntax(tmpSyntax);
}
else if (item_8.kind !== ts.SyntaxKind.Identifier) {
var itemSyntax = { name: name, isAsync: false, isExport: isExport, type: item_8.kind, typeStr: ts.SyntaxKind[item_8.kind], text: sourceId };
if (item_8.kind === ts.SyntaxKind.FunctionExpression || item_8.kind === ts.SyntaxKind.ArrowFunction) {
parseParamsIntoSyntax(item_8, itemSyntax);
}
storeSyntax(itemSyntax);
}
isValueSyntax = false;
}
else if (item_8.kind === ts.SyntaxKind.FirstAssignment) {
isValueSyntax = true;
}
}
break;
default:
break;
}
storeSyntax(syntax);
};
analyzeNode(sourceFile);
var iterator = idnetifiers.keys();
var item = iterator.next();
while (!item.done) {
var idenObj = (idnetifiers.get(item.value));
if (!idenObj.isExport
|| exports.legalExportTypes.indexOf(idenObj.type) < 0) {
idnetifiers.delete(item.value);
}
item = iterator.next();
}
return [idnetifiers, referencedTypes, importedIds, proxyIds];
}
exports.gatherExports = gatherExports;