Skip to content

Commit 56a4b57

Browse files
committed
Teach no-array-index-key about reduce and reduceRight
As @ljharb pointed out, this rule should spot array indexes when using reduce. Since the index is the third argument to the reduce callback, I needed to generalize some of my logic a bit to make this configurable for each type of function.
1 parent f5c818a commit 56a4b57

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

docs/rules/no-array-index-key.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ things.every((thing, index) => {
3838
things.findIndex((thing, index) => {
3939
otherThings.push(<Hello key={index} />);
4040
});
41+
42+
things.reduce((collection, thing, index) => (
43+
collection.concat(<Hello key={index} />)
44+
), []);
45+
46+
things.reduceRight((collection, thing, index) => (
47+
collection.concat(<Hello key={index} />)
48+
), []);
4149
```
4250

4351
The following patterns are not considered warnings:
@@ -70,4 +78,12 @@ things.every((thing) => {
7078
things.findIndex((thing) => {
7179
otherThings.push(<Hello key={thing.id} />);
7280
});
81+
82+
things.reduce((collection, thing) => (
83+
collection.concat(<Hello key={thing.id} />)
84+
), []);
85+
86+
things.reduceRight((collection, thing) => (
87+
collection.concat(<Hello key={thing.id} />)
88+
), []);
7389
```

lib/rules/no-array-index-key.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ module.exports = {
2424
// Public
2525
// --------------------------------------------------------------------------
2626
var indexParamNames = [];
27-
var iteratorFunctionNames = [
28-
'every',
29-
'filter',
30-
'find',
31-
'findIndex',
32-
'forEach',
33-
'map',
34-
'some'
35-
];
27+
var iteratorFunctionsToIndexParamPosition = {
28+
every: 1,
29+
filter: 1,
30+
find: 1,
31+
findIndex: 1,
32+
forEach: 1,
33+
map: 1,
34+
reduce: 2,
35+
reduceRight: 2,
36+
some: 1
37+
};
3638
var ERROR_MESSAGE = 'Do not use Array index in keys';
3739

3840
function isArrayIndex(node) {
@@ -48,7 +50,7 @@ module.exports = {
4850
if (callee.property.type !== 'Identifier') {
4951
return null;
5052
}
51-
if (iteratorFunctionNames.indexOf(callee.property.name) === -1) {
53+
if (!iteratorFunctionsToIndexParamPosition.hasOwnProperty(callee.property.name)) {
5254
return null;
5355
}
5456

@@ -66,11 +68,13 @@ module.exports = {
6668
}
6769

6870
var params = firstArg.params;
69-
if (params.length < 2) {
71+
72+
var indexParamPosition = iteratorFunctionsToIndexParamPosition[callee.property.name];
73+
if (params.length < indexParamPosition + 1) {
7074
return null;
7175
}
7276

73-
return params[1].name;
77+
return params[indexParamPosition].name;
7478
}
7579

7680
function getIdentifiersFromBinaryExpression(side) {

tests/lib/rules/no-array-index-key.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,26 @@ ruleTester.run('no-array-index-key', rule, {
7171
].join('\n'),
7272
errors: [{message: 'Do not use Array index in keys'}],
7373
parserOptions: parserOptions
74+
},
75+
76+
{
77+
code: 'foo.reduce((a, b) => a.concat(<Foo key={b.id} />), [])',
78+
parserOptions: parserOptions
79+
},
80+
81+
{
82+
code: 'foo.reduce((a, b, i) => a.concat(<Foo key={b.id} />), [])',
83+
parserOptions: parserOptions
84+
},
85+
86+
{
87+
code: 'foo.reduceRight((a, b) => a.concat(<Foo key={b.id} />), [])',
88+
parserOptions: parserOptions
89+
},
90+
91+
{
92+
code: 'foo.reduceRight((a, b, i) => a.concat(<Foo key={b.id} />), [])',
93+
parserOptions: parserOptions
7494
}
7595
],
7696

@@ -159,6 +179,18 @@ ruleTester.run('no-array-index-key', rule, {
159179
parserOptions: parserOptions
160180
},
161181

182+
{
183+
code: 'foo.reduce((a, b, i) => a.concat(<Foo key={i} />), [])',
184+
errors: [{message: 'Do not use Array index in keys'}],
185+
parserOptions: parserOptions
186+
},
187+
188+
{
189+
code: 'foo.reduceRight((a, b, i) => a.concat(<Foo key={i} />), [])',
190+
errors: [{message: 'Do not use Array index in keys'}],
191+
parserOptions: parserOptions
192+
},
193+
162194
{
163195
code: 'foo.map((bar, i) => React.createElement(\'Foo\', { key: i }))',
164196
errors: [{message: 'Do not use Array index in keys'}],

0 commit comments

Comments
 (0)