From d59ff170841a92a7b64f4b0656e538da3ef9e4c0 Mon Sep 17 00:00:00 2001 From: thepassle Date: Wed, 17 Jul 2024 18:55:05 +0200 Subject: [PATCH] feat: add is-date-object --- codemods/index.js | 9 ++- codemods/is-date-object/index.js | 67 +++++++++++++++++++ scripts/scaffold-codemod.js | 2 +- test/fixtures/is-date-object/case-1/after.js | 15 +++++ test/fixtures/is-date-object/case-1/before.js | 16 +++++ test/fixtures/is-date-object/case-1/result.js | 15 +++++ test/fixtures/is-date-object/case-2/after.js | 15 +++++ test/fixtures/is-date-object/case-2/before.js | 16 +++++ test/fixtures/is-date-object/case-2/result.js | 15 +++++ 9 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 codemods/is-date-object/index.js create mode 100644 test/fixtures/is-date-object/case-1/after.js create mode 100644 test/fixtures/is-date-object/case-1/before.js create mode 100644 test/fixtures/is-date-object/case-1/result.js create mode 100644 test/fixtures/is-date-object/case-2/after.js create mode 100644 test/fixtures/is-date-object/case-2/before.js create mode 100644 test/fixtures/is-date-object/case-2/result.js diff --git a/codemods/index.js b/codemods/index.js index c612b07..3ae8d9a 100644 --- a/codemods/index.js +++ b/codemods/index.js @@ -4,8 +4,11 @@ import isArrayBuffer from './is-array-buffer/index.js'; import isBooleanObject from './is-boolean-object/index.js'; +import isDateObject from './is-date-object/index.js'; + export const codemods = { - 'is-whitespace': isWhitespace, - 'is-array-buffer': isArrayBuffer, - 'is-boolean-object': isBooleanObject, + 'is-whitespace': isWhitespace, + 'is-array-buffer': isArrayBuffer, + 'is-boolean-object': isBooleanObject, + 'is-date-object': isDateObject }; diff --git a/codemods/is-date-object/index.js b/codemods/is-date-object/index.js new file mode 100644 index 0000000..9d54055 --- /dev/null +++ b/codemods/is-date-object/index.js @@ -0,0 +1,67 @@ +import jscodeshift from 'jscodeshift'; +import { removeImport } from '../shared.js'; + +/** + * @typedef {import('../../types.js').Codemod} Codemod + * @typedef {import('../../types.js').CodemodOptions} CodemodOptions + */ + +/** + * @param {CodemodOptions} [options] + * @returns {Codemod} + */ +export default function (options) { + return { + name: 'is-date-object', + transform: ({ file }) => { + const j = jscodeshift; + const root = j(file.source); + + removeImport('is-date-object', root, j); + + // Replace all calls to isDate with Object.prototype.toString.call + root + .find(j.CallExpression, { + callee: { + type: 'Identifier', + name: 'isDate', + }, + }) + .replaceWith((path) => { + const arg = path.node.arguments[0]; + return j.callExpression( + j.memberExpression( + j.memberExpression( + j.memberExpression( + j.identifier('Object'), + j.identifier('prototype'), + ), + j.identifier('toString'), + ), + j.identifier('call'), + ), + [arg], + ); + }) + .forEach((path) => { + const parent = path.parent.node; + if (j.BinaryExpression.check(parent)) { + parent.operator = '==='; + parent.right = j.literal('[object Date]'); + } else if ( + j.CallExpression.check(parent) && + parent.arguments.length === 1 + ) { + const newExpression = j.binaryExpression( + '===', + path.node, + j.literal('[object Date]'), + ); + parent.arguments[0] = newExpression; + } + }); + + return root.toSource({ quote: 'single' }); + }, + }; +} diff --git a/scripts/scaffold-codemod.js b/scripts/scaffold-codemod.js index 0712a48..e55ee90 100644 --- a/scripts/scaffold-codemod.js +++ b/scripts/scaffold-codemod.js @@ -44,7 +44,7 @@ fs.writeFileSync( export default function(options) { return { name: '${name}', - transform: ({ file, jscodeshift }) => { + transform: ({ file }) => { return ''; }, } diff --git a/test/fixtures/is-date-object/case-1/after.js b/test/fixtures/is-date-object/case-1/after.js new file mode 100644 index 0000000..85c3f5d --- /dev/null +++ b/test/fixtures/is-date-object/case-1/after.js @@ -0,0 +1,15 @@ +var assert = require('assert'); + +assert.notOk(Object.prototype.toString.call(undefined) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(null) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(false) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(true) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(42) === '[object Date]'); +assert.notOk(Object.prototype.toString.call('foo') === '[object Date]'); +assert.notOk(Object.prototype.toString.call(function () {}) === '[object Date]'); +assert.notOk(Object.prototype.toString.call([]) === '[object Date]'); +assert.notOk(Object.prototype.toString.call({}) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(/a/g) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(new RegExp('a', 'g')) === '[object Date]'); + +assert.ok(Object.prototype.toString.call(new Date()) === '[object Date]'); diff --git a/test/fixtures/is-date-object/case-1/before.js b/test/fixtures/is-date-object/case-1/before.js new file mode 100644 index 0000000..63241cd --- /dev/null +++ b/test/fixtures/is-date-object/case-1/before.js @@ -0,0 +1,16 @@ +var assert = require('assert'); +var isDate = require('is-date-object'); + +assert.notOk(isDate(undefined)); +assert.notOk(isDate(null)); +assert.notOk(isDate(false)); +assert.notOk(isDate(true)); +assert.notOk(isDate(42)); +assert.notOk(isDate('foo')); +assert.notOk(isDate(function () {})); +assert.notOk(isDate([])); +assert.notOk(isDate({})); +assert.notOk(isDate(/a/g)); +assert.notOk(isDate(new RegExp('a', 'g'))); + +assert.ok(isDate(new Date())); diff --git a/test/fixtures/is-date-object/case-1/result.js b/test/fixtures/is-date-object/case-1/result.js new file mode 100644 index 0000000..85c3f5d --- /dev/null +++ b/test/fixtures/is-date-object/case-1/result.js @@ -0,0 +1,15 @@ +var assert = require('assert'); + +assert.notOk(Object.prototype.toString.call(undefined) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(null) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(false) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(true) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(42) === '[object Date]'); +assert.notOk(Object.prototype.toString.call('foo') === '[object Date]'); +assert.notOk(Object.prototype.toString.call(function () {}) === '[object Date]'); +assert.notOk(Object.prototype.toString.call([]) === '[object Date]'); +assert.notOk(Object.prototype.toString.call({}) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(/a/g) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(new RegExp('a', 'g')) === '[object Date]'); + +assert.ok(Object.prototype.toString.call(new Date()) === '[object Date]'); diff --git a/test/fixtures/is-date-object/case-2/after.js b/test/fixtures/is-date-object/case-2/after.js new file mode 100644 index 0000000..ff9886b --- /dev/null +++ b/test/fixtures/is-date-object/case-2/after.js @@ -0,0 +1,15 @@ +import assert from 'assert'; + +assert.notOk(Object.prototype.toString.call(undefined) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(null) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(false) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(true) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(42) === '[object Date]'); +assert.notOk(Object.prototype.toString.call('foo') === '[object Date]'); +assert.notOk(Object.prototype.toString.call(function () {}) === '[object Date]'); +assert.notOk(Object.prototype.toString.call([]) === '[object Date]'); +assert.notOk(Object.prototype.toString.call({}) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(/a/g) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(new RegExp('a', 'g')) === '[object Date]'); + +assert.ok(Object.prototype.toString.call(new Date()) === '[object Date]'); diff --git a/test/fixtures/is-date-object/case-2/before.js b/test/fixtures/is-date-object/case-2/before.js new file mode 100644 index 0000000..8b8711e --- /dev/null +++ b/test/fixtures/is-date-object/case-2/before.js @@ -0,0 +1,16 @@ +import assert from 'assert'; +import isDate from 'is-date-object'; + +assert.notOk(isDate(undefined)); +assert.notOk(isDate(null)); +assert.notOk(isDate(false)); +assert.notOk(isDate(true)); +assert.notOk(isDate(42)); +assert.notOk(isDate('foo')); +assert.notOk(isDate(function () {})); +assert.notOk(isDate([])); +assert.notOk(isDate({})); +assert.notOk(isDate(/a/g)); +assert.notOk(isDate(new RegExp('a', 'g'))); + +assert.ok(isDate(new Date())); diff --git a/test/fixtures/is-date-object/case-2/result.js b/test/fixtures/is-date-object/case-2/result.js new file mode 100644 index 0000000..ff9886b --- /dev/null +++ b/test/fixtures/is-date-object/case-2/result.js @@ -0,0 +1,15 @@ +import assert from 'assert'; + +assert.notOk(Object.prototype.toString.call(undefined) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(null) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(false) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(true) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(42) === '[object Date]'); +assert.notOk(Object.prototype.toString.call('foo') === '[object Date]'); +assert.notOk(Object.prototype.toString.call(function () {}) === '[object Date]'); +assert.notOk(Object.prototype.toString.call([]) === '[object Date]'); +assert.notOk(Object.prototype.toString.call({}) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(/a/g) === '[object Date]'); +assert.notOk(Object.prototype.toString.call(new RegExp('a', 'g')) === '[object Date]'); + +assert.ok(Object.prototype.toString.call(new Date()) === '[object Date]');