eslint-plugin-react-x 5.18.1 → 5.18.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 +103 -18
- package/package.json +16 -16
package/dist/index.js
CHANGED
|
@@ -145,7 +145,7 @@ const rules$6 = {
|
|
|
145
145
|
//#endregion
|
|
146
146
|
//#region package.json
|
|
147
147
|
var name$6 = "eslint-plugin-react-x";
|
|
148
|
-
var version = "5.18.
|
|
148
|
+
var version = "5.18.3";
|
|
149
149
|
|
|
150
150
|
//#endregion
|
|
151
151
|
//#region src/utils/create-rule.ts
|
|
@@ -3396,25 +3396,90 @@ function create$23(context) {
|
|
|
3396
3396
|
|
|
3397
3397
|
//#endregion
|
|
3398
3398
|
//#region src/rules/no-nested-component-definitions/lib.ts
|
|
3399
|
+
/** Check if the node is a call expression to react-redux's `connect`. */
|
|
3400
|
+
const isConnectCall = core.isAPICall("connect");
|
|
3401
|
+
/** Check if the node is a call expression to Relay's `createFragmentContainer`. */
|
|
3402
|
+
const isCreateFragmentContainerCall = core.isAPICall("createFragmentContainer");
|
|
3403
|
+
/** Check if the node is a call expression to Relay's `createPaginationContainer`. */
|
|
3404
|
+
const isCreatePaginationContainerCall = core.isAPICall("createPaginationContainer");
|
|
3405
|
+
/** Check if the node is a call expression to Relay's `createRefetchContainer`. */
|
|
3406
|
+
const isCreateRefetchContainerCall = core.isAPICall("createRefetchContainer");
|
|
3407
|
+
/** Check if the node is a call expression to React's `forwardRef`. */
|
|
3408
|
+
const isForwardRefCall = core.isAPICall("forwardRef");
|
|
3409
|
+
/** Check if the node is a call expression to a `graphql` tag function (e.g. from Relay or Apollo). */
|
|
3410
|
+
const isGraphqlCall = core.isAPICall("graphql");
|
|
3411
|
+
/** Check if the node is a call expression to React's `memo`. */
|
|
3412
|
+
const isMemoCall = core.isAPICall("memo");
|
|
3413
|
+
/** Check if the node is a call expression to MobX's `observer`. */
|
|
3414
|
+
const isObserverCall = core.isAPICall("observer");
|
|
3415
|
+
/** Check if the node is a call expression to React's `useCallback`. */
|
|
3416
|
+
const isUseCallbackCall = core.isAPICall("useCallback");
|
|
3417
|
+
/** Check if the node is a call expression to Formik's `withFormik`. */
|
|
3418
|
+
const isWithFormikCall = core.isAPICall("withFormik");
|
|
3419
|
+
/** Check if the node is a call expression to recompose's `withHandlers`. */
|
|
3420
|
+
const isWithHandlersCall = core.isAPICall("withHandlers");
|
|
3421
|
+
/** Check if the node is a call expression to recompose's `withLifecycle`. */
|
|
3422
|
+
const isWithLifecycleCall = core.isAPICall("withLifecycle");
|
|
3423
|
+
/** Check if the node is a call expression to recompose's `withProps`. */
|
|
3424
|
+
const isWithPropsCall = core.isAPICall("withProps");
|
|
3425
|
+
/** Check if the node is a call expression to react-router v5's `withRouter`. */
|
|
3426
|
+
const isWithRouterCall = core.isAPICall("withRouter");
|
|
3427
|
+
/** Check if the node is a call expression to recompose's `withState`. */
|
|
3428
|
+
const isWithStateCall = core.isAPICall("withState");
|
|
3399
3429
|
/**
|
|
3400
|
-
*
|
|
3401
|
-
*
|
|
3402
|
-
* @
|
|
3430
|
+
* Check if a call is a well-known component wrapper call (e.g. `memo`, `connect`, `withFormik`).
|
|
3431
|
+
* Curried forms like `connect(...)(Component)` are matched via the innermost callee call.
|
|
3432
|
+
* @param context The rule context
|
|
3433
|
+
* @param call The call expression to check
|
|
3434
|
+
* @param arg The function node passed to the call
|
|
3435
|
+
* @returns `true` if the call is a component wrapper call
|
|
3403
3436
|
*/
|
|
3404
|
-
function
|
|
3405
|
-
|
|
3437
|
+
function isComponentWrapperCall(context, call, arg) {
|
|
3438
|
+
if (Extract.unwrap(call.callee) === arg) return false;
|
|
3439
|
+
call = Extract.getInnermostCall(call);
|
|
3440
|
+
if (isConnectCall(context, call)) return true;
|
|
3441
|
+
if (isCreateFragmentContainerCall(context, call)) return true;
|
|
3442
|
+
if (isCreatePaginationContainerCall(context, call)) return true;
|
|
3443
|
+
if (isCreateRefetchContainerCall(context, call)) return true;
|
|
3444
|
+
if (isForwardRefCall(context, call)) return true;
|
|
3445
|
+
if (isGraphqlCall(context, call)) return true;
|
|
3446
|
+
if (isMemoCall(context, call)) return true;
|
|
3447
|
+
if (isObserverCall(context, call)) return true;
|
|
3448
|
+
if (isUseCallbackCall(context, call)) return true;
|
|
3449
|
+
if (isWithFormikCall(context, call)) return true;
|
|
3450
|
+
if (isWithHandlersCall(context, call)) return true;
|
|
3451
|
+
if (isWithLifecycleCall(context, call)) return true;
|
|
3452
|
+
if (isWithPropsCall(context, call)) return true;
|
|
3453
|
+
if (isWithRouterCall(context, call)) return true;
|
|
3454
|
+
if (isWithStateCall(context, call)) return true;
|
|
3455
|
+
return false;
|
|
3406
3456
|
}
|
|
3407
3457
|
/**
|
|
3408
|
-
*
|
|
3409
|
-
*
|
|
3410
|
-
* @param node The
|
|
3411
|
-
* @returns `
|
|
3458
|
+
* Resolve the name a function is bound to through wrapping calls (e.g. `const C = useCallback(...)` → `C`).
|
|
3459
|
+
* @param context The rule context
|
|
3460
|
+
* @param node The function node to resolve the bound name for
|
|
3461
|
+
* @returns The bound name, or `null` if the call chain does not end at an identifier declarator
|
|
3412
3462
|
*/
|
|
3413
|
-
function
|
|
3414
|
-
|
|
3463
|
+
function getWrapperCallBoundName(context, node) {
|
|
3464
|
+
let current = node;
|
|
3465
|
+
let parent = current.parent;
|
|
3466
|
+
while (Check.isTypeExpression(parent)) {
|
|
3467
|
+
current = parent;
|
|
3468
|
+
parent = parent.parent;
|
|
3469
|
+
}
|
|
3470
|
+
while (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(context, parent, current)) {
|
|
3471
|
+
current = parent;
|
|
3472
|
+
parent = parent.parent;
|
|
3473
|
+
while (Check.isTypeExpression(parent)) {
|
|
3474
|
+
current = parent;
|
|
3475
|
+
parent = parent.parent;
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
if (parent.type !== AST_NODE_TYPES.VariableDeclarator || parent.id.type !== AST_NODE_TYPES.Identifier) return null;
|
|
3479
|
+
return parent.id.name;
|
|
3415
3480
|
}
|
|
3416
3481
|
/**
|
|
3417
|
-
*
|
|
3482
|
+
* Check if the node is inside `createElement`'s props argument
|
|
3418
3483
|
* @param context The rule context
|
|
3419
3484
|
* @param node The AST node to check
|
|
3420
3485
|
* @returns `true` if the node is inside `createElement`'s props
|
|
@@ -3426,6 +3491,23 @@ function isInsideCreateElementProps(context, node) {
|
|
|
3426
3491
|
if (prop == null) return false;
|
|
3427
3492
|
return prop === call.arguments[1];
|
|
3428
3493
|
}
|
|
3494
|
+
/**
|
|
3495
|
+
* Check if the node is inside a JSX attribute value
|
|
3496
|
+
* @param node The AST node to check
|
|
3497
|
+
* @returns `true` if the node is inside a JSX attribute value
|
|
3498
|
+
*/
|
|
3499
|
+
function isInsideJSXAttributeValue(node) {
|
|
3500
|
+
return node.parent.type === AST_NODE_TYPES.JSXAttribute || findParentAttribute(node, (n) => n.value?.type === AST_NODE_TYPES.JSXExpressionContainer) != null;
|
|
3501
|
+
}
|
|
3502
|
+
/**
|
|
3503
|
+
* Check if the node is declared inside a class component's render block
|
|
3504
|
+
* Ex: class C extends React.Component { render() { const Nested = () => <div />; } }
|
|
3505
|
+
* @param node The AST node to check
|
|
3506
|
+
* @returns `true` if the node is inside a class component's render block
|
|
3507
|
+
*/
|
|
3508
|
+
function isInsideRenderMethod(node) {
|
|
3509
|
+
return Traverse.findParent(node, (n) => core.isRenderMethodLike(n) && core.isClassComponent(n.parent.parent)) != null;
|
|
3510
|
+
}
|
|
3429
3511
|
|
|
3430
3512
|
//#endregion
|
|
3431
3513
|
//#region src/rules/no-nested-component-definitions/no-nested-component-definitions.ts
|
|
@@ -3442,21 +3524,24 @@ var no_nested_component_definitions_default = createRule({
|
|
|
3442
3524
|
defaultOptions: []
|
|
3443
3525
|
});
|
|
3444
3526
|
function create$22(context) {
|
|
3445
|
-
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;
|
|
3527
|
+
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 | core.FunctionComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayFlatMapCallback;
|
|
3446
3528
|
const fc = core.getFunctionComponentCollector(context, { hint });
|
|
3447
3529
|
const cc = core.getClassComponentCollector(context);
|
|
3448
3530
|
return merge(fc.visitor, cc.visitor, { "Program:exit"(program) {
|
|
3449
3531
|
const fComponents = [...fc.api.getAllComponents(program)];
|
|
3450
3532
|
const cComponents = [...cc.api.getAllComponents(program)];
|
|
3533
|
+
const fComponentNodes = new Set(fComponents.map((c) => c.node));
|
|
3534
|
+
const cComponentNodes = new Set(cComponents.map((c) => c.node));
|
|
3451
3535
|
function findEnclosingComponent(node) {
|
|
3452
3536
|
return Traverse.findParent(node, (n) => {
|
|
3453
|
-
if (Check.isFunction(n)) return
|
|
3454
|
-
if (Check.isClass(n)) return
|
|
3537
|
+
if (Check.isFunction(n)) return fComponentNodes.has(n);
|
|
3538
|
+
if (Check.isClass(n)) return cComponentNodes.has(n);
|
|
3455
3539
|
return false;
|
|
3456
3540
|
});
|
|
3457
3541
|
}
|
|
3458
|
-
for (
|
|
3459
|
-
|
|
3542
|
+
for (let { name, node: component } of fComponents) {
|
|
3543
|
+
name ??= getWrapperCallBoundName(context, component);
|
|
3544
|
+
if (name == null || !core.isFunctionComponentNameLoose(name)) continue;
|
|
3460
3545
|
if (isInsideJSXAttributeValue(component)) {
|
|
3461
3546
|
context.report({
|
|
3462
3547
|
data: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "5.18.
|
|
3
|
+
"version": "5.18.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,25 +36,25 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@typescript-eslint/scope-manager": "^8.
|
|
40
|
-
"@typescript-eslint/type-utils": "^8.
|
|
41
|
-
"@typescript-eslint/types": "^8.
|
|
42
|
-
"@typescript-eslint/typescript-estree": "^8.
|
|
43
|
-
"@typescript-eslint/utils": "^8.
|
|
39
|
+
"@typescript-eslint/scope-manager": "^8.66.0",
|
|
40
|
+
"@typescript-eslint/type-utils": "^8.66.0",
|
|
41
|
+
"@typescript-eslint/types": "^8.66.0",
|
|
42
|
+
"@typescript-eslint/typescript-estree": "^8.66.0",
|
|
43
|
+
"@typescript-eslint/utils": "^8.66.0",
|
|
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.18.
|
|
49
|
-
"@eslint-react/core": "5.18.
|
|
50
|
-
"@eslint-react/
|
|
51
|
-
"@eslint-react/shared": "5.18.
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/
|
|
48
|
+
"@eslint-react/ast": "5.18.3",
|
|
49
|
+
"@eslint-react/core": "5.18.3",
|
|
50
|
+
"@eslint-react/eslint": "5.18.3",
|
|
51
|
+
"@eslint-react/shared": "5.18.3",
|
|
52
|
+
"@eslint-react/var": "5.18.3",
|
|
53
|
+
"@eslint-react/jsx": "5.18.3"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@types/react": "^19.2.
|
|
57
|
-
"@types/react-dom": "^19.2.
|
|
56
|
+
"@types/react": "^19.2.18",
|
|
57
|
+
"@types/react-dom": "^19.2.4",
|
|
58
58
|
"dedent": "^1.7.2",
|
|
59
59
|
"eslint": "^10.8.0",
|
|
60
60
|
"react": "^19.2.8",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"tsl": "^1.0.30",
|
|
64
64
|
"tsl-dx": "^0.13.3",
|
|
65
65
|
"typescript": "6.0.3",
|
|
66
|
-
"@local/
|
|
67
|
-
"@local/
|
|
66
|
+
"@local/eff": "0.0.0",
|
|
67
|
+
"@local/configs": "0.0.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"eslint": "*",
|