eslint-plugin-react-x 5.14.5 → 5.14.6
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 +30 -77
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -144,7 +144,7 @@ const rules$6 = {
|
|
|
144
144
|
//#endregion
|
|
145
145
|
//#region package.json
|
|
146
146
|
var name$6 = "eslint-plugin-react-x";
|
|
147
|
-
var version = "5.14.
|
|
147
|
+
var version = "5.14.6";
|
|
148
148
|
|
|
149
149
|
//#endregion
|
|
150
150
|
//#region src/utils/create-rule.ts
|
|
@@ -1344,103 +1344,55 @@ const MUTATING_METHODS = /* @__PURE__ */ new Set([
|
|
|
1344
1344
|
"splice",
|
|
1345
1345
|
"unshift"
|
|
1346
1346
|
]);
|
|
1347
|
-
|
|
1348
|
-
* Check if `inner` is fully contained within `outer`'s source range.
|
|
1349
|
-
* @param inner The node that may be contained.
|
|
1350
|
-
* @param outer The node that may contain it.
|
|
1351
|
-
*/
|
|
1352
|
-
function isNodeWithin(inner, outer) {
|
|
1353
|
-
return inner.range[0] >= outer.range[0] && inner.range[1] <= outer.range[1];
|
|
1354
|
-
}
|
|
1355
|
-
/**
|
|
1356
|
-
* Resolve an expression to the function it ultimately refers to, following
|
|
1357
|
-
* simple local aliasing (`const fn2 = fn;`) via scope resolution.
|
|
1358
|
-
* @param context The ESLint rule context.
|
|
1359
|
-
* @param node The expression to resolve.
|
|
1360
|
-
* @param seen Identifiers already visited, to guard against cycles.
|
|
1361
|
-
*/
|
|
1347
|
+
const isUseRouterCall = core.isAPICall("useRouter");
|
|
1362
1348
|
function resolveToFunctionNode(context, node, seen = /* @__PURE__ */ new Set()) {
|
|
1363
1349
|
const expr = Extract.unwrap(node);
|
|
1364
1350
|
if (Check.isFunction(expr)) return expr;
|
|
1365
|
-
if (expr.type !== AST_NODE_TYPES.Identifier) return null;
|
|
1366
|
-
if (seen.has(expr)) return null;
|
|
1351
|
+
if (expr.type !== AST_NODE_TYPES.Identifier || seen.has(expr)) return null;
|
|
1367
1352
|
seen.add(expr);
|
|
1368
1353
|
const resolved = resolve(context, expr);
|
|
1369
|
-
|
|
1370
|
-
return resolveToFunctionNode(context, resolved, seen);
|
|
1354
|
+
return resolved == null ? null : resolveToFunctionNode(context, resolved, seen);
|
|
1371
1355
|
}
|
|
1372
|
-
/**
|
|
1373
|
-
* Follow identifier-only variable-declarator aliases to their originating
|
|
1374
|
-
* binding. Assignment aliases are intentionally left for the value-flow phase.
|
|
1375
|
-
* @param context The ESLint rule context.
|
|
1376
|
-
* @param variable The binding whose initializer aliases should be followed.
|
|
1377
|
-
* @param seen Bindings already visited, to guard against cycles.
|
|
1378
|
-
*/
|
|
1379
1356
|
function resolveVariableOrigin(context, variable, seen = /* @__PURE__ */ new Set()) {
|
|
1380
1357
|
if (seen.has(variable)) return variable;
|
|
1381
1358
|
seen.add(variable);
|
|
1382
|
-
const
|
|
1383
|
-
if (
|
|
1384
|
-
const
|
|
1385
|
-
if (
|
|
1386
|
-
const source = findVariable(context.sourceCode.getScope(
|
|
1387
|
-
|
|
1388
|
-
return resolveVariableOrigin(context, source, seen);
|
|
1359
|
+
const def = variable.defs.length === 1 ? variable.defs[0] : null;
|
|
1360
|
+
if (def?.type !== DefinitionType.Variable || def.node.init == null) return variable;
|
|
1361
|
+
const init = Extract.unwrap(def.node.init);
|
|
1362
|
+
if (init.type !== AST_NODE_TYPES.Identifier) return variable;
|
|
1363
|
+
const source = findVariable(context.sourceCode.getScope(init), init);
|
|
1364
|
+
return source == null ? variable : resolveVariableOrigin(context, source, seen);
|
|
1389
1365
|
}
|
|
1390
|
-
/**
|
|
1391
|
-
* Check if a name is ref-like ("ref" or ends with "Ref").
|
|
1392
|
-
* Refs are mutable by design and exempted from immutability checks.
|
|
1393
|
-
* @param name The identifier name to check.
|
|
1394
|
-
*/
|
|
1395
1366
|
function isRefLikeName$1(name) {
|
|
1396
1367
|
return name === "ref" || name.endsWith("Ref");
|
|
1397
1368
|
}
|
|
1398
|
-
/**
|
|
1399
|
-
* Check if any identifier or property name in a member-expression chain
|
|
1400
|
-
* is ref-like.
|
|
1401
|
-
* @param node The AST node to inspect.
|
|
1402
|
-
*/
|
|
1403
1369
|
function hasRefLikeNameInChain(node) {
|
|
1404
1370
|
if (node.type === AST_NODE_TYPES.Identifier) return isRefLikeName$1(node.name);
|
|
1405
|
-
if (node.type
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
return hasRefLikeNameInChain(node.object);
|
|
1409
|
-
}
|
|
1410
|
-
return false;
|
|
1371
|
+
if (node.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
1372
|
+
const propertyName = Extract.getPropertyName(node.property);
|
|
1373
|
+
return propertyName != null ? isRefLikeName$1(propertyName) || hasRefLikeNameInChain(node.object) : hasRefLikeNameInChain(node.object);
|
|
1411
1374
|
}
|
|
1412
|
-
|
|
1413
|
-
* Check if the root identifier of a member-expression chain is initialized
|
|
1414
|
-
* from a `useRef()` call, following variable-declarator aliases.
|
|
1415
|
-
* @param context The ESLint rule context.
|
|
1416
|
-
* @param node The AST node to inspect (an identifier or member-expression chain).
|
|
1417
|
-
*/
|
|
1418
|
-
function isInitializedFromUseRef(context, node) {
|
|
1375
|
+
function isInitializedFromCall(context, node, isCall) {
|
|
1419
1376
|
const root = node.type === AST_NODE_TYPES.Identifier ? node : Extract.getRootIdentifier(node);
|
|
1420
1377
|
if (root == null) return false;
|
|
1421
1378
|
const variable = findVariable(context.sourceCode.getScope(root), root);
|
|
1422
1379
|
if (variable == null) return false;
|
|
1423
|
-
|
|
1380
|
+
const origin = resolveVariableOrigin(context, variable);
|
|
1381
|
+
const def = origin.defs.length === 1 ? origin.defs[0] : null;
|
|
1382
|
+
if (def?.type !== DefinitionType.Variable || def.node.init == null) return false;
|
|
1383
|
+
const init = Extract.unwrap(def.node.init);
|
|
1384
|
+
return init.type === AST_NODE_TYPES.CallExpression && isCall(init);
|
|
1424
1385
|
}
|
|
1425
|
-
function
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
return source != null && isVariableInitializedFromUseRef(context, source, seen);
|
|
1386
|
+
function isInitializedFromUseRef(context, node) {
|
|
1387
|
+
return isInitializedFromCall(context, node, (init) => core.isUseRefCall(context, init));
|
|
1388
|
+
}
|
|
1389
|
+
function isInitializedFromUseRouter(context, node) {
|
|
1390
|
+
return isInitializedFromCall(context, node, (init) => isUseRouterCall(context, init));
|
|
1391
|
+
}
|
|
1392
|
+
function isKnownNonMutatingMethodCall(context, node) {
|
|
1393
|
+
const callee = Extract.unwrap(node.callee);
|
|
1394
|
+
return Check.isExpression(callee) && isInitializedFromUseRouter(context, callee);
|
|
1435
1395
|
}
|
|
1436
|
-
/**
|
|
1437
|
-
* Check if a mutated expression chain should be exempt from immutability
|
|
1438
|
-
* checks because it is rooted at a ref: either by naming convention
|
|
1439
|
-
* ({@link hasRefLikeNameInChain}) or because it is initialized from a
|
|
1440
|
-
* `useRef()` call ({@link isInitializedFromUseRef}).
|
|
1441
|
-
* @param context The ESLint rule context.
|
|
1442
|
-
* @param node The AST node to inspect (an identifier or member-expression chain).
|
|
1443
|
-
*/
|
|
1444
1396
|
function isRefLikeChain(context, node) {
|
|
1445
1397
|
return hasRefLikeNameInChain(node) || isInitializedFromUseRef(context, node);
|
|
1446
1398
|
}
|
|
@@ -1542,6 +1494,7 @@ function isRefMutation(context, mutation) {
|
|
|
1542
1494
|
function inferMutableFunctions(context, mutations) {
|
|
1543
1495
|
const mutableFunctions = /* @__PURE__ */ new Map();
|
|
1544
1496
|
for (const mutation of mutations) {
|
|
1497
|
+
if (mutation.node.type === AST_NODE_TYPES.CallExpression && isKnownNonMutatingMethodCall(context, mutation.node)) continue;
|
|
1545
1498
|
if (isRefMutation(context, mutation)) continue;
|
|
1546
1499
|
const variable = findVariable(context.sourceCode.getScope(mutation.root), mutation.root);
|
|
1547
1500
|
if (variable == null) continue;
|
|
@@ -1550,7 +1503,7 @@ function inferMutableFunctions(context, mutations) {
|
|
|
1550
1503
|
const declaration = origin.identifiers.at(0) ?? null;
|
|
1551
1504
|
let current = mutation.enclosingFunction;
|
|
1552
1505
|
while (current != null) {
|
|
1553
|
-
if (declaration != null &&
|
|
1506
|
+
if (declaration != null && Traverse.findParent(declaration, Check.isFunction) === current) break;
|
|
1554
1507
|
if (!mutableFunctions.has(current)) mutableFunctions.set(current, {
|
|
1555
1508
|
name: origin.name,
|
|
1556
1509
|
node: mutation.node
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "5.14.
|
|
3
|
+
"version": "5.14.6",
|
|
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",
|
|
@@ -45,26 +45,26 @@
|
|
|
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/
|
|
49
|
-
"@eslint-react/
|
|
50
|
-
"@eslint-react/
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/shared": "5.14.
|
|
53
|
-
"@eslint-react/var": "5.14.
|
|
48
|
+
"@eslint-react/ast": "5.14.6",
|
|
49
|
+
"@eslint-react/core": "5.14.6",
|
|
50
|
+
"@eslint-react/jsx": "5.14.6",
|
|
51
|
+
"@eslint-react/eslint": "5.14.6",
|
|
52
|
+
"@eslint-react/shared": "5.14.6",
|
|
53
|
+
"@eslint-react/var": "5.14.6"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/react": "^19.2.17",
|
|
57
57
|
"@types/react-dom": "^19.2.3",
|
|
58
58
|
"dedent": "^1.7.2",
|
|
59
|
-
"eslint": "^10.
|
|
59
|
+
"eslint": "^10.7.0",
|
|
60
60
|
"react": "^19.2.7",
|
|
61
61
|
"react-dom": "^19.2.7",
|
|
62
62
|
"tsdown": "^0.22.4",
|
|
63
63
|
"tsl": "^1.0.30",
|
|
64
64
|
"tsl-dx": "^0.13.2",
|
|
65
65
|
"typescript": "6.0.3",
|
|
66
|
-
"@local/
|
|
67
|
-
"@local/
|
|
66
|
+
"@local/configs": "0.0.0",
|
|
67
|
+
"@local/eff": "0.0.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"eslint": "*",
|