eslint-plugin-react-x 5.18.2 → 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.
Files changed (2) hide show
  1. package/dist/index.js +57 -50
  2. package/package.json +14 -14
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.2";
148
+ var version = "5.18.3";
149
149
 
150
150
  //#endregion
151
151
  //#region src/utils/create-rule.ts
@@ -3396,47 +3396,39 @@ 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
- * Well-known component wrapper function names, matched by exact or `.`-suffixed fully
3401
- * qualified name (e.g. `memo`, `React.memo`, `mobx.observer`, `connect` from react-redux,
3402
- * or Relay's `create*Container` helpers). Only wrappers whose argument is a render function
3403
- * are listed; wrappers taking a component identifier (`styled`, `motion`) or a loader
3404
- * (`lazy`, `dynamic`) are irrelevant for name resolution.
3405
- */
3406
- const WELL_KNOWN_COMPONENT_WRAPPERS = [
3407
- "connect",
3408
- "createFragmentContainer",
3409
- "createPaginationContainer",
3410
- "createRefetchContainer",
3411
- "forwardRef",
3412
- "graphql",
3413
- "memo",
3414
- "observer",
3415
- "useCallback"
3416
- ];
3417
- /** Matches the HOC naming convention shared by recompose, react-router v5, Formik and custom HOCs (e.g. `withProps`, `withRouter`, `withFormik`, `withAuth`). */
3418
- const RE_HOC_WRAPPER_NAME = /^with[A-Z]/;
3419
- /**
3420
- * Check if a call expression is a well-known component wrapper call.
3421
- * Only calls whose callee's fully qualified name is (or ends with) a well-known wrapper
3422
- * name (e.g. `memo`, `React.memo`, `React.useCallback`, `mobx.observer`) are treated as
3423
- * wrappers; anything else, including member calls on data objects (e.g. `items.map`,
3424
- * `Array.from`), is not, so array method callbacks are never mistaken for wrapped components.
3425
- * Curried wrappers like `connect(...)(Component)` or `withFormik(...)(Component)` are
3426
- * recognized by unwrapping nested callee call expressions.
3427
- * @param context The rule context
3428
- * @param node The call expression to check
3429
- * @returns `true` if the call is a well-known component wrapper call
3430
- */
3431
- function isWellKnownComponentWrapperCall(context, node) {
3432
- let callee = Extract.unwrap(node.callee);
3433
- while (callee.type === AST_NODE_TYPES.CallExpression) callee = Extract.unwrap(callee.callee);
3434
- const name = Extract.getFullyQualifiedName(callee, (n) => context.sourceCode.getText(n));
3435
- const baseName = name.slice(name.lastIndexOf(".") + 1);
3436
- return RE_HOC_WRAPPER_NAME.test(baseName) || WELL_KNOWN_COMPONENT_WRAPPERS.some((wrapper) => name === wrapper || name.endsWith(`.${wrapper}`));
3437
- }
3438
- /**
3439
- * Check if a call expression is a component wrapper call for name resolution purposes.
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.
3440
3432
  * @param context The rule context
3441
3433
  * @param call The call expression to check
3442
3434
  * @param arg The function node passed to the call
@@ -3444,14 +3436,29 @@ function isWellKnownComponentWrapperCall(context, node) {
3444
3436
  */
3445
3437
  function isComponentWrapperCall(context, call, arg) {
3446
3438
  if (Extract.unwrap(call.callee) === arg) return false;
3447
- return isWellKnownComponentWrapperCall(context, call);
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;
3448
3456
  }
3449
3457
  /**
3450
- * Resolve the name a function is bound to through a chain of wrapping call expressions,
3451
- * e.g. `const Component = useCallback(() => <div />, [])` resolves to `Component`.
3458
+ * Resolve the name a function is bound to through wrapping calls (e.g. `const C = useCallback(...)` → `C`).
3452
3459
  * @param context The rule context
3453
3460
  * @param node The function node to resolve the bound name for
3454
- * @returns The bound name if the call chain ends at a variable declarator with an identifier, `null` otherwise
3461
+ * @returns The bound name, or `null` if the call chain does not end at an identifier declarator
3455
3462
  */
3456
3463
  function getWrapperCallBoundName(context, node) {
3457
3464
  let current = node;
@@ -3472,7 +3479,7 @@ function getWrapperCallBoundName(context, node) {
3472
3479
  return parent.id.name;
3473
3480
  }
3474
3481
  /**
3475
- * Determine whether the node is inside `createElement`'s props argument
3482
+ * Check if the node is inside `createElement`'s props argument
3476
3483
  * @param context The rule context
3477
3484
  * @param node The AST node to check
3478
3485
  * @returns `true` if the node is inside `createElement`'s props
@@ -3485,17 +3492,17 @@ function isInsideCreateElementProps(context, node) {
3485
3492
  return prop === call.arguments[1];
3486
3493
  }
3487
3494
  /**
3488
- * Determine whether the node is inside JSX attribute value
3495
+ * Check if the node is inside a JSX attribute value
3489
3496
  * @param node The AST node to check
3490
- * @returns `true` if the node is inside JSX attribute value
3497
+ * @returns `true` if the node is inside a JSX attribute value
3491
3498
  */
3492
3499
  function isInsideJSXAttributeValue(node) {
3493
3500
  return node.parent.type === AST_NODE_TYPES.JSXAttribute || findParentAttribute(node, (n) => n.value?.type === AST_NODE_TYPES.JSXExpressionContainer) != null;
3494
3501
  }
3495
3502
  /**
3496
- * Check whether a given node is declared inside a class component's render block
3503
+ * Check if the node is declared inside a class component's render block
3497
3504
  * Ex: class C extends React.Component { render() { const Nested = () => <div />; } }
3498
- * @param node The AST node being checked
3505
+ * @param node The AST node to check
3499
3506
  * @returns `true` if the node is inside a class component's render block
3500
3507
  */
3501
3508
  function isInsideRenderMethod(node) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-x",
3
- "version": "5.18.2",
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,21 +36,21 @@
36
36
  "dist"
37
37
  ],
38
38
  "dependencies": {
39
- "@typescript-eslint/scope-manager": "^8.65.0",
40
- "@typescript-eslint/type-utils": "^8.65.0",
41
- "@typescript-eslint/types": "^8.65.0",
42
- "@typescript-eslint/typescript-estree": "^8.65.0",
43
- "@typescript-eslint/utils": "^8.65.0",
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.2",
49
- "@eslint-react/core": "5.18.2",
50
- "@eslint-react/eslint": "5.18.2",
51
- "@eslint-react/jsx": "5.18.2",
52
- "@eslint-react/var": "5.18.2",
53
- "@eslint-react/shared": "5.18.2"
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
56
  "@types/react": "^19.2.18",
@@ -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/configs": "0.0.0",
67
- "@local/eff": "0.0.0"
66
+ "@local/eff": "0.0.0",
67
+ "@local/configs": "0.0.0"
68
68
  },
69
69
  "peerDependencies": {
70
70
  "eslint": "*",