From b10e7de5af444016a6a807702f6ed3447dafc19f Mon Sep 17 00:00:00 2001 From: thepassle Date: Fri, 19 Jul 2024 11:29:58 +0200 Subject: [PATCH] refactor: abstract array methods --- codemods/array.prototype.at/index.js | 51 +++++++------------- codemods/array.prototype.concat/index.js | 34 ++++---------- codemods/array.prototype.every/index.js | 34 ++++---------- codemods/array.prototype.filter/index.js | 34 ++++---------- codemods/array.prototype.find/index.js | 34 ++++---------- codemods/array.prototype.findIndex/index.js | 34 ++++---------- codemods/array.prototype.flat/index.js | 34 ++++---------- codemods/array.prototype.flatMap/index.js | 34 ++++---------- codemods/array.prototype.map/index.js | 48 ++++++------------- codemods/array.prototype.some/index.js | 52 +++++++-------------- codemods/shared.js | 37 +++++++++++++++ 11 files changed, 142 insertions(+), 284 deletions(-) diff --git a/codemods/array.prototype.at/index.js b/codemods/array.prototype.at/index.js index eb4b8b9..9d90d4e 100644 --- a/codemods/array.prototype.at/index.js +++ b/codemods/array.prototype.at/index.js @@ -1,5 +1,5 @@ -import jscodeshift from "jscodeshift"; -import { removeImport } from "../shared.js"; +import jscodeshift from 'jscodeshift'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -18,39 +18,20 @@ import { removeImport } from "../shared.js"; * @returns {Codemod} */ export default function (options) { - return { - name: "array.prototype.at", - transform: ({ file }) => { - const j = jscodeshift; - const root = j(file.source); - let dirtyFlag = false; + return { + name: 'array.prototype.at', + transform: ({ file }) => { + const j = jscodeshift; + const root = j(file.source); - const { identifier } = removeImport("array.prototype.at", root, j); + const dirty = transformArrayMethod( + 'array.prototype.at', + 'at', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: "Identifier", - name: identifier, - }, - }) - .forEach((path) => { - const [arrayArg, indexArg] = path.node.arguments; - if ( - j.Identifier.check(arrayArg) || - j.ArrayExpression.check(arrayArg) - ) { - path.replace( - j.callExpression( - j.memberExpression(arrayArg, j.identifier("at")), - [indexArg] - ) - ); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; - }, - }; + return dirty ? root.toSource(options) : file.source; + }, + }; } diff --git a/codemods/array.prototype.concat/index.js b/codemods/array.prototype.concat/index.js index c7fd293..1c20ed7 100644 --- a/codemods/array.prototype.concat/index.js +++ b/codemods/array.prototype.concat/index.js @@ -1,5 +1,5 @@ import jscodeshift from 'jscodeshift'; -import { removeImport } from '../shared.js'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -16,33 +16,15 @@ export default function (options) { transform: ({ file }) => { const j = jscodeshift; const root = j(file.source); - let dirtyFlag = false; - const { identifier } = removeImport('array.prototype.concat', root, j); + const dirty = transformArrayMethod( + 'array.prototype.concat', + 'concat', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }) - .forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('concat')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; + return dirty ? root.toSource(options) : file.source; }, }; } diff --git a/codemods/array.prototype.every/index.js b/codemods/array.prototype.every/index.js index dc8ec43..bc9fefe 100644 --- a/codemods/array.prototype.every/index.js +++ b/codemods/array.prototype.every/index.js @@ -1,5 +1,5 @@ import jscodeshift from 'jscodeshift'; -import { removeImport } from '../shared.js'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -16,33 +16,15 @@ export default function (options) { transform: ({ file }) => { const j = jscodeshift; const root = j(file.source); - let dirtyFlag = false; - const { identifier } = removeImport('array.prototype.every', root, j); + const dirty = transformArrayMethod( + 'array.prototype.every', + 'every', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }) - .forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('every')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; + return dirty ? root.toSource(options) : file.source; }, }; } diff --git a/codemods/array.prototype.filter/index.js b/codemods/array.prototype.filter/index.js index 8634916..834cd35 100644 --- a/codemods/array.prototype.filter/index.js +++ b/codemods/array.prototype.filter/index.js @@ -1,5 +1,5 @@ import jscodeshift from 'jscodeshift'; -import { removeImport } from '../shared.js'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -16,33 +16,15 @@ export default function (options) { transform: ({ file }) => { const j = jscodeshift; const root = j(file.source); - let dirtyFlag = false; - const { identifier } = removeImport('array.prototype.filter', root, j); + const dirty = transformArrayMethod( + 'array.prototype.filter', + 'filter', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }) - .forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('filter')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; + return dirty ? root.toSource(options) : file.source; }, }; } diff --git a/codemods/array.prototype.find/index.js b/codemods/array.prototype.find/index.js index 2cd12c0..3b69180 100644 --- a/codemods/array.prototype.find/index.js +++ b/codemods/array.prototype.find/index.js @@ -1,5 +1,5 @@ import jscodeshift from 'jscodeshift'; -import { removeImport } from '../shared.js'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -16,33 +16,15 @@ export default function (options) { transform: ({ file }) => { const j = jscodeshift; const root = j(file.source); - let dirtyFlag = false; - const { identifier } = removeImport('array.prototype.find', root, j); + const dirty = transformArrayMethod( + 'array.prototype.find', + 'find', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }) - .forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('find')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; + return dirty ? root.toSource(options) : file.source; }, }; } diff --git a/codemods/array.prototype.findIndex/index.js b/codemods/array.prototype.findIndex/index.js index 390a273..0a885fd 100644 --- a/codemods/array.prototype.findIndex/index.js +++ b/codemods/array.prototype.findIndex/index.js @@ -1,5 +1,5 @@ import jscodeshift from 'jscodeshift'; -import { removeImport } from '../shared.js'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -16,33 +16,15 @@ export default function (options) { transform: ({ file }) => { const j = jscodeshift; const root = j(file.source); - let dirtyFlag = false; - const { identifier } = removeImport('array.prototype.findIndex', root, j); + const dirty = transformArrayMethod( + 'array.prototype.findIndex', + 'findIndex', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }) - .forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('findIndex')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; + return dirty ? root.toSource(options) : file.source; }, }; } diff --git a/codemods/array.prototype.flat/index.js b/codemods/array.prototype.flat/index.js index ba35df8..f276471 100644 --- a/codemods/array.prototype.flat/index.js +++ b/codemods/array.prototype.flat/index.js @@ -1,5 +1,5 @@ import jscodeshift from 'jscodeshift'; -import { removeImport } from '../shared.js'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -16,33 +16,15 @@ export default function (options) { transform: ({ file }) => { const j = jscodeshift; const root = j(file.source); - let dirtyFlag = false; - const { identifier } = removeImport('array.prototype.flat', root, j); + const dirty = transformArrayMethod( + 'array.prototype.flat', + 'flat', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }) - .forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('flat')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; + return dirty ? root.toSource(options) : file.source; }, }; } diff --git a/codemods/array.prototype.flatMap/index.js b/codemods/array.prototype.flatMap/index.js index fee9295..afa5ca2 100644 --- a/codemods/array.prototype.flatMap/index.js +++ b/codemods/array.prototype.flatMap/index.js @@ -1,5 +1,5 @@ import jscodeshift from 'jscodeshift'; -import { removeImport } from '../shared.js'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -16,33 +16,15 @@ export default function (options) { transform: ({ file }) => { const j = jscodeshift; const root = j(file.source); - let dirtyFlag = false; - const { identifier } = removeImport('array.prototype.flatMap', root, j); + const dirty = transformArrayMethod( + 'array.prototype.flatMap', + 'flatMap', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }) - .forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('flatMap')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; + return dirty ? root.toSource(options) : file.source; }, }; } diff --git a/codemods/array.prototype.map/index.js b/codemods/array.prototype.map/index.js index f1d0580..6d0f573 100644 --- a/codemods/array.prototype.map/index.js +++ b/codemods/array.prototype.map/index.js @@ -1,5 +1,5 @@ import jscodeshift from 'jscodeshift'; -import { removeImport } from '../shared.js'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -11,38 +11,20 @@ import { removeImport } from '../shared.js'; * @returns {Codemod} */ export default function (options) { - return { - name: 'array.prototype.map', - transform: ({ file }) => { - const j = jscodeshift; - const root = j(file.source); - let dirtyFlag = false; + return { + name: 'array.prototype.map', + transform: ({ file }) => { + const j = jscodeshift; + const root = j(file.source); - const { identifier } = removeImport('array.prototype.map', root, j); + const dirty = transformArrayMethod( + 'array.prototype.map', + 'map', + root, + j, + ); - root - .find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }) - .forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('map')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; - }, - }; + return dirty ? root.toSource(options) : file.source; + }, + }; } diff --git a/codemods/array.prototype.some/index.js b/codemods/array.prototype.some/index.js index 0561dab..57e5d45 100644 --- a/codemods/array.prototype.some/index.js +++ b/codemods/array.prototype.some/index.js @@ -1,5 +1,5 @@ -import jscodeshift from "jscodeshift"; -import { removeImport } from "../shared.js"; +import jscodeshift from 'jscodeshift'; +import { transformArrayMethod } from '../shared.js'; /** * @typedef {import('../../types.js').Codemod} Codemod @@ -10,37 +10,21 @@ import { removeImport } from "../shared.js"; * @param {CodemodOptions} [options] * @returns {Codemod} */ -export default function(options) { - return { - name: 'array.prototype.some', - transform: ({ file }) => { - const j = jscodeshift; - const root = j(file.source); - let dirtyFlag = false; +export default function (options) { + return { + name: 'array.prototype.some', + transform: ({ file }) => { + const j = jscodeshift; + const root = j(file.source); - const { identifier } = removeImport('array.prototype.some', root, j); + const dirty = transformArrayMethod( + 'array.prototype.some', + 'some', + root, + j, + ); - root.find(j.CallExpression, { - callee: { - type: 'Identifier', - name: identifier, - }, - }).forEach((path) => { - const args = path.value.arguments; - if (args.length === 2) { - const [array, callback] = args; - - const newExpression = j.callExpression( - //@ts-ignore - j.memberExpression(array, j.identifier('some')), - [callback], - ); - j(path).replaceWith(newExpression); - dirtyFlag = true; - } - }); - - return dirtyFlag ? root.toSource(options) : file.source; - }, - } -}; + return dirty ? root.toSource(options) : file.source; + }, + }; +} diff --git a/codemods/shared.js b/codemods/shared.js index 8cf8af0..19f6ad8 100644 --- a/codemods/shared.js +++ b/codemods/shared.js @@ -45,3 +45,40 @@ export function removeImport(name, root, j) { return { identifier }; } + +/** + * @param {string} method - e.g. `array.prototype.flatMap` + * @param {string} identifierName - e.g. `flatMap` + * @param {import("jscodeshift").Collection} root - package name to remove import/require calls for + * @param {import("jscodeshift").JSCodeshift} j - jscodeshift instance + * @returns + */ +export function transformArrayMethod(method, identifierName, root, j) { + const { identifier } = removeImport(method, root, j); + + let dirtyFlag = false; + root + .find(j.CallExpression, { + callee: { + type: "Identifier", + name: identifier, + }, + }) + .forEach((path) => { + const [arrayArg, indexArg] = path.node.arguments; + if ( + j.Identifier.check(arrayArg) || + j.ArrayExpression.check(arrayArg) + ) { + path.replace( + j.callExpression( + j.memberExpression(arrayArg, j.identifier(identifierName)), + [indexArg] + ) + ); + dirtyFlag = true; + } + }); + + return dirtyFlag; +} \ No newline at end of file