eslint-plugin-react-x 5.7.2 → 5.7.3
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.js +57 -31
- package/package.json +12 -12
package/dist/index.js
CHANGED
|
@@ -143,7 +143,7 @@ const rules$6 = {
|
|
|
143
143
|
//#endregion
|
|
144
144
|
//#region package.json
|
|
145
145
|
var name$6 = "eslint-plugin-react-x";
|
|
146
|
-
var version = "5.7.
|
|
146
|
+
var version = "5.7.3";
|
|
147
147
|
|
|
148
148
|
//#endregion
|
|
149
149
|
//#region src/utils/create-rule.ts
|
|
@@ -1279,6 +1279,46 @@ const MUTATING_ARRAY_METHODS = new Set([
|
|
|
1279
1279
|
"splice",
|
|
1280
1280
|
"unshift"
|
|
1281
1281
|
]);
|
|
1282
|
+
/**
|
|
1283
|
+
* Check if a name is ref-like ("ref" or ends with "Ref").
|
|
1284
|
+
* Refs are mutable by design and exempted from immutability checks.
|
|
1285
|
+
*/
|
|
1286
|
+
function isRefLikeName(name) {
|
|
1287
|
+
return name === "ref" || name.endsWith("Ref");
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Check if any identifier or property name in a member-expression chain
|
|
1291
|
+
* is ref-like.
|
|
1292
|
+
*/
|
|
1293
|
+
function hasRefLikeNameInChain(node) {
|
|
1294
|
+
if (node.type === AST_NODE_TYPES.Identifier) return isRefLikeName(node.name);
|
|
1295
|
+
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
1296
|
+
const propName = Extract.getPropertyName(node.property);
|
|
1297
|
+
if (propName != null && isRefLikeName(propName)) return true;
|
|
1298
|
+
return hasRefLikeNameInChain(node.object);
|
|
1299
|
+
}
|
|
1300
|
+
return false;
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Check if `name` appears anywhere inside a parameter pattern.
|
|
1304
|
+
* @param pattern - The parameter pattern to search in.
|
|
1305
|
+
* @param name - The identifier name to look for.
|
|
1306
|
+
*/
|
|
1307
|
+
function identifierExistsInPattern(pattern, name) {
|
|
1308
|
+
switch (pattern.type) {
|
|
1309
|
+
case AST_NODE_TYPES.Identifier: return pattern.name === name;
|
|
1310
|
+
case AST_NODE_TYPES.ObjectPattern: return pattern.properties.some((p) => {
|
|
1311
|
+
if (p.type === AST_NODE_TYPES.Property) return identifierExistsInPattern(p.value, name);
|
|
1312
|
+
if (p.type === AST_NODE_TYPES.RestElement) return identifierExistsInPattern(p.argument, name);
|
|
1313
|
+
return false;
|
|
1314
|
+
});
|
|
1315
|
+
case AST_NODE_TYPES.ArrayPattern: return pattern.elements.some((el) => el != null && identifierExistsInPattern(el, name));
|
|
1316
|
+
case AST_NODE_TYPES.RestElement: return identifierExistsInPattern(pattern.argument, name);
|
|
1317
|
+
case AST_NODE_TYPES.AssignmentPattern: return identifierExistsInPattern(pattern.left, name);
|
|
1318
|
+
case AST_NODE_TYPES.MemberExpression: return Extract.getRootIdentifier(pattern)?.name === name;
|
|
1319
|
+
default: return false;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1282
1322
|
|
|
1283
1323
|
//#endregion
|
|
1284
1324
|
//#region src/rules/immutability/immutability.ts
|
|
@@ -1289,7 +1329,8 @@ var immutability_default = createRule({
|
|
|
1289
1329
|
docs: { description: "Validates against mutating props, state, and other values that are immutable." },
|
|
1290
1330
|
messages: {
|
|
1291
1331
|
mutatingArrayMethod: "Do not call '{{method}}()' on '{{name}}'. Props and state are immutable — create a new array instead.",
|
|
1292
|
-
mutatingAssignment: "Do not mutate '{{name}}' directly. Props and state are immutable — create a new object instead."
|
|
1332
|
+
mutatingAssignment: "Do not mutate '{{name}}' directly. Props and state are immutable — create a new object instead.",
|
|
1333
|
+
noRefLikeStateName: "State variable '{{name}}' should not be named 'ref' or end with 'Ref'. Use a different name to avoid confusion with mutable refs."
|
|
1293
1334
|
},
|
|
1294
1335
|
schema: []
|
|
1295
1336
|
},
|
|
@@ -1309,14 +1350,6 @@ function create$48(context) {
|
|
|
1309
1350
|
function isUseStateCall(node) {
|
|
1310
1351
|
return core.isUseStateLikeCall(node, additionalStateHooks);
|
|
1311
1352
|
}
|
|
1312
|
-
function isUseReducerCall(node) {
|
|
1313
|
-
const callee = Extract.unwrap(node.callee);
|
|
1314
|
-
if (callee.type === AST_NODE_TYPES.Identifier) return callee.name === "useReducer";
|
|
1315
|
-
if (callee.type === AST_NODE_TYPES.MemberExpression) {
|
|
1316
|
-
if (Extract.getRootIdentifier(callee)?.name === "React") return Extract.getPropertyName(callee.property) === "useReducer";
|
|
1317
|
-
}
|
|
1318
|
-
return false;
|
|
1319
|
-
}
|
|
1320
1353
|
/**
|
|
1321
1354
|
* Return true when `id` is the *value* variable (index 0) produced by a
|
|
1322
1355
|
* `useState(…)` or `useReducer(…)` call.
|
|
@@ -1326,32 +1359,12 @@ function create$48(context) {
|
|
|
1326
1359
|
function isStateValue(id) {
|
|
1327
1360
|
const initNode = resolve(context, id);
|
|
1328
1361
|
if (initNode == null || initNode.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
1329
|
-
if (!isUseStateCall(initNode) && !isUseReducerCall(initNode)) return false;
|
|
1362
|
+
if (!isUseStateCall(initNode) && !core.isUseReducerCall(context, initNode)) return false;
|
|
1330
1363
|
const declarator = initNode.parent;
|
|
1331
1364
|
if (!("id" in declarator) || declarator.id?.type !== AST_NODE_TYPES.ArrayPattern) return true;
|
|
1332
1365
|
return declarator.id.elements.findIndex((el) => el?.type === AST_NODE_TYPES.Identifier && el.name === id.name) === 0;
|
|
1333
1366
|
}
|
|
1334
1367
|
/**
|
|
1335
|
-
* Check if `name` appears anywhere inside a parameter pattern.
|
|
1336
|
-
* @param pattern - The parameter pattern to search in.
|
|
1337
|
-
* @param name - The identifier name to look for.
|
|
1338
|
-
*/
|
|
1339
|
-
function identifierExistsInPattern(pattern, name) {
|
|
1340
|
-
switch (pattern.type) {
|
|
1341
|
-
case AST_NODE_TYPES.Identifier: return pattern.name === name;
|
|
1342
|
-
case AST_NODE_TYPES.ObjectPattern: return pattern.properties.some((p) => {
|
|
1343
|
-
if (p.type === AST_NODE_TYPES.Property) return identifierExistsInPattern(p.value, name);
|
|
1344
|
-
if (p.type === AST_NODE_TYPES.RestElement) return identifierExistsInPattern(p.argument, name);
|
|
1345
|
-
return false;
|
|
1346
|
-
});
|
|
1347
|
-
case AST_NODE_TYPES.ArrayPattern: return pattern.elements.some((el) => el != null && identifierExistsInPattern(el, name));
|
|
1348
|
-
case AST_NODE_TYPES.RestElement: return identifierExistsInPattern(pattern.argument, name);
|
|
1349
|
-
case AST_NODE_TYPES.AssignmentPattern: return identifierExistsInPattern(pattern.left, name);
|
|
1350
|
-
case AST_NODE_TYPES.MemberExpression: return Extract.getRootIdentifier(pattern)?.name === name;
|
|
1351
|
-
default: return false;
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
/**
|
|
1355
1368
|
* Return the function node when `id` is a parameter of any position in any
|
|
1356
1369
|
* ancestor function; otherwise return `null`.
|
|
1357
1370
|
*
|
|
@@ -1396,6 +1409,17 @@ function create$48(context) {
|
|
|
1396
1409
|
* @param node The CallExpression node to analyze.
|
|
1397
1410
|
*/
|
|
1398
1411
|
CallExpression(node) {
|
|
1412
|
+
if (isUseStateCall(node) || core.isUseReducerCall(context, node)) {
|
|
1413
|
+
const declarator = node.parent;
|
|
1414
|
+
if (declarator?.type === AST_NODE_TYPES.VariableDeclarator && declarator.id?.type === AST_NODE_TYPES.ArrayPattern) {
|
|
1415
|
+
const [firstElement] = declarator.id.elements;
|
|
1416
|
+
if (firstElement?.type === AST_NODE_TYPES.Identifier && isRefLikeName(firstElement.name)) context.report({
|
|
1417
|
+
data: { name: firstElement.name },
|
|
1418
|
+
messageId: "noRefLikeStateName",
|
|
1419
|
+
node: firstElement
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1399
1423
|
const callee = Extract.unwrap(node.callee);
|
|
1400
1424
|
if (callee.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
1401
1425
|
const { object, property } = callee;
|
|
@@ -1404,6 +1428,7 @@ function create$48(context) {
|
|
|
1404
1428
|
const rootId = Extract.getRootIdentifier(object);
|
|
1405
1429
|
if (rootId == null) return;
|
|
1406
1430
|
if (rootId.name === "draft") return;
|
|
1431
|
+
if (hasRefLikeNameInChain(object)) return;
|
|
1407
1432
|
const enclosingFn = Traverse.findParent(node, Check.isFunction);
|
|
1408
1433
|
if (enclosingFn == null) return;
|
|
1409
1434
|
const isState = isStateValue(rootId);
|
|
@@ -1434,6 +1459,7 @@ function create$48(context) {
|
|
|
1434
1459
|
const rootId = Extract.getRootIdentifier(node.left);
|
|
1435
1460
|
if (rootId == null) return;
|
|
1436
1461
|
if (rootId.name === "draft") return;
|
|
1462
|
+
if (hasRefLikeNameInChain(node.left.object)) return;
|
|
1437
1463
|
const enclosingFn = Traverse.findParent(node, Check.isFunction);
|
|
1438
1464
|
if (enclosingFn == null) return;
|
|
1439
1465
|
const isState = isStateValue(rootId);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "5.7.
|
|
3
|
+
"version": "5.7.3",
|
|
4
4
|
"description": "A set of composable ESLint rules for libraries and frameworks that use React as a UI runtime.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -36,21 +36,21 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@typescript-eslint/scope-manager": "^8.59.
|
|
40
|
-
"@typescript-eslint/type-utils": "^8.59.
|
|
41
|
-
"@typescript-eslint/types": "^8.59.
|
|
42
|
-
"@typescript-eslint/typescript-estree": "^8.59.
|
|
43
|
-
"@typescript-eslint/utils": "^8.59.
|
|
39
|
+
"@typescript-eslint/scope-manager": "^8.59.2",
|
|
40
|
+
"@typescript-eslint/type-utils": "^8.59.2",
|
|
41
|
+
"@typescript-eslint/types": "^8.59.2",
|
|
42
|
+
"@typescript-eslint/typescript-estree": "^8.59.2",
|
|
43
|
+
"@typescript-eslint/utils": "^8.59.2",
|
|
44
44
|
"compare-versions": "^6.1.1",
|
|
45
45
|
"string-ts": "^2.3.1",
|
|
46
46
|
"ts-api-utils": "^2.5.0",
|
|
47
47
|
"ts-pattern": "^5.9.0",
|
|
48
|
-
"@eslint-react/ast": "5.7.
|
|
49
|
-
"@eslint-react/
|
|
50
|
-
"@eslint-react/
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/var": "5.7.
|
|
48
|
+
"@eslint-react/ast": "5.7.3",
|
|
49
|
+
"@eslint-react/eslint": "5.7.3",
|
|
50
|
+
"@eslint-react/jsx": "5.7.3",
|
|
51
|
+
"@eslint-react/shared": "5.7.3",
|
|
52
|
+
"@eslint-react/core": "5.7.3",
|
|
53
|
+
"@eslint-react/var": "5.7.3"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/react": "^19.2.14",
|