eslint-plugin-react-x 5.5.4-next.0 → 5.5.6-beta.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.js +68 -16
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -142,7 +142,7 @@ const rules$6 = {
|
|
|
142
142
|
//#endregion
|
|
143
143
|
//#region package.json
|
|
144
144
|
var name$6 = "eslint-plugin-react-x";
|
|
145
|
-
var version = "5.5.
|
|
145
|
+
var version = "5.5.6-beta.0";
|
|
146
146
|
|
|
147
147
|
//#endregion
|
|
148
148
|
//#region src/utils/create-rule.ts
|
|
@@ -6584,10 +6584,45 @@ function isInitializedFromRef(context, name, initialScope) {
|
|
|
6584
6584
|
switch (true) {
|
|
6585
6585
|
case init.type === AST_NODE_TYPES.MemberExpression && init.object.type === AST_NODE_TYPES.Identifier && (init.object.name === "ref" || init.object.name.endsWith("Ref")): return true;
|
|
6586
6586
|
case init.type === AST_NODE_TYPES.CallExpression && core.isUseRefCall(context, init): return true;
|
|
6587
|
+
case init.type === AST_NODE_TYPES.CallExpression: return getNestedIdentifiers(init).some((id) => isInitializedFromRef(context, id.name, context.sourceCode.getScope(id)));
|
|
6587
6588
|
}
|
|
6588
6589
|
}
|
|
6589
6590
|
return false;
|
|
6590
6591
|
}
|
|
6592
|
+
/**
|
|
6593
|
+
* Check if a setState call is inside a conditional block whose test expression
|
|
6594
|
+
* is derived from a ref value (e.g. `if (prevRef.current !== value) setState(...)`).
|
|
6595
|
+
* @param context The ESLint rule context
|
|
6596
|
+
* @param node The AST node to check
|
|
6597
|
+
* @returns `true` if the node is inside a ref-gated conditional block
|
|
6598
|
+
*/
|
|
6599
|
+
function isRefGatedContext(context, node) {
|
|
6600
|
+
let current = node.parent;
|
|
6601
|
+
while (current != null) {
|
|
6602
|
+
if (Check.isFunction(current)) break;
|
|
6603
|
+
if (current.type === AST_NODE_TYPES.IfStatement) {
|
|
6604
|
+
if (isRefInExpression(context, current.test)) return true;
|
|
6605
|
+
}
|
|
6606
|
+
if (current.type === AST_NODE_TYPES.ConditionalExpression) {
|
|
6607
|
+
if (isRefInExpression(context, current.test)) return true;
|
|
6608
|
+
}
|
|
6609
|
+
current = current.parent;
|
|
6610
|
+
}
|
|
6611
|
+
return false;
|
|
6612
|
+
}
|
|
6613
|
+
function isRefInExpression(context, node) {
|
|
6614
|
+
return getNestedIdentifiers(node).some((id) => isInitializedFromRef(context, id.name, context.sourceCode.getScope(id)));
|
|
6615
|
+
}
|
|
6616
|
+
/**
|
|
6617
|
+
* Get the actual CallExpression node from a setState call reference.
|
|
6618
|
+
* When the node is an Identifier that is the callee of a CallExpression,
|
|
6619
|
+
* returns the parent CallExpression; otherwise returns the node itself.
|
|
6620
|
+
* @param node The setState call node (CallExpression or Identifier)
|
|
6621
|
+
* @returns The actual CallExpression node
|
|
6622
|
+
*/
|
|
6623
|
+
function getSetStateCallExpression(node) {
|
|
6624
|
+
return node.type === AST_NODE_TYPES.Identifier && node.parent?.type === AST_NODE_TYPES.CallExpression ? node.parent : node;
|
|
6625
|
+
}
|
|
6591
6626
|
|
|
6592
6627
|
//#endregion
|
|
6593
6628
|
//#region src/rules/set-state-in-effect/set-state-in-effect.ts
|
|
@@ -6711,6 +6746,13 @@ function create$5(context) {
|
|
|
6711
6746
|
case AST_NODE_TYPES.Identifier: return isInitializedFromRef(context, n.name, context.sourceCode.getScope(n));
|
|
6712
6747
|
case AST_NODE_TYPES.MemberExpression: return isUsingRefValue(n.object);
|
|
6713
6748
|
case AST_NODE_TYPES.CallExpression: return isUsingRefValue(n.callee) || getNestedIdentifiers(n).some(isUsingRefValue);
|
|
6749
|
+
case AST_NODE_TYPES.BinaryExpression:
|
|
6750
|
+
case AST_NODE_TYPES.LogicalExpression: return isUsingRefValue(n.left) || isUsingRefValue(n.right);
|
|
6751
|
+
case AST_NODE_TYPES.UnaryExpression:
|
|
6752
|
+
case AST_NODE_TYPES.UpdateExpression: return isUsingRefValue(n.argument);
|
|
6753
|
+
case AST_NODE_TYPES.ConditionalExpression: return isUsingRefValue(n.consequent) || isUsingRefValue(n.alternate);
|
|
6754
|
+
case AST_NODE_TYPES.SequenceExpression: return n.expressions.some(isUsingRefValue);
|
|
6755
|
+
case AST_NODE_TYPES.AssignmentExpression: return isUsingRefValue(n.right);
|
|
6714
6756
|
default: return false;
|
|
6715
6757
|
}
|
|
6716
6758
|
};
|
|
@@ -6718,6 +6760,7 @@ function create$5(context) {
|
|
|
6718
6760
|
return Check.isFunction(node) && context.sourceCode.getScope(node.body).references.some((r) => isUsingRefValue(r.identifier));
|
|
6719
6761
|
}
|
|
6720
6762
|
if (isArgumentUsingRefValue(context, args0)) return;
|
|
6763
|
+
if (isRefGatedContext(context, node)) return;
|
|
6721
6764
|
context.report({
|
|
6722
6765
|
data: { name: context.sourceCode.getText(node.callee) },
|
|
6723
6766
|
messageId: "default",
|
|
@@ -6772,27 +6815,36 @@ function create$5(context) {
|
|
|
6772
6815
|
}
|
|
6773
6816
|
return [];
|
|
6774
6817
|
};
|
|
6775
|
-
for (const [, calls] of setStateInEffectSetup) for (const call of calls)
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6818
|
+
for (const [, calls] of setStateInEffectSetup) for (const call of calls) {
|
|
6819
|
+
if (isRefGatedContext(context, getSetStateCallExpression(call))) continue;
|
|
6820
|
+
context.report({
|
|
6821
|
+
data: { name: call.name },
|
|
6822
|
+
messageId: "default",
|
|
6823
|
+
node: call
|
|
6824
|
+
});
|
|
6825
|
+
}
|
|
6780
6826
|
for (const { callee } of trackedFnCalls) {
|
|
6781
6827
|
if (!("name" in callee)) continue;
|
|
6782
6828
|
const setStateCalls = getSetStateCalls(context, callee);
|
|
6783
|
-
for (const setStateCall of setStateCalls)
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6829
|
+
for (const setStateCall of setStateCalls) {
|
|
6830
|
+
if (isRefGatedContext(context, getSetStateCallExpression(setStateCall))) continue;
|
|
6831
|
+
context.report({
|
|
6832
|
+
data: { name: getCallName(setStateCall) },
|
|
6833
|
+
messageId: "default",
|
|
6834
|
+
node: setStateCall
|
|
6835
|
+
});
|
|
6836
|
+
}
|
|
6788
6837
|
}
|
|
6789
6838
|
for (const id of setupFnIds) {
|
|
6790
6839
|
const setStateCalls = getSetStateCalls(context, id);
|
|
6791
|
-
for (const setStateCall of setStateCalls)
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6840
|
+
for (const setStateCall of setStateCalls) {
|
|
6841
|
+
if (isRefGatedContext(context, getSetStateCallExpression(setStateCall))) continue;
|
|
6842
|
+
context.report({
|
|
6843
|
+
data: { name: getCallName(setStateCall) },
|
|
6844
|
+
messageId: "default",
|
|
6845
|
+
node: setStateCall
|
|
6846
|
+
});
|
|
6847
|
+
}
|
|
6796
6848
|
}
|
|
6797
6849
|
}
|
|
6798
6850
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.6-beta.0",
|
|
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,12 +45,12 @@
|
|
|
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.5.
|
|
49
|
-
"@eslint-react/
|
|
50
|
-
"@eslint-react/
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/
|
|
48
|
+
"@eslint-react/ast": "5.5.6-beta.0",
|
|
49
|
+
"@eslint-react/core": "5.5.6-beta.0",
|
|
50
|
+
"@eslint-react/eslint": "5.5.6-beta.0",
|
|
51
|
+
"@eslint-react/shared": "5.5.6-beta.0",
|
|
52
|
+
"@eslint-react/var": "5.5.6-beta.0",
|
|
53
|
+
"@eslint-react/jsx": "5.5.6-beta.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/react": "^19.2.14",
|