Skip to content

Commit

Permalink
Add destructuring
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed May 18, 2020
1 parent 271b680 commit bed2aaa
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 2 deletions.
4 changes: 4 additions & 0 deletions docs/rules/prefer-array-find.md
Expand Up @@ -14,6 +14,10 @@ const item = array.filter(x => x === '🦄')[0];
const item = array.filter(x => x === '🦄').shift();
```

```js
const [item] = array.filter(x => x === '🦄');
```

## Pass

```js
Expand Down
27 changes: 26 additions & 1 deletion rules/prefer-array-find.js
Expand Up @@ -4,6 +4,7 @@ const methodSelector = require('./utils/method-selector');

const MESSAGE_ID_ZERO_INDEX = 'prefer-array-find-over-filter-zero-index';
const MESSAGE_ID_SHIFT = 'prefer-array-find-over-filter-shift';
const MESSAGE_ID_DESTRUCTURING = 'prefer-array-find-over-filter-destructuring';

const zeroIndexSelector = [
'MemberExpression',
Expand Down Expand Up @@ -31,6 +32,19 @@ const shiftSelector = [
})
].join('');

const destructuringSelector = [
'VariableDeclarator',
'[id.type="ArrayPattern"]',
'[id.elements.length=1]',
'[id.elements.0.type="Identifier"]',
methodSelector({
name: 'filter',
min: 1,
max: 2,
property: 'init'
})
].join('');

const create = context => {
return {
[zeroIndexSelector](node) {
Expand All @@ -52,6 +66,16 @@ const create = context => {
fixer.removeRange([node.callee.object.range[1], node.range[1]])
]
});
},
[destructuringSelector](node) {
context.report({
node,
messageId: MESSAGE_ID_DESTRUCTURING,
fix: fixer => [
fixer.replaceText(node.init.callee.property, 'find'),
fixer.replaceText(node.id, context.getSourceCode().getText(node.id.elements[0]))
]
});
}
};
};
Expand All @@ -66,7 +90,8 @@ module.exports = {
fixable: 'code',
messages: {
[MESSAGE_ID_ZERO_INDEX]: 'Prefer `.find(…)` over `.filter(…)[0]`.',
[MESSAGE_ID_SHIFT]: 'Prefer `.find(…)` over `.filter(…).shift()`.'
[MESSAGE_ID_SHIFT]: 'Prefer `.find(…)` over `.filter(…).shift()`.',
[MESSAGE_ID_DESTRUCTURING]: 'Prefer `.find(…)` over destructuring `.filter(…)`.'
}
}
};
89 changes: 88 additions & 1 deletion test/prefer-array-find.js
Expand Up @@ -5,6 +5,7 @@ import rule from '../rules/prefer-array-find';

const MESSAGE_ID_ZERO_INDEX = 'prefer-array-find-over-filter-zero-index';
const MESSAGE_ID_SHIFT = 'prefer-array-find-over-filter-shift';
const MESSAGE_ID_DESTRUCTURING = 'prefer-array-find-over-filter-destructuring';

const ruleTester = avaRuleTester(test, {
parserOptions: {
Expand Down Expand Up @@ -39,29 +40,50 @@ ruleTester.run('prefer-array-find', rule, {
'array.filter(foo).shift(extraArgument)',
'array.filter(foo).shift(...[])',

// Test `const [item] = `
// Not `VariableDeclarator`
'[foo] = array.filter(bar)',
// Not `ArrayPattern`
'const foo = array.filter(bar)',
'const {0: foo} = array.filter(bar)',
// `elements`
'const [] = array.filter(bar)',
'const [foo, another] = array.filter(bar)',
'const [, foo] = array.filter(bar)',
'const [foo = bar] = array.filter(baz)',
'const [{foo}] = array.filter(bar)',

// Test `.filter()`
// Not `CallExpression`
'array.filter[0]',
'array.filter.shift()',
'const [foo] = array.filter',
// Not `MemberExpression`
'filter(foo)[0]',
'filter(foo).shift()',
'const [foo] = filter(foo)',
// `callee.property` is not a `Identifier`
'array["filter"](foo)[0]',
'array["filter"](foo).shift()',
'const [foo] = array["filter"](bar)',
// Computed
'array[filter](foo)[0]',
'array[filter](foo).shift()',
'const [foo] = array[filter](bar)',
// Not `filter`
'array.notFilter(foo)[0]',
'array.notFilter(foo).shift()',
'const [foo] = array.notFilter(bar)',
// More or less argument(s)
'array.filter()[0]',
'array.filter(foo, thisArgument, extraArgument)[0]',
'array.filter(...foo)[0]',
'array.filter().shift()',
'array.filter(foo, thisArgument, extraArgument).shift()',
'array.filter(...foo).shift()'
'array.filter(...foo).shift()',
'const [foo] = array.filter()',
'const [foo] = array.filter(foo, thisArgument, extraArgument)',
'const [foo] = array.filter(...foo)'
],
invalid: [
{
Expand All @@ -74,6 +96,36 @@ ruleTester.run('prefer-array-find', rule, {
output: 'array.find(foo)',
errors: [{messageId: MESSAGE_ID_SHIFT}]
},
{
code: 'const [foo] = array.filter(bar)',
output: 'const foo = array.find(bar)',
errors: [{messageId: MESSAGE_ID_DESTRUCTURING}]
},
{
code: 'const [foo, ] = array.filter(bar)',
output: 'const foo = array.find(bar)',
errors: [{messageId: MESSAGE_ID_DESTRUCTURING}]
},
{
code: 'var [foo, ] = array.filter(bar)',
output: 'var foo = array.find(bar)',
errors: [{messageId: MESSAGE_ID_DESTRUCTURING}]
},
{
code: 'let [foo, ] = array.filter(bar)',
output: 'let foo = array.find(bar)',
errors: [{messageId: MESSAGE_ID_DESTRUCTURING}]
},
{
code: 'let a = 1, [foo, ] = array.filter(bar)',
output: 'let a = 1, foo = array.find(bar)',
errors: [{messageId: MESSAGE_ID_DESTRUCTURING}]
},
{
code: 'for (let [i] = array.filter(bar); i< 10; i++) {}',
output: 'for (let i = array.find(bar); i< 10; i++) {}',
errors: [{messageId: MESSAGE_ID_DESTRUCTURING}]
},
{
code: 'array.filter(foo, thisArgument)[0]',
output: 'array.find(foo, thisArgument)',
Expand All @@ -84,6 +136,11 @@ ruleTester.run('prefer-array-find', rule, {
output: 'array.find(foo, thisArgument)',
errors: [{messageId: MESSAGE_ID_SHIFT}]
},
{
code: 'const [foo] = array.filter(bar, thisArgument)',
output: 'const foo = array.find(bar, thisArgument)',
errors: [{messageId: MESSAGE_ID_DESTRUCTURING}]
},
{
code: outdent`
const item = array
Expand All @@ -108,6 +165,36 @@ ruleTester.run('prefer-array-find', rule, {
;
`,
errors: [{messageId: MESSAGE_ID_SHIFT}]
},
{
code: outdent`
const [
// comment 1
item
]
// comment 2
= array
// comment 3
.filter(
// comment 4
x => x === '🦄'
)
// comment 5
;
`,
output: outdent`
const item
// comment 2
= array
// comment 3
.find(
// comment 4
x => x === '🦄'
)
// comment 5
;
`,
errors: [{messageId: MESSAGE_ID_DESTRUCTURING}]
}
]
});

0 comments on commit bed2aaa

Please sign in to comment.