Skip to content

Commit

Permalink
prefer-array-find: Check array.filter().at(0) (#2284)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed Feb 19, 2024
1 parent 5ce4169 commit e6074fe
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 1 deletion.
28 changes: 28 additions & 0 deletions rules/prefer-array-find.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const {isMethodCall} = require('./ast/index.js');
const ERROR_ZERO_INDEX = 'error-zero-index';
const ERROR_SHIFT = 'error-shift';
const ERROR_POP = 'error-pop';
const ERROR_AT_ZERO = 'error-at-zero';
const ERROR_AT_MINUS_ONE = 'error-at-minus-one';
const ERROR_DESTRUCTURING_DECLARATION = 'error-destructuring-declaration';
const ERROR_DESTRUCTURING_ASSIGNMENT = 'error-destructuring-assignment';
Expand All @@ -27,6 +28,7 @@ const SUGGESTION_LOGICAL_OR_OPERATOR = 'suggest-logical-or-operator';
const messages = {
[ERROR_DECLARATION]: 'Prefer `.find(…)` over `.filter(…)`.',
[ERROR_ZERO_INDEX]: 'Prefer `.find(…)` over `.filter(…)[0]`.',
[ERROR_AT_ZERO]: 'Prefer `.find(…)` over `.filter(…).at(0)`.',
[ERROR_SHIFT]: 'Prefer `.find(…)` over `.filter(…).shift()`.',
[ERROR_POP]: 'Prefer `.findLast(…)` over `.filter(…).pop()`.',
[ERROR_AT_MINUS_ONE]: 'Prefer `.findLast(…)` over `.filter(…).at(-1)`.',
Expand Down Expand Up @@ -335,6 +337,32 @@ const create = context => {
return problem;
});

// `array.filter().at(0)`
context.on('CallExpression', node => {
if (!(
isMethodCall(node, {
method: 'at',
argumentsLength: 1,
optionalCall: false,
optionalMember: false,
})
&& node.arguments[0].type === 'Literal'
&& node.arguments[0].raw === '0'
&& isArrayFilterCall(node.callee.object)
)) {
return;
}

return {
node: node.callee.object.callee.property,
messageId: ERROR_AT_ZERO,
fix: fixer => [
fixer.replaceText(node.callee.object.callee.property, 'find'),
...removeMethodCall(fixer, node, sourceCode),
],
};
});

if (!checkFromLast) {
return;
}
Expand Down
89 changes: 88 additions & 1 deletion test/prefer-array-find.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const {test} = getTester(import.meta);
const ERROR_ZERO_INDEX = 'error-zero-index';
const ERROR_SHIFT = 'error-shift';
const ERROR_POP = 'error-pop';
const ERROR_AT_ZERO = 'error-at-zero';
const ERROR_AT_MINUS_ONE = 'error-at-minus-one';
const ERROR_DESTRUCTURING_DECLARATION = 'error-destructuring-declaration';
const ERROR_DESTRUCTURING_ASSIGNMENT = 'error-destructuring-assignment';
Expand Down Expand Up @@ -1030,7 +1031,7 @@ test({
'array.filter(foo).at(1)',
'array.filter(foo).at(+1)',
'const ONE = 1; array.filter(foo).at(-ONE)',
'const MINUS_ONE = 1; array.filter(foo).at(MINUS_ONE)',
'const MINUS_ONE = -1; array.filter(foo).at(MINUS_ONE)',
'const a = {b: 1}; array.filter(foo).at(-a.b)',
'const a = {b: -1}; array.filter(foo).at(a.b)',
'array.filter(foo).at(-2)',
Expand Down Expand Up @@ -1100,3 +1101,89 @@ test({
},
].map(test => ({...test, options: checkFromLastOptions})),
});

// `.at(0)`
test({
valid: [
// Test `.at()`
// Not `CallExpression`
'array2.filter(foo).at',
// Not `MemberExpression`
'at(array.filter(foo), 0)',
// `callee.property` is not a `Identifier`
'array.filter(foo)["at"](0)',
// Computed
'array.filter(foo)[at](0)',
// Not `at`
'array.filter(foo).notAt(0)',
// More or less argument(s)
'array2.filter(foo).at()',
'array.filter(foo).at(0, extraArgument)',
'array.filter(foo).at(...[0])',

// Test `0`
'array.filter(foo).at(100)',
'array.filter(foo).at(+0)',
'const ZERO = 0; array.filter(foo).at(ZERO)',
'const a = {b: 0}; array.filter(foo).at(a.b)',
'array.filter(foo).at(0b0)',
'array.filter(foo).at("0")',

// Test `.filter()`
// Not `CallExpression`
'array.filter.at(0)',
// Not `MemberExpression`
'filter(foo).at(0)',
// `callee.property` is not a `Identifier`
'array["filter"](foo).at(0)',
// Computed
'array[filter](foo).at(0)',
// Not `filter`
'array.notFilter(foo).at(0)',
// More or less argument(s)
'array.filter().at(0)',
'array.filter(foo, thisArgument, extraArgument).at(0)',
'array.filter(...foo).at(0)',
],
invalid: [
{
code: 'array.filter(foo).at(0)',
output: 'array.find(foo)',
errors: [{messageId: ERROR_AT_ZERO}],
},
{
code: 'array.filter(foo, thisArgument).at(0)',
output: 'array.find(foo, thisArgument)',
errors: [{messageId: ERROR_AT_ZERO}],
},
{
code: outdent`
const item = array
// comment 1
.filter(
// comment 2
x => x === '🦄'
)
// comment 3
.at(
// comment 4
0
// comment 5
)
// comment 6
;
`,
output: outdent`
const item = array
// comment 1
.find(
// comment 2
x => x === '🦄'
)
// comment 6
;
`,
errors: [{messageId: ERROR_AT_ZERO}],
},
],
});

0 comments on commit e6074fe

Please sign in to comment.