eslint-plugin-remeda 1.7.0 → 1.8.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/dist/index.cjs +81 -53
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +78 -50
- package/package.json +6 -5
package/dist/index.cjs
CHANGED
@@ -41,12 +41,13 @@ var main = "dist/index.js";
|
|
41
41
|
var scripts = {
|
42
42
|
"build": "tsdown",
|
43
43
|
"typecheck": "tsc",
|
44
|
-
"lint": "eslint",
|
44
|
+
"lint": "eslint --max-warnings=0",
|
45
45
|
"knip": "knip",
|
46
46
|
"test:watch": "vitest --ui",
|
47
47
|
"test": "vitest run",
|
48
|
-
"
|
49
|
-
"
|
48
|
+
"check-sheriff-inconsistencies": "sheriff",
|
49
|
+
"attw": "attw --ignore-rules=false-export-default --pack .",
|
50
|
+
"qa": "pnpm build && pnpm typecheck && pnpm lint && pnpm test && pnpm knip && pnpm attw && pnpm check-sheriff-inconsistencies",
|
50
51
|
"nuke": "rm -rf node_modules pnpm-lock.yaml",
|
51
52
|
"update:eslint-docs": "eslint-doc-generator",
|
52
53
|
"lint:eslint-docs": "pnpm update:eslint-docs -- --check",
|
@@ -80,7 +81,7 @@ var bugs = "https://github.com/AndreaPontrandolfo/eslint-plugin-remeda/issues";
|
|
80
81
|
var peerDependencies = { "eslint": ">=9.0.0" };
|
81
82
|
var devDependencies = {
|
82
83
|
"@arethetypeswrong/cli": "^0.17.4",
|
83
|
-
"@sherifforg/cli": "^8.
|
84
|
+
"@sherifforg/cli": "^8.3.0",
|
84
85
|
"@types/lodash-es": "^4.17.12",
|
85
86
|
"@types/node": "^22.14.0",
|
86
87
|
"@typescript-eslint/utils": "^8.29.0",
|
@@ -202,8 +203,8 @@ function isMemberExpOf$1(node, objectName, { maxLength = Number.MAX_VALUE, allow
|
|
202
203
|
let currentNode = node;
|
203
204
|
let depth = maxLength;
|
204
205
|
while (currentNode && depth) if (allowComputed || isPropAccess(currentNode)) {
|
205
|
-
if (currentNode.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression &&
|
206
|
-
currentNode =
|
206
|
+
if (currentNode.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && currentNode.object.type === __typescript_eslint_utils.AST_NODE_TYPES.Identifier && currentNode.object.name === objectName) return true;
|
207
|
+
currentNode = currentNode.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression ? currentNode.object : void 0;
|
207
208
|
depth = depth - 1;
|
208
209
|
} else return false;
|
209
210
|
return false;
|
@@ -239,7 +240,7 @@ function hasOnlyOneStatement$2(func) {
|
|
239
240
|
* @param node - The node to check.
|
240
241
|
*/
|
241
242
|
function isObjectOfMethodCall(node) {
|
242
|
-
return (0, lodash_es.get)(node, "parent.object") === node && (0, lodash_es.get)(node, "parent.parent.type") ===
|
243
|
+
return (0, lodash_es.get)(node, "parent.object") === node && (0, lodash_es.get)(node, "parent.parent.type") === __typescript_eslint_utils.AST_NODE_TYPES.CallExpression;
|
243
244
|
}
|
244
245
|
/**
|
245
246
|
* Returns whether the node is a literal.
|
@@ -405,7 +406,9 @@ function getExpressionComparedToInt$1(node, value$1, checkOver) {
|
|
405
406
|
*
|
406
407
|
* @param node - The node to check.
|
407
408
|
*/
|
408
|
-
const isIndexOfCall = (node) =>
|
409
|
+
const isIndexOfCall = (node) => {
|
410
|
+
return isMethodCall$1(node) && getMethodName$2(node) === "indexOf";
|
411
|
+
};
|
409
412
|
/**
|
410
413
|
* Returns whether the node is a call to findIndex.
|
411
414
|
*
|
@@ -549,7 +552,7 @@ __export(methodData_exports, {
|
|
549
552
|
fromPairs: () => fromPairs,
|
550
553
|
functions: () => functions,
|
551
554
|
functionsIn: () => functionsIn,
|
552
|
-
get: () => get$
|
555
|
+
get: () => get$4,
|
553
556
|
groupBy: () => groupBy,
|
554
557
|
gt: () => gt,
|
555
558
|
gte: () => gte,
|
@@ -593,14 +596,14 @@ __export(methodData_exports, {
|
|
593
596
|
isNative: () => isNative,
|
594
597
|
isNull: () => isNull,
|
595
598
|
isNullish: () => isNullish,
|
596
|
-
isNumber: () => isNumber$
|
599
|
+
isNumber: () => isNumber$2,
|
597
600
|
isObject: () => isObject$1,
|
598
601
|
isObjectLike: () => isObjectLike,
|
599
602
|
isPlainObject: () => isPlainObject,
|
600
603
|
isRegExp: () => isRegExp,
|
601
604
|
isSafeInteger: () => isSafeInteger,
|
602
605
|
isSet: () => isSet,
|
603
|
-
isString: () => isString,
|
606
|
+
isString: () => isString$1,
|
604
607
|
isSymbol: () => isSymbol,
|
605
608
|
isTypedArray: () => isTypedArray,
|
606
609
|
isUndefined: () => isUndefined,
|
@@ -1324,7 +1327,7 @@ const functionsIn = {
|
|
1324
1327
|
iteratee: false,
|
1325
1328
|
args: 1
|
1326
1329
|
};
|
1327
|
-
const get$
|
1330
|
+
const get$4 = {
|
1328
1331
|
wrapper: false,
|
1329
1332
|
shorthand: false,
|
1330
1333
|
chainable: false,
|
@@ -1633,7 +1636,7 @@ const isNull = {
|
|
1633
1636
|
iteratee: false,
|
1634
1637
|
args: 1
|
1635
1638
|
};
|
1636
|
-
const isNumber$
|
1639
|
+
const isNumber$2 = {
|
1637
1640
|
wrapper: false,
|
1638
1641
|
shorthand: false,
|
1639
1642
|
chainable: false,
|
@@ -1682,7 +1685,7 @@ const isSet = {
|
|
1682
1685
|
iteratee: false,
|
1683
1686
|
args: 1
|
1684
1687
|
};
|
1685
|
-
const isString = {
|
1688
|
+
const isString$1 = {
|
1686
1689
|
wrapper: false,
|
1687
1690
|
shorthand: false,
|
1688
1691
|
chainable: false,
|
@@ -2889,8 +2892,7 @@ const zipWith = {
|
|
2889
2892
|
*
|
2890
2893
|
*/
|
2891
2894
|
function methodSupportsShorthand(method$1, shorthandType) {
|
2892
|
-
const
|
2893
|
-
const methodShorthandData = (0, lodash_es.get)(methodData_exports, path);
|
2895
|
+
const methodShorthandData = methodData_exports[method$1].shorthand;
|
2894
2896
|
const isShorthandObject = (0, lodash_es.isObject)(methodShorthandData);
|
2895
2897
|
return isShorthandObject ? Boolean(shorthandType && methodShorthandData[shorthandType]) : Boolean(methodShorthandData);
|
2896
2898
|
}
|
@@ -3088,8 +3090,9 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
|
|
3088
3090
|
let iterateeIndex;
|
3089
3091
|
if (remedaContext.isRemedaCall(node)) {
|
3090
3092
|
const method$1 = astUtil_default.getMethodName(node);
|
3093
|
+
if (!(0, lodash_es.isString)(method$1)) return;
|
3091
3094
|
iterateeIndex = getIterateeIndex(method$1);
|
3092
|
-
reporter(node, node.arguments[iterateeIndex], {
|
3095
|
+
if ((0, lodash_es.isNumber)(iterateeIndex)) reporter(node, node.arguments[iterateeIndex], {
|
3093
3096
|
callType: "method",
|
3094
3097
|
method: method$1,
|
3095
3098
|
remedaContext
|
@@ -3098,7 +3101,7 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
|
|
3098
3101
|
const method$1 = remedaContext.getImportedRemedaMethod(node);
|
3099
3102
|
if (method$1) {
|
3100
3103
|
iterateeIndex = getIterateeIndex(method$1);
|
3101
|
-
reporter(node, node.arguments[iterateeIndex], {
|
3104
|
+
if ((0, lodash_es.isNumber)(iterateeIndex)) reporter(node, node.arguments[iterateeIndex], {
|
3102
3105
|
method: method$1,
|
3103
3106
|
callType: "single",
|
3104
3107
|
remedaContext
|
@@ -3108,10 +3111,11 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
|
|
3108
3111
|
};
|
3109
3112
|
}
|
3110
3113
|
function isRemedaCallToMethod(node, method$1, remedaContext) {
|
3114
|
+
if (!node) return false;
|
3111
3115
|
return remedaContext.isRemedaCall(node) && isCallToMethod(node, method$1);
|
3112
3116
|
}
|
3113
3117
|
function isCallToRemedaMethod(node, method$1, remedaContext) {
|
3114
|
-
if (!node || node.type !==
|
3118
|
+
if (!node || node.type !== __typescript_eslint_utils.AST_NODE_TYPES.CallExpression) return false;
|
3115
3119
|
return isRemedaCallToMethod(node, method$1, remedaContext) || method$1 === remedaContext.getImportedRemedaMethod(node);
|
3116
3120
|
}
|
3117
3121
|
function getRemedaMethodVisitors(context, remedaCallExpVisitor) {
|
@@ -3141,7 +3145,7 @@ function isSideEffectIterationMethod(method$1) {
|
|
3141
3145
|
return (0, lodash_es.includes)(getSideEffectIterationMethods(), method$1);
|
3142
3146
|
}
|
3143
3147
|
function isParentCommit(node, callType) {
|
3144
|
-
return callType === "chained" && isCallToMethod(node.parent.parent, "commit");
|
3148
|
+
return callType === "chained" && node.parent.parent && isCallToMethod(node.parent.parent, "commit");
|
3145
3149
|
}
|
3146
3150
|
var collection_method_value_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getDocsUrl)({
|
3147
3151
|
name: RULE_NAME$14,
|
@@ -3193,18 +3197,22 @@ var collection_return_default = __typescript_eslint_utils.ESLintUtils.RuleCreato
|
|
3193
3197
|
create(context) {
|
3194
3198
|
const remedaContext = getRemedaContext(context);
|
3195
3199
|
return {
|
3196
|
-
"CallExpression:exit": getRemedaMethodCallExpVisitor(
|
3197
|
-
|
3198
|
-
|
3199
|
-
|
3200
|
-
|
3201
|
-
|
3202
|
-
|
3203
|
-
|
3204
|
-
|
3205
|
-
|
3206
|
-
|
3207
|
-
|
3200
|
+
"CallExpression:exit": getRemedaMethodCallExpVisitor(
|
3201
|
+
remedaContext,
|
3202
|
+
// @ts-expect-error
|
3203
|
+
(node, iteratee$1, { method: method$1 }) => {
|
3204
|
+
if (!isCollectionMethod(method$1)) return;
|
3205
|
+
if (!astUtil_default.isFunctionDefinitionWithBlock(iteratee$1) || iteratee$1.async || iteratee$1.generator) return;
|
3206
|
+
const hasReturnStatement = iteratee$1.body.type === __typescript_eslint_utils.AST_NODE_TYPES.BlockStatement && iteratee$1.body.body.some((statement) => {
|
3207
|
+
return statement.type === __typescript_eslint_utils.AST_NODE_TYPES.ReturnStatement;
|
3208
|
+
});
|
3209
|
+
if (!hasReturnStatement) context.report({
|
3210
|
+
node,
|
3211
|
+
messageId: "no-return",
|
3212
|
+
data: { method: method$1 }
|
3213
|
+
});
|
3214
|
+
}
|
3215
|
+
),
|
3208
3216
|
...remedaContext.getImportVisitors()
|
3209
3217
|
};
|
3210
3218
|
}
|
@@ -3232,8 +3240,14 @@ var prefer_constant_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(
|
|
3232
3240
|
description: "enforce using R.constant over functions returning literals",
|
3233
3241
|
url: getDocsUrl(RULE_NAME$12)
|
3234
3242
|
},
|
3235
|
-
schema: [{
|
3236
|
-
|
3243
|
+
schema: [{
|
3244
|
+
type: "boolean",
|
3245
|
+
description: "Whether to check arrow functions for literals in return statements. Default: true."
|
3246
|
+
}, {
|
3247
|
+
type: "boolean",
|
3248
|
+
description: "Whether to check function declarations for literals in return statements. Default: false."
|
3249
|
+
}],
|
3250
|
+
defaultOptions: [true, false],
|
3237
3251
|
messages: { [MESSAGE_ID$1]: "Prefer R.constant over a function returning a literal" }
|
3238
3252
|
},
|
3239
3253
|
defaultOptions: [true, false],
|
@@ -3321,7 +3335,7 @@ var prefer_filter_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(ge
|
|
3321
3335
|
defaultOptions: [{ maxPropertyPathLength: 3 }],
|
3322
3336
|
messages: { "prefer-filter": MESSAGE$2 }
|
3323
3337
|
},
|
3324
|
-
defaultOptions: [{}],
|
3338
|
+
defaultOptions: [{ maxPropertyPathLength: 3 }],
|
3325
3339
|
create(context, [options]) {
|
3326
3340
|
const DEFAULT_MAX_PROPERTY_PATH_LENGTH = 3;
|
3327
3341
|
const maxLength = options.maxPropertyPathLength ?? DEFAULT_MAX_PROPERTY_PATH_LENGTH;
|
@@ -3353,7 +3367,7 @@ function isZeroIndexAccess(node) {
|
|
3353
3367
|
return node.type === __typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && node.property.type === __typescript_eslint_utils.AST_NODE_TYPES.Literal && node.property.value === 0;
|
3354
3368
|
}
|
3355
3369
|
function isChainedBeforeMethod(callType, node, method$1) {
|
3356
|
-
return callType === "chained" && isCallToMethod(node.parent
|
3370
|
+
return callType === "chained" && node.parent?.parent !== void 0 && isCallToMethod(node.parent.parent, method$1);
|
3357
3371
|
}
|
3358
3372
|
var prefer_find_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getDocsUrl)({
|
3359
3373
|
name: RULE_NAME$9,
|
@@ -3373,7 +3387,7 @@ var prefer_find_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getD
|
|
3373
3387
|
create(context) {
|
3374
3388
|
return getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1, callType, remedaContext }) => {
|
3375
3389
|
if (method$1 === "filter") {
|
3376
|
-
if (isZeroIndexAccess(node.parent) || isCallToRemedaMethod(node.parent, "first", remedaContext) || isChainedBeforeMethod(callType, node, "first")) context.report({
|
3390
|
+
if (node.parent && isZeroIndexAccess(node.parent) || isCallToRemedaMethod(node.parent, "first", remedaContext) || isChainedBeforeMethod(callType, node, "first")) context.report({
|
3377
3391
|
node,
|
3378
3392
|
messageId: "prefer-find"
|
3379
3393
|
});
|
@@ -3391,7 +3405,8 @@ var prefer_find_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getD
|
|
3391
3405
|
const { getCaller } = astUtil_default;
|
3392
3406
|
const RULE_NAME$8 = "prefer-flat-map";
|
3393
3407
|
function isChainedMapFlatten(node) {
|
3394
|
-
|
3408
|
+
const caller = getCaller(node);
|
3409
|
+
return caller ? isCallToMethod(caller, "map") : false;
|
3395
3410
|
}
|
3396
3411
|
var prefer_flat_map_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getDocsUrl)({
|
3397
3412
|
name: RULE_NAME$8,
|
@@ -3406,12 +3421,16 @@ var prefer_flat_map_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(
|
|
3406
3421
|
},
|
3407
3422
|
defaultOptions: [],
|
3408
3423
|
create(context) {
|
3409
|
-
return getRemedaMethodVisitors(
|
3410
|
-
|
3411
|
-
|
3412
|
-
|
3413
|
-
|
3414
|
-
|
3424
|
+
return getRemedaMethodVisitors(
|
3425
|
+
context,
|
3426
|
+
// @ts-expect-error
|
3427
|
+
(node, iteratee$1, { method: method$1, remedaContext }) => {
|
3428
|
+
if (method$1 === "flat" && (isChainedMapFlatten(node) || isCallToRemedaMethod(node.arguments[0], "map", remedaContext))) context.report({
|
3429
|
+
node,
|
3430
|
+
messageId: "prefer-flat-map"
|
3431
|
+
});
|
3432
|
+
}
|
3433
|
+
);
|
3415
3434
|
}
|
3416
3435
|
});
|
3417
3436
|
|
@@ -3647,12 +3666,21 @@ var prefer_is_nullish_default = __typescript_eslint_utils.ESLintUtils.RuleCreato
|
|
3647
3666
|
return isNegationExpression(node) && checkExpression(nil, "===", node.argument) || checkExpression(nil, "!==", node);
|
3648
3667
|
}
|
3649
3668
|
function isEquivalentExistingExpression(node, leftNil, rightNil) {
|
3669
|
+
if (node.type !== __typescript_eslint_utils.AST_NODE_TYPES.LogicalExpression) return false;
|
3650
3670
|
const leftExp = checkExpression(leftNil, "===", node.left);
|
3651
|
-
return leftExp && isEquivalentMemberExp(
|
3671
|
+
return leftExp && isEquivalentMemberExp(
|
3672
|
+
leftExp,
|
3673
|
+
// @ts-expect-error
|
3674
|
+
checkExpression(rightNil, "===", node.right)
|
3675
|
+
);
|
3652
3676
|
}
|
3653
3677
|
function isEquivalentExistingNegation(node, leftNil, rightNil) {
|
3654
3678
|
const leftExp = checkNegatedExpression(leftNil, node.left);
|
3655
|
-
return leftExp && isEquivalentMemberExp(
|
3679
|
+
return leftExp && isEquivalentMemberExp(
|
3680
|
+
leftExp,
|
3681
|
+
// @ts-expect-error
|
3682
|
+
checkNegatedExpression(rightNil, node.right)
|
3683
|
+
);
|
3656
3684
|
}
|
3657
3685
|
const visitors = remedaContext.getImportVisitors();
|
3658
3686
|
visitors.LogicalExpression = function(node) {
|
@@ -3674,11 +3702,11 @@ var prefer_is_nullish_default = __typescript_eslint_utils.ESLintUtils.RuleCreato
|
|
3674
3702
|
//#region src/rules/prefer-map.ts
|
3675
3703
|
const { getFirstFunctionLine, hasOnlyOneStatement, getMethodName, isFunctionDefinitionWithBlock, collectParameterValues } = astUtil_default;
|
3676
3704
|
const RULE_NAME$4 = "prefer-map";
|
3677
|
-
function onlyHasPush(
|
3678
|
-
const firstLine = getFirstFunctionLine(
|
3679
|
-
const firstParam = (0, lodash_es.get)(
|
3680
|
-
const exp =
|
3681
|
-
return
|
3705
|
+
function onlyHasPush(node) {
|
3706
|
+
const firstLine = getFirstFunctionLine(node);
|
3707
|
+
const firstParam = (0, lodash_es.get)(node, "params[0]");
|
3708
|
+
const exp = node && !isFunctionDefinitionWithBlock(node) ? firstLine : firstLine?.expression;
|
3709
|
+
return node && (node.type === __typescript_eslint_utils.AST_NODE_TYPES.ArrowFunctionExpression ? true : hasOnlyOneStatement(node)) && getMethodName(exp) === "push" && !(0, lodash_es.includes)(collectParameterValues(firstParam), (0, lodash_es.get)(exp, "callee.object.name"));
|
3682
3710
|
}
|
3683
3711
|
var prefer_map_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getDocsUrl)({
|
3684
3712
|
name: RULE_NAME$4,
|
@@ -3829,7 +3857,7 @@ var prefer_some_default = __typescript_eslint_utils.ESLintUtils.RuleCreator(getD
|
|
3829
3857
|
defaultOptions: [],
|
3830
3858
|
create(context) {
|
3831
3859
|
const visitors = getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1 }) => {
|
3832
|
-
if (method$1 === "findIndex" && node === getExpressionComparedToInt(node.parent, -1, true)) context.report({
|
3860
|
+
if (method$1 === "findIndex" && node.parent?.type === __typescript_eslint_utils.AST_NODE_TYPES.BinaryExpression && node === getExpressionComparedToInt(node.parent, -1, true)) context.report({
|
3833
3861
|
node,
|
3834
3862
|
messageId: "prefer-some"
|
3835
3863
|
});
|
@@ -3904,7 +3932,7 @@ const configs = { recommended: {
|
|
3904
3932
|
[`${pluginShortName}/prefer-constant`]: 2,
|
3905
3933
|
[`${pluginShortName}/prefer-remeda-typecheck`]: 2,
|
3906
3934
|
[`${pluginShortName}/prefer-nullish-coalescing`]: 2,
|
3907
|
-
[`${pluginShortName}/prefer-filter`]:
|
3935
|
+
[`${pluginShortName}/prefer-filter`]: 2,
|
3908
3936
|
[`${pluginShortName}/prefer-has-atleast`]: 2,
|
3909
3937
|
[`${pluginShortName}/collection-method-value`]: 2,
|
3910
3938
|
[`${pluginShortName}/collection-return`]: 2,
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { capitalize, cond, defaults, find, flatMap, get, has, includes, isEmpty, isEqualWith, isMatch, isNumber, isObject, last, map, matches, matchesProperty, overEvery, overSome, property, some } from "lodash-es";
|
1
|
+
import { capitalize, cond, defaults, find, flatMap, get, has, includes, isEmpty, isEqualWith, isMatch, isNumber, isObject, isString, last, map, matches, matchesProperty, overEvery, overSome, property, some } from "lodash-es";
|
2
2
|
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
3
3
|
|
4
4
|
//#region rolldown:runtime
|
@@ -21,12 +21,13 @@ var main = "dist/index.js";
|
|
21
21
|
var scripts = {
|
22
22
|
"build": "tsdown",
|
23
23
|
"typecheck": "tsc",
|
24
|
-
"lint": "eslint",
|
24
|
+
"lint": "eslint --max-warnings=0",
|
25
25
|
"knip": "knip",
|
26
26
|
"test:watch": "vitest --ui",
|
27
27
|
"test": "vitest run",
|
28
|
-
"
|
29
|
-
"
|
28
|
+
"check-sheriff-inconsistencies": "sheriff",
|
29
|
+
"attw": "attw --ignore-rules=false-export-default --pack .",
|
30
|
+
"qa": "pnpm build && pnpm typecheck && pnpm lint && pnpm test && pnpm knip && pnpm attw && pnpm check-sheriff-inconsistencies",
|
30
31
|
"nuke": "rm -rf node_modules pnpm-lock.yaml",
|
31
32
|
"update:eslint-docs": "eslint-doc-generator",
|
32
33
|
"lint:eslint-docs": "pnpm update:eslint-docs -- --check",
|
@@ -60,7 +61,7 @@ var bugs = "https://github.com/AndreaPontrandolfo/eslint-plugin-remeda/issues";
|
|
60
61
|
var peerDependencies = { "eslint": ">=9.0.0" };
|
61
62
|
var devDependencies = {
|
62
63
|
"@arethetypeswrong/cli": "^0.17.4",
|
63
|
-
"@sherifforg/cli": "^8.
|
64
|
+
"@sherifforg/cli": "^8.3.0",
|
64
65
|
"@types/lodash-es": "^4.17.12",
|
65
66
|
"@types/node": "^22.14.0",
|
66
67
|
"@typescript-eslint/utils": "^8.29.0",
|
@@ -182,8 +183,8 @@ function isMemberExpOf$1(node, objectName, { maxLength = Number.MAX_VALUE, allow
|
|
182
183
|
let currentNode = node;
|
183
184
|
let depth = maxLength;
|
184
185
|
while (currentNode && depth) if (allowComputed || isPropAccess(currentNode)) {
|
185
|
-
if (currentNode.type === AST_NODE_TYPES.MemberExpression &&
|
186
|
-
currentNode =
|
186
|
+
if (currentNode.type === AST_NODE_TYPES.MemberExpression && currentNode.object.type === AST_NODE_TYPES.Identifier && currentNode.object.name === objectName) return true;
|
187
|
+
currentNode = currentNode.type === AST_NODE_TYPES.MemberExpression ? currentNode.object : void 0;
|
187
188
|
depth = depth - 1;
|
188
189
|
} else return false;
|
189
190
|
return false;
|
@@ -219,7 +220,7 @@ function hasOnlyOneStatement$2(func) {
|
|
219
220
|
* @param node - The node to check.
|
220
221
|
*/
|
221
222
|
function isObjectOfMethodCall(node) {
|
222
|
-
return get(node, "parent.object") === node && get(node, "parent.parent.type") ===
|
223
|
+
return get(node, "parent.object") === node && get(node, "parent.parent.type") === AST_NODE_TYPES.CallExpression;
|
223
224
|
}
|
224
225
|
/**
|
225
226
|
* Returns whether the node is a literal.
|
@@ -385,7 +386,9 @@ function getExpressionComparedToInt$1(node, value$1, checkOver) {
|
|
385
386
|
*
|
386
387
|
* @param node - The node to check.
|
387
388
|
*/
|
388
|
-
const isIndexOfCall = (node) =>
|
389
|
+
const isIndexOfCall = (node) => {
|
390
|
+
return isMethodCall$1(node) && getMethodName$2(node) === "indexOf";
|
391
|
+
};
|
389
392
|
/**
|
390
393
|
* Returns whether the node is a call to findIndex.
|
391
394
|
*
|
@@ -580,7 +583,7 @@ __export(methodData_exports, {
|
|
580
583
|
isRegExp: () => isRegExp,
|
581
584
|
isSafeInteger: () => isSafeInteger,
|
582
585
|
isSet: () => isSet,
|
583
|
-
isString: () => isString,
|
586
|
+
isString: () => isString$1,
|
584
587
|
isSymbol: () => isSymbol,
|
585
588
|
isTypedArray: () => isTypedArray,
|
586
589
|
isUndefined: () => isUndefined,
|
@@ -1662,7 +1665,7 @@ const isSet = {
|
|
1662
1665
|
iteratee: false,
|
1663
1666
|
args: 1
|
1664
1667
|
};
|
1665
|
-
const isString = {
|
1668
|
+
const isString$1 = {
|
1666
1669
|
wrapper: false,
|
1667
1670
|
shorthand: false,
|
1668
1671
|
chainable: false,
|
@@ -2869,8 +2872,7 @@ const zipWith = {
|
|
2869
2872
|
*
|
2870
2873
|
*/
|
2871
2874
|
function methodSupportsShorthand(method$1, shorthandType) {
|
2872
|
-
const
|
2873
|
-
const methodShorthandData = get(methodData_exports, path);
|
2875
|
+
const methodShorthandData = methodData_exports[method$1].shorthand;
|
2874
2876
|
const isShorthandObject = isObject(methodShorthandData);
|
2875
2877
|
return isShorthandObject ? Boolean(shorthandType && methodShorthandData[shorthandType]) : Boolean(methodShorthandData);
|
2876
2878
|
}
|
@@ -3068,8 +3070,9 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
|
|
3068
3070
|
let iterateeIndex;
|
3069
3071
|
if (remedaContext.isRemedaCall(node)) {
|
3070
3072
|
const method$1 = astUtil_default.getMethodName(node);
|
3073
|
+
if (!isString(method$1)) return;
|
3071
3074
|
iterateeIndex = getIterateeIndex(method$1);
|
3072
|
-
reporter(node, node.arguments[iterateeIndex], {
|
3075
|
+
if (isNumber(iterateeIndex)) reporter(node, node.arguments[iterateeIndex], {
|
3073
3076
|
callType: "method",
|
3074
3077
|
method: method$1,
|
3075
3078
|
remedaContext
|
@@ -3078,7 +3081,7 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
|
|
3078
3081
|
const method$1 = remedaContext.getImportedRemedaMethod(node);
|
3079
3082
|
if (method$1) {
|
3080
3083
|
iterateeIndex = getIterateeIndex(method$1);
|
3081
|
-
reporter(node, node.arguments[iterateeIndex], {
|
3084
|
+
if (isNumber(iterateeIndex)) reporter(node, node.arguments[iterateeIndex], {
|
3082
3085
|
method: method$1,
|
3083
3086
|
callType: "single",
|
3084
3087
|
remedaContext
|
@@ -3088,10 +3091,11 @@ function getRemedaMethodCallExpVisitor(remedaContext, reporter) {
|
|
3088
3091
|
};
|
3089
3092
|
}
|
3090
3093
|
function isRemedaCallToMethod(node, method$1, remedaContext) {
|
3094
|
+
if (!node) return false;
|
3091
3095
|
return remedaContext.isRemedaCall(node) && isCallToMethod(node, method$1);
|
3092
3096
|
}
|
3093
3097
|
function isCallToRemedaMethod(node, method$1, remedaContext) {
|
3094
|
-
if (!node || node.type !==
|
3098
|
+
if (!node || node.type !== AST_NODE_TYPES.CallExpression) return false;
|
3095
3099
|
return isRemedaCallToMethod(node, method$1, remedaContext) || method$1 === remedaContext.getImportedRemedaMethod(node);
|
3096
3100
|
}
|
3097
3101
|
function getRemedaMethodVisitors(context, remedaCallExpVisitor) {
|
@@ -3121,7 +3125,7 @@ function isSideEffectIterationMethod(method$1) {
|
|
3121
3125
|
return includes(getSideEffectIterationMethods(), method$1);
|
3122
3126
|
}
|
3123
3127
|
function isParentCommit(node, callType) {
|
3124
|
-
return callType === "chained" && isCallToMethod(node.parent.parent, "commit");
|
3128
|
+
return callType === "chained" && node.parent.parent && isCallToMethod(node.parent.parent, "commit");
|
3125
3129
|
}
|
3126
3130
|
var collection_method_value_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
3127
3131
|
name: RULE_NAME$14,
|
@@ -3173,18 +3177,22 @@ var collection_return_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3173
3177
|
create(context) {
|
3174
3178
|
const remedaContext = getRemedaContext(context);
|
3175
3179
|
return {
|
3176
|
-
"CallExpression:exit": getRemedaMethodCallExpVisitor(
|
3177
|
-
|
3178
|
-
|
3179
|
-
|
3180
|
-
|
3181
|
-
|
3182
|
-
|
3183
|
-
|
3184
|
-
|
3185
|
-
|
3186
|
-
|
3187
|
-
|
3180
|
+
"CallExpression:exit": getRemedaMethodCallExpVisitor(
|
3181
|
+
remedaContext,
|
3182
|
+
// @ts-expect-error
|
3183
|
+
(node, iteratee$1, { method: method$1 }) => {
|
3184
|
+
if (!isCollectionMethod(method$1)) return;
|
3185
|
+
if (!astUtil_default.isFunctionDefinitionWithBlock(iteratee$1) || iteratee$1.async || iteratee$1.generator) return;
|
3186
|
+
const hasReturnStatement = iteratee$1.body.type === AST_NODE_TYPES.BlockStatement && iteratee$1.body.body.some((statement) => {
|
3187
|
+
return statement.type === AST_NODE_TYPES.ReturnStatement;
|
3188
|
+
});
|
3189
|
+
if (!hasReturnStatement) context.report({
|
3190
|
+
node,
|
3191
|
+
messageId: "no-return",
|
3192
|
+
data: { method: method$1 }
|
3193
|
+
});
|
3194
|
+
}
|
3195
|
+
),
|
3188
3196
|
...remedaContext.getImportVisitors()
|
3189
3197
|
};
|
3190
3198
|
}
|
@@ -3212,8 +3220,14 @@ var prefer_constant_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3212
3220
|
description: "enforce using R.constant over functions returning literals",
|
3213
3221
|
url: getDocsUrl(RULE_NAME$12)
|
3214
3222
|
},
|
3215
|
-
schema: [{
|
3216
|
-
|
3223
|
+
schema: [{
|
3224
|
+
type: "boolean",
|
3225
|
+
description: "Whether to check arrow functions for literals in return statements. Default: true."
|
3226
|
+
}, {
|
3227
|
+
type: "boolean",
|
3228
|
+
description: "Whether to check function declarations for literals in return statements. Default: false."
|
3229
|
+
}],
|
3230
|
+
defaultOptions: [true, false],
|
3217
3231
|
messages: { [MESSAGE_ID$1]: "Prefer R.constant over a function returning a literal" }
|
3218
3232
|
},
|
3219
3233
|
defaultOptions: [true, false],
|
@@ -3301,7 +3315,7 @@ var prefer_filter_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3301
3315
|
defaultOptions: [{ maxPropertyPathLength: 3 }],
|
3302
3316
|
messages: { "prefer-filter": MESSAGE$2 }
|
3303
3317
|
},
|
3304
|
-
defaultOptions: [{}],
|
3318
|
+
defaultOptions: [{ maxPropertyPathLength: 3 }],
|
3305
3319
|
create(context, [options]) {
|
3306
3320
|
const DEFAULT_MAX_PROPERTY_PATH_LENGTH = 3;
|
3307
3321
|
const maxLength = options.maxPropertyPathLength ?? DEFAULT_MAX_PROPERTY_PATH_LENGTH;
|
@@ -3333,7 +3347,7 @@ function isZeroIndexAccess(node) {
|
|
3333
3347
|
return node.type === AST_NODE_TYPES.MemberExpression && node.property.type === AST_NODE_TYPES.Literal && node.property.value === 0;
|
3334
3348
|
}
|
3335
3349
|
function isChainedBeforeMethod(callType, node, method$1) {
|
3336
|
-
return callType === "chained" && isCallToMethod(node.parent
|
3350
|
+
return callType === "chained" && node.parent?.parent !== void 0 && isCallToMethod(node.parent.parent, method$1);
|
3337
3351
|
}
|
3338
3352
|
var prefer_find_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
3339
3353
|
name: RULE_NAME$9,
|
@@ -3353,7 +3367,7 @@ var prefer_find_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3353
3367
|
create(context) {
|
3354
3368
|
return getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1, callType, remedaContext }) => {
|
3355
3369
|
if (method$1 === "filter") {
|
3356
|
-
if (isZeroIndexAccess(node.parent) || isCallToRemedaMethod(node.parent, "first", remedaContext) || isChainedBeforeMethod(callType, node, "first")) context.report({
|
3370
|
+
if (node.parent && isZeroIndexAccess(node.parent) || isCallToRemedaMethod(node.parent, "first", remedaContext) || isChainedBeforeMethod(callType, node, "first")) context.report({
|
3357
3371
|
node,
|
3358
3372
|
messageId: "prefer-find"
|
3359
3373
|
});
|
@@ -3371,7 +3385,8 @@ var prefer_find_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3371
3385
|
const { getCaller } = astUtil_default;
|
3372
3386
|
const RULE_NAME$8 = "prefer-flat-map";
|
3373
3387
|
function isChainedMapFlatten(node) {
|
3374
|
-
|
3388
|
+
const caller = getCaller(node);
|
3389
|
+
return caller ? isCallToMethod(caller, "map") : false;
|
3375
3390
|
}
|
3376
3391
|
var prefer_flat_map_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
3377
3392
|
name: RULE_NAME$8,
|
@@ -3386,12 +3401,16 @@ var prefer_flat_map_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3386
3401
|
},
|
3387
3402
|
defaultOptions: [],
|
3388
3403
|
create(context) {
|
3389
|
-
return getRemedaMethodVisitors(
|
3390
|
-
|
3391
|
-
|
3392
|
-
|
3393
|
-
|
3394
|
-
|
3404
|
+
return getRemedaMethodVisitors(
|
3405
|
+
context,
|
3406
|
+
// @ts-expect-error
|
3407
|
+
(node, iteratee$1, { method: method$1, remedaContext }) => {
|
3408
|
+
if (method$1 === "flat" && (isChainedMapFlatten(node) || isCallToRemedaMethod(node.arguments[0], "map", remedaContext))) context.report({
|
3409
|
+
node,
|
3410
|
+
messageId: "prefer-flat-map"
|
3411
|
+
});
|
3412
|
+
}
|
3413
|
+
);
|
3395
3414
|
}
|
3396
3415
|
});
|
3397
3416
|
|
@@ -3627,12 +3646,21 @@ var prefer_is_nullish_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3627
3646
|
return isNegationExpression(node) && checkExpression(nil, "===", node.argument) || checkExpression(nil, "!==", node);
|
3628
3647
|
}
|
3629
3648
|
function isEquivalentExistingExpression(node, leftNil, rightNil) {
|
3649
|
+
if (node.type !== AST_NODE_TYPES.LogicalExpression) return false;
|
3630
3650
|
const leftExp = checkExpression(leftNil, "===", node.left);
|
3631
|
-
return leftExp && isEquivalentMemberExp(
|
3651
|
+
return leftExp && isEquivalentMemberExp(
|
3652
|
+
leftExp,
|
3653
|
+
// @ts-expect-error
|
3654
|
+
checkExpression(rightNil, "===", node.right)
|
3655
|
+
);
|
3632
3656
|
}
|
3633
3657
|
function isEquivalentExistingNegation(node, leftNil, rightNil) {
|
3634
3658
|
const leftExp = checkNegatedExpression(leftNil, node.left);
|
3635
|
-
return leftExp && isEquivalentMemberExp(
|
3659
|
+
return leftExp && isEquivalentMemberExp(
|
3660
|
+
leftExp,
|
3661
|
+
// @ts-expect-error
|
3662
|
+
checkNegatedExpression(rightNil, node.right)
|
3663
|
+
);
|
3636
3664
|
}
|
3637
3665
|
const visitors = remedaContext.getImportVisitors();
|
3638
3666
|
visitors.LogicalExpression = function(node) {
|
@@ -3654,11 +3682,11 @@ var prefer_is_nullish_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3654
3682
|
//#region src/rules/prefer-map.ts
|
3655
3683
|
const { getFirstFunctionLine, hasOnlyOneStatement, getMethodName, isFunctionDefinitionWithBlock, collectParameterValues } = astUtil_default;
|
3656
3684
|
const RULE_NAME$4 = "prefer-map";
|
3657
|
-
function onlyHasPush(
|
3658
|
-
const firstLine = getFirstFunctionLine(
|
3659
|
-
const firstParam = get(
|
3660
|
-
const exp =
|
3661
|
-
return
|
3685
|
+
function onlyHasPush(node) {
|
3686
|
+
const firstLine = getFirstFunctionLine(node);
|
3687
|
+
const firstParam = get(node, "params[0]");
|
3688
|
+
const exp = node && !isFunctionDefinitionWithBlock(node) ? firstLine : firstLine?.expression;
|
3689
|
+
return node && (node.type === AST_NODE_TYPES.ArrowFunctionExpression ? true : hasOnlyOneStatement(node)) && getMethodName(exp) === "push" && !includes(collectParameterValues(firstParam), get(exp, "callee.object.name"));
|
3662
3690
|
}
|
3663
3691
|
var prefer_map_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
3664
3692
|
name: RULE_NAME$4,
|
@@ -3809,7 +3837,7 @@ var prefer_some_default = ESLintUtils.RuleCreator(getDocsUrl)({
|
|
3809
3837
|
defaultOptions: [],
|
3810
3838
|
create(context) {
|
3811
3839
|
const visitors = getRemedaMethodVisitors(context, (node, iteratee$1, { method: method$1 }) => {
|
3812
|
-
if (method$1 === "findIndex" && node === getExpressionComparedToInt(node.parent, -1, true)) context.report({
|
3840
|
+
if (method$1 === "findIndex" && node.parent?.type === AST_NODE_TYPES.BinaryExpression && node === getExpressionComparedToInt(node.parent, -1, true)) context.report({
|
3813
3841
|
node,
|
3814
3842
|
messageId: "prefer-some"
|
3815
3843
|
});
|
@@ -3884,7 +3912,7 @@ const configs = { recommended: {
|
|
3884
3912
|
[`${pluginShortName}/prefer-constant`]: 2,
|
3885
3913
|
[`${pluginShortName}/prefer-remeda-typecheck`]: 2,
|
3886
3914
|
[`${pluginShortName}/prefer-nullish-coalescing`]: 2,
|
3887
|
-
[`${pluginShortName}/prefer-filter`]:
|
3915
|
+
[`${pluginShortName}/prefer-filter`]: 2,
|
3888
3916
|
[`${pluginShortName}/prefer-has-atleast`]: 2,
|
3889
3917
|
[`${pluginShortName}/collection-method-value`]: 2,
|
3890
3918
|
[`${pluginShortName}/collection-return`]: 2,
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint-plugin-remeda",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.8.0",
|
4
4
|
"author": "Andrea Pontrandolfo <andrea.pontra@gmail.com>",
|
5
5
|
"description": "ESLint plugin for Remeda library.",
|
6
6
|
"type": "module",
|
@@ -8,12 +8,13 @@
|
|
8
8
|
"scripts": {
|
9
9
|
"build": "tsdown",
|
10
10
|
"typecheck": "tsc",
|
11
|
-
"lint": "eslint",
|
11
|
+
"lint": "eslint --max-warnings=0",
|
12
12
|
"knip": "knip",
|
13
13
|
"test:watch": "vitest --ui",
|
14
14
|
"test": "vitest run",
|
15
|
-
"
|
16
|
-
"
|
15
|
+
"check-sheriff-inconsistencies": "sheriff",
|
16
|
+
"attw": "attw --ignore-rules=false-export-default --pack .",
|
17
|
+
"qa": "pnpm build && pnpm typecheck && pnpm lint && pnpm test && pnpm knip && pnpm attw && pnpm check-sheriff-inconsistencies",
|
17
18
|
"nuke": "rm -rf node_modules pnpm-lock.yaml",
|
18
19
|
"update:eslint-docs": "eslint-doc-generator",
|
19
20
|
"lint:eslint-docs": "pnpm update:eslint-docs -- --check",
|
@@ -49,7 +50,7 @@
|
|
49
50
|
},
|
50
51
|
"devDependencies": {
|
51
52
|
"@arethetypeswrong/cli": "^0.17.4",
|
52
|
-
"@sherifforg/cli": "^8.
|
53
|
+
"@sherifforg/cli": "^8.3.0",
|
53
54
|
"@types/lodash-es": "^4.17.12",
|
54
55
|
"@types/node": "^22.14.0",
|
55
56
|
"@typescript-eslint/utils": "^8.29.0",
|