Skip to content

Commit 6e5879b

Browse files
committed
Add prefer-both-either
1 parent 64e6b5e commit 6e5879b

3 files changed

Lines changed: 103 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Configure it in `package.json`.
4545
"ramda/no-redundant-not": "error",
4646
"ramda/no-redundant-or": "error",
4747
"ramda/pipe-simplification": "error",
48+
"ramda/prefer-both-either": "error",
4849
"ramda/prefer-complement": "error",
4950
"ramda/prefer-ramda-boolean": "error",
5051
"ramda/prop-satisfies-simplification": "error",
@@ -77,6 +78,7 @@ Configure it in `package.json`.
7778
- `no-redundant-not` - Forbids `not` with 1 parameter in favor of `!`
7879
- `no-redundant-or` - Forbids `or` with 2 parameters in favor of `||`
7980
- `pipe-simplification` - Detects when a function that has the same behavior already exists
81+
- `prefer-both-either` - Enforces using `both`/`either` instead of `allPass`/`anyPass` with a list of only two predicates
8082
- `prefer-complement` - Enforces using `complement` instead of compositions using `not`
8183
- `prefer-ramda-boolean` - Enforces using `R.T` and `R.F` instead of explicit functions
8284
- `prop-satisfies-simplification` - Detects when can replace `propSatisfies` by more simple functions

rules/prefer-both-either.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
'use strict';
2+
const R = require('ramda');
3+
const ast = require('../ast-helper');
4+
5+
const isCalling = ast.isCalling;
6+
const getName = ast.getName;
7+
8+
const prefer = {
9+
allPass: 'both',
10+
anyPass: 'either'
11+
}
12+
13+
const match = name => isCalling({
14+
name,
15+
arguments: R.where({
16+
0: R.both(
17+
R.propEq('type', 'ArrayExpression'),
18+
R.pathEq(['elements', 'length'], 2)
19+
),
20+
})
21+
})
22+
23+
const elementsToString = R.pipe(
24+
R.prop('elements'),
25+
R.map(getName),
26+
R.join(', ')
27+
);
28+
29+
const report = (instead, args) => `Instead of \`${instead}([${args}])\`, prefer \`${prefer[instead]}(${args})\``
30+
31+
const create = context => ({
32+
CallExpression(node) {
33+
if (match('allPass')(node) || match('anyPass')(node)) {
34+
const callee = getName(node.callee);
35+
const args = elementsToString(node.arguments[0]);
36+
context.report({
37+
node,
38+
message: report(callee, args)
39+
});
40+
}
41+
}
42+
});
43+
44+
module.exports = {
45+
create,
46+
meta: {
47+
docs: {
48+
description: 'Enforces using `both`/`either` instead of `allPass`/`anyPass` with a list of only two predicates',
49+
recommended: 'off'
50+
}
51+
}
52+
};

test/prefer-both-either.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import test from 'ava';
2+
import avaRuleTester from 'eslint-ava-rule-tester';
3+
import rule from '../rules/prefer-both-either';
4+
5+
const ruleTester = avaRuleTester(test, {
6+
env: {
7+
es6: true
8+
},
9+
parserOptions: {
10+
sourceType: 'module'
11+
}
12+
});
13+
14+
const prefer = {
15+
allPass: 'both',
16+
anyPass: 'either'
17+
}
18+
19+
const error = (instead, args) => ({
20+
ruleId: 'prefer-both-either',
21+
message: `Instead of \`${instead}([${args}])\`, prefer \`${prefer[instead]}(${args})\``
22+
});
23+
24+
ruleTester.run('prefer-both-either', rule, {
25+
valid: [
26+
'both(foo, bar)',
27+
'either(foo, bar)',
28+
'allPass([foo, bar, baz])',
29+
'anyPass([foo, bar, baz])'
30+
],
31+
invalid: [
32+
{
33+
code: 'allPass([foo, bar])',
34+
errors: [error('allPass', 'foo, bar')]
35+
},
36+
{
37+
code: 'allPass([foo, bar], baz)',
38+
errors: [error('allPass', 'foo, bar')]
39+
},
40+
{
41+
code: 'anyPass([foo, bar])',
42+
errors: [error('anyPass', 'foo, bar')]
43+
},
44+
{
45+
code: 'anyPass([foo, bar], baz)',
46+
errors: [error('anyPass', 'foo, bar')]
47+
}
48+
]
49+
});

0 commit comments

Comments
 (0)