Skip to content

Commit

Permalink
abstract out utils
Browse files Browse the repository at this point in the history
  • Loading branch information
planttheidea committed Dec 16, 2023
1 parent c9ba520 commit 0c2251a
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 136 deletions.
153 changes: 17 additions & 136 deletions src/inline-loops.macro.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
const { MacroError, createMacro } = require('babel-plugin-macros');
const { createTemplates } = require('./templates');
const { createTraverseConfigs } = require('./traverse');
const { rename } = require('./utils');
const {
getCachedFnArgs,
getLocalName,
handleArrowFunctionExpressionUse,
handleInvalidUsage,
processNestedInlineLoopMacros,
rename,
replaceOrRemove,
} = require('./utils');

function myMacro({ references, babel }) {
const { template, types: t } = babel;
Expand Down Expand Up @@ -66,68 +74,6 @@ function myMacro({ references, babel }) {
someRight: createHandleEverySome('some-right'),
};

function getImportedHandlerName(callee) {
const binding = callee.scope.getBinding(callee.node.name);

if (!binding) {
return;
}

const owner = binding.path;

if (owner.isImportSpecifier()) {
const imported = owner.get('imported');
const name = imported.node.name;

if (!Object.keys(handlers).some((handler) => handler === name)) {
return;
}

const importSource = owner.parentPath.get('source.value');

if (!importSource.node.endsWith('inline-loops.macro')) {
return;
}

return name;
}

if (owner.isVariableDeclarator()) {
const init = owner.get('init');

if (
!init.isCallExpression() ||
!init.get('callee').isIdentifier({ name: 'require' })
) {
return;
}

const requireSource = init.get('arguments.0.value');

if (!requireSource.node.endsWith('inline-loops.macro')) {
return;
}

const imported = owner
.get('id.properties')
.find((property) =>
property.get('value').isIdentifier({ name: callee.node.name }),
);

if (!imported) {
return;
}

const name = imported.get('key').node.name;

if (!Object.keys(handlers).some((handler) => handler === name)) {
return;
}

return name;
}
}

function getInjectedBodyAndLogic({
callback,
isForEach,
Expand Down Expand Up @@ -216,16 +162,6 @@ function myMacro({ references, babel }) {
return { injectedBody: [], logic };
}

function getCachedFnArgs(local, isReduce) {
return isReduce
? [local.accumulated, local.value, local.key, local.collection]
: [local.value, local.key, local.collection];
}

function getLocalName(path, name = path.node.name) {
return path.scope.generateUidIdentifier(name);
}

function getLocalReferences(path, statement, isReduce) {
const args = path.get('arguments');

Expand Down Expand Up @@ -317,61 +253,6 @@ function myMacro({ references, babel }) {
};
}

function handleArrowFunctionExpressionUse(path) {
if (path.parentPath.isArrowFunctionExpression()) {
path.parentPath.arrowFunctionToExpression({
allowInsertArrow: false,
noNewArrows: true,
});
}
}

function handleInvalidUsage(path) {
const [collection, callback] = path.get('arguments');

if (collection.isSpreadElement()) {
throw new MacroError(
'You cannot use spread arguments with `inline-loops.macro`; please declare the arguments explicitly.',
);
}

const importedHandlerName = getImportedHandlerName(callback);

if (importedHandlerName) {
throw new MacroError(
'You cannot use a method from `inline-loops.macro` directly as a handler; please wrap it in a function call.',
);
}
}

function processNestedInlineLoopMacros(path) {
if (!path.isCallExpression()) {
return;
}

const callee = path.get('callee');

if (!callee.isIdentifier()) {
return;
}

const importedHandlerName = getImportedHandlerName(callee);

if (importedHandlerName) {
handlers[importedHandlerName](path.get('callee'));
}
}

function replaceOrRemove(path, replacement) {
const parentPath = path.parentPath;

if (parentPath.isExpressionStatement()) {
path.remove();
} else {
path.replaceWith(replacement);
}
}

function createHandleEverySome(type) {
return function handleFilter(referencePath) {
const path = referencePath.parentPath;
Expand All @@ -380,12 +261,12 @@ function myMacro({ references, babel }) {
return;
}

handleInvalidUsage(path);
handleInvalidUsage({ handlers, path });
handleArrowFunctionExpressionUse(path);

const [collection, callback] = path.get('arguments');

processNestedInlineLoopMacros(collection);
processNestedInlineLoopMacros(collection, handlers);

const statement = path.getStatementParent();
const local = getLocalReferences(path, statement);
Expand Down Expand Up @@ -495,12 +376,12 @@ function myMacro({ references, babel }) {
return;
}

handleInvalidUsage(path);
handleInvalidUsage({ handlers, path });
handleArrowFunctionExpressionUse(path);

const [collection, callback] = path.get('arguments');

processNestedInlineLoopMacros(collection);
processNestedInlineLoopMacros(collection, handlers);

const statement = path.getStatementParent();
const local = getLocalReferences(path, statement);
Expand Down Expand Up @@ -610,12 +491,12 @@ function myMacro({ references, babel }) {
return;
}

handleInvalidUsage(path);
handleInvalidUsage({ handlers, path });
handleArrowFunctionExpressionUse(path);

const [collection, callback] = path.get('arguments');

processNestedInlineLoopMacros(collection);
processNestedInlineLoopMacros(collection, handlers);

const statement = path.getStatementParent();
const local = getLocalReferences(path, statement);
Expand Down Expand Up @@ -778,12 +659,12 @@ function myMacro({ references, babel }) {
return;
}

handleInvalidUsage(path);
handleInvalidUsage({ handlers, path });
handleArrowFunctionExpressionUse(path);

const [collection, callback, initialValue] = path.get('arguments');

processNestedInlineLoopMacros(collection);
processNestedInlineLoopMacros(collection, handlers);

const statement = path.getStatementParent();
const local = getLocalReferences(path, statement, true);
Expand Down
136 changes: 136 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,143 @@
const { MacroError } = require('babel-plugin-macros');

function getCachedFnArgs(local, isReduce) {
return isReduce
? [local.accumulated, local.value, local.key, local.collection]
: [local.value, local.key, local.collection];
}

function getImportedHandlerName(callee, handlers) {
const binding = callee.scope.getBinding(callee.node.name);

if (!binding) {
return;
}

const owner = binding.path;

if (owner.isImportSpecifier()) {
const imported = owner.get('imported');
const name = imported.node.name;

if (!Object.keys(handlers).some((handler) => handler === name)) {
return;
}

const importSource = owner.parentPath.get('source.value');

if (!importSource.node.endsWith('inline-loops.macro')) {
return;
}

return name;
}

if (owner.isVariableDeclarator()) {
const init = owner.get('init');

if (
!init.isCallExpression() ||
!init.get('callee').isIdentifier({ name: 'require' })
) {
return;
}

const requireSource = init.get('arguments.0.value');

if (!requireSource.node.endsWith('inline-loops.macro')) {
return;
}

const imported = owner
.get('id.properties')
.find((property) =>
property.get('value').isIdentifier({ name: callee.node.name }),
);

if (!imported) {
return;
}

const name = imported.get('key').node.name;

if (!Object.keys(handlers).some((handler) => handler === name)) {
return;
}

return name;
}
}

function getLocalName(path, name = path.node.name) {
return path.scope.generateUidIdentifier(name);
}

function handleArrowFunctionExpressionUse(path) {
if (path.parentPath.isArrowFunctionExpression()) {
path.parentPath.arrowFunctionToExpression({
allowInsertArrow: false,
noNewArrows: true,
});
}
}

function handleInvalidUsage({ handlers, path }) {
const [collection, callback] = path.get('arguments');

if (collection.isSpreadElement()) {
throw new MacroError(
'You cannot use spread arguments with `inline-loops.macro`; please declare the arguments explicitly.',
);
}

const importedHandlerName = getImportedHandlerName(callback, handlers);

if (importedHandlerName) {
throw new MacroError(
'You cannot use a method from `inline-loops.macro` directly as a handler; please wrap it in a function call.',
);
}
}

function processNestedInlineLoopMacros(path, handlers) {
if (!path.isCallExpression()) {
return;
}

const callee = path.get('callee');

if (!callee.isIdentifier()) {
return;
}

const importedHandlerName = getImportedHandlerName(callee, handlers);

if (importedHandlerName) {
handlers[importedHandlerName](path.get('callee'));
}
}

function rename(path, newName) {
path.scope.rename(path.node.name, newName);
}

function replaceOrRemove(path, replacement) {
const parentPath = path.parentPath;

if (parentPath.isExpressionStatement()) {
path.remove();
} else {
path.replaceWith(replacement);
}
}

module.exports = {
getCachedFnArgs,
getImportedHandlerName,
getLocalName,
handleArrowFunctionExpressionUse,
handleInvalidUsage,
processNestedInlineLoopMacros,
rename,
replaceOrRemove,
};

0 comments on commit 0c2251a

Please sign in to comment.