UNPKG

babel-plugin-transform-currency-operators

Version:

https://github.com/scurker/babel-plugin-transform-currency-operators

231 lines (188 loc) 7.68 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var path = _interopDefault(require('path')); function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var rootPath = process.cwd(); function resolveRelativePath(currentFile, importPath) { var absolutePath = path.resolve(rootPath, importPath), relativePathToImport = path.relative(path.dirname(currentFile), absolutePath); // Check to see if path is relative to currentFile's folder if (relativePathToImport.indexOf('../') !== 0) { relativePathToImport = "./".concat(relativePathToImport); } return relativePathToImport; } var arithmeticOperators = { '+': 'add', '-': 'subtract', '/': 'divide', '*': 'multiply' }; var compareOperators = ['===', '==', '>', '<', '>=', '<=', '!=', '!==']; function transformCurrencyOperators(_ref) { var t = _ref.types; function expressionCallsCurrency(node, identifiers) { if (!node) { return false; } if (t.isBinaryExpression(node)) { return expressionCallsCurrency(node.left, identifiers); } if (t.isCallExpression(node)) { return expressionCallsCurrency(node.callee, identifiers); } if (t.isMemberExpression(node)) { return expressionCallsCurrency(node.object, identifiers); } if (t.isFunctionExpression(node)) { return expressionCallsCurrency(node.body.body.find(function (n) { return t.isReturnStatement(n); }), identifiers); } if (t.isArrowFunctionExpression(node)) { if (t.isCallExpression(node.body)) { return expressionCallsCurrency(node.body, identifiers); } else if (t.isBlockStatement(node.body)) { return expressionCallsCurrency(node.body.body.find(function (n) { return t.isReturnStatement(n); }), identifiers); } } if (t.isReturnStatement(node)) { return expressionCallsCurrency(node.argument.callee, identifiers); } return t.isIdentifier(node) && identifiers.has(node.name); } function pathContainsCurrency(refPath, methodName) { var node = refPath.node, currencyVariables = new Set([methodName]); var Visitors = { FunctionDeclaration: function FunctionDeclaration(_ref2) { var node = _ref2.node; if (expressionCallsCurrency(node.body.body.find(function (n) { return t.isReturnStatement(n); }), currencyVariables)) { currencyVariables.add(node.id.name); } }, VariableDeclarator: function VariableDeclarator(_ref3) { var scope = _ref3.scope, node = _ref3.node; if (expressionCallsCurrency(node.init, currencyVariables)) { var binding = scope.bindings[node.id.name] || {}; if (binding.kind !== 'let' || binding.kind === 'let' && binding.scope === refPath.scope) { currencyVariables.add(node.id.name); } } }, AssignmentExpression: function AssignmentExpression(_ref4) { var node = _ref4.node; var left = node.left, right = node.right; if (!expressionCallsCurrency(right, currencyVariables)) { currencyVariables["delete"](left.name); } else { currencyVariables.add(left.name); } } }; // Attempt to find any currency variables in scope var currentPath = refPath.parentPath; while (currentPath) { currentPath.traverse(Visitors); currentPath = currentPath.parentPath; } return node && expressionCallsCurrency(node, currencyVariables); } function buildExpression(path, methodName) { var node = path.node, operator = node.operator, left = node.left, right = node.right; if (t.isBinaryExpression(left)) { left = buildExpression(path.get('left')); } var currencyMethod = arithmeticOperators[operator]; if (currencyMethod) { return t.callExpression(t.memberExpression(t.isIdentifier(left) ? t.identifier(left.name) : left, t.identifier(currencyMethod)), [right]); } else if (compareOperators.includes(operator) && !t.isMemberExpression(node.left)) { return t.binaryExpression(operator, t.memberExpression(left, t.identifier('value')), pathContainsCurrency(path.get('right'), methodName) ? t.memberExpression(right, t.identifier('value')) : right); } else { return node; } } return { pre: function pre(_ref5) { var opts = _ref5.opts; var filename = opts.filename, pluginOptions = this.opts, paths = Array.isArray(pluginOptions.customCurrency) ? pluginOptions.customCurrency.filter(function (path) { return typeof path === 'string'; }) : typeof pluginOptions.customCurrency === 'string' ? [pluginOptions.customCurrency] : []; this.currencyResolution = new Set(['currency.js'].concat(_toConsumableArray(paths.map(function (path) { return resolveRelativePath(filename, path); })))); }, visitor: { VariableDeclarator: function VariableDeclarator(_ref6, _ref7) { var node = _ref6.node; var opts = _ref7.opts, currencyResolution = _ref7.currencyResolution; var init = node.init; if (t.isCallExpression(init) && init.callee.name === 'require' && currencyResolution.has(init.arguments[0].value)) { opts.hasCurrency = true; opts.methodName = node.id.name; } return; }, ImportDeclaration: function ImportDeclaration(_ref8, _ref9) { var node = _ref8.node; var opts = _ref9.opts, currencyResolution = _ref9.currencyResolution; var source = node.source, specifiers = node.specifiers; if (currencyResolution.has(source.value)) { var defaultImport = specifiers.find(function (specifier) { return t.isImportDefaultSpecifier(specifier); }); opts.hasCurrency = true; opts.methodName = defaultImport.local.name; } return; }, BinaryExpression: function BinaryExpression(path, _ref10) { var opts = _ref10.opts; if (opts.hasCurrency && pathContainsCurrency(path.get('left'), opts.methodName)) { // Prevent replacement nodes from being visited multiple times path.stop(); path.replaceWith(buildExpression(path, opts.methodName)); return; } return; } } }; } module.exports = transformCurrencyOperators;