Skip to content

Commit fec60a4

Browse files
authored
Merge pull request #16 from jogold/prefer-both-either
Add prefer-both-either
2 parents 64e6b5e + 7e18afd commit fec60a4

3 files changed

Lines changed: 118 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: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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 => `Instead of \`${instead}\`, prefer \`${prefer[instead]}\` when there are only two predicates`
30+
31+
const create = context => ({
32+
CallExpression(node) {
33+
if (match('allPass')(node) || match('anyPass')(node)) {
34+
const callee = getName(node.callee);
35+
context.report({
36+
node,
37+
message: report(callee)
38+
});
39+
}
40+
}
41+
});
42+
43+
module.exports = {
44+
create,
45+
meta: {
46+
docs: {
47+
description: 'Enforces using `both`/`either` instead of `allPass`/`anyPass` with a list of only two predicates',
48+
recommended: 'off'
49+
}
50+
}
51+
};

test/prefer-both-either.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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 => ({
20+
ruleId: 'prefer-both-either',
21+
message: `Instead of \`${instead}\`, prefer \`${prefer[instead]}\` when there are only two predicates`
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+
'allPass(predicates)',
31+
'allPass(predicates, foo)',
32+
'anyPass(predicates)',
33+
'anyPass(predicates, foo)'
34+
],
35+
invalid: [
36+
{
37+
code: 'allPass([foo, bar])',
38+
errors: [error('allPass')]
39+
},
40+
{
41+
code: 'allPass([foo, bar], baz)',
42+
errors: [error('allPass')]
43+
},
44+
{
45+
code: 'allPass([(foo) => !foo, function () { return false; }])',
46+
errors: [error('allPass')]
47+
},
48+
{
49+
code: 'allPass([complement(foo), complement(bar)])',
50+
errors: [error('allPass')]
51+
},
52+
{
53+
code: 'anyPass([foo, bar])',
54+
errors: [error('anyPass')]
55+
},
56+
{
57+
code: 'anyPass([foo, bar], baz)',
58+
errors: [error('anyPass')]
59+
},
60+
{
61+
code: 'anyPass([R.T, R.F])',
62+
errors: [error('anyPass')]
63+
}
64+
]
65+
});

0 commit comments

Comments
 (0)