eslint-plugin-react-x 2.0.0-next.175 → 2.0.0-next.177
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 +39 -68
- package/package.json +12 -12
package/dist/index.js
CHANGED
|
@@ -115,7 +115,7 @@ const settings = { ...settings$1 };
|
|
|
115
115
|
//#endregion
|
|
116
116
|
//#region package.json
|
|
117
117
|
var name = "eslint-plugin-react-x";
|
|
118
|
-
var version = "2.0.0-next.
|
|
118
|
+
var version = "2.0.0-next.177";
|
|
119
119
|
|
|
120
120
|
//#endregion
|
|
121
121
|
//#region src/utils/create-rule.ts
|
|
@@ -378,15 +378,13 @@ var jsx_shorthand_fragment_default = createRule({
|
|
|
378
378
|
});
|
|
379
379
|
function create$55(context) {
|
|
380
380
|
const policy = context.options[0] ?? defaultOptions$2[0];
|
|
381
|
-
const
|
|
381
|
+
const { jsxFragmentFactory } = {
|
|
382
382
|
...JsxConfig.getFromContext(context),
|
|
383
383
|
...JsxConfig.getFromAnnotation(context)
|
|
384
384
|
};
|
|
385
|
-
const { jsxFragmentFactory } = jsxConfig;
|
|
386
385
|
return match(policy).with(1, () => ({ JSXElement(node) {
|
|
387
386
|
if (!ER.isFragmentElement(context, node)) return;
|
|
388
|
-
|
|
389
|
-
if (hasAttributes) return;
|
|
387
|
+
if (node.openingElement.attributes.length > 0) return;
|
|
390
388
|
context.report({
|
|
391
389
|
messageId: "jsxShorthandFragment",
|
|
392
390
|
node,
|
|
@@ -430,11 +428,10 @@ var jsx_uses_react_default = createRule({
|
|
|
430
428
|
defaultOptions: []
|
|
431
429
|
});
|
|
432
430
|
function create$54(context) {
|
|
433
|
-
const
|
|
431
|
+
const { jsx, jsxFactory, jsxFragmentFactory } = {
|
|
434
432
|
...JsxConfig.getFromContext(context),
|
|
435
433
|
...JsxConfig.getFromAnnotation(context)
|
|
436
434
|
};
|
|
437
|
-
const { jsx, jsxFactory, jsxFragmentFactory } = jsxConfig;
|
|
438
435
|
if (jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev) return {};
|
|
439
436
|
function handleJsxElement(node) {
|
|
440
437
|
context.sourceCode.markVariableAsUsed(jsxFactory, node);
|
|
@@ -577,8 +574,7 @@ function create$52(context) {
|
|
|
577
574
|
const [setState, hasThisState = false] = setStateEntries.at(-1) ?? [];
|
|
578
575
|
if (setState == null || hasThisState) return;
|
|
579
576
|
if (node.init == null || !AST.isThisExpression(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
|
|
580
|
-
|
|
581
|
-
if (!hasState) return;
|
|
577
|
+
if (!node.id.properties.some((prop) => prop.type === AST_NODE_TYPES.Property && isKeyLiteral$2(prop, prop.key) && AST.getPropertyName(prop.key) === "state")) return;
|
|
582
578
|
context.report({
|
|
583
579
|
messageId: "noAccessStateInSetstate",
|
|
584
580
|
node
|
|
@@ -832,8 +828,7 @@ var no_children_prop_default = createRule({
|
|
|
832
828
|
});
|
|
833
829
|
function create$46(context) {
|
|
834
830
|
return { JSXElement(node) {
|
|
835
|
-
const
|
|
836
|
-
const childrenProp = getAttribute("children");
|
|
831
|
+
const childrenProp = ER.getAttribute(context, node.openingElement.attributes, context.sourceCode.getScope(node))("children");
|
|
837
832
|
if (childrenProp != null) context.report({
|
|
838
833
|
messageId: "noChildrenProp",
|
|
839
834
|
node: childrenProp
|
|
@@ -1079,8 +1074,7 @@ function create$39(context) {
|
|
|
1079
1074
|
const { version: version$1 } = getSettingsFromContext(context);
|
|
1080
1075
|
if (compare(version$1, "19.0.0", "<")) return {};
|
|
1081
1076
|
return { JSXElement(node) {
|
|
1082
|
-
const
|
|
1083
|
-
const parts = fullName.split(".");
|
|
1077
|
+
const parts = ER.getElementType(context, node).split(".");
|
|
1084
1078
|
const selfName = parts.pop();
|
|
1085
1079
|
const contextFullName = parts.join(".");
|
|
1086
1080
|
const contextSelfName = parts.pop();
|
|
@@ -1335,8 +1329,7 @@ function create$34(context, [option]) {
|
|
|
1335
1329
|
if ("includedNodes" in forbiddenPropItem && !forbiddenPropItem.includedNodes.includes(nodeName)) continue;
|
|
1336
1330
|
}
|
|
1337
1331
|
const forbiddenProp = typeof forbiddenPropItem === "string" ? forbiddenPropItem : forbiddenPropItem.prop;
|
|
1338
|
-
|
|
1339
|
-
if (forbiddenPropRegExp.test(name$4)) context.report({
|
|
1332
|
+
if (RegExp.toRegExp(forbiddenProp).test(name$4)) context.report({
|
|
1340
1333
|
messageId,
|
|
1341
1334
|
node: attr,
|
|
1342
1335
|
data: { name: name$4 }
|
|
@@ -1517,19 +1510,16 @@ function create$31(context) {
|
|
|
1517
1510
|
type: AST_NODE_TYPES.LogicalExpression,
|
|
1518
1511
|
operator: "&&"
|
|
1519
1512
|
}, ({ left, right }) => {
|
|
1520
|
-
|
|
1521
|
-
if (isLeftUnaryNot) return getReportDescriptor(right);
|
|
1513
|
+
if (left.type === AST_NODE_TYPES.UnaryExpression && left.operator === "!") return getReportDescriptor(right);
|
|
1522
1514
|
const initialScope = context.sourceCode.getScope(left);
|
|
1523
|
-
|
|
1524
|
-
if (isLeftNan) return {
|
|
1515
|
+
if (left.type === AST_NODE_TYPES.Identifier && left.name === "NaN" || getStaticValue(left, initialScope)?.value === "NaN") return {
|
|
1525
1516
|
messageId: "noLeakedConditionalRendering",
|
|
1526
1517
|
node: left,
|
|
1527
1518
|
data: { value: context.sourceCode.getText(left) }
|
|
1528
1519
|
};
|
|
1529
1520
|
const leftType = getConstrainedTypeAtLocation(services, left);
|
|
1530
1521
|
const leftTypeVariants = ER.getTypeVariants(unionConstituents(leftType));
|
|
1531
|
-
|
|
1532
|
-
if (isLeftValid) return getReportDescriptor(right);
|
|
1522
|
+
if (Array.from(leftTypeVariants.values()).every((type) => allowedVariants.some((allowed) => allowed === type))) return getReportDescriptor(right);
|
|
1533
1523
|
return {
|
|
1534
1524
|
messageId: "noLeakedConditionalRendering",
|
|
1535
1525
|
node: left,
|
|
@@ -1538,8 +1528,7 @@ function create$31(context) {
|
|
|
1538
1528
|
}).with({ type: AST_NODE_TYPES.ConditionalExpression }, ({ alternate, consequent }) => {
|
|
1539
1529
|
return getReportDescriptor(consequent) ?? getReportDescriptor(alternate);
|
|
1540
1530
|
}).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
1541
|
-
const
|
|
1542
|
-
const variableDefNode = variable?.defs.at(0)?.node;
|
|
1531
|
+
const variableDefNode = VAR.findVariable(n.name, context.sourceCode.getScope(n))?.defs.at(0)?.node;
|
|
1543
1532
|
return match(variableDefNode).with({ init: P.select({ type: P.not(AST_NODE_TYPES.VariableDeclaration) }) }, getReportDescriptor).otherwise(() => unit);
|
|
1544
1533
|
}).otherwise(() => unit);
|
|
1545
1534
|
}
|
|
@@ -1629,13 +1618,12 @@ function create$29(context) {
|
|
|
1629
1618
|
});
|
|
1630
1619
|
continue;
|
|
1631
1620
|
}
|
|
1632
|
-
|
|
1621
|
+
if (!displayNameAssignments.some((node) => {
|
|
1633
1622
|
const left = node.left;
|
|
1634
1623
|
if (left.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
1635
1624
|
const object = left.object;
|
|
1636
1625
|
return ER.isInstanceIdEqual(context, id, object);
|
|
1637
|
-
})
|
|
1638
|
-
if (!hasDisplayNameAssignment) {
|
|
1626
|
+
})) {
|
|
1639
1627
|
const semi = LanguagePreference.defaultLanguagePreference.semicolons === "always" ? ";" : "";
|
|
1640
1628
|
context.report({
|
|
1641
1629
|
messageId: "noMissingContextDisplayName",
|
|
@@ -1983,19 +1971,16 @@ function create$25(context) {
|
|
|
1983
1971
|
"Program:exit"(program) {
|
|
1984
1972
|
const functionComponents = [...collector.ctx.getAllComponents(program).values()];
|
|
1985
1973
|
const classComponents = [...collectorLegacy.ctx.getAllComponents(program).values()];
|
|
1986
|
-
for (const lazy of lazyComponentDeclarations) {
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
node: lazy
|
|
1997
|
-
});
|
|
1998
|
-
}
|
|
1974
|
+
for (const lazy of lazyComponentDeclarations) if (AST.findParentNode(lazy, (n) => {
|
|
1975
|
+
if (AST.isJSX(n)) return true;
|
|
1976
|
+
if (n.type === AST_NODE_TYPES.CallExpression) return ER.isReactHookCall(n) || ER.isCreateElementCall(context, n) || ER.isCreateContextCall(context, n);
|
|
1977
|
+
if (AST.isFunction(n)) return functionComponents.some((c) => c.node === n);
|
|
1978
|
+
if (AST.isClass(n)) return classComponents.some((c) => c.node === n);
|
|
1979
|
+
return false;
|
|
1980
|
+
}) != null) context.report({
|
|
1981
|
+
messageId: "noNestedLazyComponentDeclarations",
|
|
1982
|
+
node: lazy
|
|
1983
|
+
});
|
|
1999
1984
|
}
|
|
2000
1985
|
};
|
|
2001
1986
|
}
|
|
@@ -2314,13 +2299,12 @@ function create$17(context) {
|
|
|
2314
2299
|
if (!AST.isFunction(component)) return;
|
|
2315
2300
|
const [arg0, arg1] = node.arguments;
|
|
2316
2301
|
if (arg0 == null || arg1 == null) return;
|
|
2317
|
-
|
|
2302
|
+
if (!match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
2318
2303
|
const variable = VAR.findVariable(n.name, initialScope);
|
|
2319
2304
|
const variableNode = VAR.getVariableDefinitionNode(variable, 0);
|
|
2320
2305
|
if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) return false;
|
|
2321
2306
|
return variableNode.elements.length === 0;
|
|
2322
|
-
}).otherwise(() => false);
|
|
2323
|
-
if (!hasEmptyDeps) return;
|
|
2307
|
+
}).otherwise(() => false)) return;
|
|
2324
2308
|
const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
|
|
2325
2309
|
if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) return n.body;
|
|
2326
2310
|
return n;
|
|
@@ -2332,9 +2316,7 @@ function create$17(context) {
|
|
|
2332
2316
|
}).otherwise(() => null);
|
|
2333
2317
|
if (arg0Node == null) return;
|
|
2334
2318
|
const arg0NodeScope = context.sourceCode.getScope(arg0Node);
|
|
2335
|
-
|
|
2336
|
-
const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
|
|
2337
|
-
if (!isReferencedToComponentScope) context.report({
|
|
2319
|
+
if (!VAR.getChildScopes(arg0NodeScope).flatMap((x) => x.references).some((x) => x.resolved?.scope.block === component)) context.report({
|
|
2338
2320
|
messageId: "noUnnecessaryUseCallback",
|
|
2339
2321
|
node
|
|
2340
2322
|
});
|
|
@@ -2364,20 +2346,17 @@ function create$16(context) {
|
|
|
2364
2346
|
return { CallExpression(node) {
|
|
2365
2347
|
const initialScope = context.sourceCode.getScope(node);
|
|
2366
2348
|
if (!ER.isUseMemoCall(node)) return;
|
|
2367
|
-
const
|
|
2368
|
-
const component = scope.block;
|
|
2349
|
+
const component = context.sourceCode.getScope(node).block;
|
|
2369
2350
|
if (!AST.isFunction(component)) return;
|
|
2370
2351
|
const [arg0, arg1] = node.arguments;
|
|
2371
2352
|
if (arg0 == null || arg1 == null) return;
|
|
2372
|
-
|
|
2373
|
-
if (
|
|
2374
|
-
const hasEmptyDeps = match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
2353
|
+
if (AST.isFunction(arg0) && [...AST.getNestedCallExpressions(arg0.body), ...AST.getNestedNewExpressions(arg0.body)].length > 0) return;
|
|
2354
|
+
if (!match(arg1).with({ type: AST_NODE_TYPES.ArrayExpression }, (n) => n.elements.length === 0).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
2375
2355
|
const variable = VAR.findVariable(n.name, initialScope);
|
|
2376
2356
|
const variableNode = VAR.getVariableDefinitionNode(variable, 0);
|
|
2377
2357
|
if (variableNode?.type !== AST_NODE_TYPES.ArrayExpression) return false;
|
|
2378
2358
|
return variableNode.elements.length === 0;
|
|
2379
|
-
}).otherwise(() => false);
|
|
2380
|
-
if (!hasEmptyDeps) return;
|
|
2359
|
+
}).otherwise(() => false)) return;
|
|
2381
2360
|
const arg0Node = match(arg0).with({ type: AST_NODE_TYPES.ArrowFunctionExpression }, (n) => {
|
|
2382
2361
|
if (n.body.type === AST_NODE_TYPES.ArrowFunctionExpression) return n.body;
|
|
2383
2362
|
return n;
|
|
@@ -2389,9 +2368,7 @@ function create$16(context) {
|
|
|
2389
2368
|
}).otherwise(() => null);
|
|
2390
2369
|
if (arg0Node == null) return;
|
|
2391
2370
|
const arg0NodeScope = context.sourceCode.getScope(arg0Node);
|
|
2392
|
-
|
|
2393
|
-
const isReferencedToComponentScope = arg0NodeReferences.some((x) => x.resolved?.scope.block === component);
|
|
2394
|
-
if (!isReferencedToComponentScope) context.report({
|
|
2371
|
+
if (!VAR.getChildScopes(arg0NodeScope).flatMap((x) => x.references).some((x) => x.resolved?.scope.block === component)) context.report({
|
|
2395
2372
|
messageId: "noUnnecessaryUseMemo",
|
|
2396
2373
|
node
|
|
2397
2374
|
});
|
|
@@ -2576,8 +2553,7 @@ function create$11(context) {
|
|
|
2576
2553
|
return {
|
|
2577
2554
|
...listeners,
|
|
2578
2555
|
JSXOpeningElement(node) {
|
|
2579
|
-
const
|
|
2580
|
-
const selfName = fullName.split(".").at(-1);
|
|
2556
|
+
const selfName = ER.getElementType(context, node.parent).split(".").at(-1);
|
|
2581
2557
|
if (selfName == null) return;
|
|
2582
2558
|
if (!isContextName(selfName, isReact18OrBelow)) return;
|
|
2583
2559
|
const functionEntry = ctx.getCurrentEntry();
|
|
@@ -2825,8 +2801,7 @@ function create$8(context) {
|
|
|
2825
2801
|
const [props] = component.node.params;
|
|
2826
2802
|
if (props == null) continue;
|
|
2827
2803
|
const usedPropKeys = /* @__PURE__ */ new Set();
|
|
2828
|
-
|
|
2829
|
-
if (!couldFindAllUsedPropKeys) continue;
|
|
2804
|
+
if (!collectUsedPropKeysOfParameter(context, usedPropKeys, props)) continue;
|
|
2830
2805
|
const tsNode = services.esTreeNodeToTSNodeMap.get(props);
|
|
2831
2806
|
const declaredProps = checker.getTypeAtLocation(tsNode).getProperties();
|
|
2832
2807
|
for (const declaredProp of declaredProps) {
|
|
@@ -2867,8 +2842,7 @@ function collectUsedPropsOfRestElement(context, usedPropKeys, restElement) {
|
|
|
2867
2842
|
}
|
|
2868
2843
|
}
|
|
2869
2844
|
function collectUsedPropKeysOfIdentifier(context, usedPropKeys, identifier) {
|
|
2870
|
-
const
|
|
2871
|
-
const variable = scope.variables.find((v) => v.name === identifier.name);
|
|
2845
|
+
const variable = context.sourceCode.getScope(identifier).variables.find((v) => v.name === identifier.name);
|
|
2872
2846
|
if (variable == null) return false;
|
|
2873
2847
|
for (const ref of variable.references) {
|
|
2874
2848
|
if (ref.identifier === identifier) continue;
|
|
@@ -3031,11 +3005,10 @@ function create$7(context) {
|
|
|
3031
3005
|
if (currentMethod === constructorEntries.at(-1)) return;
|
|
3032
3006
|
if (!currentClass.body.body.includes(currentMethod)) return;
|
|
3033
3007
|
if (node.init == null || !AST.isThisExpression(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
|
|
3034
|
-
|
|
3008
|
+
if (!node.id.properties.some((prop) => {
|
|
3035
3009
|
if (prop.type === AST_NODE_TYPES.Property && isKeyLiteral(prop, prop.key)) return AST.getPropertyName(prop.key) === "state";
|
|
3036
3010
|
return false;
|
|
3037
|
-
});
|
|
3038
|
-
if (!hasState) return;
|
|
3011
|
+
})) return;
|
|
3039
3012
|
const defNode = stateDefs.get(currentClass)?.node;
|
|
3040
3013
|
stateDefs.set(currentClass, {
|
|
3041
3014
|
node: defNode,
|
|
@@ -3150,8 +3123,7 @@ function create$5(context) {
|
|
|
3150
3123
|
if (!ER.isForwardRefCall(context, node)) return;
|
|
3151
3124
|
const [component] = node.arguments;
|
|
3152
3125
|
if (component == null || !AST.isFunction(component)) return;
|
|
3153
|
-
|
|
3154
|
-
if (ref != null) return;
|
|
3126
|
+
if (component.params[1] != null) return;
|
|
3155
3127
|
context.report({
|
|
3156
3128
|
messageId: "noUselessForwardRef",
|
|
3157
3129
|
node: node.callee
|
|
@@ -3385,8 +3357,7 @@ function create$2(context) {
|
|
|
3385
3357
|
const importDeclarationText = context.sourceCode.getText(node.parent);
|
|
3386
3358
|
const semi = importDeclarationText.endsWith(";") ? ";" : "";
|
|
3387
3359
|
const quote = node.parent.source.raw.at(0) ?? "'";
|
|
3388
|
-
const
|
|
3389
|
-
const importStringPrefix = `import${isTypeImport ? " type" : ""}`;
|
|
3360
|
+
const importStringPrefix = `import${node.parent.importKind === "type" ? " type" : ""}`;
|
|
3390
3361
|
const importSourceQuoted = `${quote}${importSource}${quote}`;
|
|
3391
3362
|
if (!hasOtherSpecifiers) return fixer.replaceText(node.parent, `${importStringPrefix} * as ${node.local.name} from ${importSourceQuoted}${semi}`);
|
|
3392
3363
|
const specifiers = importDeclarationText.slice(importDeclarationText.indexOf("{"), importDeclarationText.indexOf("}") + 1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.177",
|
|
4
4
|
"description": "A set of composable ESLint rules for for libraries and frameworks that use React as a UI runtime.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -34,26 +34,26 @@
|
|
|
34
34
|
"./package.json"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@typescript-eslint/scope-manager": "^8.
|
|
38
|
-
"@typescript-eslint/type-utils": "^8.
|
|
39
|
-
"@typescript-eslint/types": "^8.
|
|
40
|
-
"@typescript-eslint/utils": "^8.
|
|
37
|
+
"@typescript-eslint/scope-manager": "^8.43.0",
|
|
38
|
+
"@typescript-eslint/type-utils": "^8.43.0",
|
|
39
|
+
"@typescript-eslint/types": "^8.43.0",
|
|
40
|
+
"@typescript-eslint/utils": "^8.43.0",
|
|
41
41
|
"compare-versions": "^6.1.1",
|
|
42
42
|
"is-immutable-type": "^5.0.1",
|
|
43
43
|
"string-ts": "^2.2.1",
|
|
44
44
|
"ts-pattern": "^5.8.0",
|
|
45
|
-
"@eslint-react/ast": "2.0.0-next.
|
|
46
|
-
"@eslint-react/core": "2.0.0-next.
|
|
47
|
-
"@eslint-react/eff": "2.0.0-next.
|
|
48
|
-
"@eslint-react/kit": "2.0.0-next.
|
|
49
|
-
"@eslint-react/var": "2.0.0-next.
|
|
50
|
-
"@eslint-react/shared": "2.0.0-next.
|
|
45
|
+
"@eslint-react/ast": "2.0.0-next.177",
|
|
46
|
+
"@eslint-react/core": "2.0.0-next.177",
|
|
47
|
+
"@eslint-react/eff": "2.0.0-next.177",
|
|
48
|
+
"@eslint-react/kit": "2.0.0-next.177",
|
|
49
|
+
"@eslint-react/var": "2.0.0-next.177",
|
|
50
|
+
"@eslint-react/shared": "2.0.0-next.177"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/react": "^19.1.12",
|
|
54
54
|
"@types/react-dom": "^19.1.9",
|
|
55
55
|
"ts-api-utils": "^2.1.0",
|
|
56
|
-
"tsdown": "^0.
|
|
56
|
+
"tsdown": "^0.15.0",
|
|
57
57
|
"@local/configs": "0.0.0"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|