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,6 +1,6 @@
|
|
1
|
-
# Prefer [`R.flatMap`] over consecutive [`R.map`] and [`R.
|
1
|
+
# Prefer [`R.flatMap`] over consecutive [`R.map`] and [`R.flat`]
|
2
2
|
|
3
|
-
When using [`R.map`] and [`R.
|
3
|
+
When using [`R.map`] and [`R.flat`], it can be more concise to use [`R.flatMap`] instead.
|
4
4
|
|
5
5
|
## Rule Details
|
6
6
|
|
@@ -9,7 +9,7 @@ This rule takes no arguments.
|
|
9
9
|
The following patterns are considered warnings:
|
10
10
|
|
11
11
|
```js
|
12
|
-
t = R.
|
12
|
+
t = R.flat(R.map(a, f));
|
13
13
|
```
|
14
14
|
|
15
15
|
The following patterns are not considered warnings:
|
@@ -22,4 +22,4 @@ t = R.flatMap(a, f);
|
|
22
22
|
|
23
23
|
## When Not To Use It
|
24
24
|
|
25
|
-
If you do not want to enforce using [`R.flatMap`], and prefer [`R.map`] and [`R.
|
25
|
+
If you do not want to enforce using [`R.flatMap`], and prefer [`R.map`] and [`R.flat`] instead, you should not use this rule.
|
@@ -1,6 +1,6 @@
|
|
1
|
-
# Prefer
|
1
|
+
# Prefer Remeda typecheck
|
2
2
|
|
3
|
-
Getting the specific type of a variable or expression can be done with `typeof` or `instanceof`. However, it's often more expressive to use the
|
3
|
+
Getting the specific type of a variable or expression can be done with `typeof` or `instanceof`. However, it's often more expressive to use the Remeda equivalent function
|
4
4
|
|
5
5
|
## Rule Details
|
6
6
|
|
@@ -9,28 +9,23 @@ This rule takes no arguments.
|
|
9
9
|
The following patterns are considered warnings:
|
10
10
|
|
11
11
|
```js
|
12
|
-
|
13
|
-
if (typeof a === 'number') {
|
12
|
+
if (typeof a === "number") {
|
14
13
|
// ...
|
15
14
|
}
|
16
15
|
|
17
|
-
var isNotString = typeof b !==
|
16
|
+
var isNotString = typeof b !== "string";
|
18
17
|
|
19
18
|
var isArray = a instanceof Array;
|
20
|
-
|
21
19
|
```
|
22
20
|
|
23
21
|
The following patterns are not considered warnings:
|
24
22
|
|
25
23
|
```js
|
26
|
-
|
27
24
|
var areSameType = typeof a === typeof b;
|
28
|
-
|
29
|
-
var isCar = truck instanceof Car;
|
30
25
|
|
26
|
+
var isCar = truck instanceof Car;
|
31
27
|
```
|
32
28
|
|
33
|
-
|
34
29
|
## When Not To Use It
|
35
30
|
|
36
|
-
If you do not want to enforce using
|
31
|
+
If you do not want to enforce using Remeda methods for type checks, you should not use this rule.
|
package/package.json
CHANGED
@@ -1,59 +1,74 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint-plugin-remeda",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.2.0",
|
4
4
|
"author": "Andrea Pontrandolfo <andrea.pontra@gmail.com>",
|
5
5
|
"description": "ESLint plugin for Remeda library.",
|
6
|
-
"type": "
|
7
|
-
"main": "
|
6
|
+
"type": "module",
|
7
|
+
"main": "dist/index.js",
|
8
8
|
"scripts": {
|
9
|
-
"
|
9
|
+
"build": "tsup",
|
10
|
+
"typecheck": "tsc",
|
10
11
|
"knip": "knip",
|
11
12
|
"publint": "publint",
|
12
|
-
"test": "
|
13
|
-
"
|
14
|
-
"
|
13
|
+
"test:watch": "vitest --ui",
|
14
|
+
"test": "vitest run",
|
15
|
+
"attw": "attw --pack .",
|
16
|
+
"qa": "pnpm typecheck && pnpm test && pnpm knip && pnpm publint && attw",
|
17
|
+
"semantic-release": "pnpm build && semantic-release"
|
15
18
|
},
|
16
19
|
"files": [
|
17
20
|
"README.md",
|
18
|
-
"
|
21
|
+
"dist",
|
19
22
|
"docs"
|
20
23
|
],
|
24
|
+
"exports": {
|
25
|
+
"./package.json": "./package.json",
|
26
|
+
".": {
|
27
|
+
"import": "./dist/index.js",
|
28
|
+
"default": "./dist/index.cjs"
|
29
|
+
}
|
30
|
+
},
|
21
31
|
"repository": {
|
22
32
|
"type": "git",
|
23
|
-
"url": "https://github.com/AndreaPontrandolfo/eslint-plugin-remeda"
|
33
|
+
"url": "git+https://github.com/AndreaPontrandolfo/eslint-plugin-remeda.git"
|
24
34
|
},
|
25
35
|
"homepage": "https://github.com/AndreaPontrandolfo/eslint-plugin-remeda",
|
26
36
|
"bugs": "https://github.com/AndreaPontrandolfo/eslint-plugin-remeda/issues",
|
27
37
|
"peerDependencies": {
|
28
|
-
"eslint": ">=
|
38
|
+
"eslint": ">=9.0.0"
|
29
39
|
},
|
30
40
|
"devDependencies": {
|
41
|
+
"@arethetypeswrong/cli": "^0.15.4",
|
42
|
+
"@types/lodash": "^4.17.7",
|
31
43
|
"@types/node": "^20.14.9",
|
32
|
-
"
|
33
|
-
"
|
34
|
-
"
|
35
|
-
"eslint": "^8.16.0",
|
36
|
-
"eslint-config-wix-editor": "^8.4.2",
|
37
|
-
"eslint-import-resolver-node": "^0.3.6",
|
44
|
+
"@vitest/coverage-v8": "^2.0.3",
|
45
|
+
"@vitest/ui": "^2.0.3",
|
46
|
+
"eslint": "^9.7.0",
|
38
47
|
"eslint-plugin-eslint-plugin": "^4.2.0",
|
39
|
-
"eslint-
|
40
|
-
"
|
41
|
-
"knip": "^5.23.2",
|
42
|
-
"mocha": "^9.2.2",
|
43
|
-
"nyc": "^15.1.0",
|
48
|
+
"eslint-vitest-rule-tester": "^0.3.3",
|
49
|
+
"knip": "^5.29.1",
|
44
50
|
"prettier": "^3.3.2",
|
45
|
-
"publint": "^0.2.
|
51
|
+
"publint": "^0.2.10",
|
46
52
|
"semantic-release": "^24.0.0",
|
47
|
-
"
|
53
|
+
"tsup": "^8.2.4",
|
54
|
+
"typescript": "^5.5.2",
|
55
|
+
"vitest": "^2.0.3"
|
48
56
|
},
|
49
57
|
"engines": {
|
50
58
|
"node": ">=20"
|
51
59
|
},
|
60
|
+
"packageManager": "pnpm@9.7.1",
|
61
|
+
"publishConfig": {
|
62
|
+
"access": "public"
|
63
|
+
},
|
52
64
|
"keywords": [
|
53
65
|
"eslint",
|
54
66
|
"eslint-plugin",
|
67
|
+
"eslint plugin",
|
55
68
|
"eslintplugin",
|
56
|
-
"remeda"
|
69
|
+
"remeda",
|
70
|
+
"functional",
|
71
|
+
"fp"
|
57
72
|
],
|
58
73
|
"license": "MIT",
|
59
74
|
"dependencies": {
|
package/src/index.js
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
const fs = require("fs");
|
3
|
-
const path = require("path");
|
4
|
-
const _ = require("lodash");
|
5
|
-
const rules = fs
|
6
|
-
.readdirSync(path.resolve(__dirname, "rules"))
|
7
|
-
.map((f) => f.replace(/\.js$/, ""));
|
8
|
-
const recommended = {
|
9
|
-
plugins: ["remeda"],
|
10
|
-
rules: {
|
11
|
-
"remeda/prefer-is-empty": 2,
|
12
|
-
"remeda/prefer-is-nil": 2,
|
13
|
-
"remeda/prefer-times": 2,
|
14
|
-
"remeda/prefer-constant": 2,
|
15
|
-
"remeda/prefer-remeda-typecheck": 2,
|
16
|
-
"remeda/prefer-nullish-coalescing": 2,
|
17
|
-
"remeda/prefer-filter": [2, 3],
|
18
|
-
"remeda/collection-method-value": 2,
|
19
|
-
"remeda/collection-return": 2,
|
20
|
-
"remeda/prefer-map": 2,
|
21
|
-
"remeda/prefer-find": 2,
|
22
|
-
"remeda/prefer-some": 2,
|
23
|
-
"remeda/prefer-flat-map": 2,
|
24
|
-
"remeda/prefer-do-nothing": 2,
|
25
|
-
},
|
26
|
-
};
|
27
|
-
module.exports = {
|
28
|
-
rules: _.zipObject(
|
29
|
-
rules,
|
30
|
-
rules.map((rule) => require(`./rules/${rule}`)),
|
31
|
-
),
|
32
|
-
configs: {
|
33
|
-
recommended,
|
34
|
-
},
|
35
|
-
};
|
@@ -1,82 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to enforce usage of collection method values
|
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("collection-method-value"),
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const {
|
23
|
-
isChainBreaker,
|
24
|
-
getRemedaMethodVisitors,
|
25
|
-
isCallToMethod,
|
26
|
-
} = require("../util/lodashUtil");
|
27
|
-
const { getMethodName } = require("../util/astUtil");
|
28
|
-
const {
|
29
|
-
isCollectionMethod,
|
30
|
-
isAliasOfMethod,
|
31
|
-
getSideEffectIterationMethods,
|
32
|
-
} = require("../util/methodDataUtil");
|
33
|
-
const includes = require("lodash/includes");
|
34
|
-
|
35
|
-
function parentUsesValue(node, callType) {
|
36
|
-
const isBeforeChainBreaker =
|
37
|
-
callType === "chained" && isChainBreaker(node.parent.parent);
|
38
|
-
return (
|
39
|
-
(isBeforeChainBreaker ? node.parent.parent : node).parent.type !==
|
40
|
-
"ExpressionStatement"
|
41
|
-
);
|
42
|
-
}
|
43
|
-
|
44
|
-
function isPureRemedaCollectionMethod(method) {
|
45
|
-
return isCollectionMethod(method) && !isAliasOfMethod("remove", method);
|
46
|
-
}
|
47
|
-
|
48
|
-
function isSideEffectIterationMethod(method) {
|
49
|
-
return includes(getSideEffectIterationMethods(), method);
|
50
|
-
}
|
51
|
-
|
52
|
-
function isParentCommit(node, callType) {
|
53
|
-
return (
|
54
|
-
callType === "chained" && isCallToMethod(node.parent.parent, "commit")
|
55
|
-
);
|
56
|
-
}
|
57
|
-
|
58
|
-
return getRemedaMethodVisitors(
|
59
|
-
context,
|
60
|
-
(node, iteratee, { method, callType }) => {
|
61
|
-
if (
|
62
|
-
isPureRemedaCollectionMethod(method) &&
|
63
|
-
!parentUsesValue(node, callType)
|
64
|
-
) {
|
65
|
-
context.report({
|
66
|
-
node,
|
67
|
-
message: `Use value returned from R.${method}`,
|
68
|
-
});
|
69
|
-
} else if (
|
70
|
-
isSideEffectIterationMethod(method) &&
|
71
|
-
parentUsesValue(node, callType) &&
|
72
|
-
!isParentCommit(node, callType)
|
73
|
-
) {
|
74
|
-
context.report({
|
75
|
-
node,
|
76
|
-
message: `Do not use value returned from R.${getMethodName(node)}`,
|
77
|
-
});
|
78
|
-
}
|
79
|
-
},
|
80
|
-
);
|
81
|
-
},
|
82
|
-
};
|
@@ -1,71 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check that iteratees for all collection functions except forEach return a 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("collection-return"),
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const {
|
23
|
-
getRemedaMethodCallExpVisitor,
|
24
|
-
getLodashContext,
|
25
|
-
} = require("../util/lodashUtil");
|
26
|
-
const { isCollectionMethod } = require("../util/methodDataUtil");
|
27
|
-
const { isFunctionDefinitionWithBlock } = require("../util/astUtil");
|
28
|
-
const assign = require("lodash/assign");
|
29
|
-
const funcInfos = new Map();
|
30
|
-
let currFuncInfo = {};
|
31
|
-
const lodashContext = getLodashContext(context);
|
32
|
-
return assign(
|
33
|
-
{
|
34
|
-
"CallExpression:exit": getRemedaMethodCallExpVisitor(
|
35
|
-
lodashContext,
|
36
|
-
(node, iteratee, { method }) => {
|
37
|
-
if (isCollectionMethod(method) && funcInfos.has(iteratee)) {
|
38
|
-
const { hasReturn } = funcInfos.get(iteratee);
|
39
|
-
if (
|
40
|
-
isFunctionDefinitionWithBlock(iteratee) &&
|
41
|
-
!hasReturn &&
|
42
|
-
!iteratee.async &&
|
43
|
-
!iteratee.generator
|
44
|
-
) {
|
45
|
-
context.report({
|
46
|
-
node,
|
47
|
-
message: `Do not use R.${method} without returning a value`,
|
48
|
-
});
|
49
|
-
}
|
50
|
-
}
|
51
|
-
},
|
52
|
-
),
|
53
|
-
ReturnStatement() {
|
54
|
-
currFuncInfo.hasReturn = true;
|
55
|
-
},
|
56
|
-
onCodePathStart(codePath, node) {
|
57
|
-
currFuncInfo = {
|
58
|
-
upper: currFuncInfo,
|
59
|
-
codePath,
|
60
|
-
hasReturn: false,
|
61
|
-
};
|
62
|
-
funcInfos.set(node, currFuncInfo);
|
63
|
-
},
|
64
|
-
onCodePathEnd() {
|
65
|
-
currFuncInfo = currFuncInfo.upper;
|
66
|
-
},
|
67
|
-
},
|
68
|
-
lodashContext.getImportVisitors(),
|
69
|
-
);
|
70
|
-
},
|
71
|
-
};
|
@@ -1,87 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check if the expression could be better expressed as a R.constant
|
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-constant"),
|
17
|
-
},
|
18
|
-
schema: [
|
19
|
-
{
|
20
|
-
type: "boolean",
|
21
|
-
},
|
22
|
-
{
|
23
|
-
type: "boolean",
|
24
|
-
},
|
25
|
-
],
|
26
|
-
},
|
27
|
-
|
28
|
-
create(context) {
|
29
|
-
const { getValueReturnedInFirstStatement } = require("../util/astUtil");
|
30
|
-
const shouldCheckArrowFunctions =
|
31
|
-
context.options[0] !== undefined ? context.options[0] : true;
|
32
|
-
const shouldCheckFunctionDeclarations =
|
33
|
-
context.options[1] !== undefined ? context.options[1] : false;
|
34
|
-
|
35
|
-
function isCompletelyLiteral(node) {
|
36
|
-
switch (node.type) {
|
37
|
-
case "Literal":
|
38
|
-
return true;
|
39
|
-
case "BinaryExpression":
|
40
|
-
return (
|
41
|
-
isCompletelyLiteral(node.left) && isCompletelyLiteral(node.right)
|
42
|
-
);
|
43
|
-
case "UnaryExpression":
|
44
|
-
return isCompletelyLiteral(node.argument);
|
45
|
-
case "ConditionalExpression":
|
46
|
-
return (
|
47
|
-
isCompletelyLiteral(node.test) &&
|
48
|
-
isCompletelyLiteral(node.consequent) &&
|
49
|
-
isCompletelyLiteral(node.alternate)
|
50
|
-
);
|
51
|
-
default:
|
52
|
-
return false;
|
53
|
-
}
|
54
|
-
}
|
55
|
-
|
56
|
-
function reportIfLikeConstant(func, node) {
|
57
|
-
const valueReturnedInFirstLine = func(node);
|
58
|
-
if (
|
59
|
-
valueReturnedInFirstLine &&
|
60
|
-
isCompletelyLiteral(valueReturnedInFirstLine)
|
61
|
-
) {
|
62
|
-
context.report({
|
63
|
-
node,
|
64
|
-
message: "Prefer R.constant over a function returning a literal",
|
65
|
-
});
|
66
|
-
}
|
67
|
-
}
|
68
|
-
|
69
|
-
function handleFunctionDefinition(node) {
|
70
|
-
reportIfLikeConstant(getValueReturnedInFirstStatement, node);
|
71
|
-
}
|
72
|
-
|
73
|
-
return {
|
74
|
-
FunctionExpression: handleFunctionDefinition,
|
75
|
-
FunctionDeclaration(node) {
|
76
|
-
if (shouldCheckFunctionDeclarations) {
|
77
|
-
handleFunctionDefinition(node);
|
78
|
-
}
|
79
|
-
},
|
80
|
-
ArrowFunctionExpression(node) {
|
81
|
-
if (shouldCheckArrowFunctions) {
|
82
|
-
handleFunctionDefinition(node);
|
83
|
-
}
|
84
|
-
},
|
85
|
-
};
|
86
|
-
},
|
87
|
-
};
|
@@ -1,44 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to prefer R.doNothing() or R.constant(undefined) over an empty function
|
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-do-nothing"),
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const { getFirstFunctionLine } = require("../util/astUtil");
|
23
|
-
|
24
|
-
function reportIfEmptyFunction(node) {
|
25
|
-
if (
|
26
|
-
!getFirstFunctionLine(node) &&
|
27
|
-
node.parent.type !== "MethodDefinition" &&
|
28
|
-
!node.generator &&
|
29
|
-
!node.async
|
30
|
-
) {
|
31
|
-
context.report({
|
32
|
-
node,
|
33
|
-
message:
|
34
|
-
"Prefer R.doNothing() or R.constant(undefined) over an empty function",
|
35
|
-
});
|
36
|
-
}
|
37
|
-
}
|
38
|
-
|
39
|
-
return {
|
40
|
-
FunctionExpression: reportIfEmptyFunction,
|
41
|
-
ArrowFunctionExpression: reportIfEmptyFunction,
|
42
|
-
};
|
43
|
-
},
|
44
|
-
};
|
@@ -1,82 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check if a call to R.forEach should be a call to R.filter
|
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-filter"),
|
17
|
-
},
|
18
|
-
schema: [
|
19
|
-
{
|
20
|
-
type: "integer",
|
21
|
-
},
|
22
|
-
],
|
23
|
-
},
|
24
|
-
|
25
|
-
create(context) {
|
26
|
-
const { getRemedaMethodVisitors } = require("../util/lodashUtil");
|
27
|
-
const {
|
28
|
-
isIdentifierWithName,
|
29
|
-
isMemberExpOf,
|
30
|
-
isNegationOfMemberOf,
|
31
|
-
isEqEqEqToMemberOf,
|
32
|
-
isNotEqEqToMemberOf,
|
33
|
-
getFirstFunctionLine,
|
34
|
-
hasOnlyOneStatement,
|
35
|
-
getFirstParamName,
|
36
|
-
} = require("../util/astUtil");
|
37
|
-
const { isAliasOfMethod } = require("../util/methodDataUtil");
|
38
|
-
const DEFAULT_MAX_PROPERTY_PATH_LENGTH = 3;
|
39
|
-
const maxLength =
|
40
|
-
parseInt(context.options[0], 10) || DEFAULT_MAX_PROPERTY_PATH_LENGTH;
|
41
|
-
|
42
|
-
function isIfWithoutElse(statement) {
|
43
|
-
return (
|
44
|
-
statement && statement.type === "IfStatement" && !statement.alternate
|
45
|
-
);
|
46
|
-
}
|
47
|
-
|
48
|
-
function canBeShorthand(exp, paramName) {
|
49
|
-
return (
|
50
|
-
isIdentifierWithName(exp, paramName) ||
|
51
|
-
isMemberExpOf(exp, paramName, { maxLength }) ||
|
52
|
-
isNegationOfMemberOf(exp, paramName, { maxLength }) ||
|
53
|
-
isEqEqEqToMemberOf(exp, paramName, { maxLength }) ||
|
54
|
-
isNotEqEqToMemberOf(exp, paramName, { maxLength })
|
55
|
-
);
|
56
|
-
}
|
57
|
-
|
58
|
-
function onlyHasSimplifiableIf(func) {
|
59
|
-
const firstLine = getFirstFunctionLine(func);
|
60
|
-
return (
|
61
|
-
func &&
|
62
|
-
hasOnlyOneStatement(func) &&
|
63
|
-
func.params.length === 1 &&
|
64
|
-
isIfWithoutElse(firstLine) &&
|
65
|
-
canBeShorthand(firstLine.test, getFirstParamName(func))
|
66
|
-
);
|
67
|
-
}
|
68
|
-
|
69
|
-
return getRemedaMethodVisitors(context, (node, iteratee, { method }) => {
|
70
|
-
if (
|
71
|
-
isAliasOfMethod("forEach", method) &&
|
72
|
-
onlyHasSimplifiableIf(iteratee)
|
73
|
-
) {
|
74
|
-
context.report({
|
75
|
-
node,
|
76
|
-
message:
|
77
|
-
"Prefer R.filter or R.some over an if statement inside a R.forEach",
|
78
|
-
});
|
79
|
-
}
|
80
|
-
});
|
81
|
-
},
|
82
|
-
};
|
package/src/rules/prefer-find.js
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check if a call to `R.filter` should be a call to `R.find`.
|
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-find"),
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const {
|
23
|
-
getRemedaMethodVisitors,
|
24
|
-
isCallToMethod,
|
25
|
-
isCallToLodashMethod,
|
26
|
-
} = require("../util/lodashUtil");
|
27
|
-
const { isAliasOfMethod } = require("../util/methodDataUtil");
|
28
|
-
|
29
|
-
function isZeroIndexAccess(node) {
|
30
|
-
return node.type === "MemberExpression" && node.property.value === 0;
|
31
|
-
}
|
32
|
-
|
33
|
-
function isChainedBeforeMethod(callType, node, method) {
|
34
|
-
return (
|
35
|
-
callType === "chained" && isCallToMethod(node.parent.parent, method)
|
36
|
-
);
|
37
|
-
}
|
38
|
-
|
39
|
-
return getRemedaMethodVisitors(
|
40
|
-
context,
|
41
|
-
(node, iteratee, { method, callType, lodashContext }) => {
|
42
|
-
if (isAliasOfMethod("filter", method)) {
|
43
|
-
if (
|
44
|
-
isZeroIndexAccess(node.parent) ||
|
45
|
-
isCallToLodashMethod(node.parent, "first", lodashContext) ||
|
46
|
-
isChainedBeforeMethod(callType, node, "first")
|
47
|
-
) {
|
48
|
-
context.report({
|
49
|
-
node,
|
50
|
-
message:
|
51
|
-
"Prefer using `R.find` over selecting the first item of a filtered result",
|
52
|
-
});
|
53
|
-
}
|
54
|
-
if (
|
55
|
-
isCallToLodashMethod(node.parent, "last", lodashContext) ||
|
56
|
-
isChainedBeforeMethod(callType, node, "last")
|
57
|
-
) {
|
58
|
-
context.report({
|
59
|
-
node,
|
60
|
-
message:
|
61
|
-
"Prefer using `R.findLast` over selecting the last item of a filtered result",
|
62
|
-
});
|
63
|
-
}
|
64
|
-
}
|
65
|
-
},
|
66
|
-
);
|
67
|
-
},
|
68
|
-
};
|
@@ -1,50 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @fileoverview Rule to check if a call to map and flatten should be a call to R.flatMap
|
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-flat-map"),
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
create(context) {
|
22
|
-
const {
|
23
|
-
getRemedaMethodVisitors,
|
24
|
-
isCallToMethod,
|
25
|
-
isCallToLodashMethod,
|
26
|
-
} = require("../util/lodashUtil");
|
27
|
-
const { getCaller } = require("../util/astUtil");
|
28
|
-
const { isAliasOfMethod } = require("../util/methodDataUtil");
|
29
|
-
|
30
|
-
function isChainedMapFlatten(callType, node) {
|
31
|
-
return callType === "chained" && isCallToMethod(getCaller(node), "map");
|
32
|
-
}
|
33
|
-
|
34
|
-
return getRemedaMethodVisitors(
|
35
|
-
context,
|
36
|
-
(node, iteratee, { method, callType, lodashContext }) => {
|
37
|
-
if (
|
38
|
-
isAliasOfMethod("flatten", method) &&
|
39
|
-
(isChainedMapFlatten(callType, node) ||
|
40
|
-
isCallToLodashMethod(node.arguments[0], "map", lodashContext))
|
41
|
-
) {
|
42
|
-
context.report({
|
43
|
-
node,
|
44
|
-
message: "Prefer R.flatMap over consecutive map and flatten.",
|
45
|
-
});
|
46
|
-
}
|
47
|
-
},
|
48
|
-
);
|
49
|
-
},
|
50
|
-
};
|