UNPKG

@jesobreira/babel-plugin-transform-currency-operators

Version:

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

209 lines (163 loc) 6.49 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var path = _interopDefault(require('path')); 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 = './' + relativePathToImport; } return relativePathToImport; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 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$$1, methodName) { var node = path$$1.node, operator = node.operator, left = node.left, right = node.right; if (t.isBinaryExpression(left)) { left = buildExpression(path$$1.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$$1.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, paths = Array.isArray(this.opts) ? this.opts.map(function (path$$1) { return resolveRelativePath(filename, path$$1); }) : []; this.currencyResolution = new Set(['currency.js'].concat(_toConsumableArray(paths))); }, 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$$1, _ref10) { var opts = _ref10.opts; if (opts.hasCurrency && pathContainsCurrency(path$$1.get('left'), opts.methodName)) { // Prevent replacement nodes from being visited multiple times path$$1.stop(); path$$1.replaceWith(buildExpression(path$$1, opts.methodName)); return; } return; } } }; } module.exports = transformCurrencyOperators;