mirror of
https://github.com/toss/es-toolkit.git
synced 2024-12-01 02:33:54 +03:00
chore(script): enhance transforming lodash test codes script (#546)
* Handle import lodash methods * Supports assert.deepStrictEqual * Enhance brokenSyntax * Update assert * Enhance import * Enhance Error log * Enhance brokenSyntax and add commenting delete local variable
This commit is contained in:
parent
c21874ef3b
commit
f53bfd5c34
@ -1,21 +1,54 @@
|
|||||||
export function formatBrokenSyntax(source: string): string {
|
function fixExpectFunction(source: string): string {
|
||||||
// Fix broken syntax
|
const expectMatched = source.match(/expect(\(.+\)).toEqual.+\);/g);
|
||||||
const brokenMatched = source.match(/(?<=,)[\s\d\w?]+\[.+\).toEqual\((?!\[).+\]\);/g);
|
|
||||||
if (brokenMatched != null) {
|
if (!expectMatched) {
|
||||||
for (const match of brokenMatched) {
|
return source;
|
||||||
const splited = match.split(').toEqual(');
|
|
||||||
const formatted = `).toEqual(${splited.join(', ')}`;
|
|
||||||
source = source.replace(match, formatted);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove deleting local variable
|
const splitMatched = expectMatched.map(match => match.split('.toEqual('));
|
||||||
const deleteMatched = source.match(/delete [\w\d]+;/g);
|
const brokenSyntax = splitMatched.map(([expect]) => {
|
||||||
if (deleteMatched != null) {
|
let count = 0;
|
||||||
for (const match of deleteMatched) {
|
|
||||||
source = source.replace(match, '');
|
for (const char of expect) {
|
||||||
|
if (['(', '{', '['].includes(char)) {
|
||||||
|
count++;
|
||||||
|
} else if ([')', '}', ']'].includes(char)) {
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 0; i < expectMatched.length; i++) {
|
||||||
|
if (brokenSyntax[i]) {
|
||||||
|
const front = splitMatched[i][0];
|
||||||
|
const startWithBracket = front.match(/expect\([{[].+[}\]],/);
|
||||||
|
const startWithFunction = front.match(/expect\(.+\(.+\),/);
|
||||||
|
|
||||||
|
const start = startWithFunction
|
||||||
|
? startWithFunction[0].length
|
||||||
|
: startWithBracket
|
||||||
|
? startWithBracket[0].length
|
||||||
|
: front.indexOf(',') + 1;
|
||||||
|
const fixed = `${front.slice(0, start)}).toEqual(${front.slice(start, front.length - 1)}, ${splitMatched[i][1]}`;
|
||||||
|
|
||||||
|
source = source.replace(expectMatched[i], fixed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatBrokenSyntax(source: string): string {
|
||||||
|
// Fix broken syntax
|
||||||
|
source = fixExpectFunction(source);
|
||||||
|
|
||||||
|
// `delete localvariable` to comment
|
||||||
|
source = source.replace(
|
||||||
|
/delete [^.[\]]+;/g,
|
||||||
|
match => `// Deleting local variable in strict mode. So commenting it out.\n// ${match}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
53
.scripts/tests/_internal/transform/assert.ts
Normal file
53
.scripts/tests/_internal/transform/assert.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import type { Collection, JSCodeshift } from 'jscodeshift';
|
||||||
|
|
||||||
|
export function transformAssert(root: Collection, jscodeshift: JSCodeshift): void {
|
||||||
|
// Change `assert.deepStrictEqual(a, b, c)` to `expect(a, c).toEqual(b)`
|
||||||
|
root
|
||||||
|
.find(jscodeshift.CallExpression, {
|
||||||
|
callee: {
|
||||||
|
type: 'MemberExpression',
|
||||||
|
object: {
|
||||||
|
name: 'assert',
|
||||||
|
},
|
||||||
|
property: {
|
||||||
|
type: 'Identifier',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.replaceWith(({ node }) => {
|
||||||
|
if (node.callee.type === 'MemberExpression' && node.callee.property.type === 'Identifier') {
|
||||||
|
const expectArguments =
|
||||||
|
node.arguments.length === 3 ? [node.arguments[0], node.arguments[2]] : [node.arguments[0]];
|
||||||
|
const expect = jscodeshift.callExpression(jscodeshift.identifier('expect'), expectArguments);
|
||||||
|
|
||||||
|
switch (node.callee.property.name) {
|
||||||
|
case 'deepStrictEqual':
|
||||||
|
return jscodeshift.memberExpression(
|
||||||
|
expect,
|
||||||
|
jscodeshift.callExpression(jscodeshift.identifier('toEqual'), [node.arguments[1]])
|
||||||
|
);
|
||||||
|
case 'deepEqual':
|
||||||
|
return jscodeshift.memberExpression(
|
||||||
|
expect,
|
||||||
|
jscodeshift.callExpression(jscodeshift.identifier('toEqual'), [node.arguments[1]])
|
||||||
|
);
|
||||||
|
case 'strictEqual':
|
||||||
|
return jscodeshift.memberExpression(
|
||||||
|
expect,
|
||||||
|
jscodeshift.callExpression(jscodeshift.identifier('toBe'), [node.arguments[1]])
|
||||||
|
);
|
||||||
|
case 'notEqual':
|
||||||
|
return jscodeshift.memberExpression(
|
||||||
|
expect,
|
||||||
|
jscodeshift.callExpression(jscodeshift.identifier('not.toBe'), [node.arguments[1]])
|
||||||
|
);
|
||||||
|
case 'notStrictEqual':
|
||||||
|
return jscodeshift.memberExpression(
|
||||||
|
expect,
|
||||||
|
jscodeshift.callExpression(jscodeshift.identifier('not.toBe'), [node.arguments[1]])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
}
|
@ -35,15 +35,44 @@ export function transformImport(root: Collection, jscodeshift: JSCodeshift): voi
|
|||||||
.remove();
|
.remove();
|
||||||
|
|
||||||
// Add import { describe, it, expect } from 'vitest';
|
// Add import { describe, it, expect } from 'vitest';
|
||||||
const vitestImport = jscodeshift.importDeclaration(
|
const vitestImport = root.find(jscodeshift.ImportDeclaration, {
|
||||||
[
|
source: {
|
||||||
jscodeshift.importSpecifier(jscodeshift.identifier('describe')),
|
value: 'vitest',
|
||||||
jscodeshift.importSpecifier(jscodeshift.identifier('it')),
|
},
|
||||||
jscodeshift.importSpecifier(jscodeshift.identifier('expect')),
|
specifiers: [
|
||||||
|
{
|
||||||
|
type: 'ImportSpecifier',
|
||||||
|
imported: {
|
||||||
|
name: 'describe',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'ImportSpecifier',
|
||||||
|
imported: {
|
||||||
|
name: 'it',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'ImportSpecifier',
|
||||||
|
imported: {
|
||||||
|
name: 'expect',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
jscodeshift.literal('vitest')
|
});
|
||||||
);
|
|
||||||
astPath.value.program.body.unshift(vitestImport);
|
if (!vitestImport.length) {
|
||||||
|
astPath.value.program.body.unshift(
|
||||||
|
jscodeshift.importDeclaration(
|
||||||
|
[
|
||||||
|
jscodeshift.importSpecifier(jscodeshift.identifier('describe')),
|
||||||
|
jscodeshift.importSpecifier(jscodeshift.identifier('it')),
|
||||||
|
jscodeshift.importSpecifier(jscodeshift.identifier('expect')),
|
||||||
|
],
|
||||||
|
jscodeshift.literal('vitest')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove import from 'lodash'
|
// Remove import from 'lodash'
|
||||||
root
|
root
|
||||||
@ -53,4 +82,28 @@ export function transformImport(root: Collection, jscodeshift: JSCodeshift): voi
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.remove();
|
.remove();
|
||||||
|
|
||||||
|
// Change '../src/merge' to '../index'
|
||||||
|
const methodSet = new Set<string>();
|
||||||
|
root
|
||||||
|
.find(jscodeshift.ImportDeclaration, {
|
||||||
|
source: {
|
||||||
|
value: (value: string) => value.startsWith('../src/'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.forEach(({ node }) => {
|
||||||
|
if (node.specifiers && node.specifiers[0].type === 'ImportDefaultSpecifier' && node.specifiers[0].local) {
|
||||||
|
methodSet.add(node.specifiers[0].local.name);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.remove();
|
||||||
|
|
||||||
|
if (methodSet.size) {
|
||||||
|
const methodImport = jscodeshift.importDeclaration(
|
||||||
|
Array.from(methodSet).map(method => jscodeshift.importSpecifier(jscodeshift.identifier(method))),
|
||||||
|
jscodeshift.literal('../index')
|
||||||
|
);
|
||||||
|
|
||||||
|
astPath.value.program.body.unshift(methodImport);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import type { Collection, JSCodeshift } from 'jscodeshift';
|
import type { Collection, JSCodeshift } from 'jscodeshift';
|
||||||
|
|
||||||
export function transformLodashStable(root: Collection, jscodeshift: JSCodeshift): void {
|
export function transformLodashStable(root: Collection, jscodeshift: JSCodeshift): void {
|
||||||
// Replace lodashStable.each and lodashStable.map with Array.prototype.forEach and Array.prototype.map
|
const astPath = root.getAST()[0];
|
||||||
|
let needImportEsToolkit = false;
|
||||||
|
|
||||||
root
|
root
|
||||||
.find(jscodeshift.CallExpression, {
|
.find(jscodeshift.CallExpression, {
|
||||||
callee: {
|
callee: {
|
||||||
@ -28,10 +30,19 @@ export function transformLodashStable(root: Collection, jscodeshift: JSCodeshift
|
|||||||
node.callee.object = node.arguments[0] as any;
|
node.callee.object = node.arguments[0] as any;
|
||||||
return jscodeshift.callExpression(node.callee, node.arguments.slice(1));
|
return jscodeshift.callExpression(node.callee, node.arguments.slice(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove lodashStable from the callee
|
// Remove lodashStable from the callee
|
||||||
return jscodeshift.callExpression(node.callee.property, node.arguments);
|
node.callee.object = jscodeshift.identifier('esToolkit');
|
||||||
|
needImportEsToolkit = true;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (needImportEsToolkit) {
|
||||||
|
const esToolkitImport = jscodeshift.importDeclaration(
|
||||||
|
[jscodeshift.importNamespaceSpecifier(jscodeshift.identifier('esToolkit'))],
|
||||||
|
jscodeshift.literal('../index')
|
||||||
|
);
|
||||||
|
|
||||||
|
astPath.value.program.body.unshift(esToolkitImport);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,19 @@ import type { API, FileInfo } from 'jscodeshift';
|
|||||||
import { formatBrokenSyntax } from './_internal/formatter/brokenSyntax';
|
import { formatBrokenSyntax } from './_internal/formatter/brokenSyntax';
|
||||||
import { transformImport } from './_internal/transform/import';
|
import { transformImport } from './_internal/transform/import';
|
||||||
import { transformLodashStable } from './_internal/transform/lodashStable';
|
import { transformLodashStable } from './_internal/transform/lodashStable';
|
||||||
|
import { transformAssert } from './_internal/transform/assert';
|
||||||
|
|
||||||
export default function transform(file: FileInfo, { jscodeshift }: API) {
|
export default function transform(file: FileInfo, { jscodeshift }: API) {
|
||||||
try {
|
try {
|
||||||
const root = jscodeshift(formatBrokenSyntax(file.source));
|
const root = jscodeshift(formatBrokenSyntax(file.source));
|
||||||
|
|
||||||
transformImport(root, jscodeshift);
|
|
||||||
transformLodashStable(root, jscodeshift);
|
transformLodashStable(root, jscodeshift);
|
||||||
|
transformImport(root, jscodeshift);
|
||||||
|
transformAssert(root, jscodeshift);
|
||||||
|
|
||||||
return root.toSource();
|
return root.toSource();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
|
console.error(`File Path: ${file.path}`);
|
||||||
console.error(`Error Messaging: ${error.message}`);
|
console.error(`Error Messaging: ${error.message}`);
|
||||||
console.error('Please resolve the error before continuing.');
|
console.error('Please resolve the error before continuing.');
|
||||||
console.error('If you need help, please open an issue on GitHub.');
|
console.error('If you need help, please open an issue on GitHub.');
|
||||||
|
Loading…
Reference in New Issue
Block a user