eslint-plugin-remeda 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -5
- package/dist/index.cjs +3768 -0
- package/dist/index.d.cts +187 -0
- package/dist/index.d.ts +187 -0
- package/dist/index.js +3755 -0
- package/docs/rules/prefer-flat-map.md +4 -4
- package/docs/rules/prefer-remeda-typecheck.md +6 -11
- package/package.json +39 -24
- package/src/index.js +0 -35
- package/src/rules/collection-method-value.js +0 -82
- package/src/rules/collection-return.js +0 -71
- package/src/rules/prefer-constant.js +0 -87
- package/src/rules/prefer-do-nothing.js +0 -44
- package/src/rules/prefer-filter.js +0 -82
- package/src/rules/prefer-find.js +0 -68
- package/src/rules/prefer-flat-map.js +0 -50
- package/src/rules/prefer-is-empty.js +0 -134
- package/src/rules/prefer-is-nil.js +0 -97
- package/src/rules/prefer-map.js +0 -62
- package/src/rules/prefer-nullish-coalescing.js +0 -63
- package/src/rules/prefer-remeda-typecheck.js +0 -93
- package/src/rules/prefer-some.js +0 -43
- package/src/rules/prefer-times.js +0 -37
- package/src/util/LodashContext.js +0 -128
- package/src/util/astUtil.js +0 -353
- package/src/util/getDocsUrl.js +0 -17
- package/src/util/importUtil.js +0 -24
- package/src/util/lodashUtil.js +0 -123
- package/src/util/methodData.js +0 -2417
- package/src/util/methodDataUtil.js +0 -115
- package/src/util/ruleUtil.js +0 -13
- package/src/util/settingsUtil.js +0 -31
@@ -1,134 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to prefer isEmpty over manually checking for length value.
|
3
|
-
*/
|
4
|
-
"use strict";
|
5
|
-
|
6
|
-
//------------------------------------------------------------------------------
|
7
|
-
// Rule Definition
|
8
|
-
//------------------------------------------------------------------------------
|
9
|
-
|
10
|
-
const getDocsUrl = require("../util/getDocsUrl");
|
11
|
-
|
12
|
-
module.exports = {
|
13
|
-
meta: {
|
14
|
-
type: "problem",
|
15
|
-
schema: [],
|
16
|
-
docs: {
|
17
|
-
url: getDocsUrl("prefer-is-empty"),
|
18
|
-
},
|
19
|
-
fixable: "code",
|
20
|
-
},
|
21
|
-
|
22
|
-
create(context) {
|
23
|
-
const { getLodashContext } = require("../util/lodashUtil");
|
24
|
-
const lodashContext = getLodashContext(context);
|
25
|
-
|
26
|
-
function getTextOfNode(node) {
|
27
|
-
if (node) {
|
28
|
-
if (node.type === "Identifier") {
|
29
|
-
return node.name;
|
30
|
-
}
|
31
|
-
return context.getSourceCode().getText(node);
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
const visitors = lodashContext.getImportVisitors();
|
36
|
-
visitors.BinaryExpression = function (node) {
|
37
|
-
if (node.operator === "===") {
|
38
|
-
if (node.left) {
|
39
|
-
if (node.left.property && node.right) {
|
40
|
-
const leftExpressionMember = node.left.property.name;
|
41
|
-
const rightExpressionMember = node.right.value;
|
42
|
-
if (
|
43
|
-
leftExpressionMember === "length" &&
|
44
|
-
rightExpressionMember === 0
|
45
|
-
) {
|
46
|
-
const subjectObject = node.left.object;
|
47
|
-
context.report({
|
48
|
-
node,
|
49
|
-
message:
|
50
|
-
"Prefer isEmpty over manually checking for length value.",
|
51
|
-
fix(fixer) {
|
52
|
-
return fixer.replaceText(
|
53
|
-
node,
|
54
|
-
`isEmpty(${getTextOfNode(subjectObject)})`
|
55
|
-
);
|
56
|
-
},
|
57
|
-
});
|
58
|
-
}
|
59
|
-
} else if (
|
60
|
-
node.left.expression &&
|
61
|
-
node.right &&
|
62
|
-
node.left.expression.property
|
63
|
-
) {
|
64
|
-
const leftExpressionMember = node.left.expression.property.name;
|
65
|
-
const rightExpressionMember = node.right.value;
|
66
|
-
if (
|
67
|
-
leftExpressionMember === "length" &&
|
68
|
-
rightExpressionMember === 0
|
69
|
-
) {
|
70
|
-
const subjectObject = node.left.expression.object;
|
71
|
-
context.report({
|
72
|
-
node,
|
73
|
-
message:
|
74
|
-
"Prefer isEmpty over manually checking for length value.",
|
75
|
-
fix(fixer) {
|
76
|
-
return fixer.replaceText(
|
77
|
-
node,
|
78
|
-
`isEmpty(${getTextOfNode(subjectObject)})`
|
79
|
-
);
|
80
|
-
},
|
81
|
-
});
|
82
|
-
}
|
83
|
-
}
|
84
|
-
}
|
85
|
-
}
|
86
|
-
if (node.operator === ">") {
|
87
|
-
if (node.left) {
|
88
|
-
if (node.left.property && node.right) {
|
89
|
-
const leftExpressionMember = node.left.property.name;
|
90
|
-
const rightExpressionMember = node.right.value;
|
91
|
-
if (
|
92
|
-
leftExpressionMember === "length" &&
|
93
|
-
rightExpressionMember === 0
|
94
|
-
) {
|
95
|
-
const subjectObject = node.left.object;
|
96
|
-
context.report({
|
97
|
-
node,
|
98
|
-
message:
|
99
|
-
"Prefer isEmpty over manually checking for length value.",
|
100
|
-
fix(fixer) {
|
101
|
-
return fixer.replaceText(
|
102
|
-
node,
|
103
|
-
`!isEmpty(${getTextOfNode(subjectObject)})`
|
104
|
-
);
|
105
|
-
},
|
106
|
-
});
|
107
|
-
}
|
108
|
-
} else if (node.left.expression && node.right) {
|
109
|
-
const leftExpressionMember = node.left.expression.property.name;
|
110
|
-
const rightExpressionMember = node.right.value;
|
111
|
-
if (
|
112
|
-
leftExpressionMember === "length" &&
|
113
|
-
rightExpressionMember === 0
|
114
|
-
) {
|
115
|
-
const subjectObject = node.left.expression.object;
|
116
|
-
context.report({
|
117
|
-
node,
|
118
|
-
message:
|
119
|
-
"Prefer isEmpty over manually checking for length value.",
|
120
|
-
fix(fixer) {
|
121
|
-
return fixer.replaceText(
|
122
|
-
node,
|
123
|
-
`!isEmpty(${getTextOfNode(subjectObject)})`
|
124
|
-
);
|
125
|
-
},
|
126
|
-
});
|
127
|
-
}
|
128
|
-
}
|
129
|
-
}
|
130
|
-
}
|
131
|
-
};
|
132
|
-
return visitors;
|
133
|
-
},
|
134
|
-
};
|
@@ -1,97 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to prefer isNil over manual checking for undefined or null.
|
3
|
-
*/
|
4
|
-
'use strict'
|
5
|
-
|
6
|
-
//------------------------------------------------------------------------------
|
7
|
-
// Rule Definition
|
8
|
-
//------------------------------------------------------------------------------
|
9
|
-
|
10
|
-
const getDocsUrl = require('../util/getDocsUrl')
|
11
|
-
|
12
|
-
module.exports = {
|
13
|
-
meta: {
|
14
|
-
type: 'problem',
|
15
|
-
schema: [],
|
16
|
-
docs: {
|
17
|
-
url: getDocsUrl('prefer-is-nil')
|
18
|
-
}
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const {isNegationExpression, isEquivalentMemberExp} = require('../util/astUtil')
|
23
|
-
const {isCallToLodashMethod, getLodashContext} = require('../util/lodashUtil')
|
24
|
-
const _ = require('lodash')
|
25
|
-
const lodashContext = getLodashContext(context)
|
26
|
-
const nilChecks = {
|
27
|
-
null: {
|
28
|
-
isValue: _.matches({type: 'Literal', value: null}),
|
29
|
-
expressionChecks: [getLodashTypeCheckedBy('isNull'), getValueComparedTo('null')]
|
30
|
-
},
|
31
|
-
undefined: {
|
32
|
-
isValue: _.matches({type: 'Identifier', name: 'undefined'}),
|
33
|
-
expressionChecks: [getLodashTypeCheckedBy('isUndefined'), getValueComparedTo('undefined'), getValueWithTypeofUndefinedComparison]
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
function getLodashTypeCheckedBy(typecheck) {
|
38
|
-
return function (node) {
|
39
|
-
return isCallToLodashMethod(node, typecheck, lodashContext) && node.arguments[0]
|
40
|
-
}
|
41
|
-
}
|
42
|
-
|
43
|
-
function getValueComparedTo(nil) {
|
44
|
-
return function (node, operator) {
|
45
|
-
return node.type === 'BinaryExpression' && node.operator === operator &&
|
46
|
-
((nilChecks[nil].isValue(node.right) && node.left) || (nilChecks[nil].isValue(node.left) && node.right))
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
|
51
|
-
const getTypeofArgument = _.cond([
|
52
|
-
[_.matches({type: 'UnaryExpression', operator: 'typeof'}), _.property('argument')]
|
53
|
-
])
|
54
|
-
|
55
|
-
const isUndefinedString = _.matches({type: 'Literal', value: 'undefined'})
|
56
|
-
|
57
|
-
function getValueWithTypeofUndefinedComparison(node, operator) {
|
58
|
-
return node.type === 'BinaryExpression' && node.operator === operator &&
|
59
|
-
((isUndefinedString(node.right) && getTypeofArgument(node.left)) ||
|
60
|
-
(isUndefinedString(node.left) && getTypeofArgument(node.right)))
|
61
|
-
}
|
62
|
-
|
63
|
-
function checkExpression(nil, operator, node) {
|
64
|
-
return _(nilChecks[nil].expressionChecks)
|
65
|
-
.map(check => check(node, operator))
|
66
|
-
.find()
|
67
|
-
}
|
68
|
-
|
69
|
-
function checkNegatedExpression(nil, node) {
|
70
|
-
return (isNegationExpression(node) && checkExpression(nil, '===', node.argument)) || checkExpression(nil, '!==', node)
|
71
|
-
}
|
72
|
-
|
73
|
-
function isEquivalentExistingExpression(node, leftNil, rightNil) {
|
74
|
-
const leftExp = checkExpression(leftNil, '===', node.left)
|
75
|
-
return leftExp && isEquivalentMemberExp(leftExp, checkExpression(rightNil, '===', node.right))
|
76
|
-
}
|
77
|
-
|
78
|
-
function isEquivalentExistingNegation(node, leftNil, rightNil) {
|
79
|
-
const leftExp = checkNegatedExpression(leftNil, node.left)
|
80
|
-
return leftExp && isEquivalentMemberExp(leftExp, checkNegatedExpression(rightNil, node.right))
|
81
|
-
}
|
82
|
-
|
83
|
-
const visitors = lodashContext.getImportVisitors()
|
84
|
-
visitors.LogicalExpression = function (node) {
|
85
|
-
if (node.operator === '||') {
|
86
|
-
if (isEquivalentExistingExpression(node, 'undefined', 'null') ||
|
87
|
-
isEquivalentExistingExpression(node, 'null', 'undefined')) {
|
88
|
-
context.report({node, message: 'Prefer isNil over checking for undefined or null.'})
|
89
|
-
}
|
90
|
-
} else if (isEquivalentExistingNegation(node, 'undefined', 'null') ||
|
91
|
-
isEquivalentExistingNegation(node, 'null', 'undefined')) {
|
92
|
-
context.report({node, message: 'Prefer isNil over checking for undefined or null.'})
|
93
|
-
}
|
94
|
-
}
|
95
|
-
return visitors
|
96
|
-
}
|
97
|
-
}
|
package/src/rules/prefer-map.js
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check if a call to R.forEach should be a call to R.map
|
3
|
-
*/
|
4
|
-
"use strict";
|
5
|
-
|
6
|
-
//------------------------------------------------------------------------------
|
7
|
-
// Rule Definition
|
8
|
-
//------------------------------------------------------------------------------
|
9
|
-
|
10
|
-
const getDocsUrl = require("../util/getDocsUrl");
|
11
|
-
|
12
|
-
module.exports = {
|
13
|
-
meta: {
|
14
|
-
type: "problem",
|
15
|
-
schema: [],
|
16
|
-
docs: {
|
17
|
-
url: getDocsUrl("prefer-map"),
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const { getRemedaMethodVisitors } = require("../util/lodashUtil");
|
23
|
-
const {
|
24
|
-
getFirstFunctionLine,
|
25
|
-
hasOnlyOneStatement,
|
26
|
-
getMethodName,
|
27
|
-
isFunctionDefinitionWithBlock,
|
28
|
-
collectParameterValues,
|
29
|
-
} = require("../util/astUtil");
|
30
|
-
const { isAliasOfMethod } = require("../util/methodDataUtil");
|
31
|
-
const get = require("lodash/get");
|
32
|
-
const includes = require("lodash/includes");
|
33
|
-
|
34
|
-
function onlyHasPush(func) {
|
35
|
-
const firstLine = getFirstFunctionLine(func);
|
36
|
-
const firstParam = get(func, "params[0]");
|
37
|
-
const exp =
|
38
|
-
func && !isFunctionDefinitionWithBlock(func)
|
39
|
-
? firstLine
|
40
|
-
: firstLine && firstLine.expression;
|
41
|
-
return (
|
42
|
-
func &&
|
43
|
-
hasOnlyOneStatement(func) &&
|
44
|
-
getMethodName(exp) === "push" &&
|
45
|
-
!includes(
|
46
|
-
collectParameterValues(firstParam),
|
47
|
-
get(exp, "callee.object.name"),
|
48
|
-
)
|
49
|
-
);
|
50
|
-
}
|
51
|
-
|
52
|
-
return getRemedaMethodVisitors(context, (node, iteratee, { method }) => {
|
53
|
-
if (isAliasOfMethod("forEach", method) && onlyHasPush(iteratee)) {
|
54
|
-
context.report({
|
55
|
-
node,
|
56
|
-
message:
|
57
|
-
"Prefer R.map over a R.forEach with a push to an array inside",
|
58
|
-
});
|
59
|
-
}
|
60
|
-
});
|
61
|
-
},
|
62
|
-
};
|
@@ -1,63 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to prefer nullish coalescing over checking a ternary with !isNullish.
|
3
|
-
*/
|
4
|
-
"use strict";
|
5
|
-
|
6
|
-
//------------------------------------------------------------------------------
|
7
|
-
// Rule Definition
|
8
|
-
//------------------------------------------------------------------------------
|
9
|
-
|
10
|
-
const getDocsUrl = require("../util/getDocsUrl");
|
11
|
-
|
12
|
-
module.exports = {
|
13
|
-
meta: {
|
14
|
-
type: "problem",
|
15
|
-
schema: [],
|
16
|
-
docs: {
|
17
|
-
url: getDocsUrl("prefer-nullish-coalescing"),
|
18
|
-
},
|
19
|
-
fixable: "code",
|
20
|
-
},
|
21
|
-
|
22
|
-
create(context) {
|
23
|
-
const { getLodashContext } = require("../util/lodashUtil");
|
24
|
-
const lodashContext = getLodashContext(context);
|
25
|
-
|
26
|
-
function getTextOfNode(node) {
|
27
|
-
if (node) {
|
28
|
-
if (node.type === "Identifier") {
|
29
|
-
return node.name;
|
30
|
-
}
|
31
|
-
return context.getSourceCode().getText(node);
|
32
|
-
}
|
33
|
-
}
|
34
|
-
|
35
|
-
const visitors = lodashContext.getImportVisitors();
|
36
|
-
visitors.ConditionalExpression = function (node) {
|
37
|
-
const statement = node.test;
|
38
|
-
if (statement.operator === "!") {
|
39
|
-
if (
|
40
|
-
statement.argument &&
|
41
|
-
statement.argument.callee &&
|
42
|
-
statement.argument.callee.name &&
|
43
|
-
statement.argument.callee.name === "isNullish"
|
44
|
-
) {
|
45
|
-
const argument = getTextOfNode(statement.argument.arguments[0]);
|
46
|
-
const consequent = getTextOfNode(node.consequent);
|
47
|
-
const alternate = getTextOfNode(node.alternate);
|
48
|
-
if (argument === consequent) {
|
49
|
-
context.report({
|
50
|
-
node,
|
51
|
-
message:
|
52
|
-
"Prefer nullish coalescing over checking a ternary with !isNullish.",
|
53
|
-
fix(fixer) {
|
54
|
-
return fixer.replaceText(node, `${argument} ?? ${alternate}`);
|
55
|
-
},
|
56
|
-
});
|
57
|
-
}
|
58
|
-
}
|
59
|
-
}
|
60
|
-
};
|
61
|
-
return visitors;
|
62
|
-
},
|
63
|
-
};
|
@@ -1,93 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check if there's a method in the chain start that can be in the chain
|
3
|
-
*/
|
4
|
-
"use strict";
|
5
|
-
|
6
|
-
//------------------------------------------------------------------------------
|
7
|
-
// Rule Definition
|
8
|
-
//------------------------------------------------------------------------------
|
9
|
-
|
10
|
-
const getDocsUrl = require("../util/getDocsUrl");
|
11
|
-
|
12
|
-
module.exports = {
|
13
|
-
meta: {
|
14
|
-
type: "problem",
|
15
|
-
schema: [],
|
16
|
-
docs: {
|
17
|
-
url: getDocsUrl("prefer-remeda-typecheck"),
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const some = require("lodash/some");
|
23
|
-
const { getIsTypeMethod } = require("../util/lodashUtil");
|
24
|
-
|
25
|
-
const otherSides = {
|
26
|
-
left: "right",
|
27
|
-
right: "left",
|
28
|
-
};
|
29
|
-
|
30
|
-
function isTypeOf(node) {
|
31
|
-
return (
|
32
|
-
node && node.type === "UnaryExpression" && node.operator === "typeof"
|
33
|
-
);
|
34
|
-
}
|
35
|
-
|
36
|
-
function isStrictComparison(node) {
|
37
|
-
return node.operator === "===" || node.operator === "!==";
|
38
|
-
}
|
39
|
-
|
40
|
-
function isDeclaredVariable(node) {
|
41
|
-
const definedVariables = context.getScope().variables;
|
42
|
-
return some(definedVariables, { name: node.name });
|
43
|
-
}
|
44
|
-
|
45
|
-
function getValueForSide(node, side) {
|
46
|
-
const otherSide = otherSides[side];
|
47
|
-
if (
|
48
|
-
isTypeOf(node[side]) &&
|
49
|
-
(node[otherSide].value !== "undefined" ||
|
50
|
-
node[side].argument.type !== "Identifier" ||
|
51
|
-
isDeclaredVariable(node[side].argument))
|
52
|
-
) {
|
53
|
-
return node[otherSide].value;
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
function getTypeofCompareType(node) {
|
58
|
-
if (isStrictComparison(node)) {
|
59
|
-
return getValueForSide(node, "left") || getValueForSide(node, "right");
|
60
|
-
}
|
61
|
-
}
|
62
|
-
|
63
|
-
const REPORT_MESSAGE = "Prefer 'R.{{method}}' over {{actual}}.";
|
64
|
-
|
65
|
-
return {
|
66
|
-
BinaryExpression(node) {
|
67
|
-
const typeofCompareType = getTypeofCompareType(node);
|
68
|
-
if (typeofCompareType) {
|
69
|
-
context.report({
|
70
|
-
node,
|
71
|
-
message: REPORT_MESSAGE,
|
72
|
-
data: {
|
73
|
-
method: getIsTypeMethod(typeofCompareType),
|
74
|
-
actual: "'typeof' comparison",
|
75
|
-
},
|
76
|
-
});
|
77
|
-
} else if (node.operator === "instanceof") {
|
78
|
-
const lodashEquivalent = getIsTypeMethod(node.right.name);
|
79
|
-
if (node.right.type === "Identifier" && lodashEquivalent) {
|
80
|
-
context.report({
|
81
|
-
node,
|
82
|
-
message: REPORT_MESSAGE,
|
83
|
-
data: {
|
84
|
-
method: lodashEquivalent,
|
85
|
-
actual: `'instanceof ${node.right.name}'`,
|
86
|
-
},
|
87
|
-
});
|
88
|
-
}
|
89
|
-
}
|
90
|
-
},
|
91
|
-
};
|
92
|
-
},
|
93
|
-
};
|
package/src/rules/prefer-some.js
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check if a findIndex comparison should be a call to R.some
|
3
|
-
*/
|
4
|
-
"use strict";
|
5
|
-
|
6
|
-
//------------------------------------------------------------------------------
|
7
|
-
// Rule Definition
|
8
|
-
//------------------------------------------------------------------------------
|
9
|
-
|
10
|
-
const getDocsUrl = require("../util/getDocsUrl");
|
11
|
-
|
12
|
-
module.exports = {
|
13
|
-
meta: {
|
14
|
-
type: "problem",
|
15
|
-
docs: {
|
16
|
-
url: getDocsUrl("prefer-some"),
|
17
|
-
},
|
18
|
-
schema: [],
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const { getExpressionComparedToInt } = require("../util/astUtil");
|
23
|
-
const { getRemedaMethodVisitors } = require("../util/lodashUtil");
|
24
|
-
const { isAliasOfMethod } = require("../util/methodDataUtil");
|
25
|
-
|
26
|
-
const visitors = getRemedaMethodVisitors(
|
27
|
-
context,
|
28
|
-
(node, iteratee, { method }) => {
|
29
|
-
if (
|
30
|
-
isAliasOfMethod("findIndex", method) &&
|
31
|
-
node === getExpressionComparedToInt(node.parent, -1, true)
|
32
|
-
) {
|
33
|
-
context.report({
|
34
|
-
node,
|
35
|
-
message: "Prefer R.some over findIndex comparison to -1",
|
36
|
-
});
|
37
|
-
}
|
38
|
-
},
|
39
|
-
);
|
40
|
-
|
41
|
-
return visitors;
|
42
|
-
},
|
43
|
-
};
|
@@ -1,37 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check if a call to map should be a call to times
|
3
|
-
*/
|
4
|
-
"use strict";
|
5
|
-
|
6
|
-
//------------------------------------------------------------------------------
|
7
|
-
// Rule Definition
|
8
|
-
//------------------------------------------------------------------------------
|
9
|
-
|
10
|
-
const getDocsUrl = require("../util/getDocsUrl");
|
11
|
-
|
12
|
-
module.exports = {
|
13
|
-
meta: {
|
14
|
-
type: "problem",
|
15
|
-
schema: [],
|
16
|
-
docs: {
|
17
|
-
url: getDocsUrl("prefer-times"),
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const { getRemedaMethodVisitors } = require("../util/lodashUtil");
|
23
|
-
const { isAliasOfMethod } = require("../util/methodDataUtil");
|
24
|
-
const get = require("lodash/get");
|
25
|
-
return getRemedaMethodVisitors(context, (node, iteratee, { method }) => {
|
26
|
-
if (
|
27
|
-
isAliasOfMethod("map", method) &&
|
28
|
-
get(iteratee, "params.length") === 0
|
29
|
-
) {
|
30
|
-
context.report({
|
31
|
-
node,
|
32
|
-
message: "Prefer R.times over R.map without using arguments",
|
33
|
-
});
|
34
|
-
}
|
35
|
-
});
|
36
|
-
},
|
37
|
-
};
|
@@ -1,128 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
|
3
|
-
const { getSettings } = require("./settingsUtil");
|
4
|
-
const {
|
5
|
-
isMethodCall,
|
6
|
-
isCallFromObject,
|
7
|
-
getCaller,
|
8
|
-
getMethodName,
|
9
|
-
} = require("./astUtil");
|
10
|
-
const {
|
11
|
-
getNameFromCjsRequire,
|
12
|
-
isFullRemedaImport,
|
13
|
-
getMethodImportFromName,
|
14
|
-
} = require("./importUtil");
|
15
|
-
|
16
|
-
/* Class representing remeda data for a given context */
|
17
|
-
module.exports = class {
|
18
|
-
/**
|
19
|
-
* Create a Remeda context wrapper from a file's RuleContext
|
20
|
-
* @param {RuleContext} context
|
21
|
-
*/
|
22
|
-
constructor(context) {
|
23
|
-
this.context = context;
|
24
|
-
this.general = Object.create(null);
|
25
|
-
this.methods = Object.create(null);
|
26
|
-
}
|
27
|
-
|
28
|
-
/**
|
29
|
-
* Gets visitors to collect remeda declarations in the context
|
30
|
-
* @returns {Object} visitors for everywhere Remeda can be declared
|
31
|
-
*/
|
32
|
-
getImportVisitors() {
|
33
|
-
const self = this;
|
34
|
-
return {
|
35
|
-
ImportDeclaration({ source, specifiers }) {
|
36
|
-
if (isFullRemedaImport(source.value)) {
|
37
|
-
specifiers.forEach((spec) => {
|
38
|
-
switch (spec.type) {
|
39
|
-
case "ImportNamespaceSpecifier":
|
40
|
-
case "ImportDefaultSpecifier":
|
41
|
-
self.general[spec.local.name] = true;
|
42
|
-
break;
|
43
|
-
case "ImportSpecifier":
|
44
|
-
self.methods[spec.local.name] = spec.imported.name;
|
45
|
-
|
46
|
-
if (spec.imported.name === "chain") {
|
47
|
-
self.general[spec.local.name] = true;
|
48
|
-
}
|
49
|
-
break;
|
50
|
-
}
|
51
|
-
});
|
52
|
-
} else {
|
53
|
-
const method = getMethodImportFromName(source.value);
|
54
|
-
if (method) {
|
55
|
-
self.methods[specifiers[0].local.name] = method;
|
56
|
-
}
|
57
|
-
}
|
58
|
-
},
|
59
|
-
VariableDeclarator({ init, id }) {
|
60
|
-
const required = getNameFromCjsRequire(init);
|
61
|
-
if (isFullRemedaImport(required)) {
|
62
|
-
if (id.type === "Identifier") {
|
63
|
-
self.general[id.name] = true;
|
64
|
-
} else if (id.type === "ObjectPattern") {
|
65
|
-
id.properties.forEach((prop) => {
|
66
|
-
self.methods[prop.value.name] = prop.key.name;
|
67
|
-
|
68
|
-
if (prop.value.name === "chain") {
|
69
|
-
self.general[prop.value.name] = true;
|
70
|
-
}
|
71
|
-
});
|
72
|
-
}
|
73
|
-
} else if (required) {
|
74
|
-
const method = getMethodImportFromName(required);
|
75
|
-
if (method) {
|
76
|
-
self.methods[id.name] = method;
|
77
|
-
}
|
78
|
-
}
|
79
|
-
},
|
80
|
-
};
|
81
|
-
}
|
82
|
-
|
83
|
-
/**
|
84
|
-
* Returns whether the node is an imported Remeda in this context
|
85
|
-
* @param node
|
86
|
-
* @returns {boolean|undefined}
|
87
|
-
*/
|
88
|
-
isImportedRemeda(node) {
|
89
|
-
if (node && node.type === "Identifier") {
|
90
|
-
return this.general[node.name];
|
91
|
-
}
|
92
|
-
}
|
93
|
-
|
94
|
-
/**
|
95
|
-
* Returns the name of the Remeda method for this node, if any
|
96
|
-
* @param node
|
97
|
-
* @returns {string|undefined}
|
98
|
-
*/
|
99
|
-
getImportedRemedaMethod(node) {
|
100
|
-
if (node && node.type === "CallExpression" && !isMethodCall(node)) {
|
101
|
-
return this.methods[node.callee.name];
|
102
|
-
}
|
103
|
-
}
|
104
|
-
|
105
|
-
/**
|
106
|
-
* Returns whether the node is a call from a Lodash object
|
107
|
-
* @param node
|
108
|
-
* @returns {boolean|undefined}
|
109
|
-
*/
|
110
|
-
isLodashCall(node) {
|
111
|
-
return (
|
112
|
-
(this.pragma && isCallFromObject(node, this.pragma)) ||
|
113
|
-
this.isImportedRemeda(getCaller(node))
|
114
|
-
);
|
115
|
-
}
|
116
|
-
|
117
|
-
/**
|
118
|
-
*
|
119
|
-
* @returns {string|undefined} the current Remeda pragma
|
120
|
-
*/
|
121
|
-
get pragma() {
|
122
|
-
if (!this._pragma) {
|
123
|
-
const { pragma } = getSettings(this.context);
|
124
|
-
this._pragma = pragma;
|
125
|
-
}
|
126
|
-
return this._pragma;
|
127
|
-
}
|
128
|
-
};
|