UNPKG

@typestrong/ts-mockito

Version:
275 lines 12.1 kB
"use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockableFunctionsFinder = void 0; var parser_1 = require("@babel/parser"); var ObjectInspector_1 = require("./ObjectInspector"); var ObjectPropertyCodeRetriever_1 = require("./ObjectPropertyCodeRetriever"); var lodash_1 = require("lodash"); var methodTokenName = new Set([ "ObjectMethod", "ClassMethod", "ClassPrivateMethod", "FunctionDeclaration", "FunctionExpression" ]); function getPropName(n) { if ('name' in n) return [n.name]; if ('value' in n) return [n.value.toString()]; if (n.type === 'PrivateName') return getPropName(n.id); return handleExpression(n); } function handleAssignment(n) { if (methodTokenName.has(n.right.type)) return __spreadArray(__spreadArray([], handleLVal(n.left), true), handleExpression(n.right), true); return handleExpression(n.right); } function handleObject(n) { var names = []; n.properties.forEach(function (p) { if ('key' in p) names.push.apply(names, getPropName(p.key)); if ('body' in p) names.push.apply(names, p.body.body.flatMap(handleStatement)); if ('value' in p) names.push.apply(names, handleExpression(p.value)); }); return names; } var isSpread = function (n) { return n.type === 'SpreadElement'; }; function handleExpression(n) { if (!n) return []; switch (n.type) { case "ArrayExpression": return n.elements.flatMap(function (e) { return e ? (isSpread(e) ? handleUnaryLike(e) : handleExpression(e)) : []; }); case "AssignmentExpression": return handleAssignment(n); case "BinaryExpression": return __spreadArray(__spreadArray([], (n.left.type !== 'PrivateName' ? handleExpression(n.left) : []), true), handleExpression(n.right), true); case "CallExpression": return n.arguments.flatMap(function (a) { if (a.type === 'JSXNamespacedName') return []; if (a.type === 'ArgumentPlaceholder') return []; return isSpread(a) ? handleUnaryLike(a) : handleExpression(a); }); case "ConditionalExpression": return __spreadArray(__spreadArray(__spreadArray([], handleExpression(n.test), true), handleExpression(n.consequent), true), handleExpression(n.alternate), true); case "FunctionExpression": return handleBlock(n.body); case "Identifier": return [n.name]; case "LogicalExpression": return __spreadArray(__spreadArray([], handleExpression(n.left), true), handleExpression(n.right), true); case "MemberExpression": return n.property.type === 'PrivateName' ? handleExpression(n.property.id) : handleExpression(n.property); case "ObjectExpression": return handleObject(n); case "SequenceExpression": return n.expressions.flatMap(handleExpression); case "ParenthesizedExpression": return handleExpression(n.expression); case "UnaryExpression": case "UpdateExpression": case "YieldExpression": case "AwaitExpression": return handleExpression(n.argument); case "ArrowFunctionExpression": return n.body.type === 'BlockStatement' ? handleBlock(n.body) : handleExpression(n.body); case "ClassExpression": return handleClass(n); case "TaggedTemplateExpression": return handleExpression(n.tag); case "TemplateLiteral": return n.expressions.flatMap(function (e) { return handleExpression(e); }); case "OptionalMemberExpression": return __spreadArray([], (n.property.type !== 'Identifier' ? handleExpression(n.property) : []), true); case "OptionalCallExpression": return n.arguments.flatMap(function (a) { if (a.type === 'SpreadElement') return handleExpression(a.argument); if (a.type === 'JSXNamespacedName') return []; if (a.type === 'ArgumentPlaceholder') return []; return handleExpression(a); }); case "BindExpression": return handleExpression(n.object); case "DoExpression": return handleBlock(n.body); case "RecordExpression": case "NewExpression": case "StringLiteral": case "NumericLiteral": case "BooleanLiteral": case "RegExpLiteral": case "NullLiteral": case "ThisExpression": case "MetaProperty": case "Super": case "Import": case "BigIntLiteral": case "TypeCastExpression": case "JSXElement": case "JSXFragment": case "PipelinePrimaryTopicReference": case "TupleExpression": case "DecimalLiteral": case "ModuleExpression": case "TSAsExpression": case "TSTypeAssertion": case "TSNonNullExpression": default: return []; } } function handleBlock(n) { if (!n) return []; return n.body.flatMap(handleStatement); } function handleStatement(n) { var _a; switch (n.type) { case "BlockStatement": return n.body.flatMap(handleStatement); case "DoWhileStatement": return __spreadArray(__spreadArray([], handleExpression(n.test), true), handleStatement(n.body), true); case "ExpressionStatement": return handleExpression(n.expression); case "ForInStatement": return __spreadArray(__spreadArray([], handleExpression(n.right), true), handleStatement(n.body), true); case "ForStatement": return __spreadArray(__spreadArray(__spreadArray([], (n.test ? handleExpression(n.test) : []), true), (n.update ? handleExpression(n.update) : []), true), handleStatement(n.body), true); case "FunctionDeclaration": return __spreadArray(__spreadArray([], (n.id ? [n.id.name] : []), true), handleBlock(n.body), true); case "IfStatement": return __spreadArray(__spreadArray(__spreadArray([], handleExpression(n.test), true), handleStatement(n.consequent), true), (n.alternate ? handleStatement(n.alternate) : []), true); case "LabeledStatement": return handleStatement(n.body); case "ReturnStatement": return __spreadArray([], (n.argument ? handleExpression(n.argument) : []), true); case "SwitchStatement": return __spreadArray(__spreadArray([], handleExpression(n.discriminant), true), n.cases.flatMap(function (c) { return __spreadArray(__spreadArray([], handleExpression(c.test), true), c.consequent.flatMap(handleStatement), true); }), true); case "ThrowStatement": return handleExpression(n.argument); case "TryStatement": return __spreadArray(__spreadArray(__spreadArray([], handleBlock(n.block), true), handleBlock((_a = n.handler) === null || _a === void 0 ? void 0 : _a.body), true), handleBlock(n.finalizer), true); case "WhileStatement": return __spreadArray(__spreadArray([], handleExpression(n.test), true), handleStatement(n.body), true); case "WithStatement": return __spreadArray(__spreadArray([], handleExpression(n.object), true), handleStatement(n.body), true); case "ClassDeclaration": return handleClass(n); case "ForOfStatement": return __spreadArray(__spreadArray([], handleExpression(n.right), true), handleStatement(n.body), true); case "VariableDeclaration": return n.declarations.flatMap(function (d) { return handleExpression(d.init); }); case "DebuggerStatement": case "BreakStatement": case "ContinueStatement": case "EmptyStatement": case "ExportAllDeclaration": case "ExportDefaultDeclaration": case "ExportNamedDeclaration": case "ImportDeclaration": case "DeclareClass": case "DeclareFunction": case "DeclareInterface": case "DeclareModule": case "DeclareModuleExports": case "DeclareTypeAlias": case "DeclareOpaqueType": case "DeclareVariable": case "DeclareExportDeclaration": case "DeclareExportAllDeclaration": case "InterfaceDeclaration": case "OpaqueType": case "TypeAlias": case "EnumDeclaration": case "TSDeclareFunction": case "TSInterfaceDeclaration": case "TSTypeAliasDeclaration": case "TSEnumDeclaration": case "TSModuleDeclaration": case "TSImportEqualsDeclaration": case "TSExportAssignment": case "TSNamespaceExportDeclaration": default: return []; } } function handleLVal(n) { if ('name' in n) return [n.name]; if ('property' in n) return getPropName(n.property); return []; } function handleUnaryLike(n) { return handleExpression(n.argument); } function handleClass(n) { return n.body.body.flatMap(function (b) { switch (b.type) { case "ClassMethod": return __spreadArray(__spreadArray([], getPropName(b.key), true), handleStatement(b.body), true); case "ClassPrivateMethod": return __spreadArray(__spreadArray([], getPropName(b.key), true), handleStatement(b.body), true); case "ClassProperty": return __spreadArray(__spreadArray([], getPropName(b.key), true), handleExpression(b.value), true); case "ClassPrivateProperty": return __spreadArray(__spreadArray([], getPropName(b.key), true), handleExpression(b.value), true); case "TSIndexSignature": case "TSDeclareMethod": return []; } }); } function handleBody(n) { return n.body.flatMap(handleStatement); } var MockableFunctionsFinder = (function () { function MockableFunctionsFinder() { this.excludedFunctionNames = new Set(["hasOwnProperty", "function"]); } MockableFunctionsFinder.prototype.find = function (clazz) { var _this = this; var codes = this.getClassCodeAsStringWithInheritance(clazz); var asts = codes.map(function (code) { return (0, parser_1.parse)(code); }); var names = asts.flatMap(function (ast) { return handleBody(ast.program); }); return (0, lodash_1.uniq)(names) .filter(function (functionName) { return _this.isMockable(functionName); }); }; MockableFunctionsFinder.prototype.isMockable = function (name) { if (!name) return false; return !this.excludedFunctionNames.has(name); }; MockableFunctionsFinder.prototype.getClassCodeAsStringWithInheritance = function (clazz) { return __spreadArray(["const clazz = ".concat(this.getClassAsString(clazz))], ObjectInspector_1.ObjectInspector.getObjectPrototypes(clazz.prototype).map(ObjectPropertyCodeRetriever_1.ObjectPropertyCodeRetriever.getObject), true); }; MockableFunctionsFinder.prototype.getClassAsString = function (clazz) { var classCode = typeof clazz.toString !== "undefined" ? clazz.toString() : "{}"; if (classCode === '[object Object]') return '{}'; return classCode; }; return MockableFunctionsFinder; }()); exports.MockableFunctionsFinder = MockableFunctionsFinder; //# sourceMappingURL=MockableFunctionsFinder.js.map