Skip to content

Commit 55e51b2

Browse files
author
Brady Blair
committed
feat: add codemod for iterate-iterator
1 parent 574e0c2 commit 55e51b2

File tree

7 files changed

+249
-0
lines changed

7 files changed

+249
-0
lines changed

codemods/iterate-iterator/index.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import jscodeshift from 'jscodeshift';
2+
import { removeImport } from '../shared.js';
3+
4+
/**
5+
* @typedef {import('../../types.js').Codemod} Codemod
6+
* @typedef {import('../../types.js').CodemodOptions} CodemodOptions
7+
*/
8+
9+
/**
10+
* @param {CodemodOptions} [options]
11+
* @returns {Codemod}
12+
*/
13+
export default function (options) {
14+
return {
15+
name: 'iterate-iterator',
16+
transform: ({ file }) => {
17+
const j = jscodeshift;
18+
const root = j(file.source);
19+
let isDirty = false;
20+
21+
const { identifier } = removeImport('iterate-iterator', root, j);
22+
23+
if (identifier) {
24+
const callExpressions = root.find(j.CallExpression, {
25+
callee: {
26+
type: 'Identifier',
27+
name: identifier,
28+
},
29+
});
30+
31+
for (const path of callExpressions.paths()) {
32+
const args = path.node.arguments;
33+
34+
if (args.length === 1) {
35+
// Case: Converting an iterator to an array
36+
const [iterable] = args;
37+
const arrayFromExpression = j.callExpression(
38+
j.memberExpression(j.identifier('Array'), j.identifier('from')),
39+
[iterable],
40+
);
41+
42+
j(path).replaceWith(arrayFromExpression);
43+
isDirty = true;
44+
} else if (args.length === 2) {
45+
// Case: Using a callback function
46+
const [iterable, callback] = args;
47+
const iterableArg =
48+
iterable.type === 'SpreadElement' ? iterable.argument : iterable;
49+
50+
if (
51+
callback.type !== 'Identifier' &&
52+
callback.type !== 'FunctionExpression' &&
53+
callback.type !== 'ArrowFunctionExpression'
54+
) {
55+
continue;
56+
}
57+
58+
const forOfStatement = j.forOfStatement(
59+
j.variableDeclaration('const', [
60+
j.variableDeclarator(j.identifier('i')),
61+
]),
62+
iterableArg,
63+
j.blockStatement([
64+
j.expressionStatement(
65+
j.callExpression(callback, [j.identifier('i')]),
66+
),
67+
]),
68+
);
69+
70+
j(path).replaceWith(forOfStatement);
71+
isDirty = true;
72+
}
73+
}
74+
}
75+
76+
return isDirty ? root.toSource(options) : file.source;
77+
},
78+
};
79+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import assert from 'assert';
2+
3+
assert.deepEqual(Array.from('a 💩'[Symbol.iterator]()), ['a', ' ', '💩']);
4+
assert.deepEqual(Array.from([1, 2][Symbol.iterator]()), [1, 2]);
5+
assert.deepEqual(Array.from(new Set([1, 2]).values()), [1, 2]);
6+
assert.deepEqual(Array.from(new Map([[1, 2], [3, 4]]).entries()), [[1, 2], [3, 4]]);
7+
8+
function assertWithCallback(iterable, expected) {
9+
const values = [];
10+
const callback = function (x) { values.push(x); };
11+
12+
for (const i of iterable) {
13+
callback(i);
14+
};
15+
16+
assert.deepEqual(values, expected);
17+
}
18+
19+
assertWithCallback('a 💩'[Symbol.iterator](), ['a', ' ', '💩']);
20+
assertWithCallback([1, 2][Symbol.iterator](), [1, 2]);
21+
assertWithCallback(new Set([1, 2]).values(), [1, 2]);
22+
assertWithCallback(new Map([[1, 2], [3, 4]]).entries(), [[1, 2], [3, 4]]);
23+
24+
for (const i of [1, 2][Symbol.iterator]()) {
25+
(function(x) { console.log(x); })(i);
26+
};
27+
28+
for (const i of [1, 2][Symbol.iterator]()) {
29+
(x => console.log(x))(i);
30+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { iterate } from 'iterate-iterator';
2+
import assert from 'assert';
3+
4+
assert.deepEqual(iterate('a 💩'[Symbol.iterator]()), ['a', ' ', '💩']);
5+
assert.deepEqual(iterate([1, 2][Symbol.iterator]()), [1, 2]);
6+
assert.deepEqual(iterate(new Set([1, 2]).values()), [1, 2]);
7+
assert.deepEqual(iterate(new Map([[1, 2], [3, 4]]).entries()), [[1, 2], [3, 4]]);
8+
9+
function assertWithCallback(iterable, expected) {
10+
const values = [];
11+
const callback = function (x) { values.push(x); };
12+
13+
iterate(iterable, callback);
14+
15+
assert.deepEqual(values, expected);
16+
}
17+
18+
assertWithCallback('a 💩'[Symbol.iterator](), ['a', ' ', '💩']);
19+
assertWithCallback([1, 2][Symbol.iterator](), [1, 2]);
20+
assertWithCallback(new Set([1, 2]).values(), [1, 2]);
21+
assertWithCallback(new Map([[1, 2], [3, 4]]).entries(), [[1, 2], [3, 4]]);
22+
23+
iterate([1, 2][Symbol.iterator](), function (x) { console.log(x); });
24+
25+
iterate([1, 2][Symbol.iterator](), x => console.log(x));
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import assert from 'assert';
2+
3+
assert.deepEqual(Array.from('a 💩'[Symbol.iterator]()), ['a', ' ', '💩']);
4+
assert.deepEqual(Array.from([1, 2][Symbol.iterator]()), [1, 2]);
5+
assert.deepEqual(Array.from(new Set([1, 2]).values()), [1, 2]);
6+
assert.deepEqual(Array.from(new Map([[1, 2], [3, 4]]).entries()), [[1, 2], [3, 4]]);
7+
8+
function assertWithCallback(iterable, expected) {
9+
const values = [];
10+
const callback = function (x) { values.push(x); };
11+
12+
for (const i of iterable) {
13+
callback(i);
14+
};
15+
16+
assert.deepEqual(values, expected);
17+
}
18+
19+
assertWithCallback('a 💩'[Symbol.iterator](), ['a', ' ', '💩']);
20+
assertWithCallback([1, 2][Symbol.iterator](), [1, 2]);
21+
assertWithCallback(new Set([1, 2]).values(), [1, 2]);
22+
assertWithCallback(new Map([[1, 2], [3, 4]]).entries(), [[1, 2], [3, 4]]);
23+
24+
for (const i of [1, 2][Symbol.iterator]()) {
25+
(function(x) { console.log(x); })(i);
26+
};
27+
28+
for (const i of [1, 2][Symbol.iterator]()) {
29+
(x => console.log(x))(i);
30+
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const assert = require('assert');
2+
3+
assert.deepEqual(Array.from('a 💩'[Symbol.iterator]()), ['a', ' ', '💩']);
4+
assert.deepEqual(Array.from([1, 2][Symbol.iterator]()), [1, 2]);
5+
assert.deepEqual(Array.from(new Set([1, 2]).values()), [1, 2]);
6+
assert.deepEqual(Array.from(new Map([[1, 2], [3, 4]]).entries()), [[1, 2], [3, 4]]);
7+
8+
function assertWithCallback(iterable, expected) {
9+
const values = [];
10+
const callback = function (x) { values.push(x); };
11+
12+
for (const i of iterable) {
13+
callback(i);
14+
};
15+
16+
assert.deepEqual(values, expected);
17+
}
18+
19+
assertWithCallback('a 💩'[Symbol.iterator](), ['a', ' ', '💩']);
20+
assertWithCallback([1, 2][Symbol.iterator](), [1, 2]);
21+
assertWithCallback(new Set([1, 2]).values(), [1, 2]);
22+
assertWithCallback(new Map([[1, 2], [3, 4]]).entries(), [[1, 2], [3, 4]]);
23+
24+
for (const i of [1, 2][Symbol.iterator]()) {
25+
(function(x) { console.log(x); })(i);
26+
};
27+
28+
for (const i of [1, 2][Symbol.iterator]()) {
29+
(x => console.log(x))(i);
30+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const assert = require('assert');
2+
const iterate = require('iterate-iterator');
3+
4+
assert.deepEqual(iterate('a 💩'[Symbol.iterator]()), ['a', ' ', '💩']);
5+
assert.deepEqual(iterate([1, 2][Symbol.iterator]()), [1, 2]);
6+
assert.deepEqual(iterate(new Set([1, 2]).values()), [1, 2]);
7+
assert.deepEqual(iterate(new Map([[1, 2], [3, 4]]).entries()), [[1, 2], [3, 4]]);
8+
9+
function assertWithCallback(iterable, expected) {
10+
const values = [];
11+
const callback = function (x) { values.push(x); };
12+
13+
iterate(iterable, callback);
14+
15+
assert.deepEqual(values, expected);
16+
}
17+
18+
assertWithCallback('a 💩'[Symbol.iterator](), ['a', ' ', '💩']);
19+
assertWithCallback([1, 2][Symbol.iterator](), [1, 2]);
20+
assertWithCallback(new Set([1, 2]).values(), [1, 2]);
21+
assertWithCallback(new Map([[1, 2], [3, 4]]).entries(), [[1, 2], [3, 4]]);
22+
23+
iterate([1, 2][Symbol.iterator](), function (x) { console.log(x); });
24+
25+
iterate([1, 2][Symbol.iterator](), x => console.log(x));
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const assert = require('assert');
2+
3+
assert.deepEqual(Array.from('a 💩'[Symbol.iterator]()), ['a', ' ', '💩']);
4+
assert.deepEqual(Array.from([1, 2][Symbol.iterator]()), [1, 2]);
5+
assert.deepEqual(Array.from(new Set([1, 2]).values()), [1, 2]);
6+
assert.deepEqual(Array.from(new Map([[1, 2], [3, 4]]).entries()), [[1, 2], [3, 4]]);
7+
8+
function assertWithCallback(iterable, expected) {
9+
const values = [];
10+
const callback = function (x) { values.push(x); };
11+
12+
for (const i of iterable) {
13+
callback(i);
14+
};
15+
16+
assert.deepEqual(values, expected);
17+
}
18+
19+
assertWithCallback('a 💩'[Symbol.iterator](), ['a', ' ', '💩']);
20+
assertWithCallback([1, 2][Symbol.iterator](), [1, 2]);
21+
assertWithCallback(new Set([1, 2]).values(), [1, 2]);
22+
assertWithCallback(new Map([[1, 2], [3, 4]]).entries(), [[1, 2], [3, 4]]);
23+
24+
for (const i of [1, 2][Symbol.iterator]()) {
25+
(function(x) { console.log(x); })(i);
26+
};
27+
28+
for (const i of [1, 2][Symbol.iterator]()) {
29+
(x => console.log(x))(i);
30+
};

0 commit comments

Comments
 (0)