eslint-plugin-react-x 5.27.1 → 5.27.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 +73 -70
- package/package.json +9 -7
package/dist/index.js
CHANGED
|
@@ -135,7 +135,7 @@ const rules$6 = {
|
|
|
135
135
|
//#endregion
|
|
136
136
|
//#region package.json
|
|
137
137
|
var name$6 = "eslint-plugin-react-x";
|
|
138
|
-
var version = "5.27.
|
|
138
|
+
var version = "5.27.3";
|
|
139
139
|
//#endregion
|
|
140
140
|
//#region src/utils/create-rule.ts
|
|
141
141
|
function getDocsUrl(ruleName) {
|
|
@@ -6422,7 +6422,8 @@ function isHookDecl(node) {
|
|
|
6422
6422
|
if (node.type !== AST_NODE_TYPES.VariableDeclarator) return false;
|
|
6423
6423
|
if (!Check.isIdentifier(node.id)) return false;
|
|
6424
6424
|
const init = node.init;
|
|
6425
|
-
if (init == null
|
|
6425
|
+
if (init == null) return false;
|
|
6426
|
+
if (init.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
6426
6427
|
const name = Extract.getCalleeName(init);
|
|
6427
6428
|
return name != null && core.isHookName(name);
|
|
6428
6429
|
}
|
|
@@ -6462,13 +6463,11 @@ function createFactCollector$3(additionalStateHooks, additionalEffectHooks) {
|
|
|
6462
6463
|
}
|
|
6463
6464
|
function getFunctionKind(node) {
|
|
6464
6465
|
const parent = Traverse.findParent(node, not(Check.isTypeExpression)) ?? node.parent;
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
default: return "other";
|
|
6471
|
-
}
|
|
6466
|
+
if (node.async) return "deferred";
|
|
6467
|
+
if (parent.type === AST_NODE_TYPES.CallExpression && isThenCall(parent)) return "deferred";
|
|
6468
|
+
if (node.type !== AST_NODE_TYPES.FunctionDeclaration && parent.type === AST_NODE_TYPES.CallExpression && parent.callee === node) return "immediate";
|
|
6469
|
+
if (isUseEffectSetupCallback(node)) return "setup";
|
|
6470
|
+
return "other";
|
|
6472
6471
|
}
|
|
6473
6472
|
return {
|
|
6474
6473
|
facts,
|
|
@@ -6488,7 +6487,8 @@ function createFactCollector$3(additionalStateHooks, additionalEffectHooks) {
|
|
|
6488
6487
|
},
|
|
6489
6488
|
CallExpression(node) {
|
|
6490
6489
|
const entry = functionEntries.at(-1);
|
|
6491
|
-
if (entry == null
|
|
6490
|
+
if (entry == null) return;
|
|
6491
|
+
if (entry.node.async) return;
|
|
6492
6492
|
if (isUseStateCall(node)) return;
|
|
6493
6493
|
if (isUseEffectCall(node)) {
|
|
6494
6494
|
const setup = node.arguments.at(0);
|
|
@@ -6504,20 +6504,17 @@ function createFactCollector$3(additionalStateHooks, additionalEffectHooks) {
|
|
|
6504
6504
|
},
|
|
6505
6505
|
Identifier(node) {
|
|
6506
6506
|
if (node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) return;
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
return;
|
|
6514
|
-
case AST_NODE_TYPES.CallExpression:
|
|
6515
|
-
if (node === node.parent.arguments.at(0)) facts.setStateReferences.push({
|
|
6516
|
-
kind: "call-argument",
|
|
6517
|
-
node
|
|
6518
|
-
});
|
|
6519
|
-
return;
|
|
6507
|
+
if (node.parent.type === AST_NODE_TYPES.ArrowFunctionExpression && node === node.parent.body) {
|
|
6508
|
+
facts.setStateReferences.push({
|
|
6509
|
+
kind: "callback-body",
|
|
6510
|
+
node
|
|
6511
|
+
});
|
|
6512
|
+
return;
|
|
6520
6513
|
}
|
|
6514
|
+
if (node.parent.type === AST_NODE_TYPES.CallExpression && node === node.parent.arguments.at(0)) facts.setStateReferences.push({
|
|
6515
|
+
kind: "call-argument",
|
|
6516
|
+
node
|
|
6517
|
+
});
|
|
6521
6518
|
}
|
|
6522
6519
|
}
|
|
6523
6520
|
};
|
|
@@ -6547,9 +6544,9 @@ function createSetStateResolver$1(context) {
|
|
|
6547
6544
|
const innerCallee = Extract.unwrap(callee.callee);
|
|
6548
6545
|
if (innerCallee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
6549
6546
|
if (!hasProperty(innerCallee.object, "name")) return false;
|
|
6550
|
-
|
|
6547
|
+
if (!(Extract.getCalleeName(callee) === "at")) return false;
|
|
6551
6548
|
const [index] = callee.arguments;
|
|
6552
|
-
if (
|
|
6549
|
+
if (index == null) return false;
|
|
6553
6550
|
const indexScope = context.sourceCode.getScope(node);
|
|
6554
6551
|
return getStaticValue(index, indexScope)?.value === 1 && isSetStateId(innerCallee.object);
|
|
6555
6552
|
}
|
|
@@ -6591,32 +6588,30 @@ function isInitializedFromRef(context, id, refParams, seen = /* @__PURE__ */ new
|
|
|
6591
6588
|
const writeExpr = reference.writeExpr == null ? null : Extract.unwrap(reference.writeExpr);
|
|
6592
6589
|
if (writeExpr == null) continue;
|
|
6593
6590
|
if (writeExpr.range[1] > id.range[0]) continue;
|
|
6594
|
-
if (Traverse.
|
|
6591
|
+
if (Traverse.hasParent(writeExpr, and(Check.isFunction, (n) => !Traverse.hasParent(id, (m) => m === n)))) continue;
|
|
6595
6592
|
if (isExpressionFromRef(context, writeExpr, refParams, seen)) return true;
|
|
6596
6593
|
}
|
|
6597
6594
|
return false;
|
|
6598
6595
|
}
|
|
6599
6596
|
function isExpressionFromRef(context, init, refParams, seen) {
|
|
6600
6597
|
const { additionalRefHooks } = getSettingsFromContext(context);
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
}
|
|
6612
|
-
current = object;
|
|
6598
|
+
if (init.type === AST_NODE_TYPES.CallExpression && core.isUseRefLikeCall(init, additionalRefHooks)) return true;
|
|
6599
|
+
if (init.type === AST_NODE_TYPES.MemberExpression) {
|
|
6600
|
+
let current = init;
|
|
6601
|
+
while (current.type === AST_NODE_TYPES.MemberExpression) {
|
|
6602
|
+
const property = Extract.unwrap(current.property);
|
|
6603
|
+
const object = Extract.unwrap(current.object);
|
|
6604
|
+
if (!current.computed && Check.isIdentifier(property, "current")) {
|
|
6605
|
+
const sourceName = getRefSourceName(object);
|
|
6606
|
+
if (sourceName === "ref" || sourceName?.endsWith("Ref") === true) return true;
|
|
6607
|
+
if (object.type === AST_NODE_TYPES.Identifier && isParameterId(context, object)) return true;
|
|
6613
6608
|
}
|
|
6614
|
-
|
|
6615
|
-
return getNestedIdentifiers(init).some((id) => isInitializedFromRef(context, id, refParams, seen));
|
|
6609
|
+
current = object;
|
|
6616
6610
|
}
|
|
6617
|
-
|
|
6618
|
-
|
|
6611
|
+
if (Check.isIdentifier(current) && (current.name === "ref" || current.name.endsWith("Ref"))) return true;
|
|
6612
|
+
return getNestedIdentifiers(init).some((id) => isInitializedFromRef(context, id, refParams, seen));
|
|
6619
6613
|
}
|
|
6614
|
+
return getNestedIdentifiers(init).some((id) => isInitializedFromRef(context, id, refParams, seen));
|
|
6620
6615
|
}
|
|
6621
6616
|
function isArgumentUsingRefValue(context, node, refParams) {
|
|
6622
6617
|
const isUsingRefValue = (n) => {
|
|
@@ -6708,11 +6703,14 @@ function inferViolations$2(context, facts) {
|
|
|
6708
6703
|
for (const { enclosingFunction, enclosingFunctionKind, node, setupFunction } of facts.calls) {
|
|
6709
6704
|
if (isUseStateOrThenCall(node)) continue;
|
|
6710
6705
|
if (!resolver.isSetStateCall(node)) {
|
|
6711
|
-
if (setupFunction
|
|
6706
|
+
if (setupFunction == null) continue;
|
|
6707
|
+
if (enclosingFunction !== setupFunction) continue;
|
|
6708
|
+
trackedFnCalls.push(node);
|
|
6712
6709
|
continue;
|
|
6713
6710
|
}
|
|
6714
6711
|
if (enclosingFunctionKind === "deferred") continue;
|
|
6715
|
-
|
|
6712
|
+
const syncEnclosingFunction = enclosingFunctionKind === "immediate" ? Traverse.findParent(enclosingFunction, Check.isFunction) : enclosingFunction;
|
|
6713
|
+
if (setupFunction != null && syncEnclosingFunction === setupFunction) {
|
|
6716
6714
|
const args0 = node.arguments.at(0);
|
|
6717
6715
|
if (args0 == null) continue;
|
|
6718
6716
|
if (isArgumentUsingRefValue(context, args0)) continue;
|
|
@@ -6755,7 +6753,8 @@ function inferViolations$2(context, facts) {
|
|
|
6755
6753
|
};
|
|
6756
6754
|
const getRefDerivedParams = (call, callee) => {
|
|
6757
6755
|
const origin = resolveOrigin(context, callee);
|
|
6758
|
-
if (origin == null
|
|
6756
|
+
if (origin == null) return void 0;
|
|
6757
|
+
if (!Check.isFunction(origin)) return void 0;
|
|
6759
6758
|
const refParams = /* @__PURE__ */ new Set();
|
|
6760
6759
|
origin.params.forEach((param, index) => {
|
|
6761
6760
|
const paramId = param.type === AST_NODE_TYPES.Identifier ? param : param.type === AST_NODE_TYPES.AssignmentPattern && param.left.type === AST_NODE_TYPES.Identifier ? param.left : null;
|
|
@@ -6819,9 +6818,9 @@ var set_state_in_effect_default = createRule({
|
|
|
6819
6818
|
function create$5(context) {
|
|
6820
6819
|
if (!/use\w*Effect/u.test(context.sourceCode.text)) return {};
|
|
6821
6820
|
const { additionalEffectHooks, additionalStateHooks } = getSettingsFromContext(context);
|
|
6822
|
-
const facts = createFactCollector$3(additionalStateHooks, additionalEffectHooks);
|
|
6823
|
-
return merge(
|
|
6824
|
-
for (const violation of inferViolations$2(context, facts
|
|
6821
|
+
const { facts, visitor } = createFactCollector$3(additionalStateHooks, additionalEffectHooks);
|
|
6822
|
+
return merge(visitor, { "Program:exit"() {
|
|
6823
|
+
for (const violation of inferViolations$2(context, facts)) context.report({
|
|
6825
6824
|
data: { name: violation.name },
|
|
6826
6825
|
messageId: "default",
|
|
6827
6826
|
node: violation.node
|
|
@@ -6901,7 +6900,8 @@ function createFactCollector$2(context) {
|
|
|
6901
6900
|
const componentFn = componentFnStack.at(-1);
|
|
6902
6901
|
if (componentFn == null) return;
|
|
6903
6902
|
const entry = functionEntries.at(-1);
|
|
6904
|
-
if (entry == null
|
|
6903
|
+
if (entry == null) return;
|
|
6904
|
+
if (entry.node !== componentFn) return;
|
|
6905
6905
|
if (componentFn.body.type !== AST_NODE_TYPES.BlockStatement) return;
|
|
6906
6906
|
const body = componentFn.body.body;
|
|
6907
6907
|
let stmt = node;
|
|
@@ -6943,9 +6943,9 @@ function createSetStateResolver(context) {
|
|
|
6943
6943
|
const innerCallee = Extract.unwrap(callee.callee);
|
|
6944
6944
|
if (innerCallee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
6945
6945
|
if (!hasProperty(innerCallee.object, "name")) return false;
|
|
6946
|
-
|
|
6946
|
+
if (!(Extract.getCalleeName(callee) === "at")) return false;
|
|
6947
6947
|
const [index] = callee.arguments;
|
|
6948
|
-
if (
|
|
6948
|
+
if (index == null) return false;
|
|
6949
6949
|
const indexScope = context.sourceCode.getScope(node);
|
|
6950
6950
|
return getStaticValue(index, indexScope)?.value === 1 && isSetStateId(innerCallee.object);
|
|
6951
6951
|
}
|
|
@@ -6997,9 +6997,9 @@ var set_state_in_render_default = createRule({
|
|
|
6997
6997
|
create: create$4
|
|
6998
6998
|
});
|
|
6999
6999
|
function create$4(context) {
|
|
7000
|
-
const facts = createFactCollector$2(context);
|
|
7001
|
-
return merge(
|
|
7002
|
-
for (const violation of inferViolations$1(context, facts
|
|
7000
|
+
const { facts, visitor } = createFactCollector$2(context);
|
|
7001
|
+
return merge(visitor, { "Program:exit"() {
|
|
7002
|
+
for (const violation of inferViolations$1(context, facts)) context.report({
|
|
7003
7003
|
data: { name: violation.name },
|
|
7004
7004
|
messageId: "default",
|
|
7005
7005
|
node: violation.node
|
|
@@ -7061,7 +7061,8 @@ function findReassignmentCreationSite(context, variable, isInsideRender, seen) {
|
|
|
7061
7061
|
for (const ref of variable.references) {
|
|
7062
7062
|
if (!ref.isWrite()) continue;
|
|
7063
7063
|
const { identifier } = ref;
|
|
7064
|
-
if (identifier.parent.type !== AST_NODE_TYPES.AssignmentExpression
|
|
7064
|
+
if (identifier.parent.type !== AST_NODE_TYPES.AssignmentExpression) continue;
|
|
7065
|
+
if (identifier.parent.left !== identifier) continue;
|
|
7065
7066
|
const source = findDynamicCreationSite(context, identifier.parent.right, isInsideRender, seen);
|
|
7066
7067
|
if (source != null) return source;
|
|
7067
7068
|
}
|
|
@@ -7081,11 +7082,13 @@ function resolveDynamicComponentOrigin(context, variable, isInsideRender, seen =
|
|
|
7081
7082
|
isDynamic: true
|
|
7082
7083
|
};
|
|
7083
7084
|
if (defNode.type !== AST_NODE_TYPES.VariableDeclarator) continue;
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7085
|
+
if (defNode.init != null) {
|
|
7086
|
+
const initSource = findDynamicCreationSite(context, defNode.init, isInsideRender, seen);
|
|
7087
|
+
if (initSource != null) return {
|
|
7088
|
+
creationNode: initSource,
|
|
7089
|
+
isDynamic: true
|
|
7090
|
+
};
|
|
7091
|
+
}
|
|
7089
7092
|
const reassignmentSource = findReassignmentCreationSite(context, variable, isInsideRender, seen);
|
|
7090
7093
|
if (reassignmentSource != null) return {
|
|
7091
7094
|
creationNode: reassignmentSource,
|
|
@@ -7134,22 +7137,22 @@ function create$3(context) {
|
|
|
7134
7137
|
const hint = core.FunctionComponentDetectionHint.DoNotIncludeJsxWithNumberValue | core.FunctionComponentDetectionHint.DoNotIncludeJsxWithBooleanValue | core.FunctionComponentDetectionHint.DoNotIncludeJsxWithNullValue | core.FunctionComponentDetectionHint.DoNotIncludeJsxWithStringValue | core.FunctionComponentDetectionHint.DoNotIncludeJsxWithUndefinedValue | core.FunctionComponentDetectionHint.RequireBothSidesOfLogicalExpressionToBeJsx | core.FunctionComponentDetectionHint.RequireBothBranchesOfConditionalExpressionToBeJsx | core.FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayPatternElement | core.FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayExpressionElement | core.FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayMapCallback;
|
|
7135
7138
|
const fc = core.getFunctionComponentCollector(context, { hint });
|
|
7136
7139
|
const cc = core.getClassComponentCollector(context);
|
|
7137
|
-
const facts = createFactCollector$1();
|
|
7138
|
-
return merge(fc.visitor, cc.visitor,
|
|
7140
|
+
const { facts, visitor } = createFactCollector$1();
|
|
7141
|
+
return merge(fc.visitor, cc.visitor, visitor, { "Program:exit"(program) {
|
|
7139
7142
|
const isInsideRender = createRenderBoundaryChecker([...fc.api.getAllComponents(program), ...cc.api.getAllComponents(program)].map((component) => component.node));
|
|
7140
7143
|
const reportedCreations = /* @__PURE__ */ new Set();
|
|
7141
|
-
for (const effect of inferCreatedComponents(context, facts.
|
|
7144
|
+
for (const effect of inferCreatedComponents(context, facts.componentUsages, isInsideRender)) {
|
|
7142
7145
|
context.report({
|
|
7143
7146
|
messageId: "default",
|
|
7144
7147
|
node: effect.node
|
|
7145
7148
|
});
|
|
7146
|
-
if (effect.creationNode
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
}
|
|
7149
|
+
if (effect.creationNode == null) continue;
|
|
7150
|
+
if (reportedCreations.has(effect.creationNode)) continue;
|
|
7151
|
+
reportedCreations.add(effect.creationNode);
|
|
7152
|
+
context.report({
|
|
7153
|
+
messageId: "created-here",
|
|
7154
|
+
node: effect.creationNode
|
|
7155
|
+
});
|
|
7153
7156
|
}
|
|
7154
7157
|
} });
|
|
7155
7158
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "5.27.
|
|
3
|
+
"version": "5.27.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,12 +36,12 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@eslint-react/ast": "5.27.
|
|
40
|
-
"@eslint-react/core": "5.27.
|
|
41
|
-
"@eslint-react/eslint": "5.27.
|
|
42
|
-
"@eslint-react/jsx": "5.27.
|
|
43
|
-
"@eslint-react/shared": "5.27.
|
|
44
|
-
"@eslint-react/var": "5.27.
|
|
39
|
+
"@eslint-react/ast": "5.27.3",
|
|
40
|
+
"@eslint-react/core": "5.27.3",
|
|
41
|
+
"@eslint-react/eslint": "5.27.3",
|
|
42
|
+
"@eslint-react/jsx": "5.27.3",
|
|
43
|
+
"@eslint-react/shared": "5.27.3",
|
|
44
|
+
"@eslint-react/var": "5.27.3",
|
|
45
45
|
"@typescript-eslint/scope-manager": "^8.71.2",
|
|
46
46
|
"@typescript-eslint/types": "^8.71.2",
|
|
47
47
|
"@typescript-eslint/typescript-estree": "^8.71.2",
|
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
"@local/eff": "0.0.0",
|
|
57
57
|
"@local/testkit": "0.0.0",
|
|
58
58
|
"@rbxts/react": "17.3.7-ts.2",
|
|
59
|
+
"@tsconfig/node20": "^20.1.10",
|
|
60
|
+
"@types/node": "^20.19.43",
|
|
59
61
|
"@types/react": "^19.3.0",
|
|
60
62
|
"@types/react-dom": "^19.3.0",
|
|
61
63
|
"dedent": "^1.7.2",
|